@@ -200,6 +200,7 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
200200private:
201201 AVCaptureDevice *device;
202202 MyCaptureSession *capture_session;
203+ bool format_locked;
203204
204205public:
205206 AVCaptureDevice *get_device () const ;
@@ -210,6 +211,9 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
210211
211212 bool activate_feed () override ;
212213 void deactivate_feed () override ;
214+
215+ bool set_format (int p_index, const Dictionary &p_parameters) override ;
216+ Array get_formats () const override ;
213217};
214218
215219AVCaptureDevice *CameraFeedMacOS::get_device () const {
@@ -219,6 +223,7 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
219223CameraFeedMacOS::CameraFeedMacOS () {
220224 device = nullptr ;
221225 capture_session = nullptr ;
226+ format_locked = false ;
222227}
223228
224229void CameraFeedMacOS::set_device (AVCaptureDevice *p_device) {
@@ -239,6 +244,14 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
239244 if (capture_session) {
240245 // Already recording!
241246 } else {
247+ // Configure device format if specified.
248+ if (selected_format != -1 ) {
249+ NSError *error;
250+ ERR_FAIL_INDEX_V ((unsigned int )selected_format, device.formats .count , false );
251+ format_locked = [device lockForConfiguration: &error];
252+ ERR_FAIL_COND_V_MSG (!format_locked, false , error.localizedFailureReason .UTF8String );
253+ [device setActiveFormat: device.formats[selected_format]];
254+ }
242255 // Start camera capture, check permission.
243256 if (@available (macOS 10.14 , *)) {
244257 AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType: AVMediaTypeVideo];
@@ -267,6 +280,42 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
267280 [capture_session cleanup ];
268281 capture_session = nullptr ;
269282 };
283+ if (format_locked) {
284+ [device unlockForConfiguration ];
285+ format_locked = false ;
286+ }
287+ }
288+
289+ bool CameraFeedMacOS::set_format (int p_index, const Dictionary &p_parameters) {
290+ if (p_index == -1 ) {
291+ selected_format = p_index;
292+ emit_signal (" format_changed" );
293+ return true ;
294+ }
295+ ERR_FAIL_INDEX_V ((unsigned int )p_index, device.formats .count , false );
296+ ERR_FAIL_COND_V_MSG (capture_session != nullptr , false , " Feed is active." );
297+ selected_format = p_index;
298+ emit_signal (" format_changed" );
299+ return true ;
300+ }
301+
302+ Array get_formats () const {
303+ Array result;
304+ for (AVCaptureDeviceFormat *format in device.formats ) {
305+ Dictionary dictionary;
306+ CMFormatDescriptionRef formatDescription = format.formatDescription ;
307+ CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions (formatDescription);
308+ dictionary[" width" ] = dimension.width ;
309+ dictionary[" height" ] = dimension.height ;
310+ FourCharCode fourcc = CMFormatDescriptionGetMediaSubType (formatDescription);
311+ dictionary[" format" ] =
312+ String::chr ((char )(fourcc >> 24 ) & 0xFF ) +
313+ String::chr ((char )(fourcc >> 16 ) & 0xFF ) +
314+ String::chr ((char )(fourcc >> 8 ) & 0xFF ) +
315+ String::chr ((char )(fourcc >> 0 ) & 0xFF );
316+ result.push_back (dictionary);
317+ }
318+ return result;
270319}
271320
272321// ////////////////////////////////////////////////////////////////////////
0 commit comments