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