1 /* qv4l2: a control panel controlling v4l2 devices.
2 *
3 * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #include "capture-win-qt.h"
21
CaptureWinQt(ApplicationWindow * aw)22 CaptureWinQt::CaptureWinQt(ApplicationWindow *aw) :
23 CaptureWin(aw),
24 m_image(new QImage(0, 0, QImage::Format_Invalid)),
25 m_data(NULL),
26 m_supportedFormat(false),
27 m_filled(false),
28 m_cropBytes(0),
29 m_cropOffset(0)
30 {
31 m_videoSurface = new QLabel(this);
32 CaptureWin::buildWindow(m_videoSurface);
33 }
34
~CaptureWinQt()35 CaptureWinQt::~CaptureWinQt()
36 {
37 delete m_image;
38 }
39
resizeEvent(QResizeEvent * event)40 void CaptureWinQt::resizeEvent(QResizeEvent *event)
41 {
42 // Get size of frame viewport.
43 QSize margins = getMargins();
44 m_windowSize = size() - margins;
45 // Re-calculate sizes
46 m_frame.updated = true;
47 CaptureWin::updateSize();
48 // Draw
49 paintFrame();
50 event->accept();
51 }
52
setRenderFrame()53 void CaptureWinQt::setRenderFrame()
54 {
55 // Get/copy (TODO: use direct?)
56 m_data = m_frame.planeData[0];
57
58 QImage::Format dstFmt;
59 m_supportedFormat = findNativeFormat(m_frame.format, dstFmt);
60 if (!m_supportedFormat)
61 dstFmt = QImage::Format_RGB888;
62
63 if (m_frame.updated || m_image->format() != dstFmt ||
64 m_image->width() != m_frame.size.width() ||
65 m_image->height() != m_frame.size.height()) {
66 delete m_image;
67 m_image = new QImage(m_frame.size.width(),
68 m_frame.size.height(),
69 dstFmt);
70 }
71
72 m_frame.updated = false;
73
74 paintFrame();
75 }
76
paintFrame()77 void CaptureWinQt::paintFrame()
78 {
79 if (m_crop.updated) {
80 m_cropOffset = m_crop.delta.height() * (m_image->depth() / 8)
81 * m_frame.size.width()
82 + m_crop.delta.width() * (m_image->depth() / 8);
83
84 // Even though the values above can be valid, it might be that
85 // there is no data at all. This makes sure that it is.
86 m_cropBytes = m_crop.size.width() * m_crop.size.height()
87 * (m_image->depth() / 8);
88 m_crop.updated = false;
89 }
90
91 if (!m_supportedFormat || !m_cropBytes) {
92 if (!m_filled) {
93 m_filled = true;
94 m_image->fill(0);
95 QPixmap img = QPixmap::fromImage(*m_image);
96 m_videoSurface->setPixmap(img);
97 }
98 return;
99 }
100 m_filled = false;
101
102 unsigned char *data = (m_data == NULL) ? m_image->bits() : m_data;
103
104 QImage displayFrame(&data[m_cropOffset],
105 m_crop.size.width(), m_crop.size.height(),
106 m_image->width() * (m_image->depth() / 8),
107 m_image->format());
108
109 QPixmap img = QPixmap::fromImage(displayFrame);
110
111 // No scaling is performed by scaled() if the scaled size is equal to original size
112 img = img.scaled(m_scaledSize.width(), m_scaledSize.height(), Qt::IgnoreAspectRatio);
113
114 m_videoSurface->setPixmap(img);
115 }
116
stop()117 void CaptureWinQt::stop()
118 {
119 if (m_data != NULL)
120 #if QT_VERSION >= 0x050000
121 memcpy(m_image->bits(), m_data, m_image->byteCount());
122 #else
123 memcpy(m_image->bits(), m_data, m_image->numBytes());
124 #endif
125 m_data = NULL;
126 }
127
hasNativeFormat(uint32_t format)128 bool CaptureWinQt::hasNativeFormat(uint32_t format)
129 {
130 QImage::Format fmt;
131 return findNativeFormat(format, fmt);
132 }
133
findNativeFormat(uint32_t format,QImage::Format & dstFmt)134 bool CaptureWinQt::findNativeFormat(uint32_t format, QImage::Format &dstFmt)
135 {
136 static const struct {
137 uint32_t v4l2_pixfmt;
138 QImage::Format qt_pixfmt;
139 } supported_fmts[] = {
140 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
141 { V4L2_PIX_FMT_RGB32, QImage::Format_RGB32 },
142 { V4L2_PIX_FMT_XRGB32, QImage::Format_RGB32 },
143 { V4L2_PIX_FMT_ARGB32, QImage::Format_ARGB32 },
144 { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 },
145 { V4L2_PIX_FMT_RGB565X, QImage::Format_RGB16 },
146 { V4L2_PIX_FMT_RGB555X, QImage::Format_RGB555 },
147 #else
148 { V4L2_PIX_FMT_BGR32, QImage::Format_RGB32 },
149 { V4L2_PIX_FMT_XBGR32, QImage::Format_RGB32 },
150 { V4L2_PIX_FMT_ABGR32, QImage::Format_ARGB32 },
151 { V4L2_PIX_FMT_RGB24, QImage::Format_RGB888 },
152 { V4L2_PIX_FMT_RGB565, QImage::Format_RGB16 },
153 { V4L2_PIX_FMT_RGB555, QImage::Format_RGB555 },
154 { V4L2_PIX_FMT_XRGB555, QImage::Format_RGB555 },
155 { V4L2_PIX_FMT_RGB444, QImage::Format_RGB444 },
156 { V4L2_PIX_FMT_XRGB444, QImage::Format_RGB444 },
157 #endif
158 { 0, QImage::Format_Invalid }
159 };
160
161 for (int i = 0; supported_fmts[i].v4l2_pixfmt; i++) {
162 if (supported_fmts[i].v4l2_pixfmt == format) {
163 dstFmt = supported_fmts[i].qt_pixfmt;
164 return true;
165 }
166 }
167 return false;
168 }
169