picamera2 icon indicating copy to clipboard operation
picamera2 copied to clipboard

take pictures during a video recording -errors

Open LeifSec opened this issue 1 year ago • 11 comments

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

  1. Reconfigure (to video mode) the camera after picture has been taken failed. (see below)
  2. With the reconfiguration:
  3. Several other errors like "MmemoryAllocation" which I will describe later after I am sure that in my code are no bug itsself.

To Reproduce Because of #887 I have also tested in the next branch.

#!/usr/bin/python3

from typing import Final
from pathlib import Path
import time
import io
from threading import Condition

from picamera2.encoders import MJPEGEncoder
import libcamera
from picamera2.picamera2 import Picamera2
from picamera2.outputs import FileOutput


class StreamingOutput(io.BufferedIOBase):
    def __init__(self):
        self.__frame = None
        self.__condition = Condition()
 
    @property
    def frame(self) -> bytes:
        return self.__frame

    @frame.setter
    def frame(self, frame: bytes) -> None:
        self.__frame = frame
 
    @property
    def condition(self) -> Condition:
        return self.__condition
 
    def write(self, buf):
        with self.condition:
            self.frame = buf
            self.condition.notify_all()


STILL_CONFIGURATION: Final  = {
    'use_case': 'still',
    'transform': libcamera.Transform(hflip=1),
    'colour_space': libcamera.ColorSpace.Sycc(),
    'buffer_count': 1,
    'queue': True,
    'main': {'format': 'BGR888', 'size': (1920, 1080)},
    'lores': None,
    'raw': {'format': 'SRGGB12_CSI2P', 'size': (4056, 3040)},
    'controls': {
                 'NoiseReductionMode': libcamera.controls
                 .draft.NoiseReductionModeEnum.HighQuality,
                 'FrameDurationLimits': (100, 1000000000),
                 'Saturation': 0.0,
                 'Sharpness': 12.0,
                 'Brightness': 0.0,
                 'AnalogueGain': 5,
                 'ColourGains': (0, 0),
                 'AeExposureMode': libcamera.controls
                 .AeExposureModeEnum.Normal,
                 'AwbEnable': False,
                 'AeEnable': False,
                 'ExposureTime': 10000},
    'sensor': {'output_size': (4056, 3040)},
    'display': None, 'encode': None}


picam2 = Picamera2()

def start_recording() -> None:
    encoder = MJPEGEncoder()
    picam2.start_recording(
        encoder=encoder,
        output=FileOutput(StreamingOutput())) 


def take_picture():
    request = None
    if picam2.started:
        request = picam2.capture_request()
    started = picam2.started
    config = picam2.camera_config  #config = copy.deepcopy(picam2.camera_config)
    picam2.stop()
    picam2.configure(STILL_CONFIGURATION)
    picam2.start()
    img = picam2.capture_image("main")
    picam2.stop()
    picam2.configure(config)
    if request is not None:
         request.release()
    if started:
        picam2.start()


def test_loop():
    start_recording()
    i = 0
    while True:
        print("\n \n \n ------------------", i)
        take_picture()
        time.sleep(1.0)
        i += 1
        if i > 5:
            break

if __name__ == '__main__':
    test_loop()
  

Expected behaviour Picture taking works during video recording running infinity number of times.

Console Output, Screenshots 1.

[10:53:49.657379752] [8609]  INFO Camera camera.cpp:1183 configuring streams: (0) 1280x720-XBGR8888 (1) 2028x1080-SBGGR12_CSI2P
[10:53:49.669070213] [8604]  INFO RPI vc4.cpp:608 Sensor: /base/soc/i2c0mux/i2c@1/imx477@1a - Selected sensor format: 2028x1080-SBGGR12_1X12 - Selected unicam format: 2028x1080-pBCC
Exception in thread Thread-2 (thread_poll):
Traceback (most recent call last):
  File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.11/threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3/dist-packages/picamera2/encoders/v4l2_encoder.py", line 241, in thread_poll
    queue_item.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 81, in cleanup
    for k, v in self.mapped_buffers.items():
RuntimeError: dictionary changed size during iteration
G
Traceback (most recent call last):
  File "/home/pi/camera_websetter_python/./test_loop.py", line 116, in <module>
    test_loop()
  File "/home/pi/camera_websetter_python/./test_loop.py", line 105, in test_loop
    take_picture()
  File "/home/pi/camera_websetter_python/./test_loop.py", line 95, in take_picture
    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: 27
Exception ignored in: <function DmaAllocator.__del__ at 0x73016398>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 100, in __del__
    self.close()
  File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 92, in close
    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:
INFO:picamera2.picamera2:Camera stopped
DEBUG:picamera2.picamera2:Requesting configuration: {'use_case': 'still', 'transform': <libcamera.Transform 'hvflip'>, 'colour_space': <libcamera.ColorSpace 'sYCC'>, 'buffer_count': 1, 'queue': True, 'main': {'format': 'BGR888', 'size': (1920, 1080), 'stride': 5760, 'framesize': 6220800}, 'lores': None, 'raw': {'format': 'SRGGB12_CSI2P', 'size': (4056, 3040), 'stride': 6112, 'framesize': 18580480}, 'controls': {'NoiseReductionMode': <NoiseReductionModeEnum.HighQuality: 2>, 'FrameDurationLimits': (100, 1000000000), 'Saturation': 0.0, 'Sharpness': 12.0, 'Brightness': 0.1, 'AnalogueGain': 6, 'ColourGains': (0, 0), 'AeExposureMode': <AeExposureModeEnum.Normal: 0>, 'AwbEnable': False, 'AeEnable': False, 'ExposureTime': 10000}, 'sensor': {'bit_depth': 12, 'output_size': (4056, 3040)}, 'display': None, 'encode': None}
[11:24:21.998080685] [9006]  INFO Camera camera.cpp:1183 configuring streams: (0) 1920x1080-BGR888 (1) 4056x3040-SRGGB12_CSI2P
[11:24:22.014301048] [8939]  INFO RPI vc4.cpp:608 Sensor: /base/soc/i2c0mux/i2c@1/imx477@1a - Selected sensor format: 4056x3040-SRGGB12_1X12 - Selected unicam format: 4056x3040-pRCC
INFO:picamera2.picamera2:Configuration successful!
DEBUG:picamera2.picamera2:Final configuration: {'use_case': 'still', 'transform': <libcamera.Transform 'hvflip'>, 'colour_space': <libcamera.ColorSpace 'sYCC'>, 'buffer_count': 1, 'queue': True, 'main': {'format': 'BGR888', 'size': (1920, 1080), 'stride': 5760, 'framesize': 6220800}, 'lores': None, 'raw': {'format': 'SRGGB12_CSI2P', 'size': (4056, 3040), 'stride': 6112, 'framesize': 18580480}, 'controls': {'NoiseReductionMode': <NoiseReductionModeEnum.HighQuality: 2>, 'FrameDurationLimits': (100, 1000000000), 'Saturation': 0.0, 'Sharpness': 12.0, 'Brightness': 0.1, 'AnalogueGain': 6, 'ColourGains': (0, 0), 'AeExposureMode': <AeExposureModeEnum.Normal: 0>, 'AwbEnable': False, 'AeEnable': False, 'ExposureTime': 10000}, 'sensor': {'bit_depth': 12, 'output_size': (4056, 3040)}, 'display': None, 'encode': None}
DEBUG:picamera2.picamera2:Streams: {'main': <libcamera._libcamera.Stream object at 0x653c10a0>, 'lores': None, 'raw': <libcamera._libcamera.Stream object at 0x653c17e0>}
ERROR:root:34
DEBUG:picamera2.picamera2:Requesting configuration: {'use_case': 'preview', 'buffer_count': 4, 'transform': <libcamera.Transform 'identity'>, 'display': 'main', 'encode': 'main', 'colour_space': <libcamera.ColorSpace 'sYCC'>, 'controls': <Controls: {'NoiseReductionMode': <NoiseReductionModeEnum.Minimal: 3>, 'FrameDurationLimits': (100, 83333)}>, 'main': {'size': (640, 480), 'format': 'XBGR8888', 'stride': 2560, 'framesize': 1228800}, 'lores': None, 'raw': {'size': (2028, 1520), 'format': 'SBGGR12_CSI2P', 'stride': 3072, 'framesize': 4669440}, 'queue': True, 'sensor': {'bit_depth': 12, 'output_size': (2028, 1520)}}
INFO:picamera2.picamera2:Camera configuration has been adjusted!
[11:24:22.035280584] [9006]  INFO Camera camera.cpp:1183 configuring streams: (0) 640x480-XBGR8888 (1) 2028x1520-SBGGR12_CSI2P
[11:24:22.036419896] [8939]  INFO RPI vc4.cpp:608 Sensor: /base/soc/i2c0mux/i2c@1/imx477@1a - Selected sensor format: 2028x1520-SBGGR12_1X12 - Selected unicam format: 2028x1520-pBCC
INFO:picamera2.picamera2:Configuration successful!
DEBUG:picamera2.picamera2:Final configuration: {'use_case': 'preview', 'buffer_count': 4, 'transform': <libcamera.Transform 'identity'>, 'display': 'main', 'encode': 'main', 'colour_space': <libcamera.ColorSpace 'sYCC'>, 'controls': <Controls: {'NoiseReductionMode': <NoiseReductionModeEnum.Minimal: 3>, 'FrameDurationLimits': (100, 83333)}>, 'main': {'size': (640, 480), 'format': 'XBGR8888', 'stride': 2560, 'framesize': 1228800}, 'lores': None, 'raw': {'size': (2028, 1520), 'format': 'SBGGR12_CSI2P', 'stride': 3072, 'framesize': 4669440}, 'queue': True, 'sensor': {'bit_depth': 12, 'output_size': (2028, 1520)}}
DEBUG:picamera2.picamera2:Streams: {'main': <libcamera._libcamera.Stream object at 0x653c10a0>, 'lores': None, 'raw': <libcamera._libcamera.Stream object at 0x653c17e0>}
DEBUG:picamera2:Allocated 4 buffers for stream 0 with fds [33, 36, 41, 48]
DEBUG:picamera2:Allocated 4 buffers for stream 1 with fds [51, 55, 75, 78]
INFO:picamera2.picamera2:Camera started
DEBUG:picamera2.picamera2:Execute job: <picamera2.job.Job object at 0x624b4810>
ERROR:picamera2.previews.null_preview:Exception during process_requests()
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/picamera2/previews/null_preview.py", line 85, in handle_request
    picam2.process_requests(self)
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1265, in process_requests
    encoder.encode(encoder.name, req)
  File "/usr/lib/python3/dist-packages/picamera2/encoders/encoder.py", line 210, in encode
    self._encode(stream, request)
  File "/usr/lib/python3/dist-packages/picamera2/encoders/v4l2_encoder.py", line 279, in _encode
    fcntl.ioctl(self.vd, VIDIOC_QBUF, buf)
OSError: [Errno 22] Invalid argument
Exception in thread Thread-4 (thread_func):
Traceback (most recent call last):
  File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.11/threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3/dist-packages/picamera2/previews/null_preview.py", line 29, in thread_func
    callback(picam2)
  File "/usr/lib/python3/dist-packages/picamera2/previews/null_preview.py", line 85, in handle_request
    picam2.process_requests(self)
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1265, in process_requests
    encoder.encode(encoder.name, req)
  File "/usr/lib/python3/dist-packages/picamera2/encoders/encoder.py", line 210, in encode
    self._encode(stream, request)
  File "/usr/lib/python3/dist-packages/picamera2/encoders/v4l2_encoder.py", line 279, in _encode
    fcntl.ioctl(self.vd, VIDIOC_QBUF, buf)
OSError: [Errno 22] Invalid argument

Hardware : The problem appear with imx477 and not with imx708 on raspberry 2 and 3 with the latest firmware (rpi-update).

LeifSec avatar Jan 22 '24 16:01 LeifSec