From 9ae39f85ae6bee9761c36b9b5b80d675bc1fa369 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Tue, 30 Jan 2024 09:22:47 +0000 Subject: [PATCH] encoder: output: Fix bug where network output was not routed through libav on Pi 5 If the --codec libav option is not set, and a network stream output is specified, the NetOutput class will be initialised together with libav and fail to work on a Pi 5. Fix this by ensuring if we are going to use libav, do not initialise the NetOutput class, and allow libav to handle the network output. Signed-off-by: Naushir Patuck --- apps/rpicam_raw.cpp | 2 ++ encoder/encoder.cpp | 26 +++++++++++--------------- output/output.cpp | 4 +++- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/rpicam_raw.cpp b/apps/rpicam_raw.cpp index 9607a09e..3eade325 100644 --- a/apps/rpicam_raw.cpp +++ b/apps/rpicam_raw.cpp @@ -79,6 +79,8 @@ int main(int argc, char *argv[]) VideoOptions *options = app.GetOptions(); if (options->Parse(argc, argv)) { + // Disable any codec (h.264/libav) based operations. + options->codec = "yuv420"; options->denoise = "cdn_off"; options->nopreview = true; if (options->verbose >= 2) diff --git a/encoder/encoder.cpp b/encoder/encoder.cpp index 486636a2..99a161a2 100644 --- a/encoder/encoder.cpp +++ b/encoder/encoder.cpp @@ -21,7 +21,7 @@ #include "libav_encoder.hpp" #endif -Encoder *h264_codec_select(VideoOptions *options, const StreamInfo &info) +bool bcm2835_encoder_available() { const char hw_codec[] = "/dev/video11"; struct v4l2_capability caps; @@ -32,8 +32,15 @@ Encoder *h264_codec_select(VideoOptions *options, const StreamInfo &info) int ret = ioctl(fd, VIDIOC_QUERYCAP, &caps); close(fd); if (!ret && !strncmp((char *)caps.card, "bcm2835-codec-encode", sizeof(caps.card))) - return new H264Encoder(options, info); + return true; } + return false; +} + +static Encoder *h264_codec_select(VideoOptions *options, const StreamInfo &info) +{ + if (bcm2835_encoder_available()) + return new H264Encoder(options, info); #if LIBAV_PRESENT // No hardware codec available, use x264 through libav. @@ -45,26 +52,15 @@ Encoder *h264_codec_select(VideoOptions *options, const StreamInfo &info) } #if LIBAV_PRESENT -Encoder *libav_codec_select(VideoOptions *options, const StreamInfo &info) +static Encoder *libav_codec_select(VideoOptions *options, const StreamInfo &info) { if (options->libav_video_codec == "h264_v4l2m2m") { - const char hw_codec[] = "/dev/video11"; - struct v4l2_capability caps; - memset(&caps, 0, sizeof(caps)); - int fd = open(hw_codec, O_RDWR, 0); - if (fd) - { - int ret = ioctl(fd, VIDIOC_QUERYCAP, &caps); - close(fd); - if (!ret && !strncmp((char *)caps.card, "bcm2835-codec-encode", sizeof(caps.card))) + if (bcm2835_encoder_available()) return new LibAvEncoder(options, info); - } - // No h264_v4l2m2m libav codec available, use libx264 if nothing else is provided. options->libav_video_codec = "libx264"; } - return new LibAvEncoder(options, info); } #endif diff --git a/output/output.cpp b/output/output.cpp index de344788..93d31d65 100644 --- a/output/output.cpp +++ b/output/output.cpp @@ -13,6 +13,8 @@ #include "net_output.hpp" #include "output.hpp" +extern bool bcm2835_encoder_available(); + Output::Output(VideoOptions const *options) : options_(options), fp_timestamps_(nullptr), state_(WAITING_KEYFRAME), time_offset_(0), last_timestamp_(0), buf_metadata_(std::cout.rdbuf()), of_metadata_() @@ -101,7 +103,7 @@ void Output::outputBuffer(void *mem, size_t size, int64_t timestamp_us, uint32_t Output *Output::Create(VideoOptions const *options) { - if (options->codec == "libav") + if (options->codec == "libav" || (options->codec == "h264" && !bcm2835_encoder_available())) return new Output(options); if (strncmp(options->output.c_str(), "udp://", 6) == 0 || strncmp(options->output.c_str(), "tcp://", 6) == 0)