Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
avfcamerautility.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "avfcameradebug_p.h"
6
7#include <QtCore/qvector.h>
8#include <QtCore/qpair.h>
9#include <private/qmultimediautils_p.h>
10#include "avfvideobuffer_p.h"
11#include "qavfhelpers_p.h"
12
13#include <functional>
14#include <algorithm>
15#include <limits>
16#include <tuple>
17
19
20Q_LOGGING_CATEGORY(qLcCamera, "qt.multimedia.camera")
21
22AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection)
23{
24 Q_ASSERT(videoConnection);
25
26 AVFPSRange newRange;
27 // "The value in the videoMinFrameDuration is equivalent to the reciprocal
28 // of the maximum framerate, the value in the videoMaxFrameDuration is equivalent
29 // to the reciprocal of the minimum framerate."
30 if (videoConnection.supportsVideoMinFrameDuration) {
31 const CMTime cmMin = videoConnection.videoMinFrameDuration;
32 if (CMTimeCompare(cmMin, kCMTimeInvalid)) { // Has some non-default value:
33 if (const Float64 minSeconds = CMTimeGetSeconds(cmMin))
34 newRange.second = 1. / minSeconds;
35 }
36 }
37
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;
43 }
44 }
45
46 return newRange;
47}
48
49namespace {
50
51inline bool qt_area_sane(const QSize &size)
52{
53 return !size.isNull() && size.isValid()
54 && std::numeric_limits<int>::max() / size.width() >= size.height();
55}
56
57template <template <typename...> class Comp> // std::less or std::greater (or std::equal_to)
58struct ByResolution
59{
60 bool operator() (AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)const
61 {
62 Q_ASSERT(f1 && f2);
65 // use std::tuple for lexicograpical sorting:
66 const Comp<std::tuple<int, int>> op = {};
67 return op(std::make_tuple(r1.width(), r1.height()),
68 std::make_tuple(r2.width(), r2.height()));
69 }
70};
71
72struct FormatHasNoFPSRange
73{
74 bool operator() (AVCaptureDeviceFormat *format) const
75 {
77 return !format.videoSupportedFrameRateRanges || !format.videoSupportedFrameRateRanges.count;
78 }
79};
80
81Float64 qt_find_min_framerate_distance(AVCaptureDeviceFormat *format, Float64 fps)
82{
83 Q_ASSERT(format && format.videoSupportedFrameRateRanges
84 && format.videoSupportedFrameRateRanges.count);
85
86 AVFrameRateRange *range = [format.videoSupportedFrameRateRanges objectAtIndex:0];
87 Float64 distance = qAbs(range.maxFrameRate - fps);
88 for (NSUInteger i = 1, e = format.videoSupportedFrameRateRanges.count; i < e; ++i) {
89 range = [format.videoSupportedFrameRateRanges objectAtIndex:i];
90 distance = qMin(distance, qAbs(range.maxFrameRate - fps));
91 }
92
93 return distance;
94}
95
96} // Unnamed namespace.
97
98AVCaptureDeviceFormat *
99qt_convert_to_capture_device_format(AVCaptureDevice *captureDevice,
100 const QCameraFormat &cameraFormat,
101 const std::function<bool(uint32_t)> &cvFormatValidator)
102{
103 AVCaptureDeviceFormat *newFormat = nil;
104 NSArray<AVCaptureDeviceFormat *> *formats = captureDevice.formats;
105 for (AVCaptureDeviceFormat *format in formats) {
106 CMFormatDescriptionRef formatDesc = format.formatDescription;
107 CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDesc);
108 FourCharCode formatCodec = CMVideoFormatDescriptionGetCodecType(formatDesc);
109 if (QAVFHelpers::fromCVPixelFormat(formatCodec) == cameraFormat.pixelFormat()
110 && cameraFormat.resolution().width() == dim.width
111 && cameraFormat.resolution().height() == dim.height
112 && (!cvFormatValidator || cvFormatValidator(formatCodec))) {
113 for (AVFrameRateRange *frameRateRange in format.videoSupportedFrameRateRanges) {
114 if (frameRateRange.minFrameRate >= cameraFormat.minFrameRate()
115 && frameRateRange.maxFrameRate <= cameraFormat.maxFrameRate()) {
116 newFormat = format;
117 break;
118 }
119 }
120 }
121 if (newFormat)
122 break;
123 }
124 return newFormat;
125}
126
127QVector<AVCaptureDeviceFormat *> qt_unique_device_formats(AVCaptureDevice *captureDevice, FourCharCode filter)
128{
129 // 'filter' is the format we prefer if we have duplicates.
130 Q_ASSERT(captureDevice);
131
133
134 if (!captureDevice.formats || !captureDevice.formats.count)
135 return formats;
136
137 formats.reserve(captureDevice.formats.count);
138 for (AVCaptureDeviceFormat *format in captureDevice.formats) {
139 const QSize resolution(qt_device_format_resolution(format));
140 if (resolution.isNull() || !resolution.isValid())
141 continue;
142 formats << format;
143 }
144
145 if (!formats.size())
146 return formats;
147
148 std::sort(formats.begin(), formats.end(), ByResolution<std::less>());
149
151 FourCharCode codec = CMVideoFormatDescriptionGetCodecType(formats[0].formatDescription);
152 int last = 0;
153 for (int i = 1; i < formats.size(); ++i) {
154 const QSize nextSize(qt_device_format_resolution(formats[i]));
155 if (nextSize == size) {
156 if (codec == filter)
157 continue;
158 formats[last] = formats[i];
159 } else {
160 ++last;
161 formats[last] = formats[i];
162 size = nextSize;
163 }
164 codec = CMVideoFormatDescriptionGetCodecType(formats[i].formatDescription);
165 }
166 formats.resize(last + 1);
167
168 return formats;
169}
170
172{
173 if (!format || !format.formatDescription)
174 return QSize();
175
176 const CMVideoDimensions res = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
177 return QSize(res.width, res.height);
178}
179
181{
183 QSize res;
184#if defined(Q_OS_IOS)
185 const CMVideoDimensions hrDim(format.highResolutionStillImageDimensions);
186 res.setWidth(hrDim.width);
187 res.setHeight(hrDim.height);
188#endif
189 return res;
190}
191
193{
195
196 QVector<AVFPSRange> qtRanges;
197
198 if (!format.videoSupportedFrameRateRanges || !format.videoSupportedFrameRateRanges.count)
199 return qtRanges;
200
201 qtRanges.reserve(format.videoSupportedFrameRateRanges.count);
202 for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges)
203 qtRanges << AVFPSRange(range.minFrameRate, range.maxFrameRate);
204
205 return qtRanges;
206}
207
209{
211
212 if (!format.formatDescription) {
213 qCDebug(qLcCamera) << Q_FUNC_INFO << "no format description found";
214 return QSize();
215 }
216
217 const CMVideoDimensions res = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
218 const CGSize resPAR = CMVideoFormatDescriptionGetPresentationDimensions(format.formatDescription, true, false);
219
220 if (qAbs(resPAR.width - res.width) < 1.) {
221 // "Pixel aspect ratio is used to adjust the width, leaving the height alone."
222 return QSize(1, 1);
223 }
224
225 if (!res.width || !resPAR.width)
226 return QSize();
227
228 auto frac = qRealToFraction(resPAR.width > res.width ? res.width / qreal(resPAR.width)
229 : resPAR.width / qreal(res.width));
230
231 return QSize(frac.numerator, frac.denominator);
232}
233
234AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice,
235 const QSize &request,
236 FourCharCode filter,
237 bool stillImage)
238{
239 Q_ASSERT(captureDevice);
240 Q_ASSERT(!request.isNull() && request.isValid());
241
242 if (!captureDevice.formats || !captureDevice.formats.count)
243 return nullptr;
244
246
247 for (int i = 0; i < formats.size(); ++i) {
248 AVCaptureDeviceFormat *format = formats[i];
250 return format;
251 // iOS only (still images).
252 if (stillImage && qt_device_format_high_resolution(format) == request)
253 return format;
254 }
255
256 if (!qt_area_sane(request))
257 return nullptr;
258
259 typedef QPair<QSize, AVCaptureDeviceFormat *> FormatPair;
260
261 QVector<FormatPair> pairs; // default|HR sizes
262 pairs.reserve(formats.size());
263
264 for (int i = 0; i < formats.size(); ++i) {
265 AVCaptureDeviceFormat *format = formats[i];
267 if (!res.isNull() && res.isValid() && qt_area_sane(res))
268 pairs << FormatPair(res, format);
270 if (stillImage && !highRes.isNull() && highRes.isValid() && qt_area_sane(highRes))
271 pairs << FormatPair(highRes, format);
272 }
273
274 if (!pairs.size())
275 return nullptr;
276
277 AVCaptureDeviceFormat *best = pairs[0].second;
278 QSize next(pairs[0].first);
279 int wDiff = qAbs(request.width() - next.width());
280 int hDiff = qAbs(request.height() - next.height());
281 const int area = request.width() * request.height();
282 int areaDiff = qAbs(area - next.width() * next.height());
283 for (int i = 1; i < pairs.size(); ++i) {
284 next = pairs[i].first;
285 const int newWDiff = qAbs(next.width() - request.width());
286 const int newHDiff = qAbs(next.height() - request.height());
287 const int newAreaDiff = qAbs(area - next.width() * next.height());
288
289 if ((newWDiff < wDiff && newHDiff < hDiff)
290 || ((newWDiff <= wDiff || newHDiff <= hDiff) && newAreaDiff <= areaDiff)) {
291 wDiff = newWDiff;
292 hDiff = newHDiff;
293 best = pairs[i].second;
294 areaDiff = newAreaDiff;
295 }
296 }
297
298 return best;
299}
300
301AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevice,
302 FourCharCode filter,
303 Float64 fps)
304{
305 Q_ASSERT(captureDevice);
306 Q_ASSERT(fps > 0.);
307
308 const qreal epsilon = 0.1;
309
311 // Sort formats by their resolution in decreasing order:
312 std::sort(sorted.begin(), sorted.end(), ByResolution<std::greater>());
313 // We can use only formats with framerate ranges:
314 sorted.erase(std::remove_if(sorted.begin(), sorted.end(), FormatHasNoFPSRange()), sorted.end());
315
316 if (!sorted.size())
317 return nil;
318
319 for (int i = 0; i < sorted.size(); ++i) {
320 AVCaptureDeviceFormat *format = sorted[i];
321 for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) {
322 if (range.maxFrameRate - range.minFrameRate < epsilon) {
323 // On OS X ranges are points (built-in camera).
324 if (qAbs(fps - range.maxFrameRate) < epsilon)
325 return format;
326 }
327
328 if (fps >= range.minFrameRate && fps <= range.maxFrameRate)
329 return format;
330 }
331 }
332
333 Float64 distance = qt_find_min_framerate_distance(sorted[0], fps);
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);
337 if (newDistance < distance) {
338 distance = newDistance;
339 match = sorted[i];
340 }
341 }
342
343 return match;
344}
345
346AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *format, Float64 fps)
347{
348 Q_ASSERT(format && format.videoSupportedFrameRateRanges
349 && format.videoSupportedFrameRateRanges.count);
350
351 const qreal epsilon = 0.1;
352
353 for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) {
354 if (range.maxFrameRate - range.minFrameRate < epsilon) {
355 // On OS X ranges are points (built-in camera).
356 if (qAbs(fps - range.maxFrameRate) < epsilon)
357 return range;
358 }
359
360 if (fps >= range.minFrameRate && fps <= range.maxFrameRate)
361 return range;
362 }
363
364 AVFrameRateRange *match = [format.videoSupportedFrameRateRanges objectAtIndex:0];
365 Float64 distance = qAbs(match.maxFrameRate - fps);
366 for (NSUInteger i = 1, e = format.videoSupportedFrameRateRanges.count; i < e; ++i) {
367 AVFrameRateRange *range = [format.videoSupportedFrameRateRanges objectAtIndex:i];
368 const Float64 newDistance = qAbs(range.maxFrameRate - fps);
369 if (newDistance < distance) {
370 distance = newDistance;
371 match = range;
372 }
373 }
374
375 return match;
376}
377
378bool qt_format_supports_framerate(AVCaptureDeviceFormat *format, qreal fps)
379{
380 if (format && fps > qreal(0)) {
381 const qreal epsilon = 0.1;
382 for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) {
383 if (fps >= range.minFrameRate - epsilon && fps <= range.maxFrameRate + epsilon)
384 return true;
385 }
386 }
387
388 return false;
389}
390
391bool qt_formats_are_equal(AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2)
392{
393 if (f1 == f2)
394 return true;
395
396 if (![f1.mediaType isEqualToString:f2.mediaType])
397 return false;
398
399 return CMFormatDescriptionEqual(f1.formatDescription, f2.formatDescription);
400}
401
402bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat *format, bool preserveFps)
403{
404 static bool firstSet = true;
405
406 if (!captureDevice || !format)
407 return false;
408
409 if (qt_formats_are_equal(captureDevice.activeFormat, format)) {
410 if (firstSet) {
411 // The capture device format is persistent. The first time we set a format, report that
412 // it changed even if the formats are the same.
413 // This prevents the session from resetting the format to the default value.
414 firstSet = false;
415 return true;
416 }
417 return false;
418 }
419
420 firstSet = false;
421
422 const AVFConfigurationLock lock(captureDevice);
423 if (!lock) {
424 qWarning("Failed to set active format (lock failed)");
425 return false;
426 }
427
428 // Changing the activeFormat resets the frame rate.
429 AVFPSRange fps;
430 if (preserveFps)
431 fps = qt_current_framerates(captureDevice, nil);
432
433 captureDevice.activeFormat = format;
434
435 if (preserveFps)
436 qt_set_framerate_limits(captureDevice, nil, fps.first, fps.second);
437
438 return true;
439}
440
441void qt_set_framerate_limits(AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS)
442{
443 Q_ASSERT(videoConnection);
444
445 if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
446 qCDebug(qLcCamera) << Q_FUNC_INFO << "invalid framerates (min, max):"
447 << minFPS << maxFPS;
448 return;
449 }
450
451 CMTime minDuration = kCMTimeInvalid;
452 if (maxFPS > 0.) {
453 if (!videoConnection.supportsVideoMinFrameDuration)
454 qCDebug(qLcCamera) << Q_FUNC_INFO << "maximum framerate is not supported";
455 else
456 minDuration = CMTimeMake(1, maxFPS);
457 }
458 if (videoConnection.supportsVideoMinFrameDuration)
459 videoConnection.videoMinFrameDuration = minDuration;
460
461 CMTime maxDuration = kCMTimeInvalid;
462 if (minFPS > 0.) {
463 if (!videoConnection.supportsVideoMaxFrameDuration)
464 qCDebug(qLcCamera) << Q_FUNC_INFO << "minimum framerate is not supported";
465 else
466 maxDuration = CMTimeMake(1, minFPS);
467 }
468 if (videoConnection.supportsVideoMaxFrameDuration)
469 videoConnection.videoMaxFrameDuration = maxDuration;
470}
471
472CMTime qt_adjusted_frame_duration(AVFrameRateRange *range, qreal fps)
473{
475 Q_ASSERT(fps > 0.);
476
477 if (range.maxFrameRate - range.minFrameRate < 0.1) {
478 // Can happen on OS X.
479 return range.minFrameDuration;
480 }
481
482 if (fps <= range.minFrameRate)
483 return range.maxFrameDuration;
484 if (fps >= range.maxFrameRate)
485 return range.minFrameDuration;
486
487 auto frac = qRealToFraction(1. / fps);
488 return CMTimeMake(frac.numerator, frac.denominator);
489}
490
491void qt_set_framerate_limits(AVCaptureDevice *captureDevice, qreal minFPS, qreal maxFPS)
492{
493 Q_ASSERT(captureDevice);
494 if (!captureDevice.activeFormat) {
495 qCDebug(qLcCamera) << Q_FUNC_INFO << "no active capture device format";
496 return;
497 }
498
499 if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
500 qCDebug(qLcCamera) << Q_FUNC_INFO << "invalid framerates (min, max):"
501 << minFPS << maxFPS;
502 return;
503 }
504
505 CMTime minFrameDuration = kCMTimeInvalid;
506 CMTime maxFrameDuration = kCMTimeInvalid;
507 if (maxFPS || minFPS) {
508 AVFrameRateRange *range = qt_find_supported_framerate_range(captureDevice.activeFormat,
509 maxFPS ? maxFPS : minFPS);
510 if (!range) {
511 qCDebug(qLcCamera) << Q_FUNC_INFO << "no framerate range found, (min, max):"
512 << minFPS << maxFPS;
513 return;
514 }
515
516 if (maxFPS)
517 minFrameDuration = qt_adjusted_frame_duration(range, maxFPS);
518 if (minFPS)
519 maxFrameDuration = qt_adjusted_frame_duration(range, minFPS);
520 }
521
522 const AVFConfigurationLock lock(captureDevice);
523 if (!lock) {
524 qCDebug(qLcCamera) << Q_FUNC_INFO << "failed to lock for configuration";
525 return;
526 }
527
528 // While Apple's docs say kCMTimeInvalid will end in default
529 // settings for this format, kCMTimeInvalid on OS X ends with a runtime
530 // exception:
531 // "The activeVideoMinFrameDuration passed is not supported by the device."
532 // Instead, use the first item in the supported frame rates.
533#ifdef Q_OS_IOS
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;
542 }
543
544 if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
545 [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
546
547 if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
548 [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
549#endif // Q_OS_MACOS
550}
551
552void qt_set_framerate_limits(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection,
553 qreal minFPS, qreal maxFPS)
554{
555 Q_UNUSED(videoConnection);
556 Q_ASSERT(captureDevice);
557 qt_set_framerate_limits(captureDevice, minFPS, maxFPS);
558}
559
560AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection)
561{
562 Q_UNUSED(videoConnection);
563 Q_ASSERT(captureDevice);
564
565 AVFPSRange fps;
566 const CMTime minDuration = captureDevice.activeVideoMinFrameDuration;
567 if (CMTimeCompare(minDuration, kCMTimeInvalid)) {
568 if (const Float64 minSeconds = CMTimeGetSeconds(minDuration))
569 fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration.
570 }
571
572 const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
573 if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
574 if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
575 fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration.
576 }
577
578 return fps;
579}
580
582{
584 UInt32 format = codecId;
585 UInt32 size;
586 OSStatus err = AudioFormatGetPropertyInfo(
587 kAudioFormatProperty_AvailableEncodeSampleRates,
588 sizeof(format),
589 &format,
590 &size);
591
592 if (err != noErr)
593 return result;
594
595 UInt32 numRanges = size / sizeof(AudioValueRange);
596 AudioValueRange sampleRanges[numRanges];
597
598 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeSampleRates,
599 sizeof(format),
600 &format,
601 &size,
602 sampleRanges);
603 if (err != noErr)
604 return result;
605
606 for (UInt32 i = 0; i < numRanges; i++)
607 result << sampleRanges[i];
608
609 return result;
610}
611
613{
615 UInt32 format = codecId;
616 UInt32 size;
617 OSStatus err = AudioFormatGetPropertyInfo(
618 kAudioFormatProperty_AvailableEncodeBitRates,
619 sizeof(format),
620 &format,
621 &size);
622
623 if (err != noErr)
624 return result;
625
626 UInt32 numRanges = size / sizeof(AudioValueRange);
627 AudioValueRange bitRanges[numRanges];
628
629 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeBitRates,
630 sizeof(format),
631 &format,
632 &size,
633 bitRanges);
634 if (err != noErr)
635 return result;
636
637 for (UInt32 i = 0; i < numRanges; i++)
638 result << bitRanges[i];
639
640 return result;
641}
642
643std::optional<QList<UInt32>> qt_supported_channel_counts_for_format(int codecId)
644{
646 AudioStreamBasicDescription sf = {};
647 sf.mFormatID = codecId;
648 UInt32 size;
649 OSStatus err = AudioFormatGetPropertyInfo(
650 kAudioFormatProperty_AvailableEncodeNumberChannels,
651 sizeof(sf),
652 &sf,
653 &size);
654
655 if (err != noErr)
656 return result;
657
658 // From Apple's docs:
659 // A value of 0xFFFFFFFF indicates that any number of channels may be encoded.
660 if (int(size) == -1)
661 return std::nullopt;
662
663 UInt32 numCounts = size / sizeof(UInt32);
664 UInt32 channelCounts[numCounts];
665
666 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeNumberChannels,
667 sizeof(sf),
668 &sf,
669 &size,
670 channelCounts);
671 if (err != noErr)
672 return result;
673
674 for (UInt32 i = 0; i < numCounts; i++)
675 result << channelCounts[i];
676
677 return result;
678}
679
681{
683 AudioStreamBasicDescription sf = {};
684 sf.mFormatID = codecId;
685 sf.mChannelsPerFrame = noChannels;
686 UInt32 size;
687 OSStatus err = AudioFormatGetPropertyInfo(
688 kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
689 sizeof(sf),
690 &sf,
691 &size);
692
693 if (err != noErr)
694 return result;
695
696 UInt32 noTags = (UInt32)size / sizeof(UInt32);
697 AudioChannelLayoutTag tagsArr[noTags];
698
699 err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
700 sizeof(sf),
701 &sf,
702 &size,
703 tagsArr);
704 if (err != noErr)
705 return result;
706
707 for (UInt32 i = 0; i < noTags; i++)
708 result << tagsArr[i];
709
710 return result;
711}
712
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
The QCameraFormat class describes a video format supported by a camera device. \inmodule QtMultimedia...
QSize resolution
\qmlproperty size QtMultimedia::cameraFormat::resolution
float minFrameRate
\qmlproperty real QtMultimedia::cameraFormat::minFrameRate
QVideoFrameFormat::PixelFormat pixelFormat
\qmlproperty enumeration QtMultimedia::cameraFormat::pixelFormat
float maxFrameRate
\qmlproperty real QtMultimedia::cameraFormat::maxFrameRate
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
T & first()
Definition qlist.h:628
iterator erase(const_iterator begin, const_iterator end)
Definition qlist.h:882
iterator end()
Definition qlist.h:609
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:120
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
double e
short next
Definition keywords.cpp:445
EGLint EGLint * formats
QVideoFrameFormat::PixelFormat fromCVPixelFormat(unsigned avPixelFormat)
Combined button and popup list for selecting options.
unsigned long NSUInteger
#define Q_FUNC_INFO
std::pair< T1, T2 > QPair
QMediaFormat::AudioCodec codec
static AVCodecID codecId(QMediaFormat::VideoCodec codec)
static int area(const QSize &s)
Definition qicon.cpp:152
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
QT_BEGIN_NAMESPACE Fraction qRealToFraction(qreal value)
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei range
GLsizei GLsizei GLfloat distance
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint first
GLint GLsizei GLsizei GLenum format
GLuint res
GLuint in
GLuint64EXT * result
[6]
static const qreal epsilon
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
double qreal
Definition qtypes.h:92
QReadWriteLock lock
[0]
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
QNetworkRequest request(url)