6#include <private/qplatformmediacapture_p.h>
13#include <QtCore/qcoreapplication.h>
14#include <QtCore/qpermissions.h>
15#define AVMediaType XAVMediaType
19#include <libavutil/hwcontext_videotoolbox.h>
20#include <libavutil/hwcontext.h>
31 m_captureSession = [[AVCaptureSession alloc]
init];
38 [m_sampleBufferDelegate
release];
44bool QAVFCamera::checkCameraPermission()
49 qWarning() <<
"Access to camera not granted";
54void QAVFCamera::updateVideoInput()
56 if (!checkCameraPermission())
59 [m_captureSession beginConfiguration];
61 attachVideoInputDevice();
63 if (!m_videoDataOutput) {
64 m_videoDataOutput = [[AVCaptureVideoDataOutput alloc]
init];
67 m_delegateQueue = dispatch_queue_create(
"vf_queue",
nullptr);
69 setSampleBufferDelegate:m_sampleBufferDelegate
70 queue:m_delegateQueue];
72 [m_captureSession addOutput:m_videoDataOutput];
74 [m_captureSession commitConfiguration];
80 AVCaptureConnection *
connection = [m_videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
90 AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationPortrait;
95 orientation = AVCaptureVideoOrientationLandscapeRight;
101 orientation = AVCaptureVideoOrientationLandscapeLeft;
108void QAVFCamera::attachVideoInputDevice()
111 [m_captureSession removeInput:m_videoInput];
113 m_videoInput =
nullptr;
120 AVCaptureDevice *videoDevice = [AVCaptureDevice deviceWithUniqueID:
121 [NSString stringWithUTF8String: deviceId.
constData()]];
126 m_videoInput = [AVCaptureDeviceInput
127 deviceInputWithDevice:videoDevice
129 if (m_videoInput && [m_captureSession canAddInput:m_videoInput]) {
130 [m_videoInput retain];
131 [m_captureSession addInput:m_videoInput];
133 qWarning() <<
"Failed to create video device input";
137AVCaptureDevice *QAVFCamera::device()
const
139 return m_videoInput ? m_videoInput.device :
nullptr;
151 if (!checkCameraPermission())
160 [m_videoInput.device lockForConfiguration:nil];
161 [m_captureSession startRunning];
162 [m_videoInput.device unlockForConfiguration];
164 [m_captureSession stopRunning];
182 if (checkCameraPermission())
195 updateCameraFormat();
199void QAVFCamera::updateCameraFormat()
203 AVCaptureDevice *captureDevice = device();
213 std::uint32_t cvPixelFormat = 0;
216 const auto captureDeviceCVFormat =
217 CMVideoFormatDescriptionGetCodecType(newFormat.formatDescription);
219 if (captureDeviceCVFormat != cvPixelFormat) {
220 qCWarning(qLcCamera) <<
"Output CV format differs with capture device format!"
221 << cvPixelFormat << cvFormatToString(cvPixelFormat) <<
"vs"
222 << captureDeviceCVFormat
223 << cvFormatToString(captureDeviceCVFormat);
228 qWarning() <<
"Cannot find AVCaptureDeviceFormat; Did you use format from another camera?";
231 const AVPixelFormat avPixelFormat = av_map_videotoolbox_format_to_pixfmt(cvPixelFormat);
233 std::unique_ptr<HWAccel> hwAccel;
235 if (avPixelFormat == AV_PIX_FMT_NONE) {
236 qCWarning(qLcCamera) <<
"Videotoolbox doesn't support cvPixelFormat:" << cvPixelFormat
237 << cvFormatToString(cvPixelFormat)
241 qCDebug(qLcCamera) <<
"Create VIDEOTOOLBOX hw context" << hwAccel.get() <<
"for camera";
246 m_hwPixelFormat = hwAccel->hwFormat();
248 m_hwPixelFormat = AV_PIX_FMT_NONE;
251 [m_sampleBufferDelegate setHWAccel:std::move(hwAccel)];
256 uint32_t inputCvPixFormat)
259 NSNumber *bestFormat =
nullptr;
260 for (NSNumber *cvPixFmtNumber
in m_videoDataOutput.availableVideoCVPixelFormatTypes) {
261 auto cvPixFmt = [cvPixFmtNumber unsignedIntValue];
267 if (cvPixFmt == inputCvPixFormat)
269 if (pixFmt == cameraPixelFormat)
277 constexpr bool ShouldSuppressNotSupportedByFFmpeg =
false;
279 if (!isCVFormatSupported(cvPixFmt))
280 score -= ShouldSuppressNotSupportedByFFmpeg ? 100000 : 5;
284 if (score > bestScore) {
286 bestFormat = cvPixFmtNumber;
291 qWarning() <<
"QCamera::setCameraFormat: availableVideoCVPixelFormatTypes empty";
296 qWarning() <<
"QCamera::setCameraFormat: Cannot find hw ffmpeg supported cv pix format";
298 NSDictionary *outputSettings = @{
299 (NSString *)kCVPixelBufferPixelFormatTypeKey : bestFormat,
300 (NSString *)kCVPixelBufferMetalCompatibilityKey : @true
302 m_videoDataOutput.videoSettings = outputSettings;
304 return [bestFormat unsignedIntValue];
314 return m_hwPixelFormat == AV_PIX_FMT_NONE ? std::optional<int>{} : m_hwPixelFormat;
319 unsigned cvFormat = 0;
320 const auto isSupported =
322 return static_cast<int>(isSupported);
327#include "moc_qavfcamera_p.cpp"
bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat *format, bool preserveFps)
AVCaptureDeviceFormat * qt_convert_to_capture_device_format(AVCaptureDevice *captureDevice, const QCameraFormat &cameraFormat, const std::function< bool(uint32_t)> &cvFormatValidator)
QCameraDevice m_cameraDevice
bool setCameraFormat(const QCameraFormat &format) override
int cameraPixelFormatScore(QVideoFrameFormat::PixelFormat pixFmt) const override
void setCaptureSession(QPlatformMediaCaptureSession *) override
void setCamera(const QCameraDevice &camera) override
void deviceOrientationChanged(int angle=-1)
void setActive(bool active) override
void syncHandleFrame(const QVideoFrame &frame)
bool setCameraFormat(const QCameraFormat &format) override
QAVFCamera(QCamera *parent)
bool isActive() const override
std::optional< int > ffmpegHWPixelFormat() const override
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
The QCameraDevice class provides general information about camera devices.
QByteArray id
\qmlproperty string QtMultimedia::cameraDevice::id
Access the camera for taking pictures or videos.
The QCamera class provides interface for system camera devices.
static std::unique_ptr< HWAccel > create(AVHWDeviceType deviceType)
The QVideoFrame class represents a frame of video data.
int currentOrientation() const
bool toCVPixelFormat(QVideoFrameFormat::PixelFormat qtFormat, unsigned &conv)
QVideoFrameFormat::PixelFormat fromCVPixelFormat(unsigned avPixelFormat)
constexpr AVScore DefaultAVScore
constexpr AVScore MinAVScore
Combined button and popup list for selecting options.
DBusConnection * connection
#define qCWarning(category,...)
#define qCDebug(category,...)
GLint GLsizei GLsizei GLenum format
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent