Camera-streamer - rotating 90 degree, how?

Camera model

ov5647 with nightvision

pi@octopi:~ $ /usr/bin/libcamera-hello --list-cameras
Available cameras
-----------------
0 : ov5647 [2592x1944] (/base/soc/i2c0mux/i2c@1/ov5647@36)
    Modes: 'SGBRG10_CSI2P' : 640x480 [30.00 fps - (0, 0)/0x0 crop]
                             1296x972 [30.00 fps - (0, 0)/0x0 crop]
                             1920x1080 [30.00 fps - (0, 0)/0x0 crop]
                             2592x1944 [30.00 fps - (0, 0)/0x0 crop]

What is the problem?

  • I have a portrait setup on my printer, and I'm trying to rotate the image 90º degrees.
  • I know it is possible to do it on the OctoPrint's Configuration Webcam settings, but I want the camera to be streamed using a 90º degrees rotation right from the start so that it is shown correctly on other clients such as HomeAssistant, mobile phone, etc...
  • I'm using the new camera-streamer implementation

What did you already try to solve it?

I've done an extensive search on this matter and found no ways of streaming the camera using a 90º degree rotation...

Have you tried running in safe mode?

No

Did running in safe mode solve the problem?

No

Systeminfo Bundle

octoprint-systeminfo-20230825173247.zip (592.4 KB)

Additional information about your setup

  • Prusa Mini+
  • OctoPrint 1.9.2
  • Python 3.9.2
  • OctoPi* 1.0.0 (build 2023.07.20.144556)

OctoPrint version, OctoPi version, printer, firmware, browser, operating system, ... as much data as possible

Hi @calex,

Can you supply a copy of your current libcamera.conf from /boot/camera-streamer/?

Sure,
I've already customized some settings, but was unable to find a proper option for rotation...

$ pi@octopi:~ $ cat /boot/camera-streamer/libcamera.conf

### Options for libcamera based cameras (PiCam, Arducam, ...)

# The port on which the webcam server for the camera should listen on. If you have only
# one camera, leave at 8080. If you have more, change to 8081, 8082, etc. The primary
# camera will be considered the one with 8080.
PORT=8080

# The resolution to request on the camera sensor. Defaults to 1280x720.
WIDTH=1024
HEIGHT=1024

# The height to use for the video stream. Defaults to 720.
VIDEO_HEIGHT=720

# The height to use for the snapshots. Defaults to 1080.
SNAPSHOT_HEIGHT=1080

# The framerate to set on the camera. Defaults to 15fps.
FRAMERATE=15

# Additional options. By default enables continuous auto focus (if possible).
OPTIONS='--camera-options="AfMode=2" --camera-options="AfRange=2" --camera-options="saturation=0" --camera-options=AeConstraintMode=1 --camera-options=ExposureValue=-0.8'

Thanks, @calex. I forgot. Can you also post the output of the /option endpoint?

http://octopi.local/webcam/option

This includes the reported capabilities of your camera to libcamera.

1 Like

Hmm that does not return anything.

Here's the curl command:

$ curl http://octopi.kitt/webcam/option -v
*   Trying 192.168.3.234:80...
* TCP_NODELAY set
* Connected to octopi.kitt (192.168.3.234) port 80 (#0)
> GET /webcam/option HTTP/1.1
> Host: octopi.kitt
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< content-type: text/plain
< connection: close
<
No key or value passed.
* Closing connection 0

Simply enter that url:

into your browser without the -v and you should get back a page similar to this:

No options passed.

Set: /option?name=value

CAMERA Properties:
- property: SensorSensitivity (00000009, type=5): 1.000000
- property: ScalerCropMaximum (00000008, type=7): (0, 0)/2592x1944
- property: ColorFilterArrangement (0000000a, type=3): 2
- property: PixelArrayActiveAreas (00000007, type=7): [ (16, 6)/2592x1944 ]
- property: PixelArraySize (00000005, type=8): 2592x1944
- property: Rotation (00000002, type=3): 0
- property: Location (00000001, type=3): 2
- property: UnitCellSize (00000004, type=8): 1400x1400
- property: Model (00000003, type=6): ov5647

CAMERA Options:
- available option: AeConstraintMode (00000004, type=3): [0..3]
- available option: Saturation (00000011, type=5): [0.000000..32.000000]
- available option: AeExposureMode (00000005, type=3): [0..3]
- available option: AwbMode (0000000d, type=3): [0..7]
- available option: Brightness (00000009, type=5): [-1.000000..1.000000]
- available option: AeEnable (00000001, type=1): [false..true]
- available option: AnalogueGain (00000008, type=5): [1.000000..63.937500]
- available option: ExposureTime (00000007, type=3): [92..760636]
- available option: ScalerCrop (00000016, type=7): [(0, 0)/128x128..(0, 0)/2592x1944]
- available option: AeMeteringMode (00000003, type=3): [0..3]
- available option: AwbEnable (0000000c, type=1): [false..true]
- available option: ColourCorrectionMatrix (00000015, type=5): [-16.000000..16.000000]
- available option: NoiseReductionMode (00000027, type=3): [0..4]
- available option: ColourGains (0000000f, type=5): [0.000000..32.000000]
- available option: ExposureValue (00000006, type=5): [-8.000000..8.000000]
- available option: Sharpness (00000013, type=5): [0.000000..16.000000]
- available option: FrameDurationLimits (00000019, type=4): [23123..760729]
- available option: Contrast (0000000a, type=5): [0.000000..32.000000]

SNAPSHOT Options:
- available option: compressionquality (009d0903, type=1): [1..100]

VIDEO Options:
- available option: videobframes (009909ca, type=1): [0..0]
- available option: videogopsize (009909cb, type=1): [0..2147483647]
- available option: videobitratemode (009909ce, type=3): [0..1]
		0: Variable Bitrate
		1: Constant Bitrate
- available option: videobitrate (009909cf, type=1): [25000..25000000]
- available option: sequenceheadermode (009909d8, type=3): [0..1]
		0: Separate Buffer
		1: Joined With 1st Frame
- available option: repeatsequenceheader (009909e2, type=2): [0..1]
- available option: forcekeyframe (009909e5, type=4): button
- available option: h264minimumqpvalue (00990a61, type=1): [0..51]
- available option: h264maximumqpvalue (00990a62, type=1): [0..51]
- available option: h264iframeperiod (00990a66, type=1): [0..2147483647]
- available option: h264level (00990a67, type=3): [0..15]
		0: 1
		1: 1b
		2: 1.1
		3: 1.2
		4: 1.3
		5: 2
		6: 2.1
		7: 2.2
		8: 3
		9: 3.1
		10: 3.2
		11: 4
		12: 4.1
		13: 4.2
		14: 5
		15: 5.1
- available option: h264profile (00990a6b, type=3): [0..4]
		0: Baseline
		1: Constrained Baseline
		2: Main
		4: High

Many of the OPTIONS for the camera can be derived from this webpage. Also, if you haven't already, check out the Camera Streamer Configuration Guide.

Already tried, hence the curl command...

image

Definitely not the expected response. You are running a later version of the camera-streamer from OctoPi-UpToDate than I am. Perhaps its' behavior has changed. What do you get from?:

http://octopi.kitt/webcam/

Pay attention to the trailing backslash in this url. This should display a page where you can test all the camera-streamer endpoints.

This is what I get when browsing to that url (I already knew this page).

Looks like the /option endpoint has been replaced with the /control endpoint.

What do you get when you click the /control endpoint on that webpage?

I get something like this:

I've already spent a bunch time here configuring webcam settings, but unfortunately I was not able to find anything related to Rotation...

Definitely significant differences between your build and my older one. Used the camera-streamer build of OctoPi extensively when it first appeared in the Pi Imager, enough so that I was convinced of its' potential & am planning to switch to it full time when it achieves Release status. I run the stable build of Octopi 1.0.0/Octoprint 1.92 with mjpg-streamer & webcamd as my daily driver. I was sharing with you from memory, didn't intend to mislead. I'm putting a fresh camera-streamer build on my to-do list for this week.

FWIW, we share the same camera, ov5647-based Pi NoIR camera. The list of options I posted above is from my camera on the original camera-streamer. I'm guessing they'll still work as options in libcamera.conf on your later build, but it 'll be a few days before I can confirm that.

I understand.
Looking at your options, I don't see a rotation option either...

CAMERA Properties:
...
- property: Rotation (00000002, type=3): 0
...

Don't know the range (i.e 0 to 3 or 0 to 360) and the previously mentioned guide no longer seems to include the application of CAMERA Properties as well as CAMERA Options in libcamera.conf. Never tested it. It did respond to the properties that control flipping the image:

OPTIONS='--camera-hflip=1  --camera-vflip=1'

Never tried

OPTIONS='--camera-rotation=(?)'

Hmm I really don't know the meaning of that property...
I tried your suggestion, but camera-streamer doesn't like that option...

pi@octopi:~ $ /usr/bin/camera-streamer --http-port=8080 --camera-type=libcamera --camera-path=/base/soc/i2c0mux/i2c@1/ov5647@36 --camera-format=YUYV --camera-width=1280 --camera-height=960 --camera-fps=15 --camera-nbufs=2 --camera-options=AfMode=2 --camera-options=AfRange=2 --camera-options=saturation=0 --camera-options=AeConstraintMode=1 --camera-options=ExposureValue=-0.8 --camera-rotation=1

util/opts/opts.c: ?: Parsing '--camera-rotation=1' returned '-22'.

Is this something that still needs to be supported by camera-streamer / libcamera ?
I searched other forums, and I found lots of instructions to apply rotation (among other settings), but only for the legacy camera (aka Raspberry Pi Camera raspicam)...

Well, like it says on the /control endpoint page:

EXPERIMENTAL Some options might crash the process :upside_down_face:

I can't see any reason to remove support for what I consider to be a basic feature (rotation). It's always been present to provide flexibility in camera mounting. I'll do a fresh camera-streamer build this week and see what I can find out. In the meantime, the Camera Streamer Configuration Guide is now out-of-sync with the latest camera-streamer build.

Edit: Was just browsing through the namespace documentation for libcamera and this seems to show that libcamera supports the transforms necessary to effect any common rotation. Guess it's a matter of getting access to these transforms via camera-streamer to get your 90 degree rotation.

Sounds great!
Now what do we need to do in order to get the developers attention?
I believe that this is a development feature for the camera-streamer project, right?

Agreed. It's worth getting a feasibility assessment on the possibility of adding it.

You should post it as an issue on the camera-streamer github page. Reference this topic for background, if need be.

Great, opened issue here.