7#include <QtCore/qvector.h>
8#include <QtCore/qpair.h>
9#include <private/qmultimediautils_p.h>
10#include <private/qcameradevice_p.h>
31 if (videoConnection.supportsVideoMinFrameDuration) {
32 const CMTime cmMin = videoConnection.videoMinFrameDuration;
33 if (CMTimeCompare(cmMin, kCMTimeInvalid)) {
34 if (
const Float64 minSeconds = CMTimeGetSeconds(cmMin))
35 newRange.second = 1. / minSeconds;
39 if (videoConnection.supportsVideoMaxFrameDuration) {
40 const CMTime cmMax = videoConnection.videoMaxFrameDuration;
41 if (CMTimeCompare(cmMax, kCMTimeInvalid)) {
42 if (
const Float64 maxSeconds = CMTimeGetSeconds(cmMax))
43 newRange.first = 1. / maxSeconds;
52inline bool qt_area_sane(
const QSize &
size)
54 return !
size.isNull() &&
size.isValid()
55 && std::numeric_limits<int>::max() /
size.width() >=
size.height();
58template <
template <
typename...>
class Comp>
61 bool operator() (AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)
const
67 const Comp<std::tuple<int, int>> op = {};
73struct FormatHasNoFPSRange
75 bool operator() (AVCaptureDeviceFormat *
format)
const
78 return !
format.videoSupportedFrameRateRanges || !
format.videoSupportedFrameRateRanges.count;
85 &&
format.videoSupportedFrameRateRanges.count);
87 AVFrameRateRange *
range = [
format.videoSupportedFrameRateRanges objectAtIndex:0];
90 range = [
format.videoSupportedFrameRateRanges objectAtIndex:
i];
99AVCaptureDeviceFormat *
102 const std::function<
bool(uint32_t)> &cvFormatValidator)
105 if (!cameraFormatPrivate)
109 cameraFormatPrivate->colorRange);
114 AVCaptureDeviceFormat *newFormat = nil;
115 Float64 newFormatMaxFrameRate = {};
116 NSArray<AVCaptureDeviceFormat *> *
formats = captureDevice.formats;
118 CMFormatDescriptionRef formatDesc =
format.formatDescription;
119 CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDesc);
120 FourCharCode cvPixFormat = CMVideoFormatDescriptionGetCodecType(formatDesc);
122 if (cvPixFormat != requiredCvPixFormat)
125 if (cameraFormatPrivate->resolution !=
QSize(dim.width, dim.height))
128 if (cvFormatValidator && !cvFormatValidator(cvPixFormat))
131 for (AVFrameRateRange *frameRateRange
in format.videoSupportedFrameRateRanges) {
132 if (frameRateRange.minFrameRate >= cameraFormatPrivate->minFrameRate
133 && frameRateRange.maxFrameRate <= cameraFormatPrivate->maxFrameRate
134 && newFormatMaxFrameRate < frameRateRange.maxFrameRate) {
136 newFormatMaxFrameRate = frameRateRange.maxFrameRate;
148 QVector<AVCaptureDeviceFormat *>
formats;
150 if (!captureDevice.formats || !captureDevice.formats.count)
153 formats.reserve(captureDevice.formats.count);
154 for (AVCaptureDeviceFormat *
format in captureDevice.formats) {
164 std::sort(
formats.begin(),
formats.end(), ByResolution<std::less>());
167 FourCharCode
codec = CMVideoFormatDescriptionGetCodecType(
formats[0].formatDescription);
171 if (nextSize ==
size) {
180 codec = CMVideoFormatDescriptionGetCodecType(
formats[
i].formatDescription);
192 const CMVideoDimensions
res = CMVideoFormatDescriptionGetDimensions(
format.formatDescription);
201 const CMVideoDimensions hrDim(
format.highResolutionStillImageDimensions);
202 res.setWidth(hrDim.width);
203 res.setHeight(hrDim.height);
212 QVector<AVFPSRange> qtRanges;
214 if (!
format.videoSupportedFrameRateRanges || !
format.videoSupportedFrameRateRanges.count)
217 qtRanges.reserve(
format.videoSupportedFrameRateRanges.count);
218 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges)
228 if (!
format.formatDescription) {
233 const CMVideoDimensions
res = CMVideoFormatDescriptionGetDimensions(
format.formatDescription);
234 const CGSize resPAR = CMVideoFormatDescriptionGetPresentationDimensions(
format.formatDescription,
true,
false);
236 if (
qAbs(resPAR.width -
res.width) < 1.) {
241 if (!
res.width || !resPAR.width)
247 return QSize(frac.numerator, frac.denominator);
258 if (!captureDevice.formats || !captureDevice.formats.count)
275 typedef QPair<QSize, AVCaptureDeviceFormat *> FormatPair;
277 QVector<FormatPair> pairs;
283 if (!
res.isNull() &&
res.isValid() && qt_area_sane(
res))
286 if (stillImage && !highRes.isNull() && highRes.isValid() && qt_area_sane(highRes))
287 pairs << FormatPair(highRes,
format);
293 AVCaptureDeviceFormat *best = pairs[0].second;
299 for (
int i = 1;
i < pairs.size(); ++
i) {
300 next = pairs[
i].first;
305 if ((newWDiff < wDiff && newHDiff < hDiff)
306 || ((newWDiff <= wDiff || newHDiff <= hDiff) && newAreaDiff <= areaDiff)) {
309 best = pairs[
i].second;
310 areaDiff = newAreaDiff;
328 std::sort(sorted.begin(), sorted.end(), ByResolution<std::greater>());
330 sorted.erase(std::remove_if(sorted.begin(), sorted.end(), FormatHasNoFPSRange()), sorted.end());
335 for (
int i = 0;
i < sorted.size(); ++
i) {
336 AVCaptureDeviceFormat *
format = sorted[
i];
337 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges) {
344 if (fps >=
range.minFrameRate && fps <=
range.maxFrameRate)
350 AVCaptureDeviceFormat *
match = sorted[0];
351 for (
int i = 1;
i < sorted.size(); ++
i) {
352 const Float64 newDistance = qt_find_min_framerate_distance(sorted[
i], fps);
365 &&
format.videoSupportedFrameRateRanges.count);
369 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges) {
376 if (fps >=
range.minFrameRate && fps <=
range.maxFrameRate)
380 AVFrameRateRange *
match = [
format.videoSupportedFrameRateRanges objectAtIndex:0];
383 AVFrameRateRange *
range = [
format.videoSupportedFrameRateRanges objectAtIndex:
i];
398 for (AVFrameRateRange *
range in format.videoSupportedFrameRateRanges) {
412 if (![f1.mediaType isEqualToString:f2.mediaType])
415 return CMFormatDescriptionEqual(f1.formatDescription, f2.formatDescription);
420 static bool firstSet =
true;
422 if (!captureDevice || !
format)
440 qWarning(
"Failed to set active format (lock failed)");
449 captureDevice.activeFormat =
format;
461 if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
467 CMTime minDuration = kCMTimeInvalid;
469 if (!videoConnection.supportsVideoMinFrameDuration)
472 minDuration = CMTimeMake(1, maxFPS);
474 if (videoConnection.supportsVideoMinFrameDuration)
475 videoConnection.videoMinFrameDuration = minDuration;
477 CMTime maxDuration = kCMTimeInvalid;
479 if (!videoConnection.supportsVideoMaxFrameDuration)
482 maxDuration = CMTimeMake(1, minFPS);
484 if (videoConnection.supportsVideoMaxFrameDuration)
485 videoConnection.videoMaxFrameDuration = maxDuration;
493 if (
range.maxFrameRate -
range.minFrameRate < 0.1) {
495 return range.minFrameDuration;
498 if (fps <=
range.minFrameRate)
499 return range.maxFrameDuration;
500 if (fps >=
range.maxFrameRate)
501 return range.minFrameDuration;
504 return CMTimeMake(frac.numerator, frac.denominator);
510 if (!captureDevice.activeFormat) {
515 if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
521 CMTime minFrameDuration = kCMTimeInvalid;
522 CMTime maxFrameDuration = kCMTimeInvalid;
523 if (maxFPS || minFPS) {
525 maxFPS ? maxFPS : minFPS);
550 [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
551 [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
552#elif defined(Q_OS_MACOS)
553 if (CMTimeCompare(minFrameDuration, kCMTimeInvalid) == 0
554 && CMTimeCompare(maxFrameDuration, kCMTimeInvalid) == 0) {
555 AVFrameRateRange *
range = captureDevice.activeFormat.videoSupportedFrameRateRanges.firstObject;
556 minFrameDuration =
range.minFrameDuration;
557 maxFrameDuration =
range.maxFrameDuration;
560 if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
561 [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
563 if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
564 [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
582 const CMTime minDuration = captureDevice.activeVideoMinFrameDuration;
583 if (CMTimeCompare(minDuration, kCMTimeInvalid)) {
584 if (
const Float64 minSeconds = CMTimeGetSeconds(minDuration))
585 fps.second = 1. / minSeconds;
588 const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
589 if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
590 if (
const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
591 fps.first = 1. / maxSeconds;
599 QList<AudioValueRange>
result;
602 OSStatus err = AudioFormatGetPropertyInfo(
603 kAudioFormatProperty_AvailableEncodeSampleRates,
611 UInt32 numRanges =
size /
sizeof(AudioValueRange);
612 AudioValueRange sampleRanges[numRanges];
614 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeSampleRates,
622 for (UInt32
i = 0;
i < numRanges;
i++)
630 QList<AudioValueRange>
result;
633 OSStatus err = AudioFormatGetPropertyInfo(
634 kAudioFormatProperty_AvailableEncodeBitRates,
642 UInt32 numRanges =
size /
sizeof(AudioValueRange);
643 AudioValueRange bitRanges[numRanges];
645 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeBitRates,
653 for (UInt32
i = 0;
i < numRanges;
i++)
662 AudioStreamBasicDescription sf = {};
665 OSStatus err = AudioFormatGetPropertyInfo(
666 kAudioFormatProperty_AvailableEncodeNumberChannels,
679 UInt32 numCounts =
size /
sizeof(UInt32);
680 UInt32 channelCounts[numCounts];
682 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeNumberChannels,
690 for (UInt32
i = 0;
i < numCounts;
i++)
699 AudioStreamBasicDescription sf = {};
701 sf.mChannelsPerFrame = noChannels;
703 OSStatus err = AudioFormatGetPropertyInfo(
704 kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
712 UInt32 noTags = (UInt32)
size /
sizeof(UInt32);
713 AudioChannelLayoutTag tagsArr[noTags];
715 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
723 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
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr int width() const noexcept
Returns the width of the rectangle.
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.
CvPixelFormat toCVPixelFormat(QVideoFrameFormat::PixelFormat pixFmt, QVideoFrameFormat::ColorRange colorRange)
Combined button and popup list for selecting options.
constexpr CvPixelFormat CvPixelFormatInvalid
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)