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";
245 hwAccel->createFramesContext(avPixelFormat, adjustedResolution());
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];
307QSize QAVFCamera::adjustedResolution()
const
311 AVCaptureConnection *
connection = [m_videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
318 const bool isPortraitOrientation =
connection.videoOrientation == AVCaptureVideoOrientationPortrait;
319 const bool isPortraitResolution = resolution.
height() > resolution.
width();
320 if (isPortraitOrientation != isPortraitResolution)
333 return m_hwPixelFormat == AV_PIX_FMT_NONE ? std::optional<int>{} : m_hwPixelFormat;
340 return static_cast<int>(isCVFormatSupported(cvFormat));
345#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
void setCaptureSession(QPlatformMediaCaptureSession *) override
void setCamera(const QCameraDevice &camera) override
void deviceOrientationChanged(int angle=-1)
int cameraPixelFormatScore(QVideoFrameFormat::PixelFormat pixelFmt, QVideoFrameFormat::ColorRange colorRange) const override
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)
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
void transpose() noexcept
Swaps the width and height values.
The QVideoFrame class represents a frame of video data.
int currentOrientation() const
QVideoFrameFormat::PixelFormat fromCVPixelFormat(CvPixelFormat cvPixelFormat)
CvPixelFormat toCVPixelFormat(QVideoFrameFormat::PixelFormat pixFmt, QVideoFrameFormat::ColorRange colorRange)
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)