7#include <QtCore/qvector.h>
8#include <QtCore/qpair.h>
9#include <private/qmultimediautils_p.h>
30 if (videoConnection.supportsVideoMinFrameDuration) {
31 const CMTime cmMin = videoConnection.videoMinFrameDuration;
32 if (CMTimeCompare(cmMin, kCMTimeInvalid)) {
33 if (
const Float64 minSeconds = CMTimeGetSeconds(cmMin))
34 newRange.second = 1. / minSeconds;
38 if (videoConnection.supportsVideoMaxFrameDuration) {
39 const CMTime cmMax = videoConnection.videoMaxFrameDuration;
40 if (CMTimeCompare(cmMax, kCMTimeInvalid)) {
41 if (
const Float64 maxSeconds = CMTimeGetSeconds(cmMax))
42 newRange.first = 1. / maxSeconds;
51inline bool qt_area_sane(
const QSize &
size)
53 return !
size.isNull() &&
size.isValid()
54 && std::numeric_limits<int>::max() /
size.width() >=
size.height();
57template <
template <
typename...>
class Comp>
60 bool operator() (AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)
const
66 const Comp<std::tuple<int, int>> op = {};
72struct FormatHasNoFPSRange
74 bool operator() (AVCaptureDeviceFormat *
format)
const
77 return !
format.videoSupportedFrameRateRanges || !
format.videoSupportedFrameRateRanges.count;
84 &&
format.videoSupportedFrameRateRanges.count);
86 AVFrameRateRange *
range = [
format.videoSupportedFrameRateRanges objectAtIndex:0];
89 range = [
format.videoSupportedFrameRateRanges objectAtIndex:
i];
98AVCaptureDeviceFormat *
101 const std::function<
bool(uint32_t)> &cvFormatValidator)
103 AVCaptureDeviceFormat *newFormat = nil;
104 NSArray<AVCaptureDeviceFormat *> *
formats = captureDevice.formats;
106 CMFormatDescriptionRef formatDesc =
format.formatDescription;
107 CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDesc);
108 FourCharCode formatCodec = CMVideoFormatDescriptionGetCodecType(formatDesc);
112 && (!cvFormatValidator || cvFormatValidator(formatCodec))) {
113 for (AVFrameRateRange *frameRateRange
in format.videoSupportedFrameRateRanges) {
114 if (frameRateRange.minFrameRate >= cameraFormat.
minFrameRate()
115 && frameRateRange.maxFrameRate <= cameraFormat.
maxFrameRate()) {
134 if (!captureDevice.formats || !captureDevice.formats.count)
137 formats.reserve(captureDevice.formats.count);
138 for (AVCaptureDeviceFormat *
format in captureDevice.formats) {
148 std::sort(
formats.begin(),
formats.end(), ByResolution<std::less>());
151 FourCharCode
codec = CMVideoFormatDescriptionGetCodecType(
formats[0].formatDescription);
155 if (nextSize ==
size) {
164 codec = CMVideoFormatDescriptionGetCodecType(
formats[
i].formatDescription);
176 const CMVideoDimensions
res = CMVideoFormatDescriptionGetDimensions(
format.formatDescription);
185 const CMVideoDimensions hrDim(
format.highResolutionStillImageDimensions);
186 res.setWidth(hrDim.width);
187 res.setHeight(hrDim.height);
198 if (!
format.videoSupportedFrameRateRanges || !
format.videoSupportedFrameRateRanges.count)
201 qtRanges.
reserve(
format.videoSupportedFrameRateRanges.count);
202 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges)
212 if (!
format.formatDescription) {
217 const CMVideoDimensions
res = CMVideoFormatDescriptionGetDimensions(
format.formatDescription);
218 const CGSize resPAR = CMVideoFormatDescriptionGetPresentationDimensions(
format.formatDescription,
true,
false);
220 if (
qAbs(resPAR.width -
res.width) < 1.) {
225 if (!
res.width || !resPAR.width)
231 return QSize(frac.numerator, frac.denominator);
242 if (!captureDevice.formats || !captureDevice.formats.count)
267 if (!
res.isNull() &&
res.isValid() && qt_area_sane(
res))
270 if (stillImage && !highRes.
isNull() && highRes.
isValid() && qt_area_sane(highRes))
271 pairs << FormatPair(highRes,
format);
277 AVCaptureDeviceFormat *best = pairs[0].second;
283 for (
int i = 1;
i < pairs.
size(); ++
i) {
289 if ((newWDiff < wDiff && newHDiff < hDiff)
290 || ((newWDiff <= wDiff || newHDiff <= hDiff) && newAreaDiff <= areaDiff)) {
293 best = pairs[
i].second;
294 areaDiff = newAreaDiff;
312 std::sort(sorted.
begin(), sorted.
end(), ByResolution<std::greater>());
314 sorted.
erase(std::remove_if(sorted.
begin(), sorted.
end(), FormatHasNoFPSRange()), sorted.
end());
319 for (
int i = 0;
i < sorted.
size(); ++
i) {
320 AVCaptureDeviceFormat *
format = sorted[
i];
321 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges) {
328 if (fps >=
range.minFrameRate && fps <=
range.maxFrameRate)
334 AVCaptureDeviceFormat *
match = sorted[0];
335 for (
int i = 1;
i < sorted.
size(); ++
i) {
336 const Float64 newDistance = qt_find_min_framerate_distance(sorted[
i], fps);
349 &&
format.videoSupportedFrameRateRanges.count);
353 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges) {
360 if (fps >=
range.minFrameRate && fps <=
range.maxFrameRate)
364 AVFrameRateRange *
match = [
format.videoSupportedFrameRateRanges objectAtIndex:0];
367 AVFrameRateRange *
range = [
format.videoSupportedFrameRateRanges objectAtIndex:
i];
382 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges) {
396 if (![f1.mediaType isEqualToString:f2.mediaType])
399 return CMFormatDescriptionEqual(f1.formatDescription, f2.formatDescription);
404 static bool firstSet =
true;
406 if (!captureDevice || !
format)
424 qWarning(
"Failed to set active format (lock failed)");
433 captureDevice.activeFormat =
format;
445 if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
451 CMTime minDuration = kCMTimeInvalid;
453 if (!videoConnection.supportsVideoMinFrameDuration)
456 minDuration = CMTimeMake(1, maxFPS);
458 if (videoConnection.supportsVideoMinFrameDuration)
459 videoConnection.videoMinFrameDuration = minDuration;
461 CMTime maxDuration = kCMTimeInvalid;
463 if (!videoConnection.supportsVideoMaxFrameDuration)
466 maxDuration = CMTimeMake(1, minFPS);
468 if (videoConnection.supportsVideoMaxFrameDuration)
469 videoConnection.videoMaxFrameDuration = maxDuration;
477 if (
range.maxFrameRate -
range.minFrameRate < 0.1) {
479 return range.minFrameDuration;
482 if (fps <=
range.minFrameRate)
483 return range.maxFrameDuration;
484 if (fps >=
range.maxFrameRate)
485 return range.minFrameDuration;
488 return CMTimeMake(frac.numerator, frac.denominator);
494 if (!captureDevice.activeFormat) {
499 if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
505 CMTime minFrameDuration = kCMTimeInvalid;
506 CMTime maxFrameDuration = kCMTimeInvalid;
507 if (maxFPS || minFPS) {
509 maxFPS ? maxFPS : minFPS);
534 [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
535 [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
536#elif defined(Q_OS_MACOS)
537 if (CMTimeCompare(minFrameDuration, kCMTimeInvalid) == 0
538 && CMTimeCompare(maxFrameDuration, kCMTimeInvalid) == 0) {
539 AVFrameRateRange *
range = captureDevice.activeFormat.videoSupportedFrameRateRanges.firstObject;
540 minFrameDuration =
range.minFrameDuration;
541 maxFrameDuration =
range.maxFrameDuration;
544 if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
545 [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
547 if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
548 [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
566 const CMTime minDuration = captureDevice.activeVideoMinFrameDuration;
567 if (CMTimeCompare(minDuration, kCMTimeInvalid)) {
568 if (
const Float64 minSeconds = CMTimeGetSeconds(minDuration))
569 fps.second = 1. / minSeconds;
572 const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
573 if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
574 if (
const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
575 fps.first = 1. / maxSeconds;
586 OSStatus err = AudioFormatGetPropertyInfo(
587 kAudioFormatProperty_AvailableEncodeSampleRates,
595 UInt32 numRanges =
size /
sizeof(AudioValueRange);
596 AudioValueRange sampleRanges[numRanges];
598 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeSampleRates,
606 for (UInt32
i = 0;
i < numRanges;
i++)
617 OSStatus err = AudioFormatGetPropertyInfo(
618 kAudioFormatProperty_AvailableEncodeBitRates,
626 UInt32 numRanges =
size /
sizeof(AudioValueRange);
627 AudioValueRange bitRanges[numRanges];
629 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeBitRates,
637 for (UInt32
i = 0;
i < numRanges;
i++)
646 AudioStreamBasicDescription sf = {};
649 OSStatus err = AudioFormatGetPropertyInfo(
650 kAudioFormatProperty_AvailableEncodeNumberChannels,
663 UInt32 numCounts =
size /
sizeof(UInt32);
664 UInt32 channelCounts[numCounts];
666 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeNumberChannels,
674 for (UInt32
i = 0;
i < numCounts;
i++)
683 AudioStreamBasicDescription sf = {};
685 sf.mChannelsPerFrame = noChannels;
687 OSStatus err = AudioFormatGetPropertyInfo(
688 kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
696 UInt32 noTags = (UInt32)
size /
sizeof(UInt32);
697 AudioChannelLayoutTag tagsArr[noTags];
699 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
707 for (UInt32
i = 0;
i < noTags;
i++)
QSize qt_device_format_resolution(AVCaptureDeviceFormat *format)
bool qt_formats_are_equal(AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)
AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection)
std::optional< QList< UInt32 > > qt_supported_channel_counts_for_format(int codecId)
QVector< AVCaptureDeviceFormat * > qt_unique_device_formats(AVCaptureDevice *captureDevice, FourCharCode filter)
QVector< AVFPSRange > qt_device_format_framerates(AVCaptureDeviceFormat *format)
QT_BEGIN_NAMESPACE AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection)
QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format)
QList< AudioValueRange > qt_supported_sample_rates_for_format(int codecId)
QList< UInt32 > qt_supported_channel_layout_tags_for_format(int codecId, int noChannels)
AVCaptureDeviceFormat * qt_find_best_framerate_match(AVCaptureDevice *captureDevice, FourCharCode filter, Float64 fps)
QList< AudioValueRange > qt_supported_bit_rates_for_format(int codecId)
bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat *format, bool preserveFps)
AVFrameRateRange * qt_find_supported_framerate_range(AVCaptureDeviceFormat *format, Float64 fps)
void qt_set_framerate_limits(AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS)
QSize qt_device_format_pixel_aspect_ratio(AVCaptureDeviceFormat *format)
AVCaptureDeviceFormat * qt_find_best_resolution_match(AVCaptureDevice *captureDevice, const QSize &request, FourCharCode filter, bool stillImage)
CMTime qt_adjusted_frame_duration(AVFrameRateRange *range, qreal fps)
bool qt_format_supports_framerate(AVCaptureDeviceFormat *format, qreal fps)
AVCaptureDeviceFormat * qt_convert_to_capture_device_format(AVCaptureDevice *captureDevice, const QCameraFormat &cameraFormat, const std::function< bool(uint32_t)> &cvFormatValidator)
QPair< qreal, qreal > AVFPSRange
qsizetype size() const noexcept
iterator erase(const_iterator begin, const_iterator end)
void reserve(qsizetype size)
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
QVideoFrameFormat::PixelFormat fromCVPixelFormat(unsigned avPixelFormat)
Combined button and popup list for selecting options.
std::pair< T1, T2 > QPair
static int area(const QSize &s)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr T qAbs(const T &t)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLsizei GLfloat distance
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint GLsizei GLsizei GLenum format
static const qreal epsilon
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
QNetworkRequest request(url)