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
qvideoframeinput.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 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
6#include <QtMultimedia/qaudiobuffer.h>
7#include <QtMultimedia/private/qmediaframeinput_p.h>
8#include <QtMultimedia/private/qmediainputencoderinterface_p.h>
9#include <QtMultimedia/private/qplatformvideoframeinput_p.h>
10
12
14{
15public:
16 QVideoFrameInputPrivate(QVideoFrameInput *q) : q(q) { }
17
18 bool sendVideoFrame(const QVideoFrame &frame)
19 {
20 return sendMediaFrame([&]() { emit m_platfromVideoFrameInput->newVideoFrame(frame); });
21 }
22
23 void initialize(QVideoFrameFormat format = {})
24 {
25 m_platfromVideoFrameInput = std::make_unique<QPlatformVideoFrameInput>(std::move(format));
26 addUpdateSignal(m_platfromVideoFrameInput.get(), &QPlatformVideoFrameInput::encoderUpdated);
27 }
28
30 {
31 m_platfromVideoFrameInput.reset();
32
33 if (captureSession())
34 captureSession()->setVideoFrameInput(nullptr);
35 }
36
37 QPlatformVideoFrameInput *platfromVideoFrameInput() const
38 {
39 return m_platfromVideoFrameInput.get();
40 }
41
42protected:
45 {
46 if (prevSession)
47 removeUpdateSignal(prevSession, &QMediaCaptureSession::videoOutputChanged);
48
49 if (newSession)
50 addUpdateSignal(newSession, &QMediaCaptureSession::videoOutputChanged);
51 }
52
54 {
55 if (auto encoderInterface = m_platfromVideoFrameInput->encoderInterface())
56 return encoderInterface->canPushFrame();
57
58 return captureSession()->videoOutput() || captureSession()->videoSink();
59 }
60
61 void emitReadyToSendMediaFrame() override { emit q->readyToSendVideoFrame(); }
62
63private:
64 QVideoFrameInput *q = nullptr;
65 std::unique_ptr<QPlatformVideoFrameInput> m_platfromVideoFrameInput;
66};
67
68/*!
69 \class QVideoFrameInput
70 \inmodule QtMultimedia
71 \ingroup multimedia
72 \ingroup multimedia_video
73 \since 6.8
74
75 \brief The QVideoFrameInput class is used for providing custom video frames
76 to \l QMediaRecorder or a video output through \l QMediaCaptureSession.
77
78 QVideoFrameInput is only supported with the FFmpeg backend.
79
80 Custom video frames can be recorded by connecting a \l QVideoFrameInput and a
81 \l QMediaRecorder to a \l QMediaCaptureSession. For a pull mode implementation,
82 call \l sendVideoFrame() in response to the \l readyToSendVideoFrame() signal. In
83 the snippet below this is done by connecting the signal to a slot in a custom media
84 generator class. The slot function emits another signal with a new video frame, which
85 is connected to \l sendVideoFrame():
86
87 \snippet custommediainputsnippets/custommediainputsnippets.cpp QVideoFrameInput setup
88
89 Here's a minimal implementation of the slot function that provides video frames:
90
91 \snippet custommediainputsnippets/custommediainputsnippets.cpp nextVideoFrame()
92
93 For more details see readyToSendVideoFrame() and sendVideoFrame().
94
95 \sa QMediaRecorder, QMediaCaptureSession and QVideoSink.
96*/
97
98/*!
99 Constructs a new QVideoFrameInput object with \a parent.
100*/
101QVideoFrameInput::QVideoFrameInput(QObject *parent) : QVideoFrameInput({}, parent) { }
102
103/*!
104 Constructs a new QVideoFrameInput object with video frame \a format and \a parent.
105
106 The specified \a format will work as a hint for the initialization of the matching
107 video encoder upon invoking \l QMediaRecorder::record().
108 If the format is not specified or not valid, the video encoder will be initialized
109 upon sending the first frame.
110 Sending of video frames with another pixel format and size after initialization
111 of the matching video encoder might cause a performance penalty during recording.
112
113 We recommend specifying the format if you know in advance what kind of frames you're
114 going to send.
115*/
116QVideoFrameInput::QVideoFrameInput(const QVideoFrameFormat &format, QObject *parent)
117 : QObject(*new QVideoFrameInputPrivate(this), parent)
118{
119 Q_D(QVideoFrameInput);
120 d->initialize(format);
121}
122
123/*!
124 Destroys the object.
125 */
126QVideoFrameInput::~QVideoFrameInput()
127{
128 Q_D(QVideoFrameInput);
129 d->uninitialize();
130}
131
132/*!
133 Sends \l QVideoFrame to \l QMediaRecorder or a video output
134 through \l QMediaCaptureSession.
135
136 Returns \c true if the specified \a frame has been sent successfully
137 to the destination. Returns \c false, if the frame hasn't been sent,
138 which can happen if the instance is not assigned to
139 \l QMediaCaptureSession, the session doesn't have video outputs or
140 a media recorder, the media recorder is not started or its queue is full.
141 The signal \l readyToSendVideoFrame will be sent as soon as
142 the destination is able to handle a new frame.
143
144 Sending of an empty video frame is treated by \l QMediaRecorder
145 as an end of the input stream. QMediaRecorder stops the recording
146 automatically if \l QMediaRecorder::autoStop is \c true and
147 all the inputs have reported the end of the stream.
148*/
149bool QVideoFrameInput::sendVideoFrame(const QVideoFrame &frame)
150{
151 Q_D(QVideoFrameInput);
152 return d->sendVideoFrame(frame);
153}
154
155/*!
156 Returns the video frame format that was specified
157 upon construction of the video frame input.
158*/
159QVideoFrameFormat QVideoFrameInput::format() const
160{
161 Q_D(const QVideoFrameInput);
162 return d->platfromVideoFrameInput()->frameFormat();
163}
164
165/*!
166 Returns the capture session this video frame input is connected to, or
167 a \c nullptr if the video frame input is not connected to a capture session.
168
169 Use QMediaCaptureSession::setVideoFrameInput() to connect
170 the video frame input to a session.
171*/
172QMediaCaptureSession *QVideoFrameInput::captureSession() const
173{
174 Q_D(const QVideoFrameInput);
175 return d->captureSession();
176}
177
178void QVideoFrameInput::setCaptureSession(QMediaCaptureSession *captureSession)
179{
180 Q_D(QVideoFrameInput);
181 d->setCaptureSession(captureSession);
182}
183
184QPlatformVideoFrameInput *QVideoFrameInput::platformVideoFrameInput() const
185{
186 Q_D(const QVideoFrameInput);
187 return d->platfromVideoFrameInput();
188}
189
190/*!
191 \fn void QVideoFrameInput::readyToSendVideoFrame()
192
193 Signals that a new frame can be sent to the video frame input.
194 After receiving the signal, if you have frames to be sent, invoke \l sendVideoFrame
195 once or in a loop until it returns \c false.
196
197 \sa sendVideoFrame()
198*/
199
200QT_END_NAMESPACE
QPlatformVideoFrameInput * platfromVideoFrameInput() const
bool sendVideoFrame(const QVideoFrame &frame)
void initialize(QVideoFrameFormat format={})
QVideoFrameInputPrivate(QVideoFrameInput *q)
void updateCaptureSessionConnections(QMediaCaptureSession *prevSession, QMediaCaptureSession *newSession) override
void emitReadyToSendMediaFrame() override
bool checkIfCanSendMediaFrame() const override
Combined button and popup list for selecting options.