2525import logging
2626from threading import Condition
2727import numpy as np
28- import picamera
28+ from picamera2 import Picamera2
29+ from picamera2 .encoders import Encoder , MJPEGEncoder , H264Encoder
30+ from picamera2 .outputs import FileOutput , FfmpegOutput
2931
3032class Camera (object ):
3133
@@ -34,90 +36,83 @@ class Camera(object):
3436 VIDEO_FILE_EXT = ".mp4"
3537 VIDEO_FILE_EXT_H264 = '.h264'
3638
37- class StreamingOutputMJPEG (object ):
39+ class StreamingOutputMJPEG (io . BufferedIOBase ):
3840 def __init__ (self ):
3941 self .frame = None
40- self .buffer = io .BytesIO ()
4142 self .condition = Condition ()
4243
4344 def write (self , buf ):
44- if buf .startswith (b'\xff \xd8 ' ):
45- # New frame, copy the existing buffer's content and notify all
46- # clients it's available
47- self .buffer .truncate ()
48- with self .condition :
49- self .frame = self .buffer .getvalue ()
50- self .condition .notify_all ()
51- self .buffer .seek (0 )
52- return self .buffer .write (buf )
45+ with self .condition :
46+ self .frame = buf
47+ self .condition .notify_all ()
5348
54- class StreamingOutputBGR (object ):
49+ class StreamingOutputBGR (io . BufferedIOBase ):
5550 def __init__ (self , resolution ):
5651 self .frame = None
5752 self .condition = Condition ()
5853 self .resolution = resolution
59- self .count = 0
6054
6155 def write (self , buf ):
6256 with self .condition :
6357 frame = np .frombuffer (buf , dtype = np .uint8 )
6458 self .frame = frame .reshape (self .resolution [1 ], self .resolution [0 ], 4 )
6559 self .frame = np .delete (self .frame , 3 , 2 )
6660 self .condition .notify_all ()
67- return len (buf )
6861
6962 def __init__ (self , props ):
7063 logging .info ("camera init" )
71- self .camera = picamera .PiCamera ()
64+ self .camera = Picamera2 ()
65+ self .camera .configure (self .camera .create_video_configuration (main = {"size" : (props .get ('width' , 640 ), props .get ('height' , 512 ))}))
7266 self .camera .resolution = (props .get ('width' , 640 ), props .get ('height' , 512 ))
73- self .out_rgb_resolution = (int (self . camera . resolution [ 0 ] / int (props .get ('cv_image_factor' , 4 ))), int (self . camera . resolution [ 1 ] / int (props .get ('cv_image_factor' , 4 ))))
67+ self .out_rgb_resolution = (int (props . get ( 'width' , 640 ) / int (props .get ('cv_image_factor' , 4 ))), int (props . get ( 'height' , 512 ) / int (props .get ('cv_image_factor' , 4 ))))
7468 self .camera .framerate = float (props .get ('framerate' , 20 ))
7569 self .camera .exposure_mode = props .get ('exposure_mode' , "auto" )
7670 self .output_mjpeg = self .StreamingOutputMJPEG ()
77- self .output_bgr = self .StreamingOutputBGR (self .out_rgb_resolution )
78- self .h264_encoder = None
71+ self .encoder_streaming = MJPEGEncoder (10000000 )
72+ self .encoder_streaming .output = [FileOutput (self .output_mjpeg )]
73+ self .encoder_h264 = H264Encoder ()
74+ #self.output_bgr = self.StreamingOutputBGR(self.out_rgb_resolution)
75+ #self.h264_encoder = None
7976 self .recording = None
8077 self .video_filename = None
8178 self ._jpeg_quality = props .get ('jpeg_quality' , 20 )
8279 self ._jpeg_bitrate = props .get ('jpeg_bitrate' , 5000000 )
8380
8481 def video_rec (self , filename ):
8582 self .video_filename = filename [:filename .rfind ("." )]
86- self .camera .start_recording (self .video_filename + self .VIDEO_FILE_EXT_H264 , format = "h264" , quality = 23 , splitter_port = 2 )
83+ output = FfmpegOutput (output_filename = filename )
84+ self .encoder_h264 .output = [output ]
85+ self .camera .start_encoder (self .encoder_h264 , output )
86+ #self.camera.start_recording(self.encoder_h264, FfmpegOutput(output_filename=filename))
87+ #self.camera.start_recording(self.video_filename + self.VIDEO_FILE_EXT_H264, format="h264", quality=23, splitter_port=2)
8788
8889 def video_stop (self ):
89- logging .debug ("video_stop" )
90- self .camera .stop_recording (2 )
91-
92- # pack in mp4 container
93- params = " -loglevel quiet -stats -framerate " + str (self .camera .framerate ) + \
94- " -i " + self .video_filename + self .VIDEO_FILE_EXT_H264 + \
95- " -c copy " + self .video_filename + self .VIDEO_FILE_EXT
96-
97- os .system (self .FFMPEG_CMD + params )
98- # remove h264 file
99- os .remove (self .video_filename + self .VIDEO_FILE_EXT_H264 )
90+ logging .info ("video_stop" )
91+ self .camera .stop_encoder (encoders = [self .encoder_h264 ])
92+ #self.camera.stop_recording()
10093
10194 def grab_start (self ):
102- logging .debug ("grab_start" )
103- self .camera .start_recording (self .output_mjpeg , format = "mjpeg" , splitter_port = 0 , bitrate = self ._jpeg_bitrate )
104- self .camera .start_recording (self .output_bgr , format = "bgra" , splitter_port = 1 , resize = self .out_rgb_resolution )
95+ logging .info ("grab_start" )
96+ self .camera .start ()
97+ self .camera .start_encoder (self .encoder_streaming )
98+ #self.camera.start_recording(self.output_mjpeg, format="mjpeg", splitter_port=0, bitrate=self._jpeg_bitrate)
99+ #self.camera.start_recording(self.output_bgr, format="bgra", splitter_port=1, resize=self.out_rgb_resolution)
105100
106101 def grab_stop (self ):
107- logging .debug ("grab_stop" )
108-
109- self .camera .stop_recording (0 )
110- self .camera .stop_recording (1 )
102+ logging .info ("grab_stop" )
103+ self .camera .stop_encoder (encoders = [self .encoder_streaming ])
111104
112105 def get_image_jpeg (self ):
113106 with self .output_mjpeg .condition :
114107 self .output_mjpeg .condition .wait ()
115108 return self .output_mjpeg .frame
116109
117110 def get_image_bgr (self ):
118- with self .output_bgr .condition :
119- self .output_bgr .condition .wait ()
120- return self .output_bgr .frame
111+ buf = self .camera .capture_buffer ()
112+ frame_from_buf = np .frombuffer (buf , dtype = np .uint8 )
113+ frame = frame_from_buf .reshape (self .camera .resolution [1 ], self .camera .resolution [0 ], 4 )
114+ frame = np .delete (frame , 3 , 2 )
115+ return frame
121116
122117 def set_overlay_text (self , text ):
123118 try :
0 commit comments