4#include <QtFFmpegMediaPluginImpl/private/qavfcamera_p.h>
6#include <QtCore/qscopeguard.h>
7#include <QtCore/private/qcore_mac_p.h>
9#include <QtFFmpegMediaPluginImpl/private/qavfcamerafactory_p.h>
10#include <QtFFmpegMediaPluginImpl/private/qavfsamplebufferdelegate_p.h>
12#include <QtMultimedia/private/qavfcameradebug_p.h>
13#include <QtMultimedia/private/qavfcamerautility_p.h>
14#include <QtMultimedia/private/qavfhelpers_p.h>
15#include <QtMultimedia/private/qmultimediautils_p.h>
16#include <QtMultimedia/private/qplatformmediacapture_p.h>
18#define AVMediaType XAVMediaType
20#include <libavutil/hwcontext_videotoolbox.h>
21#include <libavutil/hwcontext.h>
31[[nodiscard]] QAVFSampleBufferDelegateTransform surfaceTransform(
32 const QFFmpeg::AvfCameraRotationTracker *rotationTracker,
33 const AVCaptureConnection *connection)
35 QAVFSampleBufferDelegateTransform transform = {};
39 if (rotationTracker !=
nullptr) {
40 captureAngle = rotationTracker->rotationDegrees();
42 bool cameraIsFrontFacing =
43 rotationTracker->avCaptureDevice() !=
nullptr
44 && rotationTracker->avCaptureDevice().position == AVCaptureDevicePositionFront;
45 if (cameraIsFrontFacing)
46 transform.presentationTransform.mirroredHorizontallyAfterRotation =
true;
55 int connectionAngle = 0;
57 if (@available(macOS 14.0, iOS 17.0, *))
58 connectionAngle =
std::lround(connection.videoRotationAngle);
60 if (connection.videoMirrored)
61 transform.surfaceTransform.mirroredHorizontallyAfterRotation =
true;
64 transform.surfaceTransform.rotation = qVideoRotationFromDegrees(captureAngle - connectionAngle);
71[[nodiscard]]
static AVCaptureDeviceFormat* findSuitableAvCaptureDeviceFormat(
72 AVCaptureDevice *avCaptureDevice,
73 const QCameraFormat &format)
75 Q_ASSERT(avCaptureDevice !=
nullptr);
76 Q_ASSERT(!format.isNull());
80 AVCaptureDeviceFormat *newDeviceFormat = qt_convert_to_capture_device_format(
83 &QFFmpeg::isCVFormatSupported);
88 newDeviceFormat = qt_convert_to_capture_device_format(avCaptureDevice, format);
90 return newDeviceFormat;
93[[nodiscard]]
static q23::expected<CvPixelFormat, QString> tryFindVideoDataOutputPixelFormat(
94 QVideoFrameFormat::PixelFormat cameraPixelFormat,
95 CvPixelFormat inputCvPixFormat,
96 AVCaptureVideoDataOutput *avCaptureVideoDataOutput)
98 Q_ASSERT(cameraPixelFormat != QVideoFrameFormat::PixelFormat::Format_Invalid);
99 Q_ASSERT(inputCvPixFormat != CvPixelFormatInvalid);
100 Q_ASSERT(avCaptureVideoDataOutput !=
nullptr);
102 using namespace Qt::Literals::StringLiterals;
104 if (avCaptureVideoDataOutput.availableVideoCVPixelFormatTypes.count == 0)
105 return q23::unexpected{
106 u"AVCaptureVideoDataOutput.availableVideoCVPixelFormatTypes is empty"_s };
108 auto bestScore = MinAVScore;
109 NSNumber *bestFormat =
nullptr;
110 for (NSNumber *cvPixFmtNumber in avCaptureVideoDataOutput.availableVideoCVPixelFormatTypes) {
111 const CvPixelFormat cvPixFmt = [cvPixFmtNumber unsignedIntValue];
112 const QVideoFrameFormat::PixelFormat pixFmt = QAVFHelpers::fromCVPixelFormat(cvPixFmt);
113 if (pixFmt == QVideoFrameFormat::Format_Invalid)
116 auto score = DefaultAVScore;
117 if (cvPixFmt == inputCvPixFormat)
119 if (pixFmt == cameraPixelFormat)
127 constexpr bool ShouldSuppressNotSupportedByFFmpeg =
false;
129 if (!isCVFormatSupported(cvPixFmt))
130 score -= ShouldSuppressNotSupportedByFFmpeg ? 100000 : 5;
132 if (score > bestScore) {
134 bestFormat = cvPixFmtNumber;
138 if (bestScore < DefaultAVScore)
139 qWarning() <<
"QAVFCamera::tryFindVideoDataOutputPixelFormat: "
140 "Cannot find hw FFmpeg supported cv pix format";
142 return [bestFormat unsignedIntValue];
149 return std::make_unique<QAVFCamera>(parent);
205 u"Cannot attach AVCaptureDeviceInput to AVCaptureSession"_s };
282 u"Unable to connect AVCaptureVideoDataOutput to AVCaptureSession"_s };
398 return q23::
unexpected{ u"AVCaptureDevice not available"_s };
418 u"Unable to find any suitable AVCaptureDeviceFormat when attempting to "
419 "apply QCameraFormat"_s };
469 qWarning() <<
"QAVFCamera::onActiveChanged: Device not available";
479 qWarning() <<
"QAVFCamera::onActiveChanged: Failed to lock AVCaptureDevice";
490 <<
"QAVFCamera::onActiveChanged: Error when trying to activate camera:"
550 <<
"Error when trying to activate new camera-device: "
572 qWarning() <<
"QAVFCamera::tryApplyCameraFormat: Unable to find any suitable "
573 "AVCaptureDeviceFormat when attempting to apply QCameraFormat";
589 qWarning() <<
"QAVFCamera::tryApplyCameraFormat: Failed to lock AVCaptureDevice when "
590 "trying to apply new QCameraFormat.";
607 <<
"Error when trying to activate camera with new format: "
692#include "moc_qavfcamera_p.cpp"
std::unique_ptr< QPlatformCamera > makeQAvfCamera(QCamera &parent)
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType