diff options
author | PatTheMav <PatTheMav@users.noreply.github.com> | 2024-02-24 03:33:04 +0100 |
---|---|---|
committer | Lain <lain@obsproject.com> | 2024-02-24 17:38:18 -0600 |
commit | 745f87f21ff6a1fca2d2dbf909b93a752736eab7 (patch) | |
tree | 062747adcf9dd1c762a3f6b8c2b4c88ddf63b069 | |
parent | 409bd12db38095f440bd59da68a7df46c6787a4e (diff) |
mac-avcapture: Fix frame rate collection for camera device formats
Some devices will report different framerate ranges for formats that
are identical apart from color primaries. Without taking these into
account, only framerates for one color primary variant would be used
to populate the framerate dropdown in the property view of the camera
source.
Checking for a difference in color primaries when iterating over all
available formats for a device thus requires checking for this
variation and adding the additional frame rate range as well.
-rw-r--r-- | plugins/mac-avcapture/OBSAVCapture.m | 1 | ||||
-rw-r--r-- | plugins/mac-avcapture/plugin-properties.m | 53 |
2 files changed, 33 insertions, 21 deletions
diff --git a/plugins/mac-avcapture/OBSAVCapture.m b/plugins/mac-avcapture/OBSAVCapture.m index df1a03e6c..ba8507ad3 100644 --- a/plugins/mac-avcapture/OBSAVCapture.m +++ b/plugins/mac-avcapture/OBSAVCapture.m @@ -197,6 +197,7 @@ [self.deviceInput.device unlockForConfiguration]; self.deviceInput = nil; self.isDeviceLocked = NO; + self.presetFormat = nil; } if (!device) { diff --git a/plugins/mac-avcapture/plugin-properties.m b/plugins/mac-avcapture/plugin-properties.m index 4aed2eda9..8bd37bbea 100644 --- a/plugins/mac-avcapture/plugin-properties.m +++ b/plugins/mac-avcapture/plugin-properties.m @@ -338,6 +338,8 @@ bool properties_update_config(OBSAVCapture *capture, obs_properties_t *propertie BOOL hasFoundColorSpace = capture.isFastPath; BOOL hasFoundVideoRange = capture.isFastPath; + CFPropertyListRef priorColorPrimary = @""; + if (device) { // Iterate over all formats reported by the device and gather them for property lists for (AVCaptureDeviceFormat *format in device.formats) { @@ -419,29 +421,38 @@ bool properties_update_config(OBSAVCapture *capture, obs_properties_t *propertie } // Only iterate over available framerates if input format, color space, and resolution are matching - if (hasFoundInputFormat && hasFoundColorSpace && hasFoundResolution && !hasFoundFramerate) { - for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges.reverseObjectEnumerator) { - FourCharCode formatSubType = CMFormatDescriptionGetMediaSubType(format.formatDescription); - int device_format = [OBSAVCapture formatFromSubtype:formatSubType]; - - if (input_format == device_format) { - struct media_frames_per_second min_fps = { - .numerator = (uint32_t) clamp_Uint(range.maxFrameDuration.timescale, 0, UINT32_MAX), - .denominator = (uint32_t) clamp_Uint(range.maxFrameDuration.value, 0, UINT32_MAX)}; - struct media_frames_per_second max_fps = { - .numerator = (uint32_t) clamp_Uint(range.minFrameDuration.timescale, 0, UINT32_MAX), - .denominator = (uint32_t) clamp_Uint(range.minFrameDuration.value, 0, UINT32_MAX)}; - - if (![frameRates containsObject:range]) { - obs_property_frame_rate_fps_range_add(prop_framerate, min_fps, max_fps); - [frameRates addObject:range]; - } - - if (!hasFoundFramerate && CMTimeCompare(range.maxFrameDuration, time) >= 0 && - CMTimeCompare(range.minFrameDuration, time) <= 0) { - hasFoundFramerate = YES; + if (hasFoundInputFormat && hasFoundColorSpace && hasFoundResolution) { + CFPropertyListRef colorPrimary = CMFormatDescriptionGetExtension( + format.formatDescription, kCMFormatDescriptionExtension_ColorPrimaries); + + CFComparisonResult isColorPrimaryMatch = CFStringCompare(colorPrimary, priorColorPrimary, 0); + + if (isColorPrimaryMatch != kCFCompareEqualTo || !hasFoundFramerate) { + for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges.reverseObjectEnumerator) { + FourCharCode formatSubType = CMFormatDescriptionGetMediaSubType(format.formatDescription); + int device_format = [OBSAVCapture formatFromSubtype:formatSubType]; + + if (input_format == device_format) { + struct media_frames_per_second min_fps = { + .numerator = (uint32_t) clamp_Uint(range.maxFrameDuration.timescale, 0, UINT32_MAX), + .denominator = (uint32_t) clamp_Uint(range.maxFrameDuration.value, 0, UINT32_MAX)}; + struct media_frames_per_second max_fps = { + .numerator = (uint32_t) clamp_Uint(range.minFrameDuration.timescale, 0, UINT32_MAX), + .denominator = (uint32_t) clamp_Uint(range.minFrameDuration.value, 0, UINT32_MAX)}; + + if (![frameRates containsObject:range]) { + obs_property_frame_rate_fps_range_add(prop_framerate, min_fps, max_fps); + [frameRates addObject:range]; + } + + if (!hasFoundFramerate && CMTimeCompare(range.maxFrameDuration, time) >= 0 && + CMTimeCompare(range.minFrameDuration, time) <= 0) { + hasFoundFramerate = YES; + } } } + + priorColorPrimary = colorPrimary; } } } |