Open dwoja22 opened 8 months ago
Hi, I wasn't quite sure what you were trying to accomplish. If the purpose is to write encoded video to the pipe, can't you just give the pipe name to the encoder object? i.e.
encoder.output = FileOutput(name_of_pipe)
Or perhaps there's some reason that doesn't work, in which case please let me know.
Trying to synchronise what the background thread is doing with your application loop sounds more than a little hair-raising. I'm impressed you got it to work at all, but I'd be surprised if it proved to be reliable!
Hi,
Yes FileOutput
works.
On the other end of the pipe I have a golang app that consumes the data from the pipe and streams it to a browser via webrtc.
I must have messed up earlier, I initially tried to implement using FileOutput
but I got an error saying I have to provide BufferedIOBase
.
Should have been more careful reading the documentation in the code, it clearly states it accepts a path as well.
:type file: str or BufferedIOBase or Path, optional
Interestingly enough, both solutions work equally well and both have a very strange symptom.
The stream always starts with around 5-10 seconds of latency and around after 30s it stabilizes and the stream is real time as expected.
Might be an issue in the golang app, so I leave it at that.
Below the corrected and much shorter script. Issue is resolved.
from picamera2.encoders import H264Encoder
from picamera2.outputs import FileOutput
import sys
import os
import io
import signal
def signal_handler(sig, frame):
print('Received CTRL+C, exiting...')
picam2.stop_encoder()
picam2.stop()
sys.exit(0)
picam2=Picamera2()
sensor_modes = picam2.sensor_modes
#loop through the sensor modes and print them
print('Sensor Modes:')
for mode in sensor_modes:
print(mode)
raw_modes = picam2._get_raw_modes()
#loop through the raw modes and print them
print('Raw Modes:')
for mode in raw_modes:
print(mode)
config = picam2.create_video_configuration(main={'size': (640, 480), 'format':'XBGR8888'}, raw={'size': (1640,1232)})
picam2.configure(config)
fifo_path = os.path.abspath('pipe1')
encoder = H264Encoder(bitrate=2000000, repeat=True, iperiod=7, framerate=30)
buffer = io.BytesIO()
encoder.output = FileOutput(fifo_path)
print('starting stream')
picam2.start()
picam2.start_encoder(encoder)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
signal.pause()
Cool, glad it works! On the camera side, there should be no meaningful latency in sending stuff to your pipe so far as I know, so I guess you need to look at the buffering in the receiving end. To see what should be achievable, maybe check out a simple a example like https://github.com/raspberrypi/picamera2/blob/main/examples/mjpeg_server_2.py which I think runs with fairly low latency.
I wrote a script that accomplishes this using a circular buffer, unfortunately I'm having sync issues with reading the buffer and writing to the pipe.
My loop that handles the read/write blocks because I do not know how to sync these two operations.
I managed to solve it with a dirty hack by introducing a 10ms sleep inside the loop.
The question is how do I sync reading the buffer and writing to the pipe? Is using a circular buffer the correct approach?
Below the python script for context