Skip to content

Commit ab9927a

Browse files
committed
Support CameraFeed format on macOS
1 parent 45fc515 commit ab9927a

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

modules/camera/camera_macos.mm

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
200200
private:
201201
AVCaptureDevice *device;
202202
MyCaptureSession *capture_session;
203+
bool format_locked;
203204

204205
public:
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

215219
AVCaptureDevice *CameraFeedMacOS::get_device() const {
@@ -219,6 +223,7 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CM
219223
CameraFeedMacOS::CameraFeedMacOS() {
220224
device = nullptr;
221225
capture_session = nullptr;
226+
format_locked = false;
222227
}
223228

224229
void 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

Comments
 (0)