New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MJPEG recording locks up camera #47
Comments
This is looking more like a firmware issue - in the lockup cases the encoder callbacks just stop and MMAL hangs when disabling the port ... weird! |
Reasonably confident this is a firmware issue now - when recording at 1080p the encoder callback gets called for about a dozen frames and then suddenly doesn't get called anymore. Attempts to disable the port don't return and a reboot is required to recover. Marking as an upstream issue for now. |
This looks awfully similar to #62... |
This shouldn't be closed as it's still an issue. Need to track down the exact resolution it occurs at and report it upstream. After updating the tests for #65 it appears even 720p locks up the MJPEG encoder. |
Same issue while trying to do a still image capture when in video capture mode (works like perfect in h264): def captureToFile(camera, file):
#camera.resolution = (2592, 1944)
camera.capture(file,format="jpeg", use_video_port=True)
def streamVideo(camera, connection):
print "start recording"
camera.resolution = (640, 480)
camera.framerate = 25
camera.start_recording(connection, format='mjpeg')
#
#camera.stop_recording()
#time.sleep(2)
print "recording stopped"
if __name__ == "__main__":
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen(0)
try:
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.framerate = 24
# Start a preview and let the camera warm up for 2 seconds
print "preview"
#camera.start_preview()
time.sleep(2)
# Accept a single connection and make a file-like object out of it
connection = server_socket.accept()[0].makefile('wb')
print "connection made"
captureStream = io.BytesIO()
streamVideo(camera, connection)
for i in range(0, 3):
camera.wait_recording(8)
t0 = time.clock()
filename = "sample-%d_%s.jpeg" % (i, time.strftime("%H:%M:%S"))
print "filename: {}", filename
captureToFile(camera, captureStream)
t1 = time.clock()
diff = t1 - t0
print ("time end of streaming => end of capture = %s" % (str(diff)))
except KeyboardInterrupt:
# quit
sys.exit()
finally:
connection.close()
server_socket.close() |
A simpler code to reproduce the issue: import picamera
with picamera.PiCamera() as camera:
camera.resolution = (800, 600)
camera.start_preview()
camera.start_recording('foo.mjpeg', format='mjpeg')
camera.wait_recording(10)
camera.capture('foo.jpg', use_video_port=True)
print " recorded foo.jpg"
camera.wait_recording(10)
camera.stop_recording()
print "stopped recording" |
The script posted by @rsacchettini above produces the following output in
After this message is produced, killing the python process leaves the camera operational and a reboot is required to restore functionality. Interestingly, reducing the resolution to 640x480 permits the script to work. MJPEG generally seems to have issues when the resolution is beyond VGA. Currently all picamera tests with MJPEG are xfailed where the vertical resolution exceeds 480; however all tests at VGA res or below succeed (including capture-while-recording, split-recording, etc). Whether the issue is the actual resolution or the bandwidth required by high resolutions, I'm not sure. |
For what it's worth, I am having no problems recording 1080p MJPEG through the v4l2 interface (using python-v4l2capture) with the Pi Camera, although I am having the same problems described here with Picamera. I'm not sure if this is helpful or not, because I am not sure if they rely on the firmware in the same way. Also, it might be worth noting that I did have to make sure that only minimal buffers were allocated by v4l2. Allocating more than 2 frames of buffer at 1080 resolution caused memory issues with my "original" model B Pi. I'm not sure if the allocation of buffers is within the control of Picamera? Any news from upstream? I'm not sure where to look for a potential upstream issue. If anyone happens to be aware of a firmware/picamera version combination where this works, I would be grateful to know! |
Interesting - I'm beginning to wonder if this has something to do with picamera's usage of a splitter after reading 6by9's fascinating comments in this thread. Stripping out the splitter isn't an option (too much functionality relies on it) but there's a possibility I might be able to make it optional (obviously in cases where it wasn't used things like multi-res recording and capture-while-recording wouldn't work). I'll mark this for 1.9 to remind me to look into it. |
More information in this response too. |
I came across the same issue. Currently I have model A + camera 1.3. For me even 640x480 doesn't work. The biggest resolution, which I can get working is 512x384. But when it is working, it seems to be stable. I used the same code as @rsacchettini to reproduce issue with file set to '/dev/null' to avoid interference with SD. I don't know if this is relevant or not, but I can set camera.resolution to max values without problem, but I have to set then resize=(512,384) in start_recording() call. |
This is still an issue on a B+ board with latest firmware, although recording at 640x480 does work reliably. Quick question -- how does MJPEG recording differ from continuous_capture(use_video_port=True) in JPEG format? My understanding is that MJPEG is just a concatenation of JPEG images with a few bytes of extra headers on each frame. continous_capture() seems to work reliably even at high resolutions. Would it be possible to emulate start_recording(format='mjpeg') using capture_continuous() under the hood? Would there be a performance penalty in this approach? |
A couple more observations:
|
First of all, many thanks to @andyg24 for testing a modified RaspiVid.c - that's been on my todo list for weeks (as a means of determining whether removing the splitter will make a difference, and in order to have something to submit upstream). That's also a very interesting observation on whether compressibility is a factor in the crash; I wonder if @nikoder's success at 1080p with the V4L2 driver had anything to do with that? I've also just realized I never responded to the comment above about whether picamera can control buffers, sorry! Via MMAL it can control the number and size of buffers allocated at each stage of the pipeline. At the moment it does what raspistill/raspivid do, which is to set them to the minimum or recommended size (the reason for minimum/recommended is there's a minor upstream bug: it's mentioned at the end of #73). Still, if circumstances demanded (i.e. if buffer allocation made a difference) I'd be happy to add a special case for MJPEG output. @andyg24 - sounds like you've got plenty for an upstream bug report there, if you fancy opening one? That said, given 6by9's comments on the state of the MJPEG codec I wouldn't hold my breath waiting for a fix! |
Sure, I can file a bug with the userland project on github (is that the best way to report this problem upstream?) I will share the steps to reproduce the issue here anyway.
wget https://github.com/raspberrypi/userland/archive/master.zip
encoder_output->format->encoding = MMAL_ENCODING_H264;
gcc -O3 -o mjpeg_test RaspiVid.c RaspiCamControl.c RaspiCLI.c RaspiPreview.c -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux -L/opt/vc/lib/ -lmmal -lmmal_components -lmmal_core -lmmal_util -lrt -lbcm_host -lvcos -lpthread
./mjpeg_test -w 640 -h 480 -fps 15 -o test.mjpeg
./mjpeg_test -w 800 -h 600 -fps 15 -o /dev/null |
I've opened issue #208 in userland project: There is not much activity in that project, and many bug reports haven't been acknowledged for months. I wouldn't hold my breath for this to be fixed quickly. Additionally, I don't see any MJPEG-related code in userland. Perhaps this functionality is part of the closed-sourced Broadcom driver? |
In the upstream discussion, a user suggested setting encoder buffer_size to a higher value. This seems to work: if I change line 465 in encoders.py to self.output_port[0].buffer_size = 500000; then MJPEG encoding seems to work at 1024 x 768 without wedging the camera. Don't know if this fix is reliable or if there are any downsides to a large buffer, but it's definitely an improvement. Another suggestion in the upstream thread was to stop capture and wait for a few milliseconds before closing the encoder. I haven't tried this yet. |
#179 seems to do the trick. No lockups since I started testing this patch three days ago. |
PR #179 merged. Note to self: run the results through the test suite to see how far we can push it with the bigger buffer and then we can close this one! |
No, I don't think compressibility is the cause of my success with V4L2: although I don't have the best performance (since I'm streaming through the network and the default MJPG quality level does not give enough compression for that), it does work without locking up. But I guess this is not so relevant, now that we know that the buffer size helps (sorry for my late response :S ). I have hacked the buffer fix, which was merged, into my Picamera installation and that allowed me to get similar results as with the v4l2 driver (including at 1080p). I have only tested it once at that resolution though. It worked many times at 720p. There were still some problems but they might be unrelated:
|
Ensure that, if the recommended size ever exceeds our guesstimate of 512k, we accept that as the correct buffer size
With #47 fixed, these all seem to pass happily now
We are seeing this exact issue, using camera V2 at high resolutions. Lowering resolution and framerate seems to help. However, getting the maximum resolution would be a large benefit to us. Manually enlarging the buffer, as indicated in #179, seems to not help. Any suggestions? |
Updating with our experiences. With the V2 camera, we seem to be able to avoid hangs by setting a resolution of 2592x1944 and a fixed framerate of 10 fps. Any use of framerate_range at this resolution causes the lockup on stop_recording(). It may be possible to go higher with either framerate or resolution, although we settled for these values. Maximum resolution seems to trigger the hang even when using fixed framerates. |
Under certain circumstances (resolution related?), MJPEG recording fails to stop. Looks like an explicit end capture signal is required (opposite of
PiCamera._enable_port
)The text was updated successfully, but these errors were encountered: