1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the documentation of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:FDL$
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 http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Free Documentation License Usage
18** Alternatively, this file may be used under the terms of the GNU Free
19** Documentation License version 1.3 as published by the Free Software
20** Foundation and appearing in the file included in the packaging of
21** this file.  Please review the following information to ensure
22** the GNU Free Documentation License version 1.3 requirements
23** will be met: http://www.gnu.org/copyleft/fdl.html.
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29    \example multimedia/videowidget
30    \title Video Widget Example
31
32    \brief The Video Widget example shows how to implement a video widget using
33    QtMultimedia's QAbstractVideoSurface
34
35    \image video-videowidget.png
36
37    \section1 VideoWidgetSurface Class Definition
38
39    \snippet examples/multimedia/videowidget/videowidgetsurface.h 0
40
41    The VideoWidgetSurface class inherits QAbstractVideoSurface and paints
42    video frames on a QWidget.  This is a separate class to VideoWidget as both
43    QAbstractVideoSurface and QWidget inherit QObject.
44
45    In addition to the functions from QAbstractVideoSurface, VideoWidgetSurface
46    has functions for determining the video display rectangle, and painting
47    the video.
48
49    \section1 VideoWidgetSurface Class Implementation
50
51    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 0
52
53    From the supportedPixelFormats() function we return a list of pixel formats
54    the surface can paint. The order of the list hints at which formats are
55    preferred by the surface.  Assuming a 32-bit RGB backbuffer, we'd expect
56    that a 32-bit RGB type with no alpha to be fastest to paint so
57    QVideoFrame::Image_RGB32 is first in the list.
58
59    Since we don't support rendering using any special frame handles we don't
60    return any pixel formats if handleType is not
61    QAbstractVideoBuffer::NoHandle.
62
63    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 1
64
65    In isFormatSupported() we test if the frame type of a surface format maps
66    to a valid QImage format, that the frame size is not empty, and the handle
67    type is QAbstractVideoBuffer::NoHandle.  Note that the
68    QAbstractVideoSurface implementation of isFormatSupported() will verify
69    that the list of supported pixel formats returned by
70    \c supportedPixelFormats(format.handleType()) contains the pixel format and
71    that the size is not empty so a reimplementation wasn't strictly necessary
72    in this case.
73
74    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 2
75
76    To start our surface we'll extract the image format and size from the
77    selected video format and save it for use in the paint() function.  If the
78    image format, or size are invalid then we'll set an error and return false.
79    Otherwise we'll save the format and confirm the surface has been started,
80    by calling QAbstractVideoSurface::start(). Finally since the video size may
81    have changed we'll trigger an update of the widget, and video geometry.
82
83    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 5
84
85    The updateVideoRect() function calculates the region within the widget the
86    video occupies.  The \l {QVideoSurfaceFormat::sizeHint()}{size hint} of the
87    video format gives a suggested size for the video calculated from the
88    \l {QVideoSurfaceFormat::viewport()}{viewport} and
89    \l {QVideoSurfaceFormat::pixelAspectRatio()}{pixel aspect ratio}.  If the
90    suggested size fits within the widget then we create a new rect of that
91    size in the center of the widget.  Otherwise we shrink the size maintaining
92    the aspect ratio so that it does fit.
93
94    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 4
95
96    We can't paint from outside a paint event, so when a new frame is received
97    in present() we save a reference to it and force an immediate repaint of
98    the video region.  We retain the saved reference to the frame after the
99    repaint so that the widget can be repainted between frame changes if
100    necessary.
101
102    If the format of the frame doesn't match the surface format we can't paint
103    it or very likely any future frames.  So we set an
104    \l {QAbstractVideoSurface::UnsupportedFormatError}{UnsupportedFormatError}
105    on our surface and stop it immediately.
106
107    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 6
108
109    The paint() function is called by the video widget to paint the current
110    video frame.  Before we draw the frame first we'll check the format for
111    the scan line direction and if the scan lines are arranged from bottom to
112    top we'll flip the painter so the frame isn't drawn upside down.  Then
113    using the image format information saved in the start() function we'll
114    construct a new QImage from the current video frame, and draw it to the
115    the widget.
116
117    \snippet examples/multimedia/videowidget/videowidgetsurface.cpp 3
118
119    When the surface is stopped we need to release the current frame and
120    invalidate the video region.   Then we confirm the surface has been
121    stopped by calling QAbstractVideoSurface::stop() which sets the started
122    state to false and finally we update so the video widget so paints over
123    the last frame.
124
125    \section1 VideoWidget Class Definition
126
127    The VideoWidget class uses the VideoWidgetSurface class to implement a
128    video widget.
129
130    \snippet examples/multimedia/videowidget/videowidget.h 0
131
132    The VideoWidget QWidget implementation is minimal with just the sizeHint(),
133    paintEvent(), and resizeEvent() functions in addition to the constructor,
134    destructor and an instance of VideoWidgetSurface.
135
136    \section1 VideoWidget Class Implementation
137
138    \snippet examples/multimedia/videowidget/videowidget.cpp 0
139
140    In the VideoWidget constructor we set some flags to speed up re-paints a
141    little.  Setting the Qt::WA_NoSystemBackground flag and disabling automatic
142    background fills will stop Qt from a painting a background that'll be
143    completely obscured by the video.  The Qt::WA_PaintOnScreen flag will
144    allow us to paint to the screen instead of the back buffer where supported.
145
146    Next we set the background color to black, so that any borders around the
147    video are filled in black rather the default background color.
148
149    Finally we construct an instance of the VideoWidgetSurface class.
150
151    \snippet examples/multimedia/videowidget/videowidget.cpp 1
152
153    In the destructor we simply delete the VideoWidgetSurface instance.
154
155    \snippet examples/multimedia/videowidget/videowidget.cpp 2
156
157    We get the size hint for the widget from the video format of the surface
158    which is calculated from viewport and pixel aspect ratio of the video
159    format.
160
161    \snippet examples/multimedia/videowidget/videowidget.cpp 3
162
163    When the video widget receives a paint event we first check if the surface
164    is started,  if not then we simply fill the widget with the background
165    color.  If it is then we draw a border around the video region clipped
166    by the paint region, before calling paint on the video surface to draw the
167    current frame.
168
169    \snippet examples/multimedia/videowidget/videowidget.cpp 4
170
171    The resizeEvent() function is reimplemented to trigger an update of the
172    video region when the widget is resized.
173*/
174