25
25
import logging
26
26
from threading import Condition
27
27
import 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
29
31
30
32
class Camera (object ):
31
33
@@ -34,90 +36,83 @@ class Camera(object):
34
36
VIDEO_FILE_EXT = ".mp4"
35
37
VIDEO_FILE_EXT_H264 = '.h264'
36
38
37
- class StreamingOutputMJPEG (object ):
39
+ class StreamingOutputMJPEG (io . BufferedIOBase ):
38
40
def __init__ (self ):
39
41
self .frame = None
40
- self .buffer = io .BytesIO ()
41
42
self .condition = Condition ()
42
43
43
44
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 ()
53
48
54
- class StreamingOutputBGR (object ):
49
+ class StreamingOutputBGR (io . BufferedIOBase ):
55
50
def __init__ (self , resolution ):
56
51
self .frame = None
57
52
self .condition = Condition ()
58
53
self .resolution = resolution
59
- self .count = 0
60
54
61
55
def write (self , buf ):
62
56
with self .condition :
63
57
frame = np .frombuffer (buf , dtype = np .uint8 )
64
58
self .frame = frame .reshape (self .resolution [1 ], self .resolution [0 ], 4 )
65
59
self .frame = np .delete (self .frame , 3 , 2 )
66
60
self .condition .notify_all ()
67
- return len (buf )
68
61
69
62
def __init__ (self , props ):
70
63
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 ))}))
72
66
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 ))))
74
68
self .camera .framerate = float (props .get ('framerate' , 20 ))
75
69
self .camera .exposure_mode = props .get ('exposure_mode' , "auto" )
76
70
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
79
76
self .recording = None
80
77
self .video_filename = None
81
78
self ._jpeg_quality = props .get ('jpeg_quality' , 20 )
82
79
self ._jpeg_bitrate = props .get ('jpeg_bitrate' , 5000000 )
83
80
84
81
def video_rec (self , filename ):
85
82
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)
87
88
88
89
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()
100
93
101
94
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)
105
100
106
101
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 ])
111
104
112
105
def get_image_jpeg (self ):
113
106
with self .output_mjpeg .condition :
114
107
self .output_mjpeg .condition .wait ()
115
108
return self .output_mjpeg .frame
116
109
117
110
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
121
116
122
117
def set_overlay_text (self , text ):
123
118
try :
0 commit comments