Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qavfsamplebufferdelegate.mm
Go to the documentation of this file.
1// Copyright (C) 2022 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
4#include <QtFFmpegMediaPluginImpl/private/qavfsamplebufferdelegate_p.h>
5
6#include <QtMultimedia/private/qavfhelpers_p.h>
7#include <QtMultimedia/private/qvideoframe_p.h>
8
9#include <QtFFmpegMediaPluginImpl/private/qcvimagevideobuffer_p.h>
10#include <QtFFmpegMediaPluginImpl/private/qffmpegdarwinhwframehelpers_p.h>
11#define AVMediaType XAVMediaType
12#include <QtFFmpegMediaPluginImpl/private/qffmpegvideobuffer_p.h>
13#include <QtFFmpegMediaPluginImpl/private/qffmpeghwaccel_p.h>
14#undef AVMediaType
15
16#include <optional>
17#include <chrono>
18
19QT_USE_NAMESPACE
20
21@implementation QAVFSampleBufferDelegate {
22@private
23 std::function<void(const QVideoFrame &)> frameHandler;
24 QFFmpeg::QAVFSampleBufferDelegateTransformProvider transformationProvider;
25 AVBufferRef *hwFramesContext;
26 std::unique_ptr<QFFmpeg::HWAccel> m_accel;
27 std::chrono::microseconds startTime;
28 std::optional<std::chrono::microseconds> baseTime;
29 qreal frameRate;
30}
31
32- (instancetype)initWithFrameHandler:(std::function<void(const QVideoFrame &)>)handler
33{
34 if (!(self = [super init]))
35 return nil;
36
37 Q_ASSERT(handler);
38
39 frameHandler = std::move(handler);
40 return self;
41}
42
43- (void)discardFutureSamples
44{
45 frameHandler = nullptr;
46}
47
48- (void)setTransformationProvider:
49 (const QFFmpeg::QAVFSampleBufferDelegateTransformProvider &)provider
50{
51 transformationProvider = std::move(provider);
52}
53
54- (void)captureOutput:(AVCaptureOutput *)captureOutput
55 didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
56 fromConnection:(AVCaptureConnection *)connection
57{
58 Q_UNUSED(captureOutput);
59
60 if (!frameHandler)
61 return;
62
63 CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
64 if (!imageBuffer || CFGetTypeID(imageBuffer) != CVPixelBufferGetTypeID()) {
65 qWarning() << "Cannot get image buffer from sample buffer";
66 return;
67 }
68
69 auto pixelBuffer = QAVFHelpers::QSharedCVPixelBuffer(
70 imageBuffer,
71 QAVFHelpers::QSharedCVPixelBuffer::RefMode::NeedsRef);
72
73 std::chrono::microseconds frameTime =
74 QAVFHelpers::CMTimeToMicroseconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer));
75 if (!baseTime) {
76 baseTime = frameTime;
77 startTime = frameTime;
78 }
79
80 QVideoFrameFormat format = QAVFHelpers::videoFormatForImageBuffer(pixelBuffer.get());
81 if (!format.isValid()) {
82 qWarning() << "Cannot get get video format for image buffer"
83 << CVPixelBufferGetWidth(pixelBuffer.get()) << 'x'
84 << CVPixelBufferGetHeight(pixelBuffer.get());
85 return;
86 }
87
88 std::optional<QFFmpeg::QAVFSampleBufferDelegateTransform> transform;
89 if (transformationProvider) {
90 transform = transformationProvider(connection);
91 const VideoTransformation &surfaceTransform = transform.value().surfaceTransform;
92 format.setRotation(surfaceTransform.rotation);
93 format.setMirrored(surfaceTransform.mirroredHorizontallyAfterRotation);
94 }
95
96 format.setStreamFrameRate(frameRate);
97
98 Q_ASSERT(self->m_accel);
99 QVideoFrame frame = QFFmpeg::qVideoFrameFromCvPixelBuffer(
100 *m_accel,
101 startTime - *baseTime,
102 pixelBuffer,
103 format);
104 if (!frame.isValid())
105 frame = QVideoFramePrivate::createFrame(
106 std::make_unique<QFFmpeg::CVImageVideoBuffer>(std::move(pixelBuffer)),
107 std::move(format));
108
109 if (transform.has_value()) {
110 const VideoTransformation &presentationTransform = transform.value().presentationTransform;
111 frame.setRotation(presentationTransform.rotation);
112 frame.setMirrored(presentationTransform.mirroredHorizontallyAfterRotation);
113 }
114
115 frame.setStartTime((startTime - *baseTime).count());
116 frame.setEndTime((frameTime - *baseTime).count());
117 startTime = frameTime;
118
119 frameHandler(frame);
120}
121
122- (void)setHWAccel:(std::unique_ptr<QFFmpeg::HWAccel> &&)accel
123{
124 m_accel = std::move(accel);
125}
126
127- (void)setVideoFormatFrameRate:(qreal)rate
128{
129 frameRate = rate;
130}
131
132@end