summaryrefslogtreecommitdiff
path: root/include/uvcgadget
diff options
context:
space:
mode:
Diffstat (limited to 'include/uvcgadget')
-rw-r--r--include/uvcgadget/meson.build1
-rw-r--r--include/uvcgadget/mjpeg_encoder.hpp89
2 files changed, 90 insertions, 0 deletions
diff --git a/include/uvcgadget/meson.build b/include/uvcgadget/meson.build
index a9e4384..af795c4 100644
--- a/include/uvcgadget/meson.build
+++ b/include/uvcgadget/meson.build
@@ -9,6 +9,7 @@ uvcgadget_public_headers = files([
'timer.h',
'v4l2-source.h',
'video-source.h',
+ 'mjpeg_encoder.hpp',
])
diff --git a/include/uvcgadget/mjpeg_encoder.hpp b/include/uvcgadget/mjpeg_encoder.hpp
new file mode 100644
index 0000000..a3e92fc
--- /dev/null
+++ b/include/uvcgadget/mjpeg_encoder.hpp
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * mjpeg_encoder.hpp - mjpeg video encoder.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+#include <functional>
+
+struct jpeg_compress_struct;
+typedef std::function<void(void *, size_t, int64_t, unsigned int)> OutputReadyCallback;
+
+struct StreamInfo
+{
+ StreamInfo() : width(0), height(0), stride(0) {}
+ unsigned int width;
+ unsigned int height;
+ unsigned int stride;
+ libcamera::PixelFormat pixel_format;
+ std::optional<libcamera::ColorSpace> colour_space;
+};
+
+class MjpegEncoder
+{
+public:
+ MjpegEncoder();
+ ~MjpegEncoder();
+
+ void EncodeBuffer(void *mem, void *dest, unsigned int size,
+ StreamInfo const &info, int64_t timestamp_us,
+ unsigned int cookie);
+ StreamInfo getStreamInfo(libcamera::Stream *stream);
+ void SetOutputReadyCallback(OutputReadyCallback callback) { output_ready_callback_ = callback; }
+
+private:
+ static const int NUM_ENC_THREADS = 4;
+
+ void encodeThread(int num);
+
+ /*
+ * Handle the output buffers in another thread so as not to block the
+ * encoders. The application can take its time, after which we return
+ * this buffer to the encoder for re-use.
+ */
+ void outputThread();
+
+ bool abortEncode_;
+ bool abortOutput_;
+ uint64_t index_;
+
+ struct EncodeItem
+ {
+ void *mem;
+ void *dest;
+ unsigned int size;
+ StreamInfo info;
+ int64_t timestamp_us;
+ uint64_t index;
+ unsigned int cookie;
+ };
+
+ std::queue<EncodeItem> encode_queue_;
+ std::mutex encode_mutex_;
+ std::condition_variable encode_cond_var_;
+ std::thread encode_thread_[NUM_ENC_THREADS];
+ void encodeJPEG(struct jpeg_compress_struct &cinfo, EncodeItem &item,
+ uint8_t *&encoded_buffer, size_t &buffer_len);
+
+ struct OutputItem
+ {
+ void *mem;
+ size_t bytes_used;
+ int64_t timestamp_us;
+ uint64_t index;
+ unsigned int cookie;
+ };
+
+ std::queue<OutputItem> output_queue_[NUM_ENC_THREADS];
+ std::mutex output_mutex_;
+ std::condition_variable output_cond_var_;
+ std::thread output_thread_;
+ OutputReadyCallback output_ready_callback_ ;
+};