Open LeifSec opened 9 months ago
Hi, thanks for the report. Reading through the code it looks like you're starting a video recording, and then while the video recording is still running, you're changing the camera mode for a still capture and then switching back to the video mode. Is that correct?
Unfortunately this isn't supported - it just won't survive having all the video buffers being wiped out and reallocated under its feet. I'm a bit surprised it doesn't spit out an error to that effect, so maybe that's something to look at.
Having said that, the next release of Picamera2 (on the "next" branch) will feature a "persistent allocator" whereby you can stop the buffers being deallocated, and force it to reuse the same ones when the video mode restarts. That might actually work better, though there's still an issue about requests be recreated during configure(). So worth a try, but no promises. @will-v-pi What do you think?
Hi, thanks for the report. Reading through the code it looks like you're starting a video recording, and then while the video recording is still running,
Yes - like show in still_during_video.py.
you're changing the camera mode for a still capture and then switching back to the video mode. Is that correct?
Yes - basically I want to take pictures with another (higher) resolution that the video stream.
Unfortunately this isn't supported - it just won't survive having all the video buffers being wiped out and reallocated under its feet. I'm a bit surprised it doesn't spit out an error to that effect, so maybe that's something to look at.
Having said that, the next release of Picamera2 (on the "next" branch) will feature a "persistent allocator" whereby you can stop the buffers being deallocated, and force it to reuse the same ones when the video mode restarts. That might actually work better, though there's still an issue about requests be recreated during configure(). So worth a try, but no promises. @will-v-pi What do you think?
I do not see why: But using my full code which has basically not changed and which should be quite similar to my example code above it works (using next
branch).
The full code just set some configurations of camera control etc. where restarting the camera several times.
By the way: Isn't picam2.still_configuration
automatically used when calling picam2.capture_image
so that I do not have to reconfigure?
Update:
self._camera.configure(self.preview_configuration)
File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1112, in configure
self.configure_(camera_config)
File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1095, in configure_
self.allocator.allocate(libcamera_config, camera_config.get("use_case"))
File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 32, in allocate
self.cleanup()
File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 86, in cleanup
del self.mapped_buffers_used[fd]
~~~~~~~~~~~~~~~~~~~~~~~~^^^^
request.release()
File "/usr/lib/python3/dist-packages/picamera2/request.py", line 140, in release
self.picam2.allocator.release(self.request.buffers)
File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 78, in release
self.cleanup()
File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 83, in cleanup
if not self.mapped_buffers_used[fd] and fd not in self.libcamera_fds:
~~~~~~~~~~~~~~~~~~~~~~~~^^^^
KeyError: 30
I will retest with the next release.
Hi again, there's quite a fundamental thing about cameras in that they run continuously, in one particular readout mode. The cameras themselves are quite pipelined, and so is all the software. You can't just change readout mode without stopping everything, waiting for everything to finish, and then starting over.
You can take still captures while a video is running, but only if you don't change the camera mode, which is what the example program does. You can choose a camera mode with a faster framerate for video, but then still resolution is limited, or you can choose a higher resolution mode, but the video framerate will be limited. There's no getting around this as things stand (until we one day have high framerate high resolution camera modes).
As I said, you may have more luck with the next release if you adjust your code to use the persistent allocator correctly, but I can't promise that because the original design did require you to stop everything when you reconfigure the camera.
In my code example above I already stop the camera before reconfiguring and that is OK for me that the video stream will stop for approximate 1 s.
In my full application it works now with > 12 pictures taken during video. The problems seem s to appear when reconfiguring video via
li = list(camera.encoders)
if camera.encoders is not None\
and len(camera.encoders) > 0\
and li[0].running:
camera.stop_recording()
camera.configure(configuration)
camera.start_encoder(encoder=encoder)
camera.start()
else:
camera.configure(configuration)
Also picture resolutions other than 1920x1080 or (5074, 3804) but with a ratio of 507 to 380 cause problems - even just run the camera for picture taking they are working.
P.S.: Some background about my application: I am taking and processing pictures which are triggers by network signals. In addition I have a web interface which shows a live stream where one can set camera settings and view the effect directly. The gui is like this - less powerful but also for picamera2 and included e.g. an exposure time setting which takes current sunup/down times into account. Maybe a can publish it in the future. picamera2
really has a lot of features and works very well - at least for ixm708
. Thanks a lot for your efford.
The PersistentAllocator on the next branch would be useful for your use case, provided you have enough memory, as it will avoid reallocating the buffers every time you call configure, so you might want to try it out. To try it just add the import from picamera2.allocators import PersistentAllocator
and use picam2 = Picamera2(allocator=PersistentAllocator())
to create your picam2 object
Thanks a lot - With my example code it works very well - tested up to more than 100 loop.
With my full software on a Raspberry Pi 2 Model B Rev 1.1 with only 1 GB RAM I got:
FO:picamera2.picamera2:Camera started
DEBUG:picamera2.picamera2:Execute job: <picamera2.job.Job object at 0x652c9b50>
[1:00:51.143660070] [1689] ERROR V4L2 v4l2_videodevice.cpp:1697 /dev/video14[23:cap]: Failed to queue buffer 0: Invalid argument
[1:00:51.144703499] [1689] ERROR RPISTREAM rpi_stream.cpp:276 Failed to queue buffer for ISP Output0
[1:00:51.146265518] [1689] ERROR V4L2 v4l2_videodevice.cpp:1697 /dev/video14[23:cap]: Failed to queue buffer 1: Invalid argument
[1:00:51.147047178] [1689] ERROR RPISTREAM rpi_stream.cpp:276 Failed to queue buffer for ISP Output0
[1:00:51.148504666] [1689] ERROR V4L2 v4l2_videodevice.cpp:1697 /dev/video14[23:cap]: Failed to queue buffer 2: Invalid argument
[1:00:51.149259348] [1689] ERROR RPISTREAM rpi_stream.cpp:276 Failed to queue buffer for ISP Output0
[1:00:51.150765065] [1689] ERROR V4L2 v4l2_videodevice.cpp:1697 /dev/video14[23:cap]: Failed to queue buffer 3: Invalid argument
[1:00:51.151552194] [1689] ERROR RPISTREAM rpi_stream.cpp:276 Failed to queue buffer for ISP Output0
[1:00:51.152979630] [1689] ERROR V4L2 v4l2_videodevice.cpp:1697 /dev/video14[23:cap]: Failed to queue buffer 4: Invalid argument
[1:00:51.153738842] [1689] ERROR RPISTREAM rpi_stream.cpp:276 Failed to queue buffer for ISP Output0
[1:00:51.155146227] [1689] ERROR V4L2 v4l2_videodevice.cpp:1697 /dev/video14[23:cap]: Failed to queue buffer 5: Invalid argument
[1:00:51.155899866] [1689] ERROR RPISTREAM rpi_stream.cpp:276 Failed to queue buffer for ISP Output0
[1:00:51.162895747] [1689] FATAL default v4l2_videodevice.cpp:1960 /dev/video14[23:cap]: assertion "cache_->isEmpty()" failed in streamOff()
Backtrace:
libcamera::V4L2VideoDevice::streamOff()+0x194 (/usr/lib/arm-linux-gnueabihf/libcamera.so.0.1.0 [0x00000000747d7534])
libcamera::RPi::PipelineHandlerBase::stopDevice(libcamera::Camera*)+0x38 (/usr/lib/arm-linux-gnueabihf/libcamera.so.0.1.0 [0x00000000747fce20])
libcamera::PipelineHandler::stop(libcamera::Camera*)+0x38 (/usr/lib/arm-linux-gnueabihf/libcamera.so.0.1.0 [0x00000000747ac0a4])
libcamera::Object::message(libcamera::Message*)+0x8c (/usr/lib/arm-linux-gnueabihf/libcamera-base.so.0.1.0 [0x00000000746d1dc0])
libcamera::Thread::dispatchMessages(libcamera::Message::Type)+0x1cc (/usr/lib/arm-linux-gnueabihf/libcamera-base.so.0.1.0 [0x00000000746d4564])
libcamera::EventDispatcherPoll::processEvents()+0x34 (/usr/lib/arm-linux-gnueabihf/libcamera-base.so.0.1.0 [0x00000000746ca7f0])
libcamera::Thread::exec()+0x7c (/usr/lib/arm-linux-gnueabihf/libcamera-base.so.0.1.0 [0x00000000746d3ee4])
libcamera::CameraManager::Private::run()+0xb8 (/usr/lib/arm-linux-gnueabihf/libcamera.so.0.1.0 [0x000000007477d348])
??? [0x000000007507e068] (/usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.30 [0x000000007507e068])
start_thread+0x164 (./nptl/pthread_create.c:443)
But you already said "provided you have enough memory".
Would it also help to fully close the camera (picam2.close()
) and delete the object (delete My_camera_object
) each time before recording video is restarted?
Because of #887 I also tested this on the next
branch - but with similar errors.
Generally I'd probably try to leave resources allocated if you can. Closing everything runs the risk that you can't reopen the camera, or fail to allocate resources. But it always depends on your application.
Just to be sure: Of course this project is the picamera2
and not the libcamera
library.
But as I understand all the issues about memory allocation etc. should be caused by libcamera
it self. Thus, using the libcamera
C++ library directly would not improve anything. (?)
Of course having a compiled C++ program, after existing it all resources should be freed again.
When you run Picamera2 applications, the buffer allocation is under the control of Picamera2. We used to ask libcamera to allocate buffers for us but now we allocate them ourselves and pass them into libcamera. The lifetime of those buffers is under the control of Picamera2 as well.
If you code C++ appliications directly it's exactly the same. You have to decide where to allocate the buffers from, and you can ask libcamera for them (which is what we used to do in our rpicam-apps), though here too we have switched to allocating them ourselves (just as Picamera2 does). Basically the situation is the same in both cases.
I want to take pictures during a video recording (webstream) is in process.
I basically follow the
still_during_video.py
example:Describe the bug
To Reproduce Because of #887 I have also tested in the
next
branch.Expected behaviour Picture taking works during video recording running infinity number of times.
Console Output, Screenshots 1.
2.
Hardware : The problem appear with
imx477
and not withimx708
on raspberry 2 and 3 with the latest firmware (rpi-update
).