bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.39k stars 1.56k forks source link

Raspberry Pi 5 with modern video stack and PiCamera #2221

Open thorsten-l opened 2 months ago

thorsten-l commented 2 months ago

After hours and hours of testing the following code is my working result, using a Raspberry Pi 5 with the modern video stack and a PiCamera.

My question: Is there a more elegant way dealing with the RPi 5 + PiCamera?

package l9g.javacv.demo2;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static org.bytedeco.ffmpeg.global.avutil.AV_PIX_FMT_BGR24;
import org.bytedeco.javacv.*;

/**
 *
 * @author Thorsten Ludewig (t.ludewig@gmail.com)
 */
public class JavacvDemo2
{
  private final static String VIDEO_STREAM_URL = "udp://0.0.0.0:9595";

  private final static String VIDEO_CODEC = "mjpeg";

  private final static double VIDEO_FRAMERATE = 15.0;

  private final static int VIDEO_WIDTH = 640;

  private final static int VIDEO_HEIGHT = 480;

  private static Process libcameraProcess;

  public static void main(String[] args) throws Exception
  {
    ProcessBuilder builder = new ProcessBuilder();
    builder.inheritIO();
    builder.command(
      "/usr/bin/libcamera-vid", "-n", "-t", "0",
      "--framerate", Double.toString(VIDEO_FRAMERATE),
      "--width", Integer.toString(VIDEO_WIDTH),
      "--height", Integer.toString(VIDEO_HEIGHT),
      "--codec", VIDEO_CODEC, "-o", VIDEO_STREAM_URL
    );
    libcameraProcess = builder.start();

    System.out.println("libcamera-vid started waiting 3s");
    Thread.sleep(3000);
    System.out.println("setup ffmpeg log callback");

    FFmpegLogCallback.set();
    FFmpegLogCallback.setLevel(0);

    System.out.println("initialize ffmpeg grabber");
    FrameGrabber grabber = new FFmpegFrameGrabber(VIDEO_STREAM_URL);
    grabber.setFrameNumber(1);
    grabber.setFrameRate(VIDEO_FRAMERATE);
    grabber.setFormat(VIDEO_CODEC);
    grabber.setPixelFormat(AV_PIX_FMT_BGR24);

    System.out.println("starting ffmpeg grabber");
    grabber.start();

    System.out.println("setup canvas");
    CanvasFrame frame = new CanvasFrame("Raspberry Pi Camera");

    frame.addWindowListener(new WindowAdapter()
    {
      @Override
      public void windowClosing(WindowEvent e)
      {
        System.out.println("exit application");
        libcameraProcess.destroy();
        System.exit(0);
      }
    });

    frame.setSize(VIDEO_WIDTH, VIDEO_HEIGHT);
    frame.setVisible(true);

    while (true)
    {
      var image = grabber.grab();
      if (image != null)
      {
        frame.showImage(image);
      }
    }
  }
}
saudet commented 2 months ago

We can probably use video4linux2? https://stackoverflow.com/questions/48035955/raspberry-pi-ffmpeg-video4linux2-v4l2-mmap-no-such-device

thorsten-l commented 2 months ago

We can probably use video4linux2? https://stackoverflow.com/questions/48035955/raspberry-pi-ffmpeg-video4linux2-v4l2-mmap-no-such-device

This post is 6 years old, i will check it, but all "old" code/solutions i've tested yet, had not worked with the modern video stack of Raspberry Pi OS (bookworm)

saudet commented 2 months ago

This? https://motion-project.github.io/motion_config.html#basic_setup_picam

thorsten-l commented 2 months ago

btw. it is possible to switch back to the legacy camera stack

https://forums.raspberrypi.com/viewtopic.php?t=323390

this works on my raspi 4 but not on my raspi 5.