]> git.sesse.net Git - kdenlive/blob - src/v4l/v4lcapture.cpp
Display webcam pixel format in wizard
[kdenlive] / src / v4l / v4lcapture.cpp
1 /***************************************************************************
2  *   Copyright (C) 2010 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26
27 #include <QDebug>
28 #include <QImage>
29 #include <QTimer>
30 #include <QPainter>
31
32 #include <KDebug>
33 #include <KLocale>
34
35 #include "v4lcapture.h"
36 #include "kdenlivesettings.h"
37
38
39 static src_t v4lsrc;
40
41 class MyDisplay : public QLabel
42 {
43 public:
44     MyDisplay(QWidget *parent = 0);
45     void setImage(QImage img);
46     virtual void paintEvent(QPaintEvent *);
47     virtual void resizeEvent(QResizeEvent *);
48
49 private:
50     QImage m_img;
51     bool m_clear;
52 };
53
54 MyDisplay::MyDisplay(QWidget *parent):
55     QLabel(parent)
56     , m_clear(false)
57 {
58     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
59     setAttribute(Qt::WA_PaintOnScreen);
60     setAttribute(Qt::WA_OpaquePaintEvent);
61 }
62
63 void MyDisplay::resizeEvent(QResizeEvent *)
64 {
65     m_clear = true;
66 }
67
68 void MyDisplay::paintEvent(QPaintEvent *)
69 {
70     QPainter p(this);
71     if (m_clear) {
72         // widget resized, cleanup
73         p.fillRect(0, 0, width(), height(), palette().background());
74         m_clear = false;
75     }
76     if (m_img.isNull()) return;
77     QImage img = m_img.scaled(width(), height(), Qt::KeepAspectRatio);
78     p.drawImage((width() - img.width()) / 2, (height() - img.height()) / 2, img);
79     p.end();
80 }
81
82 void MyDisplay::setImage(QImage img)
83 {
84     m_img = img;
85     update();
86 }
87
88
89
90 V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
91     CaptureHandler(lay, parent)
92     , m_update(false)
93 {
94     if (lay == NULL) return;
95     m_display = new MyDisplay;
96     lay->addWidget(m_display);
97 }
98
99 QStringList V4lCaptureHandler::getDeviceName(QString input)
100 {
101     fswebcam_config_t *config;
102     /* Prepare the configuration structure. */
103     config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
104     if (!config) {
105         /*WARN("Out of memory.");*/
106         fprintf(stderr, "Out of MEM....");
107         return QStringList() << input;
108     }
109
110     /* Set the defaults. */
111     config->loop = 0;
112     config->offset = 0;
113     config->background = 0;
114     config->pidfile = NULL;
115     config->logfile = NULL;
116     config->gmt = 0;
117     config->start = 0;
118     config->device = strdup(input.toUtf8().constData());
119     config->input = NULL;
120     config->tuner = 0;
121     config->frequency = 0;
122     config->delay = 0;
123     config->use_read = 0;
124     config->list = 0;
125     config->width = 384;
126     config->height = 288;
127     config->fps = 0;
128     config->frames = 1;
129     config->skipframes = 0;
130     config->palette = SRC_PAL_ANY;
131     config->option = NULL;
132     config->dumpframe = NULL;
133     config->jobs = 0;
134     config->job = NULL;
135
136     /* Set defaults and parse the command line. */
137     /*if(fswc_getopts(config, argc, argv)) return(-1);*/
138
139
140     /* Record the start time. */
141     config->start = time(NULL);
142     /* Set source options... */
143     memset(&v4lsrc, 0, sizeof(v4lsrc));
144     v4lsrc.input      = config->input;
145     v4lsrc.tuner      = config->tuner;
146     v4lsrc.frequency  = config->frequency;
147     v4lsrc.delay      = config->delay;
148     v4lsrc.timeout    = 10; /* seconds */
149     v4lsrc.use_read   = config->use_read;
150     v4lsrc.list       = config->list;
151     v4lsrc.palette    = config->palette;
152     v4lsrc.width      = config->width;
153     v4lsrc.height     = config->height;
154     v4lsrc.fps        = config->fps;
155     v4lsrc.option     = config->option;
156     char *source = config->device;
157     int width = 0;
158     int height = 0;
159     char *pixelformat;
160     QString deviceName = src_query(&v4lsrc, source, &width, &height, &pixelformat);
161     QStringList result;
162     result << (deviceName.isEmpty() ? input : deviceName) << (width == 0 ? QString() : QString("%1x%2").arg(width).arg(height)) << QString(pixelformat);
163     return result;
164 }
165
166 void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool)
167 {
168     m_display->setHidden(false);
169     fswebcam_config_t *config;
170     /* Prepare the configuration structure. */
171     config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
172     if (!config) {
173         /*WARN("Out of memory.");*/
174         fprintf(stderr, "Out of MEM....");
175         return;
176     }
177
178     /* Set the defaults. */
179     config->loop = 0;
180     config->offset = 0;
181     config->background = 0;
182     config->pidfile = NULL;
183     config->logfile = NULL;
184     config->gmt = 0;
185     config->start = 0;
186     config->device = strdup(KdenliveSettings::video4vdevice().toUtf8().constData());
187     config->input = NULL;
188     config->tuner = 0;
189     config->frequency = 0;
190     config->delay = 0;
191     config->use_read = 0;
192     config->list = 0;
193     config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
194     config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
195     config->fps = 0;
196     config->frames = 1;
197     config->skipframes = 0;
198     config->palette = SRC_PAL_ANY;
199     config->option = NULL;
200     config->dumpframe = NULL;
201     config->jobs = 0;
202     config->job = NULL;
203
204     /* Set defaults and parse the command line. */
205     /*if(fswc_getopts(config, argc, argv)) return(-1);*/
206
207
208     /* Record the start time. */
209     config->start = time(NULL);
210     /* Set source options... */
211     memset(&v4lsrc, 0, sizeof(v4lsrc));
212     v4lsrc.input      = config->input;
213     v4lsrc.tuner      = config->tuner;
214     v4lsrc.frequency  = config->frequency;
215     v4lsrc.delay      = config->delay;
216     v4lsrc.timeout    = 10; /* seconds */
217     v4lsrc.use_read   = config->use_read;
218     v4lsrc.list       = config->list;
219     v4lsrc.palette    = config->palette;
220     v4lsrc.width      = config->width;
221     v4lsrc.height     = config->height;
222     v4lsrc.fps        = config->fps;
223     v4lsrc.option     = config->option;
224     char *source = config->device;
225
226     if (src_open(&v4lsrc, source) != 0) return;
227     m_update = true;
228     QTimer::singleShot(200, this, SLOT(slotUpdate()));
229 }
230
231 V4lCaptureHandler::~V4lCaptureHandler()
232 {
233     stopCapture();
234 }
235
236 void V4lCaptureHandler::slotUpdate()
237 {
238     if (!m_update) return;
239     src_grab(&v4lsrc);
240     uint8_t *img = (uint8_t *) v4lsrc.img;
241     uint32_t i = v4lsrc.width * v4lsrc.height;
242
243     if (v4lsrc.length << 2 < i) return;
244
245     QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB32);
246     //Format_ARGB32_Premultiplied
247     //convert from uyvy422 to rgba
248     CaptureHandler::yuv2rgb((uchar *)img, (uchar *)qimg.bits(), v4lsrc.width, v4lsrc.height);
249     if (!m_captureFramePath.isEmpty()) {
250         qimg.save(m_captureFramePath);
251         emit frameSaved(m_captureFramePath);
252         m_captureFramePath.clear();
253     }
254     if (!m_overlayImage.isNull()) {
255         // overlay image
256         QPainter p(&qimg);
257         p.setOpacity(0.5);
258         p.drawImage(0, 0, m_overlayImage);
259         p.end();
260     }
261     m_display->setImage(qimg);
262     if (m_update) QTimer::singleShot(200, this, SLOT(slotUpdate()));
263 }
264
265 void V4lCaptureHandler::startCapture(const QString &/*path*/)
266 {
267 }
268
269 void V4lCaptureHandler::stopCapture()
270 {
271 }
272
273 void V4lCaptureHandler::captureFrame(const QString &fname)
274 {
275     m_captureFramePath = fname;
276 }
277
278 void V4lCaptureHandler::showOverlay(QImage img, bool /*transparent*/)
279 {
280     m_overlayImage = img;
281 }
282
283 void V4lCaptureHandler::hideOverlay()
284 {
285     m_overlayImage = QImage();
286 }
287
288 void V4lCaptureHandler::hidePreview(bool hide)
289 {
290     m_display->setHidden(hide);
291 }
292
293 void V4lCaptureHandler::stopPreview()
294 {
295     if (!m_update) return;
296     m_update = false;
297     src_close(&v4lsrc);
298 }