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