4

I have a 1080p webcam connected to a Raspberry Pi 4B over USB. The camera supports the following formats:

Raw       :     yuyv422 :           YUYV 4:2:2
Compressed:       mjpeg :          Motion-JPEG

I would like to use ffmpeg to stream the footage to file, using hardware-accelerated encoding, so I'm attempting to use the h264_v4l2m2m codec.

Problem is, if I want 1080p to work at a decent frame rate, I need to use the mjpeg stream from the camera. But this makes the output codec complain.

Here's my command:

$ ffmpeg -y -f v4l2 -framerate 24 -video_size 1920x1080 -input_format mjpeg -i /dev/video0 -c:v h264_v4l2m2m -r 24 -b:v 2386092 lmao.mp4

And the relevant output:

...
[h264_v4l2m2m @ 0xf4c2d0] Using device /dev/video11
[h264_v4l2m2m @ 0xf4c2d0] driver 'bcm2835-codec' on card 'bcm2835-codec-encode' in mplane mode
[h264_v4l2m2m @ 0xf4c2d0] requesting formats: output=YU12 capture=H264
[h264_v4l2m2m @ 0xf4c2d0] Encoder requires yuv420p pixel format.
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!

What's the deal?! This seems very limiting.

Does anyone know of alternative solutions? I've tried using the h264_omx codec, but at least on stock Raspberry Pi OS, it just complains about missing libraries, so I imagine I'd have to compile ffmpeg myself.

I'm on Raspberry Pi OS Bullseye, using ffmpeg version 4.3.4-0+deb11u1+rpt1.

3 Answers 3

0

I'm trying to achieve the same result without success, for now, but in your case the missing parameter to avoid ffmpeg error is -pix_fmt yuv420p, so your command should be:

$ ffmpeg -y -f v4l2 -framerate 24 -video_size 1920x1080 -input_format mjpeg -i /dev/video0 -c:v h264_v4l2m2m -pix_fmt yuv420p -r 24 -b:v 2386092 lmao.mp4
1
  • FWIW, I ended up streaming raw frames from the camera and software-encoding them to H264. It's stable with two cameras simultaneously, but it's right at the limit of the USB bandwidth and I had to compromise on FPS and resolution. Aug 3, 2022 at 12:21
0

You need convert to yuv420p by add filter

ffmpeg -f v4l2 -framerate 30 -video_size hd1080 -input_format mjpeg -i /dev/video0 -vf "format=yuv420p" -c:v h264_v4l2m2m -b:v 6000k -t 20  output.mp4
0

And I suggest use libopenh264 with high profile.

ffmpeg -framerate 25 -i inVideo.yuvj422p -profile:v high -c:v libopenh264 -b:v 4000000 -allow_skip_frames 1 -maxrate 7000000 outVideo.mkv

Also you can measure how long encoding works using

time ffmpeg -framerate 25 -i inVideo.yuvj422p -profile:v high -c:v libopenh264 -b:v 4000000 -allow_skip_frames 1 -maxrate 7000000 outVideo.mkv

If your ffmpeg version doesn't build with libopenh264 then you should build with libopenh264, for example

cd $HOME
git clone https://git.ffmpeg.org/ffmpeg.git
mkdir ffmpeg_build ffmpeg_build_artifacts
cd ffmpeg
PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure \
  --prefix="$HOME/ffmpeg_build/" \
  --pkg-config-flags="--static" \
  --extra-cflags="-I$HOME/ffmpeg_build/include" \
  --extra-ldflags="-L$HOME/ffmpeg_build/lib" \
  --extra-libs="-lpthread -lm" \
  --ld="g++" \
  --bindir="$HOME/ffmpeg_build_artifacts" \
  --enable-gpl \
  --enable-libopenh264
make -j16
make install

In this case use full path to ffmpeg, for example

$HOME/ffmpeg_build_artifacts/ffmpeg -framerate 25 -i inVideo.yuvj422p -profile:v high -c:v libopenh264 -b:v 4000000 -allow_skip_frames 1 -maxrate 7000000 outVideo.mkv

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.