From e2c37a7d9482af54b14bb2f99e5fb79c7949eb47 Mon Sep 17 00:00:00 2001 From: Arseniy Terekhin Date: Sat, 28 Dec 2024 17:36:06 +0300 Subject: [PATCH] format: apply .clang-format style --- .clang-format | 203 ++++++++ include/videoreader/videoreader.h | 61 ++- include/videoreader/videowriter.h | 19 +- src/ffmpeg_common.hpp | 5 +- src/spinlock.hpp | 15 +- src/thismsgpack.cpp | 79 +-- src/thismsgpack.hpp | 35 +- src/videoreader.cpp | 73 +-- src/videoreader_c.cpp | 52 +- src/videoreader_ffmpeg.cpp | 251 ++++----- src/videoreader_ffmpeg.hpp | 19 +- src/videoreader_galaxy.cpp | 821 ++++++++++++++++-------------- src/videoreader_galaxy.hpp | 19 +- src/videoreader_go.cpp | 71 +-- src/videoreader_pylon.cpp | 102 ++-- src/videoreader_pylon.hpp | 19 +- src/videowriter.cpp | 177 ++++--- 17 files changed, 1143 insertions(+), 878 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1ec8b13 --- /dev/null +++ b/.clang-format @@ -0,0 +1,203 @@ +BasedOnStyle: LLVM + +# Always break after an open bracket, if the parameters +# don’t fit on a single line, e.g.: +# +# someLongFunction( +# argument1, argument2); +# +AlignAfterOpenBracket: AlwaysBreak + +# Break constructor initializers after the colon and commas. +# +# Constructor() : +# initializer1(), +# initializer2() +# +BreakConstructorInitializers: AfterColon + +# If false, a function call’s arguments will either be all on the same +# line or will have one line each. +# +# true: +# void f() { +# f(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaa, +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); +# } +# +# false: +# void f() { +# f(aaaaaaaaaaaaaaaaaaaa, +# aaaaaaaaaaaaaaaaaaaa, +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); +# } +# +BinPackArguments: false + +# If false, a function declaration’s or function definition’s parameters will +# either all be on the same line or will have one line each. +# +# true: +# void f(int aaaaaaaaaaaaaaaaaaaa, int aaaaaaaaaaaaaaaaaaaa, +# int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} +# +# false: +# void f(int aaaaaaaaaaaaaaaaaaaa, +# int aaaaaaaaaaaaaaaaaaaa, +# int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} +# +BinPackParameters: false + +# Don’t align escaped newlines. +# +# #define A \ +# int aaaa; \ +# int b; \ +# int dddddddddd; +# +AlignEscapedNewlines: DontAlign + +# The number of spaces before trailing line comments (// - comments). +# +# ajosn_pos_t pos; // pos is public to show the position +# +SpacesBeforeTrailingComments: 2 + +# If true, aligns trailing comments. +# +# true: false: +# int a; // My comment a vs. int a; // My comment a +# int b = 2; // comment b int b = 2; // comment about b +# +AlignTrailingComments: false + + +# If true, clang-format will attempt to re-flow comments. +# +# false: +# // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information +# /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */ +# +# true: +# // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of +# // information +# /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of +# * information */ +# +ReflowComments: false + +# Never merge blocks into a single line. +# +# while (true) { +# } +# while (true) { +# continue; +# } +# +AllowShortBlocksOnASingleLine: Never + +# Never merge functions into a single line. +AllowShortFunctionsOnASingleLine: None + +# Never put short ifs on the same line. +# +# if (a) +# return; +# +# if (b) +# return; +# else +# return; +# +# if (c) +# return; +# else { +# return; +# } +# +AllowShortIfStatementsOnASingleLine: Never + +# Align reference to the left. +# +# int& a; +# +# not available in older formatter versions +# ReferenceAlignment: Left + +# Align pointer to the left. +# +# int* a; +# +PointerAlignment: Left + +# Indent width for line continuations. +# +# int i = // VeryVeryVeryVeryVeryLongComment +# longFunction( // Again a long comment +# arg); +ContinuationIndentWidth: 4 + +# The number of columns to use for indentation. +# +# void f() { +# someFunction(); +# if (true, false) { +# f(); +# } +# } +IndentWidth: 2 + +# If the constructor initializers don’t fit on a line, +# put each initializer on its own line. +# +# true: +# SomeClass::Constructor() +# : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) { +# return 0; +# } +# +# false: +# SomeClass::Constructor() +# : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), +# aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa) { +# return 0; +# } +# +ConstructorInitializerAllOnOneLineOrOnePerLine: true + +# If a constructor definition with a member initializer list doesn’t fit +# on a single line, allow putting all member initializers onto the next line, +# if `ConstructorInitializerAllOnOneLineOrOnePerLine` is true. Note that +# this parameter has no effect if +# `ConstructorInitializerAllOnOneLineOrOnePerLine` is false. +# +# true: +# MyClass::MyClass() : +# member0(0), member1(2) {} +# +# false: +# MyClass::MyClass() : +# member0(0), +# member1(2) {} +# +AllowAllConstructorInitializersOnNextLine: false + +# Always break after template declaration. +# +# template +# T foo() { +# } +# template +# T foo(int aaaaaaaaaaaaaaaaaaaaa, +# int bbbbbbbbbbbbbbbbbbbbb) { +# } +# +AlwaysBreakTemplateDeclarations: Yes + +# Never merge lambdas into a single line. +AllowShortLambdasOnASingleLine: None + +Standard: c++17 +UseTab: Never + +# AllowAllArgumentsOnNextLine: false diff --git a/include/videoreader/videoreader.h b/include/videoreader/videoreader.h index 3a2add5..5acdf57 100644 --- a/include/videoreader/videoreader.h +++ b/include/videoreader/videoreader.h @@ -1,23 +1,20 @@ #pragma once +#include #include #include -#include - -class VideoReader -{ +class VideoReader { public: - enum class SCALAR_TYPE: int32_t { - U8 - }; + enum class SCALAR_TYPE : int32_t { U8 }; struct VRImage { int32_t height; int32_t width; int32_t channels; SCALAR_TYPE scalar_type; int32_t stride; // 0 when unknown. number of bytes between rows - uint8_t *data; // pointer to the first pixel - void *user_data; // user supplied data, useful for freeing in DeallocateCallback + uint8_t* data; // pointer to the first pixel + void* + user_data; // user supplied data, useful for freeing in DeallocateCallback }; /** @@ -28,20 +25,32 @@ class VideoReader * When `VRImage.data` is left `nullptr`, the library treats it like * memory allocation error */ - using AllocateCallback = void (*)(VRImage *, void*); - using DeallocateCallback = void (*)(VRImage *, void*); + using AllocateCallback = void (*)(VRImage*, void*); + using DeallocateCallback = void (*)(VRImage*, void*); struct Frame { using number_t = uint64_t; using timestamp_s_t = double; - Frame(DeallocateCallback free, void *userdata, VRImage const& image, number_t number, timestamp_s_t timestamp_s) : - number{number}, timestamp_s{timestamp_s}, free{free}, userdata{userdata}, image{image} {} - number_t number; // zero-indexed; this number is not continuous due to possible invalid data frames + Frame( + DeallocateCallback free, + void* userdata, + VRImage const& image, + number_t number, + timestamp_s_t timestamp_s) : + number{number}, + timestamp_s{timestamp_s}, + free{free}, + userdata{userdata}, + image{image} { + } + number_t + number; // zero-indexed; this number is not continuous due to possible invalid data frames timestamp_s_t timestamp_s; // seconds since the start of the video - unsigned char const* extras{}; // nullptr ot msgpack list in requested order. MUST be freed by `free` ca;; + unsigned char const* + extras{}; // nullptr ot msgpack list in requested order. MUST be freed by `free` ca;; unsigned int extras_size{}; // num bytes in extra DeallocateCallback free; - void *userdata; + void* userdata; VRImage image; ~Frame(); // Frees VRImage and extras }; @@ -62,7 +71,8 @@ class VideoReader /** * Main logging callback. Useful for debugging and to not flood stdout */ - using LogCallback = void (*)(char const* message, LogLevel log_level, void* userdata); + using LogCallback = + void (*)(char const* message, LogLevel log_level, void* userdata); public: // url: file path or any ffmpeg url @@ -74,14 +84,13 @@ class VideoReader // // see https://ffmpeg.org/ffmpeg-protocols.html for more details static std::unique_ptr create( - std::string const& url, - std::vector const& parameter_pairs = {}, // size % 2 == 0 - std::vector const& extras = {}, // for extra_data - AllocateCallback alloc_callback = nullptr, - DeallocateCallback dealloc_callback = nullptr, - LogCallback log_callback = nullptr, - void* userdata = nullptr - ); + std::string const& url, + std::vector const& parameter_pairs = {}, // size % 2 == 0 + std::vector const& extras = {}, // for extra_data + AllocateCallback alloc_callback = nullptr, + DeallocateCallback dealloc_callback = nullptr, + LogCallback log_callback = nullptr, + void* userdata = nullptr); virtual ~VideoReader(); VideoReader& operator=(VideoReader const&) = delete; @@ -98,5 +107,5 @@ class VideoReader // decode: decode the frame (false is useful for skipping frames, // the result will be a valid frame with uinitialized pixel values) // frame data are read in a separate thread - virtual FrameUP next_frame(bool decode=true) = 0; + virtual FrameUP next_frame(bool decode = true) = 0; }; diff --git a/include/videoreader/videowriter.h b/include/videoreader/videowriter.h index 497b139..02bc1b8 100644 --- a/include/videoreader/videowriter.h +++ b/include/videoreader/videowriter.h @@ -1,8 +1,7 @@ #pragma once #include "videoreader.h" -class VideoWriter -{ +class VideoWriter { public: struct Impl; @@ -13,18 +12,18 @@ class VideoWriter // log_callback: log callback (currently unused) // userdata: data for log_callback (currently unused) VideoWriter( - std::string const& uri, - VideoReader::VRImage const& format, - std::vector const& parameter_pairs = {}, // size % 2 == 0 - bool realtime = false, - VideoReader::LogCallback log_callback = nullptr, - void* userdata = nullptr - ); + std::string const& uri, + VideoReader::VRImage const& format, + std::vector const& parameter_pairs = {}, // size % 2 == 0 + bool realtime = false, + VideoReader::LogCallback log_callback = nullptr, + void* userdata = nullptr); VideoWriter& operator=(VideoWriter const&) = delete; bool push(VideoReader::Frame const&); void close(); ~VideoWriter(); + protected: - std::unique_ptr impl; + std::unique_ptr impl; }; diff --git a/src/ffmpeg_common.hpp b/src/ffmpeg_common.hpp index f776149..265f9df 100644 --- a/src/ffmpeg_common.hpp +++ b/src/ffmpeg_common.hpp @@ -1,15 +1,14 @@ #pragma once extern "C" { -#include +#include #include +#include #include -#include } #include #include #include - struct AVDictionaryDeleter { void operator()(AVDictionary* av_dictionary) const noexcept { av_dict_free(&av_dictionary); diff --git a/src/spinlock.hpp b/src/spinlock.hpp index 9495054..2be35b8 100644 --- a/src/spinlock.hpp +++ b/src/spinlock.hpp @@ -2,17 +2,22 @@ class SpinLock { std::atomic_flag lck = ATOMIC_FLAG_INIT; + public: - void lock() { while (lck.test_and_set(std::memory_order_acquire)); } - void unlock() { lck.clear(std::memory_order_release); } + void lock() { + while (lck.test_and_set(std::memory_order_acquire)) + ; + } + void unlock() { + lck.clear(std::memory_order_release); + } }; - // Sorry, not the right place for this code. Maybe rename to common.hpp? -template +template inline void remove_every_second_item(T& c) { auto it = c.begin(); - while (it != c.end()){ + while (it != c.end()) { ++it; if (it != c.end()) { it = c.erase(it); diff --git a/src/thismsgpack.cpp b/src/thismsgpack.cpp index 4fe5318..72fd676 100644 --- a/src/thismsgpack.cpp +++ b/src/thismsgpack.cpp @@ -1,28 +1,24 @@ #include "thismsgpack.hpp" #include -MallocStream::MallocStream(size_t size) -{ -this->_data = this->_end = static_cast(malloc(size)); -this->capacity_end = this->_end + size; +MallocStream::MallocStream(size_t size) { + this->_data = this->_end = static_cast(malloc(size)); + this->capacity_end = this->_end + size; } -void MallocStream::write(unsigned char const *value, size_t size) -{ +void MallocStream::write(unsigned char const* value, size_t size) { ensure_have_n_free_bytes(size); memcpy(this->_end, value, size); this->_end += size; } -void MallocStream::ensure_have_n_free_bytes(unsigned int n) -{ +void MallocStream::ensure_have_n_free_bytes(unsigned int n) { size_t const bytes_left = this->capacity_end - this->_end; - if (bytes_left < n) - { + if (bytes_left < n) { size_t const cur_capacity = this->capacity_end - this->_data; size_t const cur_size = cur_capacity - bytes_left; size_t const new_size = cur_capacity * 2; - this->_data = static_cast(realloc(this->_data, new_size)); + this->_data = static_cast(realloc(this->_data, new_size)); if (!this->_data) { throw std::runtime_error("MallocStream out of memory"); // ToDo: cleanup } @@ -33,8 +29,7 @@ void MallocStream::ensure_have_n_free_bytes(unsigned int n) namespace { template -constexpr inline T htonT(T value) noexcept -{ +constexpr inline T htonT(T value) noexcept { #ifndef __BIG_ENDIAN__ char* ptr = reinterpret_cast(&value); std::reverse(ptr, ptr + sizeof(T)); @@ -43,51 +38,42 @@ constexpr inline T htonT(T value) noexcept } template -void inline _write_raw(const T val, MallocStream& out) -{ +void inline _write_raw(const T val, MallocStream& out) { const T net_val = htonT(val); out.write(reinterpret_cast(&net_val), sizeof(net_val)); } template <> -void inline _write_raw(const uint8_t val, MallocStream& out) -{ +void inline _write_raw(const uint8_t val, MallocStream& out) { out.write(&val, sizeof(uint8_t)); } -} +} // namespace namespace thismsgpack { -void pack_array_header(size_t const n, MallocStream& out) -{ +void pack_array_header(size_t const n, MallocStream& out) { if (n <= 0x0f) { out.write(static_cast(0x90 + n)); - } - else if (n <= 0xffff) { + } else if (n <= 0xffff) { out.write(static_cast(0xdc)); _write_raw(static_cast(n), out); - } - else if (n <= 0xffffffff) { + } else if (n <= 0xffffffff) { out.write('\xdd'); _write_raw(static_cast(n), out); - } - else { + } else { throw std::runtime_error("Array is too large"); } } - // pack `double` -void pack(double const val, MallocStream& out) -{ +void pack(double const val, MallocStream& out) { out.write('\xcb'); _write_raw(val, out); } // pack `float` -void pack(float const val, MallocStream& out) -{ +void pack(float const val, MallocStream& out) { out.write('\xca'); _write_raw(val, out); } @@ -96,44 +82,35 @@ void pack(float const val, MallocStream& out) void pack(int64_t const val, MallocStream& out) { if (0 <= val && val < 0x80) { out.write(static_cast(val)); - } - else if (-0x20 <= val && val < 0) { + } else if (-0x20 <= val && val < 0) { out.write(static_cast(val)); - } - else if (0x80 <= val && val <= std::numeric_limits::max()) { + } else if (0x80 <= val && val <= std::numeric_limits::max()) { out.write('\xcc'); // uint 8 out.write(static_cast(val)); - } - else if (std::numeric_limits::min() <= val && val < 0) { + } else if (std::numeric_limits::min() <= val && val < 0) { out.write('\xd0'); // int 8 out.write(static_cast(val)); - } - else if (0xff < val && val <= std::numeric_limits::max()) { + } else if (0xff < val && val <= std::numeric_limits::max()) { out.write('\xcd'); // uint 16 _write_raw(static_cast(val), out); - } - else if (std::numeric_limits::min() <= val && val < -0x80) { - out.write('\xd1'); // int 16 + } else if (std::numeric_limits::min() <= val && val < -0x80) { + out.write('\xd1'); // int 16 _write_raw(static_cast(val), out); - } - else if (0xffff < val && val <= std::numeric_limits::max()) { + } else if (0xffff < val && val <= std::numeric_limits::max()) { out.write('\xce'); // uint 32 _write_raw(static_cast(val), out); } // 0x80000000 else if (std::numeric_limits::min() <= val && val < -0x8000) { out.write('\xd2'); // int32 _write_raw(static_cast(val), out); - } - else if (0xffffffff < val /*&& val <= 0xffffffffffffffff*/) { + } else if (0xffffffff < val /*&& val <= 0xffffffffffffffff*/) { out.write('\xcf'); // uint 64 _write_raw(static_cast(val), out); - } - else if (/*-0x8000000000000000 <= val &&*/ val < -0x80000000LL) { + } else if (/*-0x8000000000000000 <= val &&*/ val < -0x80000000LL) { out.write('\xd3'); // int 64 _write_raw(static_cast(val), out); - } - else { + } else { throw std::runtime_error("Integer value out of range (impossible)"); } } -} \ No newline at end of file +} // namespace thismsgpack \ No newline at end of file diff --git a/src/thismsgpack.hpp b/src/thismsgpack.hpp index c9bcfa9..fe4894b 100644 --- a/src/thismsgpack.hpp +++ b/src/thismsgpack.hpp @@ -1,16 +1,14 @@ #pragma once -#include -#include -#include #include // std::reverse() +#include #include +#include +#include - -class MallocStream -{ - unsigned char *_data; - unsigned char *_end; - unsigned char *capacity_end; +class MallocStream { + unsigned char* _data; + unsigned char* _end; + unsigned char* capacity_end; public: MallocStream(size_t size); @@ -21,27 +19,24 @@ class MallocStream // } // } - void write(unsigned char const *value, size_t size); + void write(unsigned char const* value, size_t size); template - void write(const T (&bytes)[Size]) - { - this->write(reinterpret_cast(bytes), Size); + void write(const T (&bytes)[Size]) { + this->write(reinterpret_cast(bytes), Size); } template - void write(T const value) - { + void write(T const value) { static_assert(std::is_integral::value, "Integral required."); - this->write(reinterpret_cast(&value), sizeof(T)); + this->write(reinterpret_cast(&value), sizeof(T)); } - unsigned char *const data() { + unsigned char* const data() { return this->_data; } - size_t size() - { + size_t size() { return this->_end - this->_data; } @@ -61,4 +56,4 @@ void pack(float const val, MallocStream& out); // pack `int64` void pack(int64_t const val, MallocStream& out); -} \ No newline at end of file +} // namespace thismsgpack \ No newline at end of file diff --git a/src/videoreader.cpp b/src/videoreader.cpp index 54a43cb..b55e5df 100644 --- a/src/videoreader.cpp +++ b/src/videoreader.cpp @@ -1,5 +1,5 @@ -#include #include +#include #ifdef VIDEOREADER_WITH_FFMPEG #include "videoreader_ffmpeg.hpp" @@ -13,27 +13,24 @@ #include "videoreader_galaxy.hpp" #endif -static void default_vr_allocate(VideoReader::VRImage* image, void*) { - size_t size = image->stride * image->height; +static void default_vr_allocate(VideoReader::VRImage* image, void* unused) { + std::size_t size = image->stride * image->height; image->data = new (std::nothrow) uint8_t[size]; } -static void default_vr_deallocate(VideoReader::VRImage* image, void*) { +static void default_vr_deallocate(VideoReader::VRImage* image, void* unused) { delete[] static_cast(image->data); image->data = nullptr; } - std::unique_ptr VideoReader::create( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_callback, - DeallocateCallback delallocate_callback, - LogCallback log_callback, - void* userdata -) -{ + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_callback, + DeallocateCallback delallocate_callback, + LogCallback log_callback, + void* userdata) { if (parameter_pairs.size() % 2 != 0) { throw std::runtime_error("invalid videoreader parameters size"); } @@ -46,37 +43,52 @@ std::unique_ptr VideoReader::create( #ifdef VIDEOREADER_WITH_PYLON if (url == "pylon") { - return std::unique_ptr( - new VideoReaderPylon(url, parameter_pairs, extras, allocate_callback, delallocate_callback, log_callback, userdata)); + return std::unique_ptr(new VideoReaderPylon( + url, + parameter_pairs, + extras, + allocate_callback, + delallocate_callback, + log_callback, + userdata)); } #endif #ifdef VIDEOREADER_WITH_GALAXY if (url.find("galaxy://") == 0) { - return std::unique_ptr( - new VideoReaderGalaxy(url, parameter_pairs, extras, allocate_callback, delallocate_callback, log_callback, userdata)); + return std::unique_ptr(new VideoReaderGalaxy( + url, + parameter_pairs, + extras, + allocate_callback, + delallocate_callback, + log_callback, + userdata)); } #endif #ifdef VIDEOREADER_WITH_FFMPEG - return std::unique_ptr( - new VideoReaderFFmpeg(url, parameter_pairs, extras, allocate_callback, delallocate_callback, log_callback, userdata)); + return std::unique_ptr(new VideoReaderFFmpeg( + url, + parameter_pairs, + extras, + allocate_callback, + delallocate_callback, + log_callback, + userdata)); #else -# if !defined(VIDEOREADER_WITH_FFMPEG) && !defined(VIDEOREADER_WITH_PYLON) && !defined(VIDEOREADER_WITH_GALAXY) +#if !defined(VIDEOREADER_WITH_FFMPEG) && !defined(VIDEOREADER_WITH_PYLON) && \ + !defined(VIDEOREADER_WITH_GALAXY) throw std::runtime_error("build without any video backed"); -# else +#else throw std::runtime_error("unsupported uri"); -# endif +#endif #endif } -void VideoReader::set( - std::vector const& parameter_pairs -) { +void VideoReader::set(std::vector const& parameter_pairs) { throw std::runtime_error("not implemented"); } - -VideoReader::Frame::~Frame() -{ +VideoReader::Frame::~Frame() { if (this->free) { // check that the frame wasn't moved (*this->free)(&this->image, this->userdata); } @@ -85,4 +97,5 @@ VideoReader::Frame::~Frame() this->extras_size = 0; } -VideoReader::~VideoReader() {} +VideoReader::~VideoReader() { +} diff --git a/src/videoreader_c.cpp b/src/videoreader_c.cpp index c9ab0cd..cf9d297 100644 --- a/src/videoreader_c.cpp +++ b/src/videoreader_c.cpp @@ -1,10 +1,10 @@ +#include #include #include -#include #define API extern "C" -typedef void (*videoreader_log)(char const*, int, void*); -typedef void (*videoreader_allocate)(char const*); +using videoreader_log = void (*)(char const*, int, void*); +using videoreader_allocate = void (*)(char const*); typedef struct { int32_t height; @@ -12,11 +12,11 @@ typedef struct { int32_t channels; int32_t scalar_type; int32_t stride; // 0 when unknown. number of bytes between rows - uint8_t *data; // pointer to the first pixel - void *user_data; // user supplied data, useful for freeing in DeallocateCallback + uint8_t* data; // pointer to the first pixel + void* + user_data; // user supplied data, useful for freeing in DeallocateCallback } VRImage; - static_assert(sizeof(VRImage) == sizeof(VideoReader::VRImage), "error"); static std::string videoreader_what_str; @@ -38,11 +38,11 @@ API int videoreader_create( void* userdata) { try { std::vector parameter_pairs; - for (int idx{} ; idx < argc; ++idx ) { + for (int idx{}; idx < argc; ++idx) { parameter_pairs.emplace_back(argv[idx]); } std::vector extras_vec; - for (int idx{} ; idx < extrasc; ++idx ) { + for (int idx{}; idx < extrasc; ++idx) { extras_vec.emplace_back(extras[idx]); } auto video_reader = VideoReader::create( @@ -61,14 +61,11 @@ API int videoreader_create( return 0; } -API int videoreader_set( - struct videoreader* reader, - char const* argv[], - int argc -) { +API int +videoreader_set(struct videoreader* reader, char const* argv[], int argc) { try { std::vector parameter_pairs; - for (int idx{} ; idx < argc; ++idx ) { + for (int idx{}; idx < argc; ++idx) { parameter_pairs.emplace_back(argv[idx]); } reinterpret_cast(reader)->set(parameter_pairs); @@ -79,7 +76,6 @@ API int videoreader_set( return 0; } - API void videoreader_delete(struct videoreader* reader) { delete reinterpret_cast(reader); } @@ -95,8 +91,9 @@ API int videoreader_next_frame( try { VideoReader::FrameUP frame = reinterpret_cast(reader)->next_frame(decode); - if (!frame) + if (!frame) { return 1; + } auto const& image = frame->image; dst_img->height = image.height; @@ -133,11 +130,10 @@ API int videowriter_create( int argc, bool realtime, videoreader_log log_callback, - void* userdata -) { + void* userdata) { try { std::vector parameter_pairs; - for (int idx{} ; idx < argc; ++idx ) { + for (int idx{}; idx < argc; ++idx) { parameter_pairs.emplace_back(argv[idx]); } *writer = reinterpret_cast(new VideoWriter( @@ -159,13 +155,16 @@ API void videowriter_delete(struct videowriter* reader) { } API int videowriter_push( - struct videowriter* writer, - VRImage const* img, - double timestamp_s) { + struct videowriter* writer, VRImage const* img, double timestamp_s) { try { - VideoReader::Frame frame{0, nullptr, *reinterpret_cast(img), 0, timestamp_s}; - bool const successful_push = reinterpret_cast( - writer)->push(frame); + VideoReader::Frame frame{ + 0, + nullptr, + *reinterpret_cast(img), + 0, + timestamp_s}; + bool const successful_push = + reinterpret_cast(writer)->push(frame); return successful_push ? 0 : 1; } catch (std::exception& e) { videoreader_what_str = e.what(); @@ -173,8 +172,7 @@ API int videowriter_push( } } -API int videowriter_close( - struct videowriter* writer) { +API int videowriter_close(struct videowriter* writer) { try { reinterpret_cast(writer)->close(); } catch (std::exception& e) { diff --git a/src/videoreader_ffmpeg.cpp b/src/videoreader_ffmpeg.cpp index f11ac11..5a5bb33 100644 --- a/src/videoreader_ffmpeg.cpp +++ b/src/videoreader_ffmpeg.cpp @@ -10,49 +10,48 @@ extern "C" { #include +#include // needed? #include -#include // needed? } +#include "ffmpeg_common.hpp" +#include "spinlock.hpp" +#include "thismsgpack.hpp" #include #include #include +#include // std::runtime_error #include #include -#include // std::runtime_error -#include "spinlock.hpp" -#include "ffmpeg_common.hpp" -#include "thismsgpack.hpp" - static AVFormatContextUP _get_format_context( - std::string const& filename, - AVDictionaryUP &options, - void* opaque) -{ - AVInputFormat const *input_format = nullptr; + std::string const& filename, AVDictionaryUP& options, void* opaque) { + AVInputFormat const* input_format = nullptr; std::string path_to_use = filename; if (filename.find("dshow://") == 0) { input_format = av_find_input_format("dshow"); path_to_use = filename.substr(8, filename.size()); } - AVFormatContext *format_context = avformat_alloc_context(); + AVFormatContext* format_context = avformat_alloc_context(); if (format_context == nullptr) { throw std::runtime_error("Failed to allocate AVFormatContext"); } format_context->opaque = opaque; - AVDictionary *opts = options.release(); + AVDictionary* opts = options.release(); - int const ret = avformat_open_input(&format_context, path_to_use.c_str(), -# ifdef FF_API_AVIOFORMAT // silly cast for ffmpeg4 - (AVInputFormat *) -# endif - input_format, &opts); + int const ret = avformat_open_input( + &format_context, + path_to_use.c_str(), +#ifdef FF_API_AVIOFORMAT // silly cast for ffmpeg4 + (AVInputFormat*) +#endif + input_format, + &opts); options.reset(opts); if (ret < 0) { throw std::runtime_error( - "Can't open `" + filename + "`, " + get_av_error(ret)); + "Can't open `" + filename + "`, " + get_av_error(ret)); } return AVFormatContextUP(format_context); } @@ -61,22 +60,23 @@ static AVFormatContextUP _get_format_context( This is a copy from libavformat/internal.h. Helps with logging big time. */ struct DirtyHackFFStream { - int reorder; - struct AVBSFContext *bsfc; - int bitstream_checked; - AVCodecContext *avctx; + int reorder; + struct AVBSFContext* bsfc; + int bitstream_checked; + AVCodecContext* avctx; }; -static AVStream* _get_video_stream(AVFormatContext* format_context) -{ +static AVStream* _get_video_stream(AVFormatContext* format_context) { for (unsigned stream_idx = 0; stream_idx < format_context->nb_streams; ++stream_idx) { -# ifdef FF_API_AVIOFORMAT - reinterpret_cast(format_context->streams[stream_idx]->internal) -# else - reinterpret_cast(format_context->streams[stream_idx] + 1) -# endif - ->avctx->opaque = format_context->opaque; +#ifdef FF_API_AVIOFORMAT + reinterpret_cast( + format_context->streams[stream_idx]->internal) +#else + reinterpret_cast( + format_context->streams[stream_idx] + 1) +#endif + ->avctx->opaque = format_context->opaque; } if (avformat_find_stream_info(format_context, NULL) != 0) { throw std::runtime_error("avformat_find_stream_info failed"); @@ -91,10 +91,9 @@ static AVStream* _get_video_stream(AVFormatContext* format_context) } static AVCodecContextUP _get_codec_context( - AVCodecParameters const* av_codecpar, - AVDictionaryUP &options, - void* opaque) -{ + AVCodecParameters const* av_codecpar, + AVDictionaryUP& options, + void* opaque) { AVCodec const* av_codec = avcodec_find_decoder(av_codecpar->codec_id); if (!av_codec) { throw std::runtime_error("Unsupported codec"); @@ -155,21 +154,23 @@ static SwsContextUP _create_converter( } struct AVFramePusher { - enum class Type { - INT64_T, INT - } _type; + enum class Type { INT64_T, INT } _type; void* AVFrame::*ref; - AVFramePusher(int64_t AVFrame::*ref) : _type{Type::INT64_T}, - ref{reinterpret_cast(ref)} {} - AVFramePusher(int AVFrame::*ref) : _type{Type::INT}, - ref{reinterpret_cast(ref)} {} + AVFramePusher(int64_t AVFrame::*ref) : + _type{Type::INT64_T}, + ref{reinterpret_cast(ref)} { + } + AVFramePusher(int AVFrame::*ref) : + _type{Type::INT}, + ref{reinterpret_cast(ref)} { + } - void operator()(AVFrame const* frame, MallocStream &out) const{ - switch (this->_type) - { + void operator()(AVFrame const* frame, MallocStream& out) const { + switch (this->_type) { case Type::INT64_T: { - auto const value = frame->*(reinterpret_cast(this->ref)); + auto const value = + frame->*(reinterpret_cast(this->ref)); thismsgpack::pack(value, out); break; } @@ -190,7 +191,6 @@ struct AVFramePusher { // } // } - struct VideoReaderFFmpeg::Impl { decltype(VideoReader::Frame::number) current_frame = 0; std::atomic stop_requested; @@ -213,21 +213,19 @@ struct VideoReaderFFmpeg::Impl { void* userdata; Impl( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_callback, - DeallocateCallback deallocate_callback, - VideoReader::LogCallback log_callback, - void* userdata - ) : - stop_requested(false), - allocate_callback{allocate_callback}, - deallocate_callback{deallocate_callback}, - userdata{userdata}, - log_callback{log_callback}, - print_prefix{1} - { + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_callback, + DeallocateCallback deallocate_callback, + VideoReader::LogCallback log_callback, + void* userdata) : + stop_requested(false), + allocate_callback{allocate_callback}, + deallocate_callback{deallocate_callback}, + userdata{userdata}, + log_callback{log_callback}, + print_prefix{1} { for (auto const& extra : extras) { if (extra == "pkt_pos") { this->pushers.emplace_back(&AVFrame::pkt_pos); @@ -239,14 +237,16 @@ struct VideoReaderFFmpeg::Impl { this->pushers.emplace_back(&AVFrame::pkt_dts); } else { throw std::runtime_error( - "unknown extra: `" + extra + "`. Possible extras are: " - "'pkt_pos', 'quality', 'pts', 'pkt_dts'"); + "unknown extra: `" + extra + + "`. Possible extras are: " + "'pkt_pos', 'quality', 'pts', 'pkt_dts'"); } } AVDictionaryUP options = _create_dict_from_params_vec(parameter_pairs); this->format_context = _get_format_context(url, options, this); this->av_stream = _get_video_stream(format_context.get()); - this->codec_context = _get_codec_context(av_stream->codecpar, options, this); + this->codec_context = + _get_codec_context(av_stream->codecpar, options, this); this->av_frame = AVFrameUP(av_frame_alloc()); if (this->codec_context->pix_fmt != AV_PIX_FMT_NONE) { this->sws_context = _create_converter( @@ -332,8 +332,8 @@ struct VideoReaderFFmpeg::Impl { throw std::runtime_error("second call on ended stream"); } AVPacketUP local_packet(raw_packet); - int const send_ret = avcodec_send_packet( - this->codec_context.get(), local_packet.get()); + int const send_ret = + avcodec_send_packet(this->codec_context.get(), local_packet.get()); if (send_ret != 0) { // Let's guesstimate that one packet is one frame this->current_frame++; @@ -351,30 +351,38 @@ struct VideoReaderFFmpeg::Impl { "avcodec_receive_frame failed " + get_av_error(receive_ret)); } int32_t alignment = 16; - int32_t const preferred_stride = (this->codec_context->width * 3 + alignment - 1) & ~(alignment - 1); + int32_t const preferred_stride = + (this->codec_context->width * 3 + alignment - 1) & ~(alignment - 1); Frame::timestamp_s_t timestamp_s = -1.0; if (this->av_frame->pkt_dts != AV_NOPTS_VALUE) { - timestamp_s = this->av_frame->best_effort_timestamp * - av_q2d(this->format_context - ->streams[local_packet->stream_index]->time_base); + timestamp_s = + this->av_frame->best_effort_timestamp * + av_q2d(this->format_context->streams[local_packet->stream_index] + ->time_base); } Frame::number_t const number = this->current_frame++; - FrameUP ret(new Frame(this->deallocate_callback, this->userdata, { - this->codec_context->height, // height - this->codec_context->width, // width - 3, // channels - SCALAR_TYPE::U8, // scalar_type - preferred_stride, // stride - nullptr, // data - nullptr, // user_data - }, number, timestamp_s)); - VRImage *image = &ret->image; + FrameUP ret(new Frame( + this->deallocate_callback, + this->userdata, + { + this->codec_context->height, // height + this->codec_context->width, // width + 3, // channels + SCALAR_TYPE::U8, // scalar_type + preferred_stride, // stride + nullptr, // data + nullptr, // user_data + }, + number, + timestamp_s)); + VRImage* image = &ret->image; (*this->allocate_callback)(image, this->userdata); if (!image->data) { - throw std::runtime_error("allocation callback failed: data is nullptr"); + throw std::runtime_error( + "allocation callback failed: data is nullptr"); } if (!this->sws_context) { // because broken videos are weird this->sws_context = _create_converter( @@ -409,14 +417,15 @@ struct VideoReaderFFmpeg::Impl { } }; -static void videoreader_ffmpeg_callback(void* avcl, int level, const char* fmt, va_list vl) { +static void videoreader_ffmpeg_callback( + void* avcl, int level, const char* fmt, va_list vl) { if (!avcl) { return; // can't access userdata (opaque) } if (level > av_log_get_level()) { return; } - AVClass* avc = *(AVClass **) avcl; + AVClass* avc = *(AVClass**)avcl; // possible class names: // * AVFormatContext // * AVCodecContext @@ -425,33 +434,32 @@ static void videoreader_ffmpeg_callback(void* avcl, int level, const char* fmt, // * SWScaler // * URLContext - void *opaque = nullptr; - switch(avc->class_name[2]) - { - case 'F': // AVFormatContext - opaque = static_cast(avcl)->opaque; - break; - case 'C': // AVCodecContext - opaque = static_cast(avcl)->opaque; - break; - case 'I': // AVIOContext - opaque = static_cast(avcl)->opaque; - break; - // case 'R': // SWResampler - // opaque = static_cast(avcl)->opaque; - // break; - // case 'S': // SWScaler - // opaque = static_cast(avcl)->opaque; - // break; - case 'L': // URLContext - // Opaque struct. Ignore. - break; + void* opaque = nullptr; + switch (avc->class_name[2]) { + case 'F': // AVFormatContext + opaque = static_cast(avcl)->opaque; + break; + case 'C': // AVCodecContext + opaque = static_cast(avcl)->opaque; + break; + case 'I': // AVIOContext + opaque = static_cast(avcl)->opaque; + break; + // case 'R': // SWResampler + // opaque = static_cast(avcl)->opaque; + // break; + // case 'S': // SWScaler + // opaque = static_cast(avcl)->opaque; + // break; + case 'L': // URLContext + // Opaque struct. Ignore. + break; } if (opaque == nullptr) { return; } - auto *const impl = reinterpret_cast(opaque); - VideoReader::LogLevel const vr_level = [level]{ + auto* const impl = reinterpret_cast(opaque); + VideoReader::LogLevel const vr_level = [level] { if (level <= AV_LOG_FATAL) { return VideoReader::LogLevel::FATAL; } @@ -467,31 +475,36 @@ static void videoreader_ffmpeg_callback(void* avcl, int level, const char* fmt, return VideoReader::LogLevel::DEBUG; }(); char message[2048]; - av_log_format_line(avcl, level, fmt, vl, message, sizeof(message), &impl->print_prefix); + av_log_format_line( + avcl, level, fmt, vl, message, sizeof(message), &impl->print_prefix); impl->log_callback(message, vr_level, impl->userdata); } VideoReaderFFmpeg::VideoReaderFFmpeg( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_callback, - DeallocateCallback deallocate_callback, - LogCallback log_callback, - void* userdata) -{ + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_callback, + DeallocateCallback deallocate_callback, + LogCallback log_callback, + void* userdata) { avformat_network_init(); avdevice_register_all(); av_log_set_level(AV_LOG_INFO); if (log_callback != nullptr) { av_log_set_callback(videoreader_ffmpeg_callback); } -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100) av_register_all(); #endif this->impl = std::make_unique( - url, parameter_pairs, extras, allocate_callback, deallocate_callback, log_callback, userdata - ); + url, + parameter_pairs, + extras, + allocate_callback, + deallocate_callback, + log_callback, + userdata); } bool VideoReaderFFmpeg::is_seekable() const { diff --git a/src/videoreader_ffmpeg.hpp b/src/videoreader_ffmpeg.hpp index 80e94b6..cf54101 100644 --- a/src/videoreader_ffmpeg.hpp +++ b/src/videoreader_ffmpeg.hpp @@ -1,18 +1,15 @@ #include - -class VideoReaderFFmpeg : public VideoReader -{ +class VideoReaderFFmpeg : public VideoReader { public: VideoReaderFFmpeg( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_cb, - DeallocateCallback deallocate_cb, - LogCallback log_callback, - void* userdata - ); + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_cb, + DeallocateCallback deallocate_cb, + LogCallback log_callback, + void* userdata); bool is_seekable() const override; FrameUP next_frame(bool decode) override; diff --git a/src/videoreader_galaxy.cpp b/src/videoreader_galaxy.cpp index 2fc0780..d32de92 100644 --- a/src/videoreader_galaxy.cpp +++ b/src/videoreader_galaxy.cpp @@ -1,342 +1,365 @@ -#include +#include "videoreader_galaxy.hpp" +#include "spinlock.hpp" +#include "thismsgpack.hpp" +#include +#include // std::transform #include +#include #include #include -#include #include // std::runtime_error -#include -#include "videoreader_galaxy.hpp" -#include "spinlock.hpp" +#include #include -#include // std::transform -#include "thismsgpack.hpp" - static std::string get_error_string(GX_STATUS emErrorStatus) { size_t size{}; - if(GXGetLastError(&emErrorStatus, NULL, &size) == GX_STATUS_SUCCESS) { + if (GXGetLastError(&emErrorStatus, NULL, &size) == GX_STATUS_SUCCESS) { std::string ret(size, '\0'); - if (GXGetLastError(&emErrorStatus, const_cast(ret.data()), &size) - != GX_STATUS_SUCCESS) { + if (GXGetLastError(&emErrorStatus, const_cast(ret.data()), &size) != + GX_STATUS_SUCCESS) { ret = ""; } return ret; - } - else { + } else { return ""; } } static std::string to_lower(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), (int(*)(int)) std::tolower); - return s; + std::transform(s.begin(), s.end(), s.begin(), (int (*)(int))std::tolower); + return s; } -#define GALAXY_CHECK(cb) do { \ - auto const status = cb; \ - if (status != GX_STATUS_SUCCESS) { \ - throw std::runtime_error(get_error_string(status)); \ - } \ -} while(false) - -static std::unordered_map const INT_FEATURES { - {"device_link_selector", GX_INT_DEVICE_LINK_SELECTOR}, - {"device_link_throughput_limit", GX_INT_DEVICE_LINK_THROUGHPUT_LIMIT}, - {"device_link_current_throughput", GX_INT_DEVICE_LINK_CURRENT_THROUGHPUT}, - {"timestamp_tick_frequency", GX_INT_TIMESTAMP_TICK_FREQUENCY}, - {"timestamp_latch_value", GX_INT_TIMESTAMP_LATCH_VALUE}, - {"revision", GX_INT_REVISION}, - {"versions_supported", GX_INT_VERSIONS_SUPPORTED}, - {"version_used", GX_INT_VERSION_USED}, - {"temperature_detection_status", GX_INT_TEMPERATURE_DETECTION_STATUS}, - {"fan_speed", GX_INT_FAN_SPEED}, - {"air_change_detection_status", GX_INT_AIR_CHANGE_DETECTION_STATUS}, - {"air_tightness_detection_status", GX_INT_AIR_TIGHTNESS_DETECTION_STATUS}, - {"sensor_width", GX_INT_SENSOR_WIDTH}, - {"sensor_height", GX_INT_SENSOR_HEIGHT}, - {"width_max", GX_INT_WIDTH_MAX}, - {"height_max", GX_INT_HEIGHT_MAX}, - {"offset_x", GX_INT_OFFSET_X}, - {"offset_y", GX_INT_OFFSET_Y}, - {"width", GX_INT_WIDTH}, - {"height", GX_INT_HEIGHT}, - {"binning_horizontal", GX_INT_BINNING_HORIZONTAL}, - {"binning_vertical", GX_INT_BINNING_VERTICAL}, - {"decimation_horizontal", GX_INT_DECIMATION_HORIZONTAL}, - {"decimation_vertical", GX_INT_DECIMATION_VERTICAL}, - {"center_width", GX_INT_CENTER_WIDTH}, - {"center_height", GX_INT_CENTER_HEIGHT}, - {"decimation_linenumber", GX_INT_DECIMATION_LINENUMBER}, - {"sensor_decimation_horizontal", GX_INT_SENSOR_DECIMATION_HORIZONTAL}, - {"sensor_decimation_vertical", GX_INT_SENSOR_DECIMATION_VERTICAL}, - {"current_sensor_width", GX_INT_CURRENT_SENSOR_WIDTH}, - {"current_sensor_height", GX_INT_CURRENT_SENSOR_HEIGHT}, - {"current_sensor_offsetx", GX_INT_CURRENT_SENSOR_OFFSETX}, - {"current_sensor_offsety", GX_INT_CURRENT_SENSOR_OFFSETY}, - {"current_sensor_widthmax", GX_INT_CURRENT_SENSOR_WIDTHMAX}, - {"current_sensor_heightmax", GX_INT_CURRENT_SENSOR_HEIGHTMAX}, - {"payload_size", GX_INT_PAYLOAD_SIZE}, - {"estimated_bandwidth", GX_INT_ESTIMATED_BANDWIDTH}, - {"gev_heartbeat_timeout", GX_INT_GEV_HEARTBEAT_TIMEOUT}, - {"gev_packetsize", GX_INT_GEV_PACKETSIZE}, - {"gev_packetdelay", GX_INT_GEV_PACKETDELAY}, - {"gev_link_speed", GX_INT_GEV_LINK_SPEED}, - {"acquisition_speed_level", GX_INT_ACQUISITION_SPEED_LEVEL}, - {"acquisition_frame_count", GX_INT_ACQUISITION_FRAME_COUNT}, - {"transfer_block_count", GX_INT_TRANSFER_BLOCK_COUNT}, - {"acquisition_burst_frame_count", GX_INT_ACQUISITION_BURST_FRAME_COUNT}, - {"line_status_all", GX_INT_LINE_STATUS_ALL}, - {"line_range", GX_INT_LINE_RANGE}, - {"line_delay", GX_INT_LINE_DELAY}, - {"line_filter_raising_edge", GX_INT_LINE_FILTER_RAISING_EDGE}, - {"line_filter_falling_edge", GX_INT_LINE_FILTER_FALLING_EDGE}, - {"digital_shift", GX_INT_DIGITAL_SHIFT}, - {"blacklevel_calib_value", GX_INT_BLACKLEVEL_CALIB_VALUE}, - {"adc_level", GX_INT_ADC_LEVEL}, - {"h_blanking", GX_INT_H_BLANKING}, - {"v_blanking", GX_INT_V_BLANKING}, - {"gray_value", GX_INT_GRAY_VALUE}, - {"aaroi_offsetx", GX_INT_AAROI_OFFSETX}, - {"aaroi_offsety", GX_INT_AAROI_OFFSETY}, - {"aaroi_width", GX_INT_AAROI_WIDTH}, - {"aaroi_height", GX_INT_AAROI_HEIGHT}, - {"contrast_param", GX_INT_CONTRAST_PARAM}, - {"color_correction_param", GX_INT_COLOR_CORRECTION_PARAM}, - {"awbroi_offsetx", GX_INT_AWBROI_OFFSETX}, - {"awbroi_offsety", GX_INT_AWBROI_OFFSETY}, - {"awbroi_width", GX_INT_AWBROI_WIDTH}, - {"awbroi_height", GX_INT_AWBROI_HEIGHT}, - {"static_defect_correction_finish", GX_INT_STATIC_DEFECT_CORRECTION_FINISH}, - {"ffc_expected_gray", GX_INT_FFC_EXPECTED_GRAY}, - {"ffc_coefficients_size", GX_INT_FFC_COEFFICIENTS_SIZE}, - {"static_defect_correction_calib_status", GX_INT_STATIC_DEFECT_CORRECTION_CALIB_STATUS}, - {"ffc_factory_status", GX_INT_FFC_FACTORY_STATUS}, - {"dsnu_factory_status", GX_INT_DSNU_FACTORY_STATUS}, - {"prnu_factory_status", GX_INT_PRNU_FACTORY_STATUS}, - {"data_field_value_all_used_status", GX_INT_DATA_FIELD_VALUE_ALL_USED_STATUS}, - {"event_exposureend", GX_INT_EVENT_EXPOSUREEND}, - {"event_exposureend_timestamp", GX_INT_EVENT_EXPOSUREEND_TIMESTAMP}, - {"event_exposureend_frameid", GX_INT_EVENT_EXPOSUREEND_FRAMEID}, - {"event_block_discard", GX_INT_EVENT_BLOCK_DISCARD}, - {"event_block_discard_timestamp", GX_INT_EVENT_BLOCK_DISCARD_TIMESTAMP}, - {"event_overrun", GX_INT_EVENT_OVERRUN}, - {"event_overrun_timestamp", GX_INT_EVENT_OVERRUN_TIMESTAMP}, - {"event_framestart_overtrigger", GX_INT_EVENT_FRAMESTART_OVERTRIGGER}, - {"event_framestart_overtrigger_timestamp", GX_INT_EVENT_FRAMESTART_OVERTRIGGER_TIMESTAMP}, - {"event_block_not_empty", GX_INT_EVENT_BLOCK_NOT_EMPTY}, - {"event_block_not_empty_timestamp", GX_INT_EVENT_BLOCK_NOT_EMPTY_TIMESTAMP}, - {"event_internal_error", GX_INT_EVENT_INTERNAL_ERROR}, - {"event_internal_error_timestamp", GX_INT_EVENT_INTERNAL_ERROR_TIMESTAMP}, - {"event_frameburststart_overtrigger", GX_INT_EVENT_FRAMEBURSTSTART_OVERTRIGGER}, - {"event_frameburststart_overtrigger_frameid", GX_INT_EVENT_FRAMEBURSTSTART_OVERTRIGGER_FRAMEID}, - {"event_frameburststart_overtrigger_timestamp", GX_INT_EVENT_FRAMEBURSTSTART_OVERTRIGGER_TIMESTAMP}, - {"event_framestart_wait", GX_INT_EVENT_FRAMESTART_WAIT}, - {"event_framestart_wait_timestamp", GX_INT_EVENT_FRAMESTART_WAIT_TIMESTAMP}, - {"event_frameburststart_wait", GX_INT_EVENT_FRAMEBURSTSTART_WAIT}, - {"event_frameburststart_wait_timestamp", GX_INT_EVENT_FRAMEBURSTSTART_WAIT_TIMESTAMP}, - {"event_block_discard_frameid", GX_INT_EVENT_BLOCK_DISCARD_FRAMEID}, - {"event_framestart_overtrigger_frameid", GX_INT_EVENT_FRAMESTART_OVERTRIGGER_FRAMEID}, - {"event_block_not_empty_frameid", GX_INT_EVENT_BLOCK_NOT_EMPTY_FRAMEID}, - {"event_framestart_wait_frameid", GX_INT_EVENT_FRAMESTART_WAIT_FRAMEID}, - {"event_frameburststart_wait_frameid", GX_INT_EVENT_FRAMEBURSTSTART_WAIT_FRAMEID}, - {"lut_index", GX_INT_LUT_INDEX}, - {"lut_value", GX_INT_LUT_VALUE}, - {"lut_factory_status", GX_INT_LUT_FACTORY_STATUS}, - {"saturation", GX_INT_SATURATION}, - {"counter_duration", GX_INT_COUNTER_DURATION}, - {"counter_value", GX_INT_COUNTER_VALUE}, - {"hdr_target_long_value", GX_INT_HDR_TARGET_LONG_VALUE}, - {"hdr_target_short_value", GX_INT_HDR_TARGET_SHORT_VALUE}, - {"hdr_target_main_value", GX_INT_HDR_TARGET_MAIN_VALUE}, - {"mgc_selector", GX_INT_MGC_SELECTOR}, - {"frame_buffer_count", GX_INT_FRAME_BUFFER_COUNT}, - {"serialport_data_bits", GX_INT_SERIALPORT_DATA_BITS}, - {"transmit_queue_max_character_count", GX_INT_TRANSMIT_QUEUE_MAX_CHARACTER_COUNT}, - {"transmit_queue_current_character_count", GX_INT_TRANSMIT_QUEUE_CURRENT_CHARACTER_COUNT}, - {"receive_queue_max_character_count", GX_INT_RECEIVE_QUEUE_MAX_CHARACTER_COUNT}, - {"receive_queue_current_character_count", GX_INT_RECEIVE_QUEUE_CURRENT_CHARACTER_COUNT}, - {"receive_framing_error_count", GX_INT_RECEIVE_FRAMING_ERROR_COUNT}, - {"receive_parity_error_count", GX_INT_RECEIVE_PARITY_ERROR_COUNT}, - {"serialport_data_length", GX_INT_SERIALPORT_DATA_LENGTH}, - {"serial_port_detection_status", GX_INT_SERIAL_PORT_DETECTION_STATUS}, - {"image1_stream_id", GX_INT_IMAGE1_STREAM_ID}, - {"cxp_connection_test_error_count", GX_INT_CXP_CONNECTION_TEST_ERROR_COUNT}, - {"cxp_connection_test_packet_rx_count", GX_INT_CXP_CONNECTION_TEST_PACKET_RX_COUNT}, - {"cxp_connection_test_packet_tx_count", GX_INT_CXP_CONNECTION_TEST_PACKET_TX_COUNT}, - {"sequencer_set_selector", GX_INT_SEQUENCER_SET_SELECTOR}, - {"sequencer_set_count", GX_INT_SEQUENCER_SET_COUNT}, - {"sequencer_set_active", GX_INT_SEQUENCER_SET_ACTIVE}, - {"sequencer_path_selector", GX_INT_SEQUENCER_PATH_SELECTOR}, - {"sequencer_set_next", GX_INT_SEQUENCER_SET_NEXT}, - {"encoder_value", GX_INT_ENCODER_VALUE} +#define GALAXY_CHECK(cb) \ + do { \ + auto const status = cb; \ + if (status != GX_STATUS_SUCCESS) { \ + throw std::runtime_error(get_error_string(status)); \ + } \ + } while (false) + +static std::unordered_map const INT_FEATURES{ + {"device_link_selector", GX_INT_DEVICE_LINK_SELECTOR}, + {"device_link_throughput_limit", GX_INT_DEVICE_LINK_THROUGHPUT_LIMIT}, + {"device_link_current_throughput", GX_INT_DEVICE_LINK_CURRENT_THROUGHPUT}, + {"timestamp_tick_frequency", GX_INT_TIMESTAMP_TICK_FREQUENCY}, + {"timestamp_latch_value", GX_INT_TIMESTAMP_LATCH_VALUE}, + {"revision", GX_INT_REVISION}, + {"versions_supported", GX_INT_VERSIONS_SUPPORTED}, + {"version_used", GX_INT_VERSION_USED}, + {"temperature_detection_status", GX_INT_TEMPERATURE_DETECTION_STATUS}, + {"fan_speed", GX_INT_FAN_SPEED}, + {"air_change_detection_status", GX_INT_AIR_CHANGE_DETECTION_STATUS}, + {"air_tightness_detection_status", GX_INT_AIR_TIGHTNESS_DETECTION_STATUS}, + {"sensor_width", GX_INT_SENSOR_WIDTH}, + {"sensor_height", GX_INT_SENSOR_HEIGHT}, + {"width_max", GX_INT_WIDTH_MAX}, + {"height_max", GX_INT_HEIGHT_MAX}, + {"offset_x", GX_INT_OFFSET_X}, + {"offset_y", GX_INT_OFFSET_Y}, + {"width", GX_INT_WIDTH}, + {"height", GX_INT_HEIGHT}, + {"binning_horizontal", GX_INT_BINNING_HORIZONTAL}, + {"binning_vertical", GX_INT_BINNING_VERTICAL}, + {"decimation_horizontal", GX_INT_DECIMATION_HORIZONTAL}, + {"decimation_vertical", GX_INT_DECIMATION_VERTICAL}, + {"center_width", GX_INT_CENTER_WIDTH}, + {"center_height", GX_INT_CENTER_HEIGHT}, + {"decimation_linenumber", GX_INT_DECIMATION_LINENUMBER}, + {"sensor_decimation_horizontal", GX_INT_SENSOR_DECIMATION_HORIZONTAL}, + {"sensor_decimation_vertical", GX_INT_SENSOR_DECIMATION_VERTICAL}, + {"current_sensor_width", GX_INT_CURRENT_SENSOR_WIDTH}, + {"current_sensor_height", GX_INT_CURRENT_SENSOR_HEIGHT}, + {"current_sensor_offsetx", GX_INT_CURRENT_SENSOR_OFFSETX}, + {"current_sensor_offsety", GX_INT_CURRENT_SENSOR_OFFSETY}, + {"current_sensor_widthmax", GX_INT_CURRENT_SENSOR_WIDTHMAX}, + {"current_sensor_heightmax", GX_INT_CURRENT_SENSOR_HEIGHTMAX}, + {"payload_size", GX_INT_PAYLOAD_SIZE}, + {"estimated_bandwidth", GX_INT_ESTIMATED_BANDWIDTH}, + {"gev_heartbeat_timeout", GX_INT_GEV_HEARTBEAT_TIMEOUT}, + {"gev_packetsize", GX_INT_GEV_PACKETSIZE}, + {"gev_packetdelay", GX_INT_GEV_PACKETDELAY}, + {"gev_link_speed", GX_INT_GEV_LINK_SPEED}, + {"acquisition_speed_level", GX_INT_ACQUISITION_SPEED_LEVEL}, + {"acquisition_frame_count", GX_INT_ACQUISITION_FRAME_COUNT}, + {"transfer_block_count", GX_INT_TRANSFER_BLOCK_COUNT}, + {"acquisition_burst_frame_count", GX_INT_ACQUISITION_BURST_FRAME_COUNT}, + {"line_status_all", GX_INT_LINE_STATUS_ALL}, + {"line_range", GX_INT_LINE_RANGE}, + {"line_delay", GX_INT_LINE_DELAY}, + {"line_filter_raising_edge", GX_INT_LINE_FILTER_RAISING_EDGE}, + {"line_filter_falling_edge", GX_INT_LINE_FILTER_FALLING_EDGE}, + {"digital_shift", GX_INT_DIGITAL_SHIFT}, + {"blacklevel_calib_value", GX_INT_BLACKLEVEL_CALIB_VALUE}, + {"adc_level", GX_INT_ADC_LEVEL}, + {"h_blanking", GX_INT_H_BLANKING}, + {"v_blanking", GX_INT_V_BLANKING}, + {"gray_value", GX_INT_GRAY_VALUE}, + {"aaroi_offsetx", GX_INT_AAROI_OFFSETX}, + {"aaroi_offsety", GX_INT_AAROI_OFFSETY}, + {"aaroi_width", GX_INT_AAROI_WIDTH}, + {"aaroi_height", GX_INT_AAROI_HEIGHT}, + {"contrast_param", GX_INT_CONTRAST_PARAM}, + {"color_correction_param", GX_INT_COLOR_CORRECTION_PARAM}, + {"awbroi_offsetx", GX_INT_AWBROI_OFFSETX}, + {"awbroi_offsety", GX_INT_AWBROI_OFFSETY}, + {"awbroi_width", GX_INT_AWBROI_WIDTH}, + {"awbroi_height", GX_INT_AWBROI_HEIGHT}, + {"static_defect_correction_finish", GX_INT_STATIC_DEFECT_CORRECTION_FINISH}, + {"ffc_expected_gray", GX_INT_FFC_EXPECTED_GRAY}, + {"ffc_coefficients_size", GX_INT_FFC_COEFFICIENTS_SIZE}, + {"static_defect_correction_calib_status", + GX_INT_STATIC_DEFECT_CORRECTION_CALIB_STATUS}, + {"ffc_factory_status", GX_INT_FFC_FACTORY_STATUS}, + {"dsnu_factory_status", GX_INT_DSNU_FACTORY_STATUS}, + {"prnu_factory_status", GX_INT_PRNU_FACTORY_STATUS}, + {"data_field_value_all_used_status", + GX_INT_DATA_FIELD_VALUE_ALL_USED_STATUS}, + {"event_exposureend", GX_INT_EVENT_EXPOSUREEND}, + {"event_exposureend_timestamp", GX_INT_EVENT_EXPOSUREEND_TIMESTAMP}, + {"event_exposureend_frameid", GX_INT_EVENT_EXPOSUREEND_FRAMEID}, + {"event_block_discard", GX_INT_EVENT_BLOCK_DISCARD}, + {"event_block_discard_timestamp", GX_INT_EVENT_BLOCK_DISCARD_TIMESTAMP}, + {"event_overrun", GX_INT_EVENT_OVERRUN}, + {"event_overrun_timestamp", GX_INT_EVENT_OVERRUN_TIMESTAMP}, + {"event_framestart_overtrigger", GX_INT_EVENT_FRAMESTART_OVERTRIGGER}, + {"event_framestart_overtrigger_timestamp", + GX_INT_EVENT_FRAMESTART_OVERTRIGGER_TIMESTAMP}, + {"event_block_not_empty", GX_INT_EVENT_BLOCK_NOT_EMPTY}, + {"event_block_not_empty_timestamp", GX_INT_EVENT_BLOCK_NOT_EMPTY_TIMESTAMP}, + {"event_internal_error", GX_INT_EVENT_INTERNAL_ERROR}, + {"event_internal_error_timestamp", GX_INT_EVENT_INTERNAL_ERROR_TIMESTAMP}, + {"event_frameburststart_overtrigger", + GX_INT_EVENT_FRAMEBURSTSTART_OVERTRIGGER}, + {"event_frameburststart_overtrigger_frameid", + GX_INT_EVENT_FRAMEBURSTSTART_OVERTRIGGER_FRAMEID}, + {"event_frameburststart_overtrigger_timestamp", + GX_INT_EVENT_FRAMEBURSTSTART_OVERTRIGGER_TIMESTAMP}, + {"event_framestart_wait", GX_INT_EVENT_FRAMESTART_WAIT}, + {"event_framestart_wait_timestamp", GX_INT_EVENT_FRAMESTART_WAIT_TIMESTAMP}, + {"event_frameburststart_wait", GX_INT_EVENT_FRAMEBURSTSTART_WAIT}, + {"event_frameburststart_wait_timestamp", + GX_INT_EVENT_FRAMEBURSTSTART_WAIT_TIMESTAMP}, + {"event_block_discard_frameid", GX_INT_EVENT_BLOCK_DISCARD_FRAMEID}, + {"event_framestart_overtrigger_frameid", + GX_INT_EVENT_FRAMESTART_OVERTRIGGER_FRAMEID}, + {"event_block_not_empty_frameid", GX_INT_EVENT_BLOCK_NOT_EMPTY_FRAMEID}, + {"event_framestart_wait_frameid", GX_INT_EVENT_FRAMESTART_WAIT_FRAMEID}, + {"event_frameburststart_wait_frameid", + GX_INT_EVENT_FRAMEBURSTSTART_WAIT_FRAMEID}, + {"lut_index", GX_INT_LUT_INDEX}, + {"lut_value", GX_INT_LUT_VALUE}, + {"lut_factory_status", GX_INT_LUT_FACTORY_STATUS}, + {"saturation", GX_INT_SATURATION}, + {"counter_duration", GX_INT_COUNTER_DURATION}, + {"counter_value", GX_INT_COUNTER_VALUE}, + {"hdr_target_long_value", GX_INT_HDR_TARGET_LONG_VALUE}, + {"hdr_target_short_value", GX_INT_HDR_TARGET_SHORT_VALUE}, + {"hdr_target_main_value", GX_INT_HDR_TARGET_MAIN_VALUE}, + {"mgc_selector", GX_INT_MGC_SELECTOR}, + {"frame_buffer_count", GX_INT_FRAME_BUFFER_COUNT}, + {"serialport_data_bits", GX_INT_SERIALPORT_DATA_BITS}, + {"transmit_queue_max_character_count", + GX_INT_TRANSMIT_QUEUE_MAX_CHARACTER_COUNT}, + {"transmit_queue_current_character_count", + GX_INT_TRANSMIT_QUEUE_CURRENT_CHARACTER_COUNT}, + {"receive_queue_max_character_count", + GX_INT_RECEIVE_QUEUE_MAX_CHARACTER_COUNT}, + {"receive_queue_current_character_count", + GX_INT_RECEIVE_QUEUE_CURRENT_CHARACTER_COUNT}, + {"receive_framing_error_count", GX_INT_RECEIVE_FRAMING_ERROR_COUNT}, + {"receive_parity_error_count", GX_INT_RECEIVE_PARITY_ERROR_COUNT}, + {"serialport_data_length", GX_INT_SERIALPORT_DATA_LENGTH}, + {"serial_port_detection_status", GX_INT_SERIAL_PORT_DETECTION_STATUS}, + {"image1_stream_id", GX_INT_IMAGE1_STREAM_ID}, + {"cxp_connection_test_error_count", GX_INT_CXP_CONNECTION_TEST_ERROR_COUNT}, + {"cxp_connection_test_packet_rx_count", + GX_INT_CXP_CONNECTION_TEST_PACKET_RX_COUNT}, + {"cxp_connection_test_packet_tx_count", + GX_INT_CXP_CONNECTION_TEST_PACKET_TX_COUNT}, + {"sequencer_set_selector", GX_INT_SEQUENCER_SET_SELECTOR}, + {"sequencer_set_count", GX_INT_SEQUENCER_SET_COUNT}, + {"sequencer_set_active", GX_INT_SEQUENCER_SET_ACTIVE}, + {"sequencer_path_selector", GX_INT_SEQUENCER_PATH_SELECTOR}, + {"sequencer_set_next", GX_INT_SEQUENCER_SET_NEXT}, + {"encoder_value", GX_INT_ENCODER_VALUE}}; + +static std::unordered_map const FLOAT_FEATURES{ + {"device_temperature", GX_FLOAT_DEVICE_TEMPERATURE}, + {"tec_target_temperature", GX_FLOAT_TEC_TARGET_TEMPERATURE}, + {"device_humidity", GX_FLOAT_DEVICE_HUMIDITY}, + {"device_pressure", GX_FLOAT_DEVICE_PRESSURE}, + {"exposure_time", GX_FLOAT_EXPOSURE_TIME}, + {"trigger_filter_raising", GX_FLOAT_TRIGGER_FILTER_RAISING}, + {"trigger_filter_falling", GX_FLOAT_TRIGGER_FILTER_FALLING}, + {"trigger_delay", GX_FLOAT_TRIGGER_DELAY}, + {"acquisition_frame_rate", GX_FLOAT_ACQUISITION_FRAME_RATE}, + {"current_acquisition_frame_rate", GX_FLOAT_CURRENT_ACQUISITION_FRAME_RATE}, + {"exposure_delay", GX_FLOAT_EXPOSURE_DELAY}, + {"exposure_overlap_time_max", GX_FLOAT_EXPOSURE_OVERLAP_TIME_MAX}, + {"pulse_width", GX_FLOAT_PULSE_WIDTH}, + {"balance_ratio", GX_FLOAT_BALANCE_RATIO}, + {"gain", GX_FLOAT_GAIN}, + {"blacklevel", GX_FLOAT_BLACKLEVEL}, + {"gamma", GX_FLOAT_GAMMA}, + {"pga_gain", GX_FLOAT_PGA_GAIN}, + {"auto_gain_min", GX_FLOAT_AUTO_GAIN_MIN}, + {"auto_gain_max", GX_FLOAT_AUTO_GAIN_MAX}, + {"auto_exposure_time_min", GX_FLOAT_AUTO_EXPOSURE_TIME_MIN}, + {"auto_exposure_time_max", GX_FLOAT_AUTO_EXPOSURE_TIME_MAX}, + {"gamma_param", GX_FLOAT_GAMMA_PARAM}, + {"sharpness", GX_FLOAT_SHARPNESS}, + {"noise_reduction", GX_FLOAT_NOISE_REDUCTION}, + {"color_transformation_value", GX_FLOAT_COLOR_TRANSFORMATION_VALUE}, + {"timer_duration", GX_FLOAT_TIMER_DURATION}, + {"timer_delay", GX_FLOAT_TIMER_DELAY}, + {"mgc_exposure_time", GX_FLOAT_MGC_EXPOSURE_TIME}, + {"mgc_gain", GX_FLOAT_MGC_GAIN}, + {"contrast", GX_FLOAT_CONTRAST}, + {"imu_room_temperature", GX_FLOAT_IMU_ROOM_TEMPERATURE}, }; -static std::unordered_map const FLOAT_FEATURES { - {"device_temperature", GX_FLOAT_DEVICE_TEMPERATURE}, - {"tec_target_temperature", GX_FLOAT_TEC_TARGET_TEMPERATURE}, - {"device_humidity", GX_FLOAT_DEVICE_HUMIDITY}, - {"device_pressure", GX_FLOAT_DEVICE_PRESSURE}, - {"exposure_time", GX_FLOAT_EXPOSURE_TIME}, - {"trigger_filter_raising", GX_FLOAT_TRIGGER_FILTER_RAISING}, - {"trigger_filter_falling", GX_FLOAT_TRIGGER_FILTER_FALLING}, - {"trigger_delay", GX_FLOAT_TRIGGER_DELAY}, - {"acquisition_frame_rate", GX_FLOAT_ACQUISITION_FRAME_RATE}, - {"current_acquisition_frame_rate", GX_FLOAT_CURRENT_ACQUISITION_FRAME_RATE}, - {"exposure_delay", GX_FLOAT_EXPOSURE_DELAY}, - {"exposure_overlap_time_max", GX_FLOAT_EXPOSURE_OVERLAP_TIME_MAX}, - {"pulse_width", GX_FLOAT_PULSE_WIDTH}, - {"balance_ratio", GX_FLOAT_BALANCE_RATIO}, - {"gain", GX_FLOAT_GAIN}, - {"blacklevel", GX_FLOAT_BLACKLEVEL}, - {"gamma", GX_FLOAT_GAMMA}, - {"pga_gain", GX_FLOAT_PGA_GAIN}, - {"auto_gain_min", GX_FLOAT_AUTO_GAIN_MIN}, - {"auto_gain_max", GX_FLOAT_AUTO_GAIN_MAX}, - {"auto_exposure_time_min", GX_FLOAT_AUTO_EXPOSURE_TIME_MIN}, - {"auto_exposure_time_max", GX_FLOAT_AUTO_EXPOSURE_TIME_MAX}, - {"gamma_param", GX_FLOAT_GAMMA_PARAM}, - {"sharpness", GX_FLOAT_SHARPNESS}, - {"noise_reduction", GX_FLOAT_NOISE_REDUCTION}, - {"color_transformation_value", GX_FLOAT_COLOR_TRANSFORMATION_VALUE}, - {"timer_duration", GX_FLOAT_TIMER_DURATION}, - {"timer_delay", GX_FLOAT_TIMER_DELAY}, - {"mgc_exposure_time", GX_FLOAT_MGC_EXPOSURE_TIME}, - {"mgc_gain", GX_FLOAT_MGC_GAIN}, - {"contrast", GX_FLOAT_CONTRAST}, - {"imu_room_temperature", GX_FLOAT_IMU_ROOM_TEMPERATURE}, -}; - -static std::unordered_map const ENUM_FEATURES { - {"device_link_throughput_limit_mode", GX_ENUM_DEVICE_LINK_THROUGHPUT_LIMIT_MODE}, - {"device_temperature_selector", GX_ENUM_DEVICE_TEMPERATURE_SELECTOR}, - {"lowpower_mode", GX_ENUM_LOWPOWER_MODE}, - {"close_ccd", GX_ENUM_CLOSE_CCD}, - {"pixel_size", GX_ENUM_PIXEL_SIZE}, - {"pixel_color_filter", GX_ENUM_PIXEL_COLOR_FILTER}, - {"pixel_format", GX_ENUM_PIXEL_FORMAT}, - {"test_pattern", GX_ENUM_TEST_PATTERN}, - {"test_pattern_generator_selector", GX_ENUM_TEST_PATTERN_GENERATOR_SELECTOR}, - {"region_send_mode", GX_ENUM_REGION_SEND_MODE}, - {"region_mode", GX_ENUM_REGION_MODE}, - {"rregion_selector", GX_ENUM_RREGION_SELECTOR}, - {"binning_horizontal_mode", GX_ENUM_BINNING_HORIZONTAL_MODE}, - {"binning_vertical_mode", GX_ENUM_BINNING_VERTICAL_MODE}, - {"sensor_shutter_mode", GX_ENUM_SENSOR_SHUTTER_MODE}, - {"sensor_selector", GX_ENUM_SENSOR_SELECTOR}, - {"sensor_bit_depth", GX_ENUM_SENSOR_BIT_DEPTH}, - {"device_tap_geometry", GX_ENUM_DEVICE_TAP_GEOMETRY}, - {"acquisition_mode", GX_ENUM_ACQUISITION_MODE}, - {"trigger_mode", GX_ENUM_TRIGGER_MODE}, - {"trigger_activation", GX_ENUM_TRIGGER_ACTIVATION}, - {"trigger_switch", GX_ENUM_TRIGGER_SWITCH}, - {"exposure_auto", GX_ENUM_EXPOSURE_AUTO}, - {"trigger_source", GX_ENUM_TRIGGER_SOURCE}, - {"exposure_mode", GX_ENUM_EXPOSURE_MODE}, - {"trigger_selector", GX_ENUM_TRIGGER_SELECTOR}, - {"transfer_control_mode", GX_ENUM_TRANSFER_CONTROL_MODE}, - {"transfer_operation_mode", GX_ENUM_TRANSFER_OPERATION_MODE}, - {"acquisition_frame_rate_mode", GX_ENUM_ACQUISITION_FRAME_RATE_MODE}, - {"fixed_pattern_noise_correct_mode", GX_ENUM_FIXED_PATTERN_NOISE_CORRECT_MODE}, - {"acquisition_status_selector", GX_ENUM_ACQUISITION_STATUS_SELECTOR}, - {"exposure_time_mode", GX_ENUM_EXPOSURE_TIME_MODE}, - {"acquisition_burst_mode", GX_ENUM_ACQUISITION_BURST_MODE}, - {"overlap_mode", GX_ENUM_OVERLAP_MODE}, - {"multisource_selector", GX_ENUM_MULTISOURCE_SELECTOR}, - {"user_output_selector", GX_ENUM_USER_OUTPUT_SELECTOR}, - {"user_output_mode", GX_ENUM_USER_OUTPUT_MODE}, - {"strobe_switch", GX_ENUM_STROBE_SWITCH}, - {"line_selector", GX_ENUM_LINE_SELECTOR}, - {"line_mode", GX_ENUM_LINE_MODE}, - {"line_source", GX_ENUM_LINE_SOURCE}, - {"gain_auto", GX_ENUM_GAIN_AUTO}, - {"gain_selector", GX_ENUM_GAIN_SELECTOR}, - {"blacklevel_auto", GX_ENUM_BLACKLEVEL_AUTO}, - {"blacklevel_selector", GX_ENUM_BLACKLEVEL_SELECTOR}, - {"balance_white_auto", GX_ENUM_BALANCE_WHITE_AUTO}, - {"balance_ratio_selector", GX_ENUM_BALANCE_RATIO_SELECTOR}, - {"color_correct", GX_ENUM_COLOR_CORRECT}, - {"dead_pixel_correct", GX_ENUM_DEAD_PIXEL_CORRECT}, - {"gamma_mode", GX_ENUM_GAMMA_MODE}, - {"light_source_preset", GX_ENUM_LIGHT_SOURCE_PRESET}, - {"aa_light_environment", GX_ENUM_AA_LIGHT_ENVIRONMENT}, - {"image_gray_raise_switch", GX_ENUM_IMAGE_GRAY_RAISE_SWITCH}, - {"awb_lamp_house", GX_ENUM_AWB_LAMP_HOUSE}, - {"sharpness_mode", GX_ENUM_SHARPNESS_MODE}, - {"user_data_filed_selector", GX_ENUM_USER_DATA_FILED_SELECTOR}, - {"flat_field_correction", GX_ENUM_FLAT_FIELD_CORRECTION}, - {"noise_reduction_mode", GX_ENUM_NOISE_REDUCTION_MODE}, - {"static_defect_correction", GX_ENUM_STATIC_DEFECT_CORRECTION}, - {"2d_noise_reduction_mode", GX_ENUM_2D_NOISE_REDUCTION_MODE}, - {"3d_noise_reduction_mode", GX_ENUM_3D_NOISE_REDUCTION_MODE}, - {"shading_correction_mode", GX_ENUM_SHADING_CORRECTION_MODE}, - {"ffc_generate_status", GX_ENUM_FFC_GENERATE_STATUS}, - {"ffc_expected_gray_value_enable", GX_ENUM_FFC_EXPECTED_GRAY_VALUE_ENABLE}, - {"dsnu_selector", GX_ENUM_DSNU_SELECTOR}, - {"dsnu_generate_status", GX_ENUM_DSNU_GENERATE_STATUS}, - {"prnu_selector", GX_ENUM_PRNU_SELECTOR}, - {"prnu_generate_status", GX_ENUM_PRNU_GENERATE_STATUS}, - {"ffc_coefficient", GX_ENUM_FFC_COEFFICIENT}, - {"user_set_selector", GX_ENUM_USER_SET_SELECTOR}, - {"user_set_default", GX_ENUM_USER_SET_DEFAULT}, - {"event_selector", GX_ENUM_EVENT_SELECTOR}, - {"event_notification", GX_ENUM_EVENT_NOTIFICATION}, - {"event_simple_mode", GX_ENUM_EVENT_SIMPLE_MODE}, - {"lut_selector", GX_ENUM_LUT_SELECTOR}, - {"chunk_selector", GX_ENUM_CHUNK_SELECTOR}, - {"color_transformation_mode", GX_ENUM_COLOR_TRANSFORMATION_MODE}, - {"color_transformation_value_selector", GX_ENUM_COLOR_TRANSFORMATION_VALUE_SELECTOR}, - {"saturation_mode", GX_ENUM_SATURATION_MODE}, - {"timer_selector", GX_ENUM_TIMER_SELECTOR}, - {"timer_trigger_source", GX_ENUM_TIMER_TRIGGER_SOURCE}, - {"counter_selector", GX_ENUM_COUNTER_SELECTOR}, - {"counter_event_source", GX_ENUM_COUNTER_EVENT_SOURCE}, - {"counter_reset_source", GX_ENUM_COUNTER_RESET_SOURCE}, - {"counter_reset_activation", GX_ENUM_COUNTER_RESET_ACTIVATION}, - {"counter_trigger_source", GX_ENUM_COUNTER_TRIGGER_SOURCE}, - {"timer_trigger_activation", GX_ENUM_TIMER_TRIGGER_ACTIVATION}, - {"remove_parameter_limit", GX_ENUM_REMOVE_PARAMETER_LIMIT}, - {"hdr_mode", GX_ENUM_HDR_MODE}, - {"mgc_mode", GX_ENUM_MGC_MODE}, - {"imu_config_acc_range", GX_ENUM_IMU_CONFIG_ACC_RANGE}, - {"imu_config_acc_odr_low_pass_filter_switch", GX_ENUM_IMU_CONFIG_ACC_ODR_LOW_PASS_FILTER_SWITCH}, - {"imu_config_acc_odr", GX_ENUM_IMU_CONFIG_ACC_ODR}, - {"imu_config_acc_odr_low_pass_filter_frequency", GX_ENUM_IMU_CONFIG_ACC_ODR_LOW_PASS_FILTER_FREQUENCY}, - {"imu_config_gyro_xrange", GX_ENUM_IMU_CONFIG_GYRO_XRANGE}, - {"imu_config_gyro_yrange", GX_ENUM_IMU_CONFIG_GYRO_YRANGE}, - {"imu_config_gyro_zrange", GX_ENUM_IMU_CONFIG_GYRO_ZRANGE}, - {"imu_config_gyro_odr_low_pass_filter_switch", GX_ENUM_IMU_CONFIG_GYRO_ODR_LOW_PASS_FILTER_SWITCH}, - {"imu_config_gyro_odr", GX_ENUM_IMU_CONFIG_GYRO_ODR}, - {"imu_config_gyro_odr_low_pass_filter_frequency", GX_ENUM_IMU_CONFIG_GYRO_ODR_LOW_PASS_FILTER_FREQUENCY}, - {"imu_temperature_odr", GX_ENUM_IMU_TEMPERATURE_ODR}, - {"serialport_selector", GX_ENUM_SERIALPORT_SELECTOR}, - {"serialport_source", GX_ENUM_SERIALPORT_SOURCE}, - {"serialport_baudrate", GX_ENUM_SERIALPORT_BAUDRATE}, - {"serialport_stop_bits", GX_ENUM_SERIALPORT_STOP_BITS}, - {"serialport_parity", GX_ENUM_SERIALPORT_PARITY}, - {"cxp_link_configuration", GX_ENUM_CXP_LINK_CONFIGURATION}, - {"cxp_link_configuration_preferred", GX_ENUM_CXP_LINK_CONFIGURATION_PREFERRED}, - {"cxp_link_configuration_status", GX_ENUM_CXP_LINK_CONFIGURATION_STATUS}, - {"cxp_connection_selector", GX_ENUM_CXP_CONNECTION_SELECTOR}, - {"cxp_connection_test_mode", GX_ENUM_CXP_CONNECTION_TEST_MODE}, - {"sequencer_mode", GX_ENUM_SEQUENCER_MODE}, - {"sequencer_configuration_mode", GX_ENUM_SEQUENCER_CONFIGURATION_MODE}, - {"sequencer_feature_selector", GX_ENUM_SEQUENCER_FEATURE_SELECTOR}, - {"sequencer_trigger_source", GX_ENUM_SEQUENCER_TRIGGER_SOURCE}, - {"encoder_selector", GX_ENUM_ENCODER_SELECTOR}, - {"encoder_direction", GX_ENUM_ENCODER_DIRECTION}, - {"encoder_sourcea", GX_ENUM_ENCODER_SOURCEA}, - {"encoder_sourceb", GX_ENUM_ENCODER_SOURCEB}, - {"encoder_mode", GX_ENUM_ENCODER_MODE}, - {"um_resend_mode", GX_DS_ENUM_RESEND_MODE}, - {"um_stop_acquisition_mode", GX_DS_ENUM_STOP_ACQUISITION_MODE}, - {"um_stream_buffer_handling_mode", GX_DS_ENUM_STREAM_BUFFER_HANDLING_MODE}, +static std::unordered_map const ENUM_FEATURES{ + {"device_link_throughput_limit_mode", + GX_ENUM_DEVICE_LINK_THROUGHPUT_LIMIT_MODE}, + {"device_temperature_selector", GX_ENUM_DEVICE_TEMPERATURE_SELECTOR}, + {"lowpower_mode", GX_ENUM_LOWPOWER_MODE}, + {"close_ccd", GX_ENUM_CLOSE_CCD}, + {"pixel_size", GX_ENUM_PIXEL_SIZE}, + {"pixel_color_filter", GX_ENUM_PIXEL_COLOR_FILTER}, + {"pixel_format", GX_ENUM_PIXEL_FORMAT}, + {"test_pattern", GX_ENUM_TEST_PATTERN}, + {"test_pattern_generator_selector", + GX_ENUM_TEST_PATTERN_GENERATOR_SELECTOR}, + {"region_send_mode", GX_ENUM_REGION_SEND_MODE}, + {"region_mode", GX_ENUM_REGION_MODE}, + {"rregion_selector", GX_ENUM_RREGION_SELECTOR}, + {"binning_horizontal_mode", GX_ENUM_BINNING_HORIZONTAL_MODE}, + {"binning_vertical_mode", GX_ENUM_BINNING_VERTICAL_MODE}, + {"sensor_shutter_mode", GX_ENUM_SENSOR_SHUTTER_MODE}, + {"sensor_selector", GX_ENUM_SENSOR_SELECTOR}, + {"sensor_bit_depth", GX_ENUM_SENSOR_BIT_DEPTH}, + {"device_tap_geometry", GX_ENUM_DEVICE_TAP_GEOMETRY}, + {"acquisition_mode", GX_ENUM_ACQUISITION_MODE}, + {"trigger_mode", GX_ENUM_TRIGGER_MODE}, + {"trigger_activation", GX_ENUM_TRIGGER_ACTIVATION}, + {"trigger_switch", GX_ENUM_TRIGGER_SWITCH}, + {"exposure_auto", GX_ENUM_EXPOSURE_AUTO}, + {"trigger_source", GX_ENUM_TRIGGER_SOURCE}, + {"exposure_mode", GX_ENUM_EXPOSURE_MODE}, + {"trigger_selector", GX_ENUM_TRIGGER_SELECTOR}, + {"transfer_control_mode", GX_ENUM_TRANSFER_CONTROL_MODE}, + {"transfer_operation_mode", GX_ENUM_TRANSFER_OPERATION_MODE}, + {"acquisition_frame_rate_mode", GX_ENUM_ACQUISITION_FRAME_RATE_MODE}, + {"fixed_pattern_noise_correct_mode", + GX_ENUM_FIXED_PATTERN_NOISE_CORRECT_MODE}, + {"acquisition_status_selector", GX_ENUM_ACQUISITION_STATUS_SELECTOR}, + {"exposure_time_mode", GX_ENUM_EXPOSURE_TIME_MODE}, + {"acquisition_burst_mode", GX_ENUM_ACQUISITION_BURST_MODE}, + {"overlap_mode", GX_ENUM_OVERLAP_MODE}, + {"multisource_selector", GX_ENUM_MULTISOURCE_SELECTOR}, + {"user_output_selector", GX_ENUM_USER_OUTPUT_SELECTOR}, + {"user_output_mode", GX_ENUM_USER_OUTPUT_MODE}, + {"strobe_switch", GX_ENUM_STROBE_SWITCH}, + {"line_selector", GX_ENUM_LINE_SELECTOR}, + {"line_mode", GX_ENUM_LINE_MODE}, + {"line_source", GX_ENUM_LINE_SOURCE}, + {"gain_auto", GX_ENUM_GAIN_AUTO}, + {"gain_selector", GX_ENUM_GAIN_SELECTOR}, + {"blacklevel_auto", GX_ENUM_BLACKLEVEL_AUTO}, + {"blacklevel_selector", GX_ENUM_BLACKLEVEL_SELECTOR}, + {"balance_white_auto", GX_ENUM_BALANCE_WHITE_AUTO}, + {"balance_ratio_selector", GX_ENUM_BALANCE_RATIO_SELECTOR}, + {"color_correct", GX_ENUM_COLOR_CORRECT}, + {"dead_pixel_correct", GX_ENUM_DEAD_PIXEL_CORRECT}, + {"gamma_mode", GX_ENUM_GAMMA_MODE}, + {"light_source_preset", GX_ENUM_LIGHT_SOURCE_PRESET}, + {"aa_light_environment", GX_ENUM_AA_LIGHT_ENVIRONMENT}, + {"image_gray_raise_switch", GX_ENUM_IMAGE_GRAY_RAISE_SWITCH}, + {"awb_lamp_house", GX_ENUM_AWB_LAMP_HOUSE}, + {"sharpness_mode", GX_ENUM_SHARPNESS_MODE}, + {"user_data_filed_selector", GX_ENUM_USER_DATA_FILED_SELECTOR}, + {"flat_field_correction", GX_ENUM_FLAT_FIELD_CORRECTION}, + {"noise_reduction_mode", GX_ENUM_NOISE_REDUCTION_MODE}, + {"static_defect_correction", GX_ENUM_STATIC_DEFECT_CORRECTION}, + {"2d_noise_reduction_mode", GX_ENUM_2D_NOISE_REDUCTION_MODE}, + {"3d_noise_reduction_mode", GX_ENUM_3D_NOISE_REDUCTION_MODE}, + {"shading_correction_mode", GX_ENUM_SHADING_CORRECTION_MODE}, + {"ffc_generate_status", GX_ENUM_FFC_GENERATE_STATUS}, + {"ffc_expected_gray_value_enable", GX_ENUM_FFC_EXPECTED_GRAY_VALUE_ENABLE}, + {"dsnu_selector", GX_ENUM_DSNU_SELECTOR}, + {"dsnu_generate_status", GX_ENUM_DSNU_GENERATE_STATUS}, + {"prnu_selector", GX_ENUM_PRNU_SELECTOR}, + {"prnu_generate_status", GX_ENUM_PRNU_GENERATE_STATUS}, + {"ffc_coefficient", GX_ENUM_FFC_COEFFICIENT}, + {"user_set_selector", GX_ENUM_USER_SET_SELECTOR}, + {"user_set_default", GX_ENUM_USER_SET_DEFAULT}, + {"event_selector", GX_ENUM_EVENT_SELECTOR}, + {"event_notification", GX_ENUM_EVENT_NOTIFICATION}, + {"event_simple_mode", GX_ENUM_EVENT_SIMPLE_MODE}, + {"lut_selector", GX_ENUM_LUT_SELECTOR}, + {"chunk_selector", GX_ENUM_CHUNK_SELECTOR}, + {"color_transformation_mode", GX_ENUM_COLOR_TRANSFORMATION_MODE}, + {"color_transformation_value_selector", + GX_ENUM_COLOR_TRANSFORMATION_VALUE_SELECTOR}, + {"saturation_mode", GX_ENUM_SATURATION_MODE}, + {"timer_selector", GX_ENUM_TIMER_SELECTOR}, + {"timer_trigger_source", GX_ENUM_TIMER_TRIGGER_SOURCE}, + {"counter_selector", GX_ENUM_COUNTER_SELECTOR}, + {"counter_event_source", GX_ENUM_COUNTER_EVENT_SOURCE}, + {"counter_reset_source", GX_ENUM_COUNTER_RESET_SOURCE}, + {"counter_reset_activation", GX_ENUM_COUNTER_RESET_ACTIVATION}, + {"counter_trigger_source", GX_ENUM_COUNTER_TRIGGER_SOURCE}, + {"timer_trigger_activation", GX_ENUM_TIMER_TRIGGER_ACTIVATION}, + {"remove_parameter_limit", GX_ENUM_REMOVE_PARAMETER_LIMIT}, + {"hdr_mode", GX_ENUM_HDR_MODE}, + {"mgc_mode", GX_ENUM_MGC_MODE}, + {"imu_config_acc_range", GX_ENUM_IMU_CONFIG_ACC_RANGE}, + {"imu_config_acc_odr_low_pass_filter_switch", + GX_ENUM_IMU_CONFIG_ACC_ODR_LOW_PASS_FILTER_SWITCH}, + {"imu_config_acc_odr", GX_ENUM_IMU_CONFIG_ACC_ODR}, + {"imu_config_acc_odr_low_pass_filter_frequency", + GX_ENUM_IMU_CONFIG_ACC_ODR_LOW_PASS_FILTER_FREQUENCY}, + {"imu_config_gyro_xrange", GX_ENUM_IMU_CONFIG_GYRO_XRANGE}, + {"imu_config_gyro_yrange", GX_ENUM_IMU_CONFIG_GYRO_YRANGE}, + {"imu_config_gyro_zrange", GX_ENUM_IMU_CONFIG_GYRO_ZRANGE}, + {"imu_config_gyro_odr_low_pass_filter_switch", + GX_ENUM_IMU_CONFIG_GYRO_ODR_LOW_PASS_FILTER_SWITCH}, + {"imu_config_gyro_odr", GX_ENUM_IMU_CONFIG_GYRO_ODR}, + {"imu_config_gyro_odr_low_pass_filter_frequency", + GX_ENUM_IMU_CONFIG_GYRO_ODR_LOW_PASS_FILTER_FREQUENCY}, + {"imu_temperature_odr", GX_ENUM_IMU_TEMPERATURE_ODR}, + {"serialport_selector", GX_ENUM_SERIALPORT_SELECTOR}, + {"serialport_source", GX_ENUM_SERIALPORT_SOURCE}, + {"serialport_baudrate", GX_ENUM_SERIALPORT_BAUDRATE}, + {"serialport_stop_bits", GX_ENUM_SERIALPORT_STOP_BITS}, + {"serialport_parity", GX_ENUM_SERIALPORT_PARITY}, + {"cxp_link_configuration", GX_ENUM_CXP_LINK_CONFIGURATION}, + {"cxp_link_configuration_preferred", + GX_ENUM_CXP_LINK_CONFIGURATION_PREFERRED}, + {"cxp_link_configuration_status", GX_ENUM_CXP_LINK_CONFIGURATION_STATUS}, + {"cxp_connection_selector", GX_ENUM_CXP_CONNECTION_SELECTOR}, + {"cxp_connection_test_mode", GX_ENUM_CXP_CONNECTION_TEST_MODE}, + {"sequencer_mode", GX_ENUM_SEQUENCER_MODE}, + {"sequencer_configuration_mode", GX_ENUM_SEQUENCER_CONFIGURATION_MODE}, + {"sequencer_feature_selector", GX_ENUM_SEQUENCER_FEATURE_SELECTOR}, + {"sequencer_trigger_source", GX_ENUM_SEQUENCER_TRIGGER_SOURCE}, + {"encoder_selector", GX_ENUM_ENCODER_SELECTOR}, + {"encoder_direction", GX_ENUM_ENCODER_DIRECTION}, + {"encoder_sourcea", GX_ENUM_ENCODER_SOURCEA}, + {"encoder_sourceb", GX_ENUM_ENCODER_SOURCEB}, + {"encoder_mode", GX_ENUM_ENCODER_MODE}, + {"um_resend_mode", GX_DS_ENUM_RESEND_MODE}, + {"um_stop_acquisition_mode", GX_DS_ENUM_STOP_ACQUISITION_MODE}, + {"um_stream_buffer_handling_mode", GX_DS_ENUM_STREAM_BUFFER_HANDLING_MODE}, }; struct DoublePusher { const int gx_float; // `GX_FLOAT_GAIN` or `GX_FLOAT_EXPOSURE_TIME` - DoublePusher(int gx_float) : gx_float{gx_float} {} - void operator()(GX_DEV_HANDLE handle, MallocStream &out) const { + DoublePusher(int gx_float) : gx_float{gx_float} { + } + void operator()(GX_DEV_HANDLE handle, MallocStream& out) const { double dValue{}; GX_STATUS const emStatus = GXGetFloat(handle, this->gx_float, &dValue); if (emStatus != GX_STATUS_SUCCESS) { @@ -361,20 +384,19 @@ struct VideoReaderGalaxy::Impl { void* userdata; Impl( - GX_DEV_HANDLE handle, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_callback, - DeallocateCallback deallocate_callback, - VideoReader::LogCallback log_callback, - void* userdata - ) : - handle{handle}, - stop_requested{false}, - allocate_callback{allocate_callback}, - deallocate_callback{deallocate_callback}, - log_callback{log_callback}, - userdata{userdata} { + GX_DEV_HANDLE handle, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_callback, + DeallocateCallback deallocate_callback, + VideoReader::LogCallback log_callback, + void* userdata) : + handle{handle}, + stop_requested{false}, + allocate_callback{allocate_callback}, + deallocate_callback{deallocate_callback}, + log_callback{log_callback}, + userdata{userdata} { for (const std::string& extra : extras) { if (extra == "exposure") { this->pushers.push_back(DoublePusher(GX_FLOAT_EXPOSURE_TIME)); @@ -399,8 +421,8 @@ struct VideoReaderGalaxy::Impl { void set(std::vector const& parameter_pairs) { for (std::vector::const_iterator it = parameter_pairs.begin(); - it != parameter_pairs.end(); - ++it) { + it != parameter_pairs.end(); + ++it) { std::string const key = to_lower(*it); std::string const& value = *++it; set_pair(this->handle, key, value); @@ -412,24 +434,23 @@ struct VideoReaderGalaxy::Impl { } void set_pair( - GX_DEV_HANDLE handle, - std::string const& key, - std::string const& value - ) { + GX_DEV_HANDLE handle, std::string const& key, std::string const& value) { if (auto pair = INT_FEATURES.find(key); pair != INT_FEATURES.end()) { int64_t int_value = std::stoll(value); GALAXY_CHECK(GXSetInt(handle, pair->second, int_value)); - } - else if (auto pair = FLOAT_FEATURES.find(key); pair != FLOAT_FEATURES.end()) { + } else if (auto pair = FLOAT_FEATURES.find(key); + pair != FLOAT_FEATURES.end()) { double float_value = std::stod(value); GALAXY_CHECK(GXSetFloat(handle, pair->second, float_value)); - } - else if (auto pair = ENUM_FEATURES.find(key); pair != ENUM_FEATURES.end()) { + } else if (auto pair = ENUM_FEATURES.find(key); + pair != ENUM_FEATURES.end()) { uint32_t nums = 0; GALAXY_CHECK(GXGetEnumEntryNums(handle, pair->second, &nums)); size_t nBufferSize = nums * sizeof(GX_ENUM_DESCRIPTION); - auto const pEnumDescription = std::unique_ptr(new GX_ENUM_DESCRIPTION[nums]); - GALAXY_CHECK(GXGetEnumDescription(handle, pair->second, pEnumDescription.get(), &nBufferSize)); + auto const pEnumDescription = + std::unique_ptr(new GX_ENUM_DESCRIPTION[nums]); + GALAXY_CHECK(GXGetEnumDescription( + handle, pair->second, pEnumDescription.get(), &nBufferSize)); uint32_t entry_idx = 0; for (; entry_idx < nums; ++entry_idx) { auto const& item = pEnumDescription.get()[entry_idx]; @@ -444,32 +465,34 @@ struct VideoReaderGalaxy::Impl { if (entry_idx) { valid_values += ", "; } - valid_values += "`" + std::string(pEnumDescription.get()[entry_idx].szSymbolic) + "`"; + valid_values += + "`" + std::string(pEnumDescription.get()[entry_idx].szSymbolic) + + "`"; } throw std::runtime_error( - "Failed to set `" + key + "` to `" + value + "`. Valid values are: " + valid_values + "." - ); + "Failed to set `" + key + "` to `" + value + + "`. Valid values are: " + valid_values + "."); } } else { if (this->log_callback) { std::string warning{"unknown key `" + key + "`. Available keys: "}; warning.reserve(4096); - for (auto const& it: INT_FEATURES) { + for (auto const& it : INT_FEATURES) { warning.append(it.first); warning.append(", ", 2); } - for (auto const& it: FLOAT_FEATURES) { + for (auto const& it : FLOAT_FEATURES) { warning.append(it.first); warning.append(", ", 2); } - for (auto const& it: ENUM_FEATURES) { + for (auto const& it : ENUM_FEATURES) { warning.append(it.first); warning.append(", ", 2); } warning.resize(warning.size() - 2); // remove last comma this->log_callback( - warning.c_str(), VideoReader::LogLevel::WARNING, this->userdata); + warning.c_str(), VideoReader::LogLevel::WARNING, this->userdata); } } } @@ -486,10 +509,11 @@ struct VideoReaderGalaxy::Impl { uint64_t previousFrameID{}; // trying to make nFrameID contigious while (!this->stop_requested) { auto const status = GXDQAllBufs( - this->handle, pFrameBuffer, - sizeof(pFrameBuffer) / sizeof(*pFrameBuffer), - &nFrameCount, TIMEOUT_MS - ); + this->handle, + pFrameBuffer, + sizeof(pFrameBuffer) / sizeof(*pFrameBuffer), + &nFrameCount, + TIMEOUT_MS); if (status != GX_STATUS_SUCCESS) { if (status == GX_STATUS_TIMEOUT) { ++timeoutHit; @@ -497,8 +521,7 @@ struct VideoReaderGalaxy::Impl { throw std::runtime_error("no galaxy data for 3 seconds"); } continue; - } - else { + } else { throw std::runtime_error(get_error_string(status)); } } @@ -511,43 +534,53 @@ struct VideoReaderGalaxy::Impl { PGX_FRAME_BUFFER buffer = pFrameBuffer[idx]; if (buffer->nStatus != GX_FRAME_STATUS_SUCCESS) { if (this->log_callback) { - std::string const last_error = get_error_string(GX_STATUS_SUCCESS); + std::string const last_error = + get_error_string(GX_STATUS_SUCCESS); this->log_callback( - ("buffer status is " + std::to_string(buffer->nStatus) + ": " + last_error).c_str(), - VideoReader::LogLevel::WARNING, this->userdata - ); + ("buffer status is " + std::to_string(buffer->nStatus) + + ": " + last_error) + .c_str(), + VideoReader::LogLevel::WARNING, + this->userdata); } continue; } int32_t const alignment = 16; - int32_t const preferred_stride = (buffer->nWidth * 1 + alignment - 1) & ~(alignment - 1); + int32_t const preferred_stride = + (buffer->nWidth * 1 + alignment - 1) & ~(alignment - 1); - Frame::timestamp_s_t const timestamp_s = ( - static_cast(buffer->nTimestamp) / - this->timestamp_tick_frequency); // bad nTimestamp cast, sorry + Frame::timestamp_s_t const timestamp_s = + (static_cast(buffer->nTimestamp) / + this->timestamp_tick_frequency); // bad nTimestamp cast, sorry - uint64_t const frame_id = buffer->nFrameID - 1; // -1 as Galaxy starts with 1 + uint64_t const frame_id = + buffer->nFrameID - 1; // -1 as Galaxy starts with 1 if (frame_id < previousFrameID) { addFrames += (previousFrameID - frame_id) + 1; } Frame::number_t const number = frame_id + addFrames; previousFrameID = frame_id; - FrameUP frame(new Frame(this->deallocate_callback, this->userdata, { - buffer->nHeight, // height - buffer->nWidth, // width - 1, // channels - SCALAR_TYPE::U8, // scalar_type - preferred_stride, // stride - nullptr, // data - nullptr, // user_data - }, number, timestamp_s)); + FrameUP frame(new Frame( + this->deallocate_callback, + this->userdata, + { + buffer->nHeight, // height + buffer->nWidth, // width + 1, // channels + SCALAR_TYPE::U8, // scalar_type + preferred_stride, // stride + nullptr, // data + nullptr, // user_data + }, + number, + timestamp_s)); if (!this->pushers.empty()) { MallocStream stream{32}; thismsgpack::pack_array_header(this->pushers.size(), stream); - for (auto &pusher : this->pushers) { + for (auto& pusher : this->pushers) { pusher(this->handle, stream); } frame->extras = stream.data(); @@ -555,7 +588,8 @@ struct VideoReaderGalaxy::Impl { } auto const& img = frame->image; - std::memcpy(img.data, buffer->pImgBuf, buffer->nWidth * buffer->nHeight); + std::memcpy( + img.data, buffer->pImgBuf, buffer->nWidth * buffer->nHeight); { std::lock_guard guard(this->read_queue_lock); if (this->read_queue.size() > 9) { @@ -566,8 +600,7 @@ struct VideoReaderGalaxy::Impl { } GXQAllBufs(this->handle); } - } - catch (...) { + } catch (...) { this->stop_requested = true; this->exception = std::current_exception(); } @@ -599,38 +632,40 @@ struct VideoReaderGalaxy::Impl { }; VideoReaderGalaxy::VideoReaderGalaxy( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_callback, - DeallocateCallback deallocate_callback, - LogCallback log_callback, - void* userdata -) { + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_callback, + DeallocateCallback deallocate_callback, + LogCallback log_callback, + void* userdata) { auto const res = GXInitLib(); if (res != GX_STATUS_SUCCESS) { - throw std::runtime_error("GXInitLib was't successful"); + throw std::runtime_error("GXInitLib was't successful"); } auto const info = url.substr(9); GX_DEV_HANDLE handle{}; static GX_OPEN_MODE_CMD modes[] = { - GX_OPEN_IP, - GX_OPEN_SN, - GX_OPEN_MAC, - GX_OPEN_INDEX, - GX_OPEN_USERID - }; - - GX_OPEN_PARAM param{const_cast(info.c_str()), GX_OPEN_SN, GX_ACCESS_EXCLUSIVE}; - for (int mode_idx = 0; mode_idx < sizeof(modes) / sizeof(*modes); ++mode_idx) { + GX_OPEN_IP, GX_OPEN_SN, GX_OPEN_MAC, GX_OPEN_INDEX, GX_OPEN_USERID}; + + GX_OPEN_PARAM param{ + const_cast(info.c_str()), GX_OPEN_SN, GX_ACCESS_EXCLUSIVE}; + for (int mode_idx = 0; mode_idx < sizeof(modes) / sizeof(*modes); + ++mode_idx) { param.openMode = modes[mode_idx]; auto const ret = GXOpenDevice(¶m, &handle); if (ret == GX_STATUS_SUCCESS) { this->impl = std::make_unique( - handle, parameter_pairs, extras, allocate_callback, deallocate_callback, log_callback, userdata); + handle, + parameter_pairs, + extras, + allocate_callback, + deallocate_callback, + log_callback, + userdata); return; } } diff --git a/src/videoreader_galaxy.hpp b/src/videoreader_galaxy.hpp index 19ec119..d4a1e13 100644 --- a/src/videoreader_galaxy.hpp +++ b/src/videoreader_galaxy.hpp @@ -1,18 +1,15 @@ #include - -class VideoReaderGalaxy : public VideoReader -{ +class VideoReaderGalaxy : public VideoReader { public: VideoReaderGalaxy( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_callback, - DeallocateCallback deallocate_callback, - LogCallback log_callback, - void* userdata - ); + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_callback, + DeallocateCallback deallocate_callback, + LogCallback log_callback, + void* userdata); bool is_seekable() const override; VideoReader::FrameUP next_frame(bool decode) override; diff --git a/src/videoreader_go.cpp b/src/videoreader_go.cpp index 01e6e79..a9de935 100644 --- a/src/videoreader_go.cpp +++ b/src/videoreader_go.cpp @@ -1,11 +1,11 @@ -#include -#include -#include -#include +#include #include -#include #include -#include +#include +#include +#include +#include +#include #ifdef USE_MINVIEWER_CLIENT #include #endif @@ -14,33 +14,37 @@ static bool ctrl_c = false; #include BOOL WINAPI consoleHandler(DWORD signal) { - if (signal == CTRL_C_EVENT || signal == CTRL_BREAK_EVENT || signal == CTRL_CLOSE_EVENT) { + if (signal == CTRL_C_EVENT || signal == CTRL_BREAK_EVENT || + signal == CTRL_CLOSE_EVENT) { ctrl_c = true; return TRUE; } return FALSE; } - #endif -static void log_callback(char const* message, VideoReader::LogLevel log_level, void* userdata) { +static void log_callback( + char const* message, VideoReader::LogLevel log_level, void* userdata) { std::cout << "[vr]" << message << '\n'; } -static void run(std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras) { +static void +run(std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras) { #ifdef _WIN32 if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) { throw std::runtime_error("ERROR: Could not set control handler"); } #endif - auto video_reader = VideoReader::create(url, parameter_pairs, extras, nullptr, nullptr, log_callback); + auto video_reader = VideoReader::create( + url, parameter_pairs, extras, nullptr, nullptr, log_callback); uint64_t const frames_count = video_reader->size(); std::cout << "frames_count: " << frames_count << std::endl - << std::boolalpha << "is_seekaable: " << video_reader->is_seekable() << std::endl; + << std::boolalpha << "is_seekaable: " << video_reader->is_seekable() + << std::endl; unsigned int const FPS_SZ{16}; std::vector fps(FPS_SZ); std::vector durations(FPS_SZ); @@ -56,10 +60,9 @@ static void run(std::string const& url, auto prev_time = std::chrono::high_resolution_clock::now(); VideoReader::Frame::timestamp_s_t prev_timestamp{}; VideoReader::Frame::number_t prev_frame_number{ - static_cast(-1)}; // we start with #0 + static_cast(-1)}; // we start with #0 std::cout << std::fixed; - while (auto frame = video_reader->next_frame()) - { + while (auto frame = video_reader->next_frame()) { if (ctrl_c) { break; } @@ -71,20 +74,23 @@ static void run(std::string const& url, durations[counter % FPS_SZ] = cur_time - prev_time; #ifdef USE_MINVIEWER_CLIENT - c.add_image(frame->image, {{"obj_id", img_id}}); + c.add_image(frame->image, {{"obj_id", img_id}}); #endif std::cout << "[" << frame->number << "/" << frames_count - 1 << "] " - << frame->image.width << "x" - << frame->image.height << "x" - << frame->image.channels - << " @ " << std::setw(10) << frame->timestamp_s << "s [missed " << missed_frames << "]"; + << frame->image.width << "x" << frame->image.height << "x" + << frame->image.channels << " @ " << std::setw(10) + << frame->timestamp_s << "s [missed " << missed_frames << "]"; if (counter >= FPS_SZ) { - double const real_fps = fps.size() / std::accumulate(fps.begin(), fps.end(), 0.0); - auto const total_duration = std::accumulate(durations.begin(), durations.end(), std::chrono::high_resolution_clock::duration{}); + double const real_fps = + fps.size() / std::accumulate(fps.begin(), fps.end(), 0.0); + auto const total_duration = std::accumulate( + durations.begin(), + durations.end(), + std::chrono::high_resolution_clock::duration{}); std::chrono::duration duration_s = total_duration; double const read_fps = FPS_SZ / duration_s.count(); - std::cout << " [real " << std::setw(7) << std::setprecision( 2 ) << real_fps << "fps / read " - << std::setw(7) << read_fps << "fps]"; + std::cout << " [real " << std::setw(7) << std::setprecision(2) << real_fps + << "fps / read " << std::setw(7) << read_fps << "fps]"; } std::cout << std::endl; ++counter; @@ -92,7 +98,7 @@ static void run(std::string const& url, } } -int main(int argc, char **argv) { +int main(int argc, char** argv) { if (argc < 2) { std::cout << "usage:" << argv[0] << " URL [PARAMETER VALUE] ... [--extras [EXTRAS]]\n"; @@ -102,14 +108,15 @@ int main(int argc, char **argv) { std::string const uri = std::string(argv[1]); std::vector parameter_pairs(argv + 2, argv + argc); std::vector extras{}; - auto extras_it = std::find(parameter_pairs.begin(), parameter_pairs.end(), "--extras"); - if (extras_it != parameter_pairs.end()) { // have extras - std::move(extras_it + 1, parameter_pairs.end(), std::back_inserter(extras)); + auto extras_it = + std::find(parameter_pairs.begin(), parameter_pairs.end(), "--extras"); + if (extras_it != parameter_pairs.end()) { // have extras + std::move( + extras_it + 1, parameter_pairs.end(), std::back_inserter(extras)); parameter_pairs.pop_back(); // remove --extras } run(uri, parameter_pairs, extras); - } - catch (std::runtime_error &e) { + } catch (std::runtime_error& e) { std::cerr << "EXCEPTION: " << e.what() << std::endl; return 1; } diff --git a/src/videoreader_pylon.cpp b/src/videoreader_pylon.cpp index 0674c5d..c0eaf72 100644 --- a/src/videoreader_pylon.cpp +++ b/src/videoreader_pylon.cpp @@ -2,22 +2,21 @@ #if defined(_DEBUG) #undef _DEBUG -# include -# include -# include -# include +#include +#include +#include +#include #define _DEBUG 1 #else -# include -# include -# include -# include +#include +#include +#include +#include #endif -#include +#include "spinlock.hpp" #include #include -#include "spinlock.hpp" - +#include struct VideoReaderPylon::Impl { Pylon::CInstantCamera camera; @@ -31,23 +30,19 @@ struct VideoReaderPylon::Impl { void* userdata; Impl( - AllocateCallback allocate_callback, - DeallocateCallback deallocate_callback, - void* userdata - ) : - stop_requested{false}, - allocate_callback{allocate_callback}, - deallocate_callback{deallocate_callback}, - userdata{userdata} - { + AllocateCallback allocate_callback, + DeallocateCallback deallocate_callback, + void* userdata) : + stop_requested{false}, + allocate_callback{allocate_callback}, + deallocate_callback{deallocate_callback}, + userdata{userdata} { this->converter.OutputPixelFormat = Pylon::PixelType_RGB8packed; this->converter.OutputBitAlignment = Pylon::OutputBitAlignment_MsbAligned; this->camera.Attach(Pylon::CTlFactory::GetInstance().CreateFirstDevice()); try { this->camera.Open(); - } - catch (Pylon::GenericException const& e) - { + } catch (Pylon::GenericException const& e) { throw std::runtime_error(e.what()); } this->thread = std::thread(&VideoReaderPylon::Impl::read, this); @@ -70,10 +65,10 @@ struct VideoReaderPylon::Impl { void read() { this->camera.StartGrabbing(); - while (!this->stop_requested) - { + while (!this->stop_requested) { Pylon::CGrabResultPtr grabResult; - if (!this->camera.RetrieveResult(500, grabResult, Pylon::TimeoutHandling_Return)) { + if (!this->camera.RetrieveResult( + 500, grabResult, Pylon::TimeoutHandling_Return)) { //this->impl->running = false; continue; } @@ -81,8 +76,7 @@ struct VideoReaderPylon::Impl { continue; { std::lock_guard guard(this->read_queue_lock); - if (this->read_queue.size() > 10) - { + if (this->read_queue.size() > 10) { // cleanup queue for (int i = 0; i < 8; ++i) this->read_queue.pop_front(); @@ -108,25 +102,28 @@ struct VideoReaderPylon::Impl { int32_t const width = static_cast(result->GetWidth()); int32_t const height = static_cast(result->GetHeight()); int32_t alignment = 16; - int32_t const preferred_stride = (width * 3 + alignment - 1) & ~(alignment - 1); + int32_t const preferred_stride = + (width * 3 + alignment - 1) & ~(alignment - 1); Frame::number_t const number = result->GetBlockID(); Frame::timestamp_s_t const timestamp_s = result->GetTimeStamp() / 1000.0; FrameUP frame(new Frame( - this->deallocate_callback, this->userdata, { - height, // height - width, // width - 3, // channels - SCALAR_TYPE::U8, // scalar_type; - preferred_stride, // stride - nullptr, // data - nullptr // user_data - }, - number, timestamp_s - )); + this->deallocate_callback, + this->userdata, + { + height, // height + width, // width + 3, // channels + SCALAR_TYPE::U8, // scalar_type; + preferred_stride, // stride + nullptr, // data + nullptr // user_data + }, + number, + timestamp_s)); if (decode) { - VideoReader::VRImage *img = &frame->image; + VideoReader::VRImage* img = &frame->image; (*this->allocate_callback)(img, this->userdata); if (!img->data) { throw std::runtime_error("Failed to allocate image for pylon"); @@ -135,23 +132,22 @@ struct VideoReaderPylon::Impl { } return frame; } - }; VideoReaderPylon::VideoReaderPylon( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_cb, - DeallocateCallback deallocate_cb, - VideoReader::LogCallback log_callback, - void* userdata - ) { + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_cb, + DeallocateCallback deallocate_cb, + VideoReader::LogCallback log_callback, + void* userdata) { if (!extras.empty()) { throw std::runtime_error("extras not supported in pylon (yet)"); } Pylon::PylonInitialize(); - this->impl = std::unique_ptr(new Impl{allocate_cb, deallocate_cb, userdata}); + this->impl = + std::unique_ptr(new Impl{allocate_cb, deallocate_cb, userdata}); } bool VideoReaderPylon::is_seekable() const { @@ -162,12 +158,10 @@ VideoReader::FrameUP VideoReaderPylon::next_frame(bool decode) { return this->impl->next_frame(decode); } -VideoReader::Frame::number_t VideoReaderPylon::size() const -{ +VideoReader::Frame::number_t VideoReaderPylon::size() const { return 0; } - VideoReaderPylon::~VideoReaderPylon() { this->impl->stop_requested = true; this->impl->thread.join(); diff --git a/src/videoreader_pylon.hpp b/src/videoreader_pylon.hpp index 613b1fc..d563b19 100644 --- a/src/videoreader_pylon.hpp +++ b/src/videoreader_pylon.hpp @@ -1,18 +1,15 @@ #include - -class VideoReaderPylon : public VideoReader -{ +class VideoReaderPylon : public VideoReader { public: VideoReaderPylon( - std::string const& url, - std::vector const& parameter_pairs, - std::vector const& extras, - AllocateCallback allocate_cb, - DeallocateCallback deallocate_cb, - VideoReader::LogCallback log_callback, - void* userdata - ); + std::string const& url, + std::vector const& parameter_pairs, + std::vector const& extras, + AllocateCallback allocate_cb, + DeallocateCallback deallocate_cb, + VideoReader::LogCallback log_callback, + void* userdata); bool is_seekable() const override; FrameUP next_frame(bool decode) override; diff --git a/src/videowriter.cpp b/src/videowriter.cpp index fa3d38d..5387f7b 100644 --- a/src/videowriter.cpp +++ b/src/videowriter.cpp @@ -1,32 +1,34 @@ #include -extern "C" -{ +extern "C" { #include #include -#include #include +#include } -#include // std::runtime_error -#include // std::optional -#include // std::from_chars #include "ffmpeg_common.hpp" -#include -#include +#include // std::from_chars #include - +#include +#include // std::optional +#include // std::runtime_error +#include static std::string format_error(int const errnum, char const* const message) { return std::string(message) + " (" + get_av_error(errnum) + ")"; } -static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt) -{ - AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base; - printf("pts:%ld pts_time:%.6g dts:%ld dts_time:%.6g duration:%ld duration_time:%.6g stream_index:%d\n", - pkt->pts, av_q2d(*time_base) * pkt->pts, - pkt->dts, av_q2d(*time_base) * pkt->dts, - pkt->duration, av_q2d(*time_base) * pkt->duration, - pkt->stream_index); +static void log_packet(const AVFormatContext* fmt_ctx, const AVPacket* pkt) { + AVRational* time_base = &fmt_ctx->streams[pkt->stream_index]->time_base; + printf( + "pts:%ld pts_time:%.6g dts:%ld dts_time:%.6g duration:%ld " + "duration_time:%.6g stream_index:%d\n", + pkt->pts, + av_q2d(*time_base) * pkt->pts, + pkt->dts, + av_q2d(*time_base) * pkt->dts, + pkt->duration, + av_q2d(*time_base) * pkt->duration, + pkt->stream_index); } struct VideoWriter::Impl { @@ -50,38 +52,45 @@ struct VideoWriter::Impl { std::mutex m; std::exception_ptr exception; - Impl(bool realtime): - pkt(av_packet_alloc()), realtime{realtime} - {} + Impl(bool realtime) : pkt(av_packet_alloc()), realtime{realtime} { + } - void send_frame(AVFrame *frame) { + void send_frame(AVFrame* frame) { if (const int ret = avcodec_send_frame(this->enc.get(), frame); ret < 0) { - throw std::runtime_error(format_error(ret, "avcodec_send_frame() failed")); + throw std::runtime_error( + format_error(ret, "avcodec_send_frame() failed")); } for (;;) { - const int receive_packet_ret = avcodec_receive_packet(this->enc.get(), this->pkt.get()); + const int receive_packet_ret = + avcodec_receive_packet(this->enc.get(), this->pkt.get()); if (receive_packet_ret == AVERROR(EAGAIN)) // No more packets for now. break; if (receive_packet_ret == AVERROR_EOF) // No more packets, ever. break; if (receive_packet_ret < 0) { - throw std::runtime_error(format_error(receive_packet_ret, "avcodec_receive_packet() failed")); + throw std::runtime_error(format_error( + receive_packet_ret, "avcodec_receive_packet() failed")); } - av_packet_rescale_ts(this->pkt.get(), this->enc->time_base, this->st->time_base); + av_packet_rescale_ts( + this->pkt.get(), this->enc->time_base, this->st->time_base); this->pkt->stream_index = this->st->index; // log_packet(this->oc.get(), this->pkt.get()); // if (int const ret = av_write_frame(this->oc.get(), this->pkt.get()); ret < 0) { // throw std::runtime_error(format_error(ret, "av_write_frame() failed")); // } - if (int const ret = av_interleaved_write_frame(this->oc.get(), this->pkt.get()); ret < 0) { - throw std::runtime_error(format_error(ret, "av_interleaved_write_frame() failed")); + if (int const ret = + av_interleaved_write_frame(this->oc.get(), this->pkt.get()); + ret < 0) { + throw std::runtime_error( + format_error(ret, "av_interleaved_write_frame() failed")); } } if (!frame) { // close if (this->oc) { if (int const ret = av_write_trailer(this->oc.get()); ret != 0) { - throw std::runtime_error(format_error(ret, "av_write_trailer() failed")); + throw std::runtime_error( + format_error(ret, "av_write_trailer() failed")); } } if (this->oc && !(this->oc->oformat->flags & AVFMT_NOFILE)) { @@ -98,7 +107,9 @@ struct VideoWriter::Impl { for (;;) { { std::unique_lock lk(m); - cv.wait(lk, [&]{return !this->write_queue.empty() ;}); + cv.wait(lk, [&] { + return !this->write_queue.empty(); + }); popped_frame = std::move(this->write_queue.front()); this->write_queue.pop_front(); } @@ -107,25 +118,25 @@ struct VideoWriter::Impl { break; } } - } - catch (...) { + } catch (...) { this->exception = std::current_exception(); } } bool push(VideoReader::Frame const& frame) { VideoReader::VRImage const& img = frame.image; - if ( - this->frame->width != img.width || - this->frame->height != img.height - ) { + if (this->frame->width != img.width || this->frame->height != img.height) { throw std::runtime_error("can't change video frame size"); } if (const int ret = sws_scale( - this->sws_ctx.get(), - &img.data, &img.stride, 0, img.height, - this->frame->data, - this->frame->linesize); ret < 0) { + this->sws_ctx.get(), + &img.data, + &img.stride, + 0, + img.height, + this->frame->data, + this->frame->linesize); + ret < 0) { throw std::runtime_error(format_error(ret, "sws_scale() failed")); } if (this->exception) { @@ -135,7 +146,8 @@ struct VideoWriter::Impl { if (this->realtime) { AVFrameUP dynframe{av_frame_alloc()}; // `av_frame_ref` is so bad. We make a copy. It could be 300% better. - if (const int ret = av_frame_ref(dynframe.get(), this->frame.get()); ret < 0) { + if (const int ret = av_frame_ref(dynframe.get(), this->frame.get()); + ret < 0) { throw std::runtime_error(format_error(ret, "av_frame_ref() failed")); } std::unique_lock lk(this->m); @@ -167,44 +179,44 @@ struct VideoWriter::Impl { this->send_frame(nullptr); } } - }; static int64_t pop_value_int64( - AVDictionary* dict, - const char *key, - int64_t const default_value) { + AVDictionary* dict, const char* key, int64_t const default_value) { AVDictionaryEntry const* entry = av_dict_get(dict, key, NULL, 0); if (entry) { av_dict_set(&dict, key, NULL, 0); // remove item std::string const str{entry->value}; int64_t result{}; - auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result); + auto [ptr, ec] = + std::from_chars(str.data(), str.data() + str.size(), result); if (ec == std::errc()) { return result; - } else { - throw std::runtime_error("`" + str + "` is not a valid int64"); } + throw std::runtime_error("`" + str + "` is not a valid int64"); } return default_value; } VideoWriter::VideoWriter( - std::string const& uri, - VideoReader::VRImage const& format, - std::vector const& parameter_pairs, // size % 2 == 0 - bool realtime, - VideoReader::LogCallback log_callback, - void* userdata -) : impl{new Impl(realtime)} { - this->impl->sws_ctx.reset( - sws_getContext( - format.width, format.height, + std::string const& uri, + VideoReader::VRImage const& format, + std::vector const& parameter_pairs, // size % 2 == 0 + bool realtime, + VideoReader::LogCallback log_callback, + void* userdata) : + impl{new Impl(realtime)} { + this->impl->sws_ctx.reset(sws_getContext( + format.width, + format.height, AV_PIX_FMT_RGB24 /* from */, - format.width, format.height, + format.width, + format.height, AV_PIX_FMT_YUV420P /* to */, - SWS_BICUBIC, NULL, NULL, NULL) - ); + SWS_BICUBIC, + NULL, + NULL, + NULL)); if (!this->impl->sws_ctx) { throw std::runtime_error("sws_getContext() failed"); } @@ -214,13 +226,16 @@ VideoWriter::VideoWriter( // find codec AVFormatContext* oc_ = nullptr; { - if (const int ret = avformat_alloc_output_context2(&oc_, NULL, format_name, uri.c_str()); ret < 0) { - throw std::runtime_error(format_error(ret, "avformat_alloc_output_context2 error")); + if (const int ret = avformat_alloc_output_context2( + &oc_, NULL, format_name, uri.c_str()); + ret < 0) { + throw std::runtime_error( + format_error(ret, "avformat_alloc_output_context2 error")); } this->impl->oc.reset(oc_); } - const AVCodec *codec = avcodec_find_encoder_by_name(encoder_name); + const AVCodec* codec = avcodec_find_encoder_by_name(encoder_name); // oc_->oformat->video_codec = codec; // const AVCodec *codec = avcodec_find_encoder(oc_->oformat->video_codec); if (!codec) { @@ -233,7 +248,8 @@ VideoWriter::VideoWriter( } else { profile_name = "has no profiles"; } - std::string const message = "using profile `" + std::string(profile_name) + "`"; + std::string const message = + "using profile `" + std::string(profile_name) + "`"; log_callback(message.c_str(), VideoReader::LogLevel::INFO, userdata); log_callback(codec->long_name, VideoReader::LogLevel::INFO, userdata); } @@ -244,7 +260,7 @@ VideoWriter::VideoWriter( } this->impl->st->id = 0; - AVCodecContext *c = avcodec_alloc_context3(codec); + AVCodecContext* c = avcodec_alloc_context3(codec); if (!c) { throw std::runtime_error("avcodec_alloc_context3() failed"); } @@ -254,12 +270,15 @@ VideoWriter::VideoWriter( // c->codec_id = oc_->oformat->video_codec; c->codec_id = codec->id; - c->bit_rate = pop_value_int64(options.get(), "br", 4000000); // bits per second + c->bit_rate = + pop_value_int64(options.get(), "br", 4000000); // bits per second c->width = format.width; c->height = format.height; - this->impl->st->time_base = AVRational{1, 65535}; /* 65535 - is MPEG 4 limit */ + this->impl->st->time_base = + AVRational{1, 65535}; /* 65535 - is MPEG 4 limit */ c->time_base = this->impl->st->time_base; - c->framerate = AVRational{0, 1}; // AVRational{c->time_base.den, c->time_base.num}; + c->framerate = + AVRational{0, 1}; // AVRational{c->time_base.den, c->time_base.num}; //c->rc_buffer_size = 8339456; // 1 MiB c->gop_size = 12; // emit one intra frame every twelve frames at most c->pix_fmt = AV_PIX_FMT_YUV420P; @@ -277,9 +296,12 @@ VideoWriter::VideoWriter( options.reset(options_ptr); int const count = av_dict_count(options_ptr); if (count) { - const AVDictionaryEntry *e = NULL; + const AVDictionaryEntry* e = NULL; while ((e = av_dict_get(options_ptr, "", e, AV_DICT_IGNORE_SUFFIX))) { - log_callback((std::string("invalid key `") + e->key + "`").c_str(), VideoReader::LogLevel::ERROR, userdata); + log_callback( + (std::string("invalid key `") + e->key + "`").c_str(), + VideoReader::LogLevel::ERROR, + userdata); } throw std::runtime_error("invalid arguments. see logs for mare info."); } @@ -295,8 +317,10 @@ VideoWriter::VideoWriter( this->impl->frame->width = c->width; this->impl->frame->height = c->height; - if (const int ret = av_frame_get_buffer(this->impl->frame.get(), 32); ret < 0) { - throw std::runtime_error(format_error(ret, "av_frame_get_buffer() failed")); + if (const int ret = av_frame_get_buffer(this->impl->frame.get(), 32); + ret < 0) { + throw std::runtime_error( + format_error(ret, "av_frame_get_buffer() failed")); } } if (!this->impl->st->codecpar) { @@ -308,16 +332,19 @@ VideoWriter::VideoWriter( /* open the output file, if needed */ if (!(oc_->oformat->flags & AVFMT_NOFILE)) { - if (int const ret = avio_open(&oc_->pb, uri.c_str(), AVIO_FLAG_WRITE); ret < 0) { + if (int const ret = avio_open(&oc_->pb, uri.c_str(), AVIO_FLAG_WRITE); + ret < 0) { throw std::runtime_error(format_error(ret, "avio_open() failed")); } } /* Write the stream header, if any. */ if (int const ret = avformat_write_header(oc_, NULL); ret < 0) { - throw std::runtime_error(format_error(ret, "avformat_write_header() failed")); + throw std::runtime_error( + format_error(ret, "avformat_write_header() failed")); } if (realtime) { - this->impl->write_thread = std::thread(&VideoWriter::Impl::write, this->impl.get()); + this->impl->write_thread = + std::thread(&VideoWriter::Impl::write, this->impl.get()); } }