raspberrypi / picamera2

New libcamera based python library
BSD 2-Clause "Simplified" License
852 stars 180 forks source link

[BUG] RuntimeError: dictionary changed size during iteration #996

Open tranhien1612 opened 6 months ago

tranhien1612 commented 6 months ago

I have a simple code to switch two video configuration:

import time, os, socket, threading, datetime, pytz, cv2
import numpy as np

from picamera2 import Picamera2, MappedArray
from picamera2.encoders import H264Encoder, MJPEGEncoder, Quality
from picamera2.outputs import FfmpegOutput

from libcamera import controls

class MyCameraPi:
    picam2 = None;
    encoder = H264Encoder(10000000)
    mode = False;
    def __init__(self):
        self.picam2 = Picamera2();
        video_config = self.picam2.create_video_configuration(
                    main   ={"size": (1920, 1080)},
                    lores  ={"size": (1920, 1080)}, 
                    raw    ={"size": (4608, 2592)}, 
                    controls = {"FrameRate": 10.0},
                    buffer_count = 3
                ); 
        self.picam2.configure(video_config);
        self.picam2.set_controls({"AfMode": controls.AfModeEnum.Continuous})
        self.picam2.start();
        self.start_stream_udp("192.168.1.27", 10001);

    def switch_mode(self, mode):
        if(mode == False and self.mode != mode):
            print("Mode1")
            self.picam2.stop();
            video_config = self.picam2.create_video_configuration(
                    main   ={"size": (1920, 1080)},
                    lores  ={"size": (1920, 1080)}, 
                    raw    ={"size": (4608, 2592)}, 
                    controls = {"FrameRate": 10.0},
                    buffer_count = 3
                ); 
            self.picam2.configure(video_config);
            self.picam2.set_controls({"AfMode": controls.AfModeEnum.Continuous})
            self.picam2.start();
        elif(mode == True and self.mode != mode):
            print("Mode2")
            self.picam2.stop();
            video_config = self.picam2.create_video_configuration(
                    main   ={"size": (1920, 1080)},
                    lores  ={"size": (1920, 1080)}, 
                    raw    ={"size": (1920, 1080)}, 
                    controls = {"FrameRate": 50.0},
                    buffer_count = 3
                ); 
            self.picam2.configure(video_config);
            self.picam2.set_controls({"AfMode": controls.AfModeEnum.Continuous})
            self.picam2.start();

        self.mode = mode;

    def start_stream_udp(self, host, port):
        url = "-f rtp udp://{}:{}".format(host, port);
        output=FfmpegOutput(url)
        print(f"Start UDP Stream started on {host}:{port}\n")
        self.picam2.start_recording(H264Encoder(), output, name="main");
        print("output", output)

if __name__ == "__main__":        
    myCamera = MyCameraPi();
    while(True):
        myCamera.switch_mode(True);
        time.sleep(2)
        myCamera.switch_mode(False);
        time.sleep(2)

This is the error:

Exception in thread Thread-3 (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
^CTraceback (most recent call last):
  File "/home/raspi/camera/test.py", line 71, in <module>
    time.sleep(2)
KeyboardInterrupt
^CException ignored in atexit callback: <bound method Picamera2.close of <picamera2.picamera2.Picamera2 object at 0x7f87502950>>
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 611, in close
    self.camera.release()
KeyboardInterrupt:

I switch with 2 mode (two video configuration) and an error has occurred. pls support me fix it!

davidplowman commented 6 months ago

Hi, thanks for the report. Could you check your Picamera2 version first, as I think there were some problems in this area a little while ago (you can do apt list python3-picamera2). Thanks. Also can you say what kind of Pi and what OS version (Bullseye, Bookworm...) you are using.