2
2
import csv
3
3
import json
4
4
import subprocess
5
+ import signal
5
6
import numpy as np
6
7
from datetime import datetime
7
8
from collections import deque
@@ -52,8 +53,6 @@ def __init__(self, parent, label, subject_id):
52
53
self .label = label
53
54
self .settings = self .camera_setup_tab .get_camera_settings_from_label (label )
54
55
self .camera_api = init_camera_api_from_module (settings = self .settings )
55
- self .cam_width = self .camera_api .get_width ()
56
- self .cam_height = self .camera_api .get_height ()
57
56
self ._image_data = None
58
57
self .frame_timestamps = deque (maxlen = 10 )
59
58
self .controls_visible = True
@@ -174,6 +173,8 @@ def fetch_image_data(self) -> None:
174
173
if self .recording :
175
174
self .recorded_frames += len (new_images ["images" ])
176
175
for frame in new_images ["images" ]: # Send new images to FFMPEG for encoding.
176
+ # Downsample frame
177
+ frame = frame [::self .settings .downsampling_factor , ::self .settings .downsampling_factor ]
177
178
self .ffmpeg_process .stdin .write (frame .tobytes ())
178
179
for gpio_pinstate in new_images ["gpio_data" ]: # Write GPIO pinstate to file.
179
180
self .gpio_writer .writerow (gpio_pinstate )
@@ -199,28 +200,28 @@ def start_recording(self) -> None:
199
200
"subject_ID" : self .subject_id ,
200
201
"camera_unique_id" : self .settings .unique_id ,
201
202
"recorded_frames" : 0 ,
203
+ "downsampling_factor" :self .settings .downsampling_factor ,
202
204
"begin_time" : self .record_start_time .isoformat (timespec = "milliseconds" ),
203
205
"end_time" : None ,
204
206
}
205
207
with open (self .metadata_filepath , "w" ) as meta_data_file :
206
208
json .dump (self .metadata , meta_data_file , indent = 4 )
207
209
208
210
# Initalise ffmpeg process
209
- downsampled_width = int (self .cam_width / self .settings .downsampling_factor )
210
- downsampled_height = int (self .cam_height / self .settings .downsampling_factor )
211
+ self . downsampled_width = int (self .camera_api . get_width () / self .settings .downsampling_factor )
212
+ self . downsampled_height = int (self .camera_api . get_height () / self .settings .downsampling_factor )
211
213
ffmpeg_command = " " .join (
212
214
[
213
215
self .ffmpeg_path , # Path to binary
214
- "-y" , # overwrite output file if it exists
215
216
"-f rawvideo" , # Input codec (raw video)
216
- "-pix_fmt gray" , # Input Pixel format?
217
- f"-s { downsampled_width } x{ downsampled_height } " , # Input resolution
217
+ "-pix_fmt gray" , # Input Pixel Format: 8-bit grayscale input to ffmpeg process. Input array 1D
218
+ f"-s { self . downsampled_width } x{ self . downsampled_height } " , # Input resolution
218
219
f"-r { self .settings .fps } " , # Frame rate
219
220
"-i -" , # input comes from a pipe (stdin)
220
- f"-vcodec { self .video_capture_tab .ffmpeg_encoder_map [ffmpeg_config ['compression_standard' ]]} " , # Output codec
221
+ f"-c:v { self .video_capture_tab .ffmpeg_encoder_map [ffmpeg_config ['compression_standard' ]]} " , # Output codec
221
222
"-pix_fmt yuv420p" , # Output pixel format
222
223
f"-preset { ffmpeg_config ['encoding_speed' ]} " , # Encoding speed [fast, medium, slow]
223
- f"-crf { ffmpeg_config ['crf' ]} " , # Controls quality vs filesize
224
+ f"-qp { ffmpeg_config ['crf' ]} " , # Controls quality vs filesize
224
225
f'"{ self .video_filepath } "' , # Output file path
225
226
]
226
227
)
@@ -253,6 +254,7 @@ def stop_recording(self) -> None:
253
254
# Close FFMPEG process
254
255
self .ffmpeg_process .stdin .close ()
255
256
self .ffmpeg_process .wait ()
257
+
256
258
# Update GUI
257
259
self .stop_recording_button .setEnabled (False )
258
260
self .start_recording_button .setEnabled (True )
0 commit comments