From 25321ed3524e00b4d89b05528df5c7ad50cf22b0 Mon Sep 17 00:00:00 2001 From: Richard Franks Date: Wed, 4 Oct 2023 11:41:16 +0100 Subject: [PATCH] Updated libcamera (#67) * Pointers are hard * Two errors: - Neopixelpath should use _getValue - Cast output to NdiOutput* before trying to access isPreview and isProgram * Casting issue * . * Moved neopixel code * . * . * Added artifacts to build * More neopixel testing * Workflow * Fixed wrong characters * . * . * . * . * . * Well, that's broken then * Reverted to 3.0.2 * Updated libcamera-apps headers * Removed argv & argc, fixed raspindi.conf.default * Updated libcamera --- include/core/libcamera_app.hpp | 21 ++++++++++++++++++++- include/core/libcamera_encoder.hpp | 2 ++ include/core/video_options.hpp | 7 +++++++ include/encoder/encoder.hpp | 2 +- include/encoder/libav_encoder.hpp | 7 +++++++ include/image/image.hpp | 4 ++-- src/CMakeLists.txt | 4 ++-- src/main.cpp | 2 +- src/ndi_output.cpp | 27 ++++++++++++--------------- 9 files changed, 54 insertions(+), 22 deletions(-) diff --git a/include/core/libcamera_app.hpp b/include/core/libcamera_app.hpp index 2abac7a..20eb7f5 100644 --- a/include/core/libcamera_app.hpp +++ b/include/core/libcamera_app.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ class LibcameraApp using CameraConfiguration = libcamera::CameraConfiguration; using FrameBufferAllocator = libcamera::FrameBufferAllocator; using StreamRole = libcamera::StreamRole; - using StreamRoles = libcamera::StreamRoles; + using StreamRoles = std::vector; using PixelFormat = libcamera::PixelFormat; using StreamConfiguration = libcamera::StreamConfiguration; using BufferMap = Request::BufferMap; @@ -95,6 +96,7 @@ class LibcameraApp Options *GetOptions() const { return options_.get(); } std::string const &CameraId() const; + std::string CameraModel() const; void OpenCamera(); void CloseCamera(); @@ -117,6 +119,12 @@ class LibcameraApp Stream *LoresStream(StreamInfo *info = nullptr) const; Stream *GetMainStream() const; + const CameraManager *GetCameraManager() const; + std::vector> GetCameras() + { + return GetCameras(camera_manager_.get()); + } + std::vector> Mmap(FrameBuffer *buffer) const; void ShowPreview(CompletedRequestPtr &completed_request, Stream *stream); @@ -127,6 +135,17 @@ class LibcameraApp static unsigned int verbosity; static unsigned int GetVerbosity() { return verbosity; } + static std::vector> GetCameras(const CameraManager *cm) + { + std::vector> cameras = cm->cameras(); + // Do not show USB webcams as these are not supported in libcamera-apps! + auto rem = std::remove_if(cameras.begin(), cameras.end(), + [](auto &cam) { return cam->id().find("/usb") != std::string::npos; }); + cameras.erase(rem, cameras.end()); + std::sort(cameras.begin(), cameras.end(), [](auto l, auto r) { return l->id() > r->id(); }); + return cameras; + } + protected: std::unique_ptr options_; diff --git a/include/core/libcamera_encoder.hpp b/include/core/libcamera_encoder.hpp index f56d456..892b153 100644 --- a/include/core/libcamera_encoder.hpp +++ b/include/core/libcamera_encoder.hpp @@ -5,6 +5,8 @@ * libcamera_encoder.cpp - libcamera video encoding class. */ +#pragma once + #include "core/libcamera_app.hpp" #include "core/stream_info.hpp" #include "core/video_options.hpp" diff --git a/include/core/video_options.hpp b/include/core/video_options.hpp index 395d0a8..8eabcb8 100644 --- a/include/core/video_options.hpp +++ b/include/core/video_options.hpp @@ -59,6 +59,9 @@ struct VideoOptions : public Options ("frames", value(&frames)->default_value(0), "Run for the exact number of frames specified. This will override any timeout set.") #if LIBAV_PRESENT + ("libav-video-codec", value(&libav_video_codec)->default_value("h264_v4l2m2m"), + "Sets the libav video codec to use. " + "To list available codecs, run the \"ffmpeg -codecs\" command.") ("libav-format", value(&libav_format)->default_value(""), "Sets the libav encoder output format to use. " "Leave blank to try and deduce this from the filename.\n" @@ -76,6 +79,8 @@ struct VideoOptions : public Options "\"pactl list | grep -A2 'Source #' | grep 'Name: '\"\n" "or for alsa, use the following command:\n" "\"arecord -L\"") + ("audio-channels", value(&audio_channels)->default_value(0), + "Number of channels to use for recording audio. Set to 0 to use default value.") ("audio-bitrate", value(&audio_bitrate)->default_value(32768), "Set the audio bitrate for encoding, in bits/second.") ("audio-samplerate", value(&audio_samplerate)->default_value(0), @@ -94,11 +99,13 @@ struct VideoOptions : public Options unsigned int intra; bool inline_headers; std::string codec; + std::string libav_video_codec; std::string libav_format; bool libav_audio; std::string audio_codec; std::string audio_device; std::string audio_source; + uint32_t audio_channels; uint32_t audio_bitrate; uint32_t audio_samplerate; int32_t av_sync; diff --git a/include/encoder/encoder.hpp b/include/encoder/encoder.hpp index 192f09c..fda6e02 100644 --- a/include/encoder/encoder.hpp +++ b/include/encoder/encoder.hpp @@ -18,7 +18,7 @@ typedef std::function OutputReadyCallback; class Encoder { public: - static Encoder *Create(VideoOptions const *options, StreamInfo const &info); + static Encoder *Create(VideoOptions *options, StreamInfo const &info); Encoder(VideoOptions const *options) : options_(options) {} virtual ~Encoder() {} diff --git a/include/encoder/libav_encoder.hpp b/include/encoder/libav_encoder.hpp index db1694d..becb3fe 100644 --- a/include/encoder/libav_encoder.hpp +++ b/include/encoder/libav_encoder.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,7 @@ extern "C" #include "libavutil/audio_fifo.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_drm.h" +#include "libavutil/imgutils.h" #include "libavutil/timestamp.h" #include "libavutil/version.h" #include "libswresample/swresample.h" @@ -48,6 +50,8 @@ class LibAvEncoder : public Encoder void videoThread(); void audioThread(); + static void releaseBuffer(void *opaque, uint8_t *data); + std::atomic output_ready_; bool abort_video_; bool abort_audio_; @@ -67,4 +71,7 @@ class LibAvEncoder : public Encoder AVStream *stream_[3]; AVFormatContext *in_fmt_ctx_; AVFormatContext *out_fmt_ctx_; + + std::mutex drm_queue_lock_; + std::queue> drm_frame_queue_; }; diff --git a/include/image/image.hpp b/include/image/image.hpp index cc24d19..bef14fb 100644 --- a/include/image/image.hpp +++ b/include/image/image.hpp @@ -19,7 +19,7 @@ struct StillOptions; // In jpeg.cpp: void jpeg_save(std::vector> const &mem, StreamInfo const &info, - libcamera::ControlList const &metadata, std::string const &filename, std::string const &cam_name, + libcamera::ControlList const &metadata, std::string const &filename, std::string const &cam_model, StillOptions const *options); // In yuv.cpp: @@ -28,7 +28,7 @@ void yuv_save(std::vector> const &mem, StreamInfo const // In dng.cpp: void dng_save(std::vector> const &mem, StreamInfo const &info, - libcamera::ControlList const &metadata, std::string const &filename, std::string const &cam_name, + libcamera::ControlList const &metadata, std::string const &filename, std::string const &cam_model, StillOptions const *options); // In png.cpp: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8b481b5..902a61a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,8 +16,8 @@ target_link_libraries(raspindi PRIVATE # ndi # dl config++ - encoders - outputs +# encoders +# outputs ndioutput camera_app boost_program_options diff --git a/src/main.cpp b/src/main.cpp index cc52398..7b5209c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -186,4 +186,4 @@ int main(int argc, char *argv[]) return -1; } return 0; -} +} \ No newline at end of file diff --git a/src/ndi_output.cpp b/src/ndi_output.cpp index cf07682..c95c51d 100644 --- a/src/ndi_output.cpp +++ b/src/ndi_output.cpp @@ -34,32 +34,29 @@ void NdiOutput::outputBuffer(void *mem, size_t size, int64_t timestamp_us, uint3 { this->NDI_video_frame.p_data = (uint8_t*)mem; NDIlib_send_send_video_v2(this->pNDI_send, &this->NDI_video_frame); - NDIlib_tally_t* NDI_tally; - NDIlib_send_get_tally(this->pNDI_send, NDI_tally, 0); + NDIlib_tally_t NDI_tally; + NDIlib_send_get_tally(this->pNDI_send, &NDI_tally, 0); + this->program = NDI_tally.on_program; + this->preview = NDI_tally.on_preview; char pixelStatus; std::ofstream neopixel; - std::cout << "PGM: " << NDI_tally->on_program << " PVW: " << NDI_tally->on_preview << std::endl; - - if(NDI_tally->on_program) + if(this->isProgram()) { - neopixel.open(neopixelpath); - neopixel << "L"; - neopixel.close(); + pixelStatus = 'L'; } - else if (NDI_tally->on_preview) + else if (this->isPreview()) { - neopixel.open(neopixelpath); - neopixel << "P"; - neopixel.close(); + pixelStatus = 'P'; } else { - neopixel.open(neopixelpath); - neopixel << "N"; - neopixel.close(); + pixelStatus = 'N'; } + neopixel.open(neopixelpath); + neopixel << pixelStatus; + neopixel.close(); }