]> git.sesse.net Git - kdenlive/blob - src/v4l/v4lcapture.cpp
Add support for video4Linux (webcams) to stopmotion utility
[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
31 #include <KDebug>
32 #include <KLocale>
33
34 #include "v4lcapture.h"
35 #include "kdenlivesettings.h"
36
37
38 static src_t v4lsrc;
39
40 void yuv2rgb_int3(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height)
41 {
42     int len;
43     int r, g, b;
44     int Y, U, V, Y2;
45     int rgb_ptr, y_ptr, t;
46
47     len = width * height / 2;
48
49     rgb_ptr = 0;
50     y_ptr = 0;
51
52     for(t = 0; t < len; t++) { /* process 2 pixels at a time */
53         /* Compute parts of the UV components */
54
55         U = yuv_buffer[y_ptr];
56         Y = yuv_buffer[y_ptr+1];
57         V = yuv_buffer[y_ptr+2];
58         Y2 = yuv_buffer[y_ptr+3];
59         y_ptr += 4;
60
61
62         /*r = 1.164*(Y-16) + 1.596*(V-128);
63         g = 1.164*(Y-16) - 0.813*(V-128) - 0.391*(U-128);
64         b = 1.164*(Y-16) + 2.018*(U-128);*/
65
66
67         r = ((298 * (Y - 16)               + 409 * (V - 128) + 128) >> 8);
68
69         g = ((298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
70
71         b = ((298 * (Y - 16) + 516 * (U - 128)               + 128) >> 8);
72
73         if(r > 255) r = 255;
74         if(g > 255) g = 255;
75         if(b > 255) b = 255;
76
77         if(r < 0) r = 0;
78         if(g < 0) g = 0;
79         if(b < 0) b = 0;
80
81         rgb_buffer[rgb_ptr] = b;
82         rgb_buffer[rgb_ptr+1] = g;
83         rgb_buffer[rgb_ptr+2] = r;
84         rgb_buffer[rgb_ptr+3] = 255;
85
86         rgb_ptr += 4;
87         /*r = 1.164*(Y2-16) + 1.596*(V-128);
88         g = 1.164*(Y2-16) - 0.813*(V-128) - 0.391*(U-128);
89         b = 1.164*(Y2-16) + 2.018*(U-128);*/
90
91
92         r = ((298 * (Y2 - 16)               + 409 * (V - 128) + 128) >> 8);
93
94         g = ((298 * (Y2 - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
95
96         b = ((298 * (Y2 - 16) + 516 * (U - 128)               + 128) >> 8);
97
98         if(r > 255) r = 255;
99         if(g > 255) g = 255;
100         if(b > 255) b = 255;
101
102         if(r < 0) r = 0;
103         if(g < 0) g = 0;
104         if(b < 0) b = 0;
105
106         rgb_buffer[rgb_ptr] = b;
107         rgb_buffer[rgb_ptr+1] = g;
108         rgb_buffer[rgb_ptr+2] = r;
109         rgb_buffer[rgb_ptr+3] = 255;
110         rgb_ptr += 4;
111     }
112 }
113
114 V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
115     CaptureHandler(lay, parent)
116     , m_update(false)
117 {
118     m_display = new QLabel;
119     lay->addWidget(m_display);
120 }
121
122 void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/)
123 {
124     m_display->setHidden(false);
125     fswebcam_config_t *config;
126     /* Prepare the configuration structure. */
127     config = (fswebcam_config_t *) calloc(sizeof(fswebcam_config_t), 1);
128     if(!config) {
129         /*WARN("Out of memory.");*/
130         fprintf(stderr, "Out of MEM....");
131         return;
132     }
133
134     /* Set the defaults. */
135     config->loop = 0;
136     config->offset = 0;
137     config->background = 0;
138     config->pidfile = NULL;
139     config->logfile = NULL;
140     config->gmt = 0;
141     config->start = 0;
142     config->device = strdup(KdenliveSettings::video4vdevice().toUtf8().constData());
143     config->input = NULL;
144     config->tuner = 0;
145     config->frequency = 0;
146     config->delay = 0;
147     config->use_read = 0;
148     config->list = 0;
149     config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
150     config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
151     config->fps = 0;
152     config->frames = 1;
153     config->skipframes = 0;
154     config->palette = SRC_PAL_ANY;
155     config->option = NULL;
156     config->dumpframe = NULL;
157     config->jobs = 0;
158     config->job = NULL;
159
160     /* Set defaults and parse the command line. */
161     /*if(fswc_getopts(config, argc, argv)) return(-1);*/
162
163
164     /* Record the start time. */
165     config->start = time(NULL);
166     /* Set source options... */
167     memset(&v4lsrc, 0, sizeof(v4lsrc));
168     v4lsrc.input      = config->input;
169     v4lsrc.tuner      = config->tuner;
170     v4lsrc.frequency  = config->frequency;
171     v4lsrc.delay      = config->delay;
172     v4lsrc.timeout    = 10; /* seconds */
173     v4lsrc.use_read   = config->use_read;
174     v4lsrc.list       = config->list;
175     v4lsrc.palette    = config->palette;
176     v4lsrc.width      = config->width;
177     v4lsrc.height     = config->height;
178     v4lsrc.fps        = config->fps;
179     v4lsrc.option     = config->option;
180     char *source = config->device;
181
182     if(src_open(&v4lsrc, source) != 0) return;
183     m_update = true;
184     QTimer::singleShot(200, this, SLOT(slotUpdate()));
185 }
186
187 V4lCaptureHandler::~V4lCaptureHandler()
188 {
189     stopCapture();
190 }
191
192 void V4lCaptureHandler::slotUpdate()
193 {
194     if(!m_update) return;
195     src_grab(&v4lsrc);
196     uint8_t *img = (uint8_t *) v4lsrc.img;
197     uint32_t i = v4lsrc.width * v4lsrc.height;
198
199     if(v4lsrc.length << 2 < i) return;
200
201     QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB32);
202     //Format_ARGB32_Premultiplied
203     //convert from uyvy422 to rgba
204     yuv2rgb_int3((uchar *)img, (uchar *)qimg.bits(), v4lsrc.width, v4lsrc.height);
205     if(!m_captureFramePath.isEmpty()) {
206         qimg.save(m_captureFramePath);
207         m_captureFramePath.clear();
208     }
209     m_display->setPixmap(QPixmap::fromImage(qimg));
210     if(m_update) QTimer::singleShot(200, this, SLOT(slotUpdate()));
211 }
212
213 void V4lCaptureHandler::startCapture(const QString &/*path*/)
214 {
215 }
216
217 void V4lCaptureHandler::stopCapture()
218 {
219 }
220
221 void V4lCaptureHandler::captureFrame(const QString &fname)
222 {
223     m_captureFramePath = fname;
224 }
225
226 void V4lCaptureHandler::showOverlay(QImage /*img*/, bool /*transparent*/)
227 {
228 }
229
230 void V4lCaptureHandler::hideOverlay()
231 {
232 }
233
234 void V4lCaptureHandler::hidePreview(bool hide)
235 {
236     m_display->setHidden(hide);
237 }
238
239 void V4lCaptureHandler::stopPreview()
240 {
241     if(!m_update) return;
242     m_update = false;
243     src_close(&v4lsrc);
244 }