1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40//TESTED_COMPONENT=src/multimedia
41
42#include "qabstractvideosurface.h"
43
44#include "qvideosurfaceformat.h"
45
46#include <QtCore/qvariant.h>
47#include <QDebug>
48
49QT_BEGIN_NAMESPACE
50
51static void qRegisterAbstractVideoSurfaceMetaTypes()
52{
53 qRegisterMetaType<QAbstractVideoSurface::Error>();
54}
55
56Q_CONSTRUCTOR_FUNCTION(qRegisterAbstractVideoSurfaceMetaTypes)
57
58
59class QAbstractVideoSurfacePrivate {
60public:
61 QAbstractVideoSurfacePrivate()
62 : error(QAbstractVideoSurface::NoError),
63 active(false)
64 {
65 }
66
67public:
68 QVideoSurfaceFormat surfaceFormat;
69 QAbstractVideoSurface::Error error;
70 QSize nativeResolution;
71 bool active;
72};
73
74/*!
75 \class QAbstractVideoSurface
76 \brief The QAbstractVideoSurface class is a base class for video presentation surfaces.
77 \inmodule QtMultimedia
78
79 \ingroup multimedia
80 \ingroup multimedia_video
81
82 The QAbstractVideoSurface class defines the standard interface that video producers use to
83 inter-operate with video presentation surfaces. You can subclass this interface to receive
84 video frames from sources like \l {QMediaPlayer}{decoded media} or \l {QCamera}{cameras} to
85 perform your own processing.
86
87 A video surface presents a continuous stream of identically formatted QVideoFrame instances, where the format
88 of each frame is compatible with a stream format supplied when starting a presentation. Each frame
89 may have timestamp information that can be used by the surface to decide when to display that
90 frame.
91
92 A list of pixel formats a surface can present is given by the supportedPixelFormats() function,
93 and the isFormatSupported() function will test if a video surface format is supported. If a
94 format is not supported the nearestFormat() function may be able to suggest a similar format.
95 For example, if a surface supports fixed set of resolutions it may suggest the smallest
96 supported resolution that contains the proposed resolution.
97
98 The start() function takes a supported format and enables a video surface. Once started a
99 surface will begin displaying the frames it receives in the present() function. Surfaces may
100 hold a reference to the buffer of a presented video frame until a new frame is presented or
101 streaming is stopped. In addition, a video surface may hold a reference to a video frame
102 until the \l {QVideoFrame::endTime()}{end timestamp} has passed. The stop() function will
103 disable a surface and release any video buffers it holds references to.
104
105 \section2 Implementing a subclass of QAbstractVideoSurface
106
107 When implementing a subclass of this interface, there are only a handful of functions to
108 implement, broken down into two classes:
109
110 \list
111 \li Format related
112 \li Presentation related
113 \endlist
114
115 For format related functionality, you just have to describe the pixel formats that you
116 support (and the nearestFormat() function). For presentation related functionality, you
117 have to implement the present() function, and the start() and stop() functions.
118
119 \note You must call the base class implementation of start() and stop() in your implementation.
120*/
121
122/*!
123 \enum QAbstractVideoSurface::Error
124 This enum describes the errors that may be returned by the error() function.
125
126 \value NoError No error occurred.
127 \value UnsupportedFormatError A video format was not supported.
128 \value IncorrectFormatError A video frame was not compatible with the format of the surface.
129 \value StoppedError The surface has not been started.
130 \value ResourceError The surface could not allocate some resource.
131*/
132
133/*!
134 Constructs a video surface with the given \a parent.
135*/
136QAbstractVideoSurface::QAbstractVideoSurface(QObject *parent)
137 : QObject(parent),
138 d_ptr(new QAbstractVideoSurfacePrivate)
139{
140}
141
142/*!
143 Destroys a video surface.
144*/
145QAbstractVideoSurface::~QAbstractVideoSurface()
146{
147}
148
149/*!
150 \fn QAbstractVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
151
152 Returns a list of pixel formats a video surface can present for a given handle \a type.
153
154 The pixel formats returned for the QAbstractVideoBuffer::NoHandle type are valid for any buffer
155 that can be mapped in read-only mode.
156
157 Types that are first in the list can be assumed to be faster to render.
158*/
159
160/*!
161 Tests a video surface \a format to determine if a surface can accept it.
162
163 Returns true if the format is supported by the surface, and false otherwise.
164*/
165bool QAbstractVideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const
166{
167 return supportedPixelFormats(format.handleType()).contains(format.pixelFormat());
168}
169
170/*!
171 Returns a supported video surface format that is similar to \a format.
172
173 A similar surface format is one that has the same \l {QVideoSurfaceFormat::pixelFormat()}{pixel
174 format} and \l {QVideoSurfaceFormat::handleType()}{handle type} but may differ in some of the other
175 properties. For example, if there are restrictions on the \l {QVideoSurfaceFormat::frameSize()}
176 {frame sizes} a video surface can accept it may suggest a format with a larger frame size and
177 a \l {QVideoSurfaceFormat::viewport()}{viewport} the size of the original frame size.
178
179 If the format is already supported it will be returned unchanged, or if there is no similar
180 supported format an invalid format will be returned.
181*/
182QVideoSurfaceFormat QAbstractVideoSurface::nearestFormat(const QVideoSurfaceFormat &format) const
183{
184 return isFormatSupported(format)
185 ? format
186 : QVideoSurfaceFormat();
187}
188
189/*!
190 \fn QAbstractVideoSurface::supportedFormatsChanged()
191
192 Signals that the set of formats supported by a video surface has changed.
193
194 \sa supportedPixelFormats(), isFormatSupported()
195*/
196
197/*!
198 Returns the format of a video surface.
199*/
200QVideoSurfaceFormat QAbstractVideoSurface::surfaceFormat() const
201{
202 Q_D(const QAbstractVideoSurface);
203 return d->surfaceFormat;
204}
205
206/*!
207 \fn QAbstractVideoSurface::surfaceFormatChanged(const QVideoSurfaceFormat &format)
208
209 Signals that the configured \a format of a video surface has changed.
210
211 \sa surfaceFormat(), start()
212*/
213
214/*!
215 Starts a video surface presenting \a format frames.
216
217 Returns true if the surface was started, and false if an error occurred.
218
219 \note You must call the base class implementation of start() at the end of your implementation.
220 \sa isActive(), stop()
221*/
222bool QAbstractVideoSurface::start(const QVideoSurfaceFormat &format)
223{
224 Q_D(QAbstractVideoSurface);
225 bool wasActive = d->active;
226
227 d->active = true;
228 d->surfaceFormat = format;
229 d->error = NoError;
230
231 emit surfaceFormatChanged(format);
232
233 if (!wasActive)
234 emit activeChanged(true);
235
236 return true;
237}
238
239/*!
240 Stops a video surface presenting frames and releases any resources acquired in start().
241
242 \note You must call the base class implementation of stop() at the start of your implementation.
243 \sa isActive(), start()
244*/
245void QAbstractVideoSurface::stop()
246{
247 Q_D(QAbstractVideoSurface);
248 if (d->active) {
249 d->surfaceFormat = QVideoSurfaceFormat();
250 d->active = false;
251
252 emit activeChanged(false);
253 emit surfaceFormatChanged(surfaceFormat());
254 }
255}
256
257/*!
258 Indicates whether a video surface has been started.
259
260 Returns true if the surface has been started, and false otherwise.
261*/
262bool QAbstractVideoSurface::isActive() const
263{
264 Q_D(const QAbstractVideoSurface);
265 return d->active;
266}
267
268/*!
269 \fn QAbstractVideoSurface::activeChanged(bool active)
270
271 Signals that the \a active state of a video surface has changed.
272
273 \sa isActive(), start(), stop()
274*/
275
276/*!
277 \fn QAbstractVideoSurface::present(const QVideoFrame &frame)
278
279 Presents a video \a frame.
280
281 Returns true if the frame was presented, and false if an error occurred.
282
283 Not all surfaces will block until the presentation of a frame has completed. Calling present()
284 on a non-blocking surface may fail if called before the presentation of a previous frame has
285 completed. In such cases the surface may not return to a ready state until it has had an
286 opportunity to process events.
287
288 If present() fails for any other reason the surface should immediately enter the stopped state
289 and an error() value will be set.
290
291 A video surface must be in the started state for present() to succeed, and the format of the
292 video frame must be compatible with the current video surface format.
293
294 \sa error()
295*/
296
297/*!
298 Returns the last error that occurred.
299
300 If a surface fails to start(), or stops unexpectedly this function can be called to discover
301 what error occurred.
302*/
303
304QAbstractVideoSurface::Error QAbstractVideoSurface::error() const
305{
306 Q_D(const QAbstractVideoSurface);
307 return d->error;
308}
309
310/*!
311 Sets the value of error() to \a error.
312
313 This can be called by implementors of this interface to communicate
314 what the most recent error was.
315*/
316void QAbstractVideoSurface::setError(Error error)
317{
318 Q_D(QAbstractVideoSurface);
319 d->error = error;
320}
321
322/*!
323 \property QAbstractVideoSurface::nativeResolution
324
325 The native resolution of video surface.
326 This is the resolution of video frames the surface
327 can render with optimal quality and/or performance.
328
329 The native resolution is not always known and can be changed during playback.
330 */
331QSize QAbstractVideoSurface::nativeResolution() const
332{
333 Q_D(const QAbstractVideoSurface);
334 return d->nativeResolution;
335}
336
337/*!
338 Set the video surface native \a resolution.
339
340 This function can be called by implementors of this interface to specify
341 to frame producers what the native resolution of this surface is.
342 */
343void QAbstractVideoSurface::setNativeResolution(const QSize &resolution)
344{
345 Q_D(QAbstractVideoSurface);
346
347 if (d->nativeResolution != resolution) {
348 d->nativeResolution = resolution;
349
350 emit nativeResolutionChanged(resolution);
351 }
352}
353/*!
354 \fn QAbstractVideoSurface::nativeResolutionChanged(const QSize &resolution);
355
356 Signals the native \a resolution of video surface has changed.
357*/
358
359#ifndef QT_NO_DEBUG_STREAM
360QDebug operator<<(QDebug dbg, const QAbstractVideoSurface::Error& error)
361{
362 QDebugStateSaver saver(dbg);
363 dbg.nospace();
364 switch (error) {
365 case QAbstractVideoSurface::UnsupportedFormatError:
366 dbg << "UnsupportedFormatError";
367 break;
368 case QAbstractVideoSurface::IncorrectFormatError:
369 dbg << "IncorrectFormatError";
370 break;
371 case QAbstractVideoSurface::StoppedError:
372 dbg << "StoppedError";
373 break;
374 case QAbstractVideoSurface::ResourceError:
375 dbg << "ResourceError";
376 break;
377 default:
378 dbg << "NoError";
379 break;
380 }
381 return dbg;
382}
383#endif
384
385
386QT_END_NAMESPACE
387
388#include "moc_qabstractvideosurface.cpp"
389
390