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