]> git.sesse.net Git - kdenlive/commitdiff
Stopmotion widget: Improved webcam support, taken from the fswebcam project
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 1 Nov 2010 21:08:46 +0000 (21:08 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 1 Nov 2010 21:08:46 +0000 (21:08 +0000)
svn path=/trunk/kdenlive/; revision=5067

21 files changed:
src/CMakeLists.txt
src/blackmagic/capture.cpp
src/blackmagic/capture.h
src/kdenlivesettingsdialog.cpp
src/mainwindow.cpp
src/stopmotion/capturehandler.cpp
src/stopmotion/capturehandler.h
src/stopmotion/stopmotion.cpp
src/stopmotion/stopmotion.h
src/v4l/dec.h [new file with mode: 0644]
src/v4l/dec_bayer.c [new file with mode: 0644]
src/v4l/dec_grey.c [new file with mode: 0644]
src/v4l/dec_jpeg.c [new file with mode: 0644]
src/v4l/dec_rgb.c [new file with mode: 0644]
src/v4l/dec_s561.c [new file with mode: 0644]
src/v4l/dec_yuv.c [new file with mode: 0644]
src/v4l/src.c
src/v4l/src.h
src/v4l/src_v4l2.c
src/v4l/v4lcapture.cpp
src/v4l/v4lcapture.h

index 65a69c3f8ad888d7f6e8ca2ddcb6109b083ba688..501af427180ec59bb894a7c92656fe78cf16100a 100644 (file)
@@ -269,6 +269,12 @@ if (NOT APPLE)
     v4l/v4lcapture.cpp
     v4l/src.c
     v4l/src_v4l2.c
+    v4l/dec_bayer.c
+    v4l/dec_grey.c
+    v4l/dec_jpeg.c
+    v4l/dec_rgb.c
+    v4l/dec_s561.c
+    v4l/dec_yuv.c
   )
 endif (NOT APPLE)
 
@@ -277,6 +283,7 @@ endif (NOT APPLE)
 find_library( DL_LIB NAMES ${CMAKE_DL_LIBS} )
 MESSAGE( STATUS "using dl library: ${DL_LIB}" )
 
+
 kde4_add_kcfg_files(kdenlive_SRCS kdenlivesettings.kcfgc )
 QT4_ADD_DBUS_ADAPTOR(kdenlive_SRCS org.kdenlive.MainWindow.xml mainwindow.h MainWindow)
 kde4_add_executable(kdenlive ${kdenlive_SRCS} ${kdenlive_UI})
index 505c0858e3a161e322fbf2b4332f70267c0b532e..2989cacfbb3da89abb028c49a8641d52eddcacc8 100644 (file)
@@ -331,7 +331,7 @@ void DeckLinkCaptureDelegate::slotProcessFrame()
     } else {
         QImage image(videoFrame->GetWidth(), videoFrame->GetHeight(), QImage::Format_ARGB32_Premultiplied);
         //convert from uyvy422 to rgba
-        CaptureHandler::yuv2rgb((uchar *)frameBytes, (uchar *)image.bits(), videoFrame->GetWidth(), videoFrame->GetHeight());
+        CaptureHandler::uyvy2rgb((uchar *)frameBytes, (uchar *)image.bits(), videoFrame->GetWidth(), videoFrame->GetHeight());
         image.save(capturePath);
         emit frameSaved(capturePath);
     }
@@ -814,6 +814,10 @@ void BmdCaptureHandler::hideOverlay()
     if (previewView) previewView->hideOverlay();
 }
 
+void BmdCaptureHandler::setDevice(const QString , QString)
+{
+}
+
 void BmdCaptureHandler::hidePreview(bool hide)
 {
     if (previewView) previewView->setHidden(hide);
index 1a7942ec51ab28df2d72b8d6e3f4fe6c9abdebf7..1be79adb8cbf36074214f67b9ae3a69a3f98f873 100644 (file)
@@ -60,6 +60,7 @@ public:
     void hideOverlay();
     void hidePreview(bool hide);
     QStringList getDeviceName(QString);
+    void setDevice(const QString input, QString size = QString());
 
 private:
     IDeckLinkIterator       *deckLinkIterator;
index e752b39a45c3878fb5ad428f1eb112dbcccbcc1f..035408a3319f380fefe8e6e61e3f940a12acac08 100644 (file)
@@ -89,8 +89,10 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent) :
         QString path = "/dev/video" + QString::number(i);
         if (QFile::exists(path)) {
             QStringList deviceInfo = v4l.getDeviceName(path);
-            m_configCapture.kcfg_detectedv4ldevices->addItem(deviceInfo.at(0), path);
-            m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
+            if (!deviceInfo.isEmpty()) {
+                m_configCapture.kcfg_detectedv4ldevices->addItem(deviceInfo.at(0), path);
+                m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, deviceInfo.at(1), Qt::UserRole + 1);
+            }
         }
     }
     connect(m_configCapture.kcfg_detectedv4ldevices, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatev4lDevice()));
index 1dfe6e491841317e3c664b8bc591f72cb25b0394..d578f11907dcf62e31329358bcc60ecb373317f4 100644 (file)
@@ -553,6 +553,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
 MainWindow::~MainWindow()
 {
+    if (m_stopmotion) {
+        delete m_stopmotion;
+    }
     m_effectStack->slotClipItemSelected(NULL, 0);
     m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
 
@@ -2508,6 +2511,7 @@ void MainWindow::slotPreferences(int page, int option)
      * cached, in which case you want to display the cached dialog
      * instead of creating another one
      */
+    if (m_stopmotion) m_stopmotion->slotLive(false);
     if (KConfigDialog::showDialog("settings")) {
         KdenliveSettingsDialog* d = static_cast <KdenliveSettingsDialog*>(KConfigDialog::exists("settings"));
         if (page != -1) d->showPage(page, option);
@@ -4015,7 +4019,6 @@ void MainWindow::slotOpenStopmotion()
     m_stopmotion->show();
 }
 
-
 void MainWindow::slotDeleteClip(const QString &id)
 {
     QList <ClipProperties *> list = findChildren<ClipProperties *>();
index 38ee07e62d25d0924b3f217c2b2017176f1e5248..fc3a9b4989ca10f389824c3239f2a1f3c4af98dc 100644 (file)
@@ -38,7 +38,7 @@ void CaptureHandler::stopCapture()
 }
 
 //static
-void CaptureHandler::yuv2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height)
+void CaptureHandler::uyvy2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height)
 {
     int len;
     int r, g, b;
@@ -112,5 +112,78 @@ void CaptureHandler::yuv2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffe
     }
 }
 
+void CaptureHandler::yuyv2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height)
+{
+    int len;
+    int r, g, b;
+    int Y, U, V, Y2;
+    int rgb_ptr, y_ptr, t;
+
+    len = width * height / 2;
+
+    rgb_ptr = 0;
+    y_ptr = 0;
+
+    for (t = 0; t < len; t++) { /* process 2 pixels at a time */
+        /* Compute parts of the UV components */
+
+        Y = yuv_buffer[y_ptr];
+        U = yuv_buffer[y_ptr+1];
+        Y2 = yuv_buffer[y_ptr+2];
+        V = yuv_buffer[y_ptr+3];
+        y_ptr += 4;
+
+
+        /*r = 1.164*(Y-16) + 1.596*(V-128);
+        g = 1.164*(Y-16) - 0.813*(V-128) - 0.391*(U-128);
+        b = 1.164*(Y-16) + 2.018*(U-128);*/
+
+
+        r = ((298 * (Y - 16)               + 409 * (V - 128) + 128) >> 8);
+
+        g = ((298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
+
+        b = ((298 * (Y - 16) + 516 * (U - 128)               + 128) >> 8);
+
+        if (r > 255) r = 255;
+        if (g > 255) g = 255;
+        if (b > 255) b = 255;
+
+        if (r < 0) r = 0;
+        if (g < 0) g = 0;
+        if (b < 0) b = 0;
+
+        rgb_buffer[rgb_ptr] = b;
+        rgb_buffer[rgb_ptr+1] = g;
+        rgb_buffer[rgb_ptr+2] = r;
+        rgb_buffer[rgb_ptr+3] = 255;
+
+        rgb_ptr += 4;
+        /*r = 1.164*(Y2-16) + 1.596*(V-128);
+        g = 1.164*(Y2-16) - 0.813*(V-128) - 0.391*(U-128);
+        b = 1.164*(Y2-16) + 2.018*(U-128);*/
+
+
+        r = ((298 * (Y2 - 16)               + 409 * (V - 128) + 128) >> 8);
+
+        g = ((298 * (Y2 - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
+
+        b = ((298 * (Y2 - 16) + 516 * (U - 128)               + 128) >> 8);
+
+        if (r > 255) r = 255;
+        if (g > 255) g = 255;
+        if (b > 255) b = 255;
+
+        if (r < 0) r = 0;
+        if (g < 0) g = 0;
+        if (b < 0) b = 0;
+
+        rgb_buffer[rgb_ptr] = b;
+        rgb_buffer[rgb_ptr+1] = g;
+        rgb_buffer[rgb_ptr+2] = r;
+        rgb_buffer[rgb_ptr+3] = 255;
+        rgb_ptr += 4;
+    }
+}
 
 
index 342a25105161ef3f4137bd45c7a82ee76dc43555..947111ab9d5822bb5e6118559c306a71725f8b18 100644 (file)
@@ -39,7 +39,9 @@ public:
     virtual void hideOverlay() = 0;
     virtual void hidePreview(bool hide) = 0;
     virtual QStringList getDeviceName(QString input) = 0;
-    static void yuv2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height);
+    virtual void setDevice(const QString input, QString size = QString()) = 0;
+    static void uyvy2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height);
+    static void yuyv2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height);
 
 protected:
     QVBoxLayout *m_layout;
index 46c33f5209de75e4a41480f1b35b0d118e38517b..3a2dbd2b84abf401b97882bfb57f3d6518896713 100644 (file)
@@ -97,6 +97,7 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * >
     , m_sequenceFrame(0)
     , m_animatedIndex(-1)
 {
+    //setAttribute(Qt::WA_DeleteOnClose);
     addActions(actions);
     setupUi(this);
     setWindowTitle(i18n("Stop Motion Capture"));
@@ -191,13 +192,36 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * >
     }
     if (QFile::exists(KdenliveSettings::video4vdevice())) {
 #ifndef Q_WS_MAC
-        if (m_bmCapture == NULL) m_bmCapture = new V4lCaptureHandler(m_layout);
-        capture_device->addItem(m_bmCapture->getDeviceName(KdenliveSettings::video4vdevice()).at(0), "v4l");
+        V4lCaptureHandler v4l(NULL);
+        // Video 4 Linux device detection
+        for (int i = 0; i < 10; i++) {
+            QString path = "/dev/video" + QString::number(i);
+            if (QFile::exists(path)) {
+                QStringList deviceInfo = v4l.getDeviceName(path);
+                if (!deviceInfo.isEmpty()) {
+                    capture_device->addItem(deviceInfo.at(0), "v4l");
+                    capture_device->setItemData(capture_device->count() - 1, path, Qt::UserRole + 1);
+                    capture_device->setItemData(capture_device->count() - 1, deviceInfo.at(1), Qt::UserRole + 2);
+                    if (path == KdenliveSettings::video4vdevice()) capture_device->setCurrentIndex(capture_device->count() - 1);
+                }
+            }
+        }
+
+        /*V4lCaptureHandler v4lhandler(NULL);
+        QStringList deviceInfo = v4lhandler.getDeviceName(KdenliveSettings::video4vdevice());
+            capture_device->addItem(deviceInfo.at(0), "v4l");
+        capture_device->setItemData(capture_device->count() - 1, deviceInfo.at(3), Qt::UserRole + 1);*/
+        if (m_bmCapture == NULL) {
+            m_bmCapture = new V4lCaptureHandler(m_layout);
+            m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());
+        }
 #endif
     }
 
-    connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
     connect(capture_device, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateHandler()));
+    if (m_bmCapture) {
+        connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
+    } else live_button->setEnabled(false);
     m_frame_preview = new MyLabel(this);
     connect(m_frame_preview, SIGNAL(seek(bool)), this, SLOT(slotSeekFrame(bool)));
     connect(m_frame_preview, SIGNAL(switchToLive()), this, SLOT(slotSwitchLive()));
@@ -269,17 +293,21 @@ void StopmotionWidget::slotIntervalCapture(bool capture)
 void StopmotionWidget::slotUpdateHandler()
 {
     QString data = capture_device->itemData(capture_device->currentIndex()).toString();
-    m_bmCapture->stopPreview();
-    delete m_bmCapture;
+    slotLive(false);
+    if (m_bmCapture) {
+        delete m_bmCapture;
+    }
     m_layout->removeWidget(m_frame_preview);
     if (data == "v4l") {
 #ifndef Q_WS_MAC
         m_bmCapture = new V4lCaptureHandler(m_layout);
+        m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());
 #endif
     } else {
         m_bmCapture = new BmdCaptureHandler(m_layout);
-        connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
+        if (m_bmCapture) connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
     }
+    live_button->setEnabled(m_bmCapture != NULL);
     m_layout->addWidget(m_frame_preview);
 }
 
@@ -307,24 +335,24 @@ void StopmotionWidget::slotSwitchLive()
 {
     setUpdatesEnabled(false);
     if (m_frame_preview->isHidden()) {
-        m_bmCapture->hidePreview(true);
+        if (m_bmCapture) m_bmCapture->hidePreview(true);
         m_frame_preview->setHidden(false);
     } else {
         m_frame_preview->setHidden(true);
-        m_bmCapture->hidePreview(false);
+        if (m_bmCapture) m_bmCapture->hidePreview(false);
     }
     setUpdatesEnabled(true);
 }
 
 void StopmotionWidget::slotLive(bool isOn)
 {
-    if (isOn) {
+    if (isOn && m_bmCapture) {
         //m_frame_preview->setImage(QImage());
         m_frame_preview->setHidden(true);
         m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode(), false);
         capture_button->setEnabled(true);
     } else {
-        m_bmCapture->stopPreview();
+        if (m_bmCapture) m_bmCapture->stopPreview();
         m_frame_preview->setHidden(false);
         capture_button->setEnabled(false);
         live_button->setChecked(false);
@@ -337,13 +365,14 @@ void StopmotionWidget::slotShowOverlay(bool isOn)
         if (live_button->isChecked() && m_sequenceFrame > 0) {
             slotUpdateOverlay();
         }
-    } else {
+    } else if (m_bmCapture) {
         m_bmCapture->hideOverlay();
     }
 }
 
 void StopmotionWidget::slotUpdateOverlay()
 {
+    if (m_bmCapture == NULL) return;
     QString path = getPathForFrame(m_sequenceFrame - 1);
     if (!QFile::exists(path)) return;
     QImage img(path);
@@ -408,6 +437,7 @@ void StopmotionWidget::sequenceNameChanged(const QString &name)
 
 void StopmotionWidget::slotCaptureFrame()
 {
+    if (m_bmCapture == NULL) return;
     if (sequence_name->currentText().isEmpty()) {
         QString seqName = QInputDialog::getText(this, i18n("Create New Sequence"), i18n("Enter sequence name"));
         if (seqName.isEmpty()) return;
@@ -484,7 +514,7 @@ void StopmotionWidget::slotShowFrame(const QString &path)
     QImage img(path);
     capture_button->setEnabled(false);
     if (!img.isNull()) {
-        m_bmCapture->hidePreview(true);
+        if (m_bmCapture) m_bmCapture->hidePreview(true);
         m_frame_preview->setImage(img);
         m_frame_preview->setHidden(false);
         m_frame_preview->update();
index bd74a5217a6838820ebd0a814962625b0cca98e1..9da28ad60253fa3076c2932128d6ff9cb6efdeb3 100644 (file)
@@ -120,11 +120,13 @@ private:
     int m_effectIndex;
 #endif
 
-private slots:
+public slots:
     /** @brief Display the live feed from capture device.
      @param isOn enable or disable the feature */
     void slotLive(bool isOn);
 
+private slots:
+
     /** @brief Display the last captured frame over current live feed.
      @param isOn enable or disable the feature */
     void slotShowOverlay(bool isOn);
diff --git a/src/v4l/dec.h b/src/v4l/dec.h
new file mode 100644 (file)
index 0000000..75a5a1f
--- /dev/null
@@ -0,0 +1,49 @@
+/* fswebcam - Small and simple webcam for *nix                */
+/*============================================================*/
+/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
+/*                                                            */
+/* This program is distributed under the terms of the GNU     */
+/* General Public License, version 2. You may use, modify,    */
+/* and redistribute it under the terms of this license. A     */
+/* copy should be included with this source.                  */
+
+#ifdef __cplusplus
+extern "C" {
+ #endif
+
+#ifndef INC_DEC_H
+#define INC_DEC_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+extern int fswc_add_image_bayer(avgbmp_t *dst, uint8_t *img, uint32_t length, uint32_t w, uint32_t h, int palette);
+
+extern int fswc_add_image_y16(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_grey(src_t *src, avgbmp_t *abitmap);
+
+extern int verify_jpeg_dht(uint8_t *src,  uint32_t lsrc, uint8_t **dst, uint32_t *ldst);
+
+extern int fswc_add_image_png(src_t *src, avgbmp_t *abitmap);
+
+extern int fswc_add_image_rgb32(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_bgr32(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_rgb24(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_bgr24(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_rgb565(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_rgb555(src_t *src, avgbmp_t *abitmap);
+
+extern int fswc_add_image_yuyv(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_yuv420p(src_t *src, avgbmp_t *abitmap);
+extern int fswc_add_image_nv12mb(src_t *src, avgbmp_t *abitmap);
+
+extern int fswc_add_image_s561(avgbmp_t *dst, uint8_t *img, uint32_t length, uint32_t width, uint32_t height, int palette);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/src/v4l/dec_bayer.c b/src/v4l/dec_bayer.c
new file mode 100644 (file)
index 0000000..ba27e85
--- /dev/null
@@ -0,0 +1,107 @@
+/* fswebcam - Small and simple webcam for *nix                */
+/*============================================================*/
+/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
+/*                                                            */
+/* This program is distributed under the terms of the GNU     */
+/* General Public License, version 2. You may use, modify,    */
+/* and redistribute it under the terms of this license. A     */
+/* copy should be included with this source.                  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+/*#include "fswebcam.h"*/
+#include "src.h"
+
+
+int fswc_add_image_bayer(avgbmp_t *dst, uint8_t *img, uint32_t length, uint32_t w, uint32_t h, int palette)
+{
+       uint32_t x = 0, y = 0;
+       uint32_t i = w * h;
+       
+       if(length < i) return(-1);
+       
+       /* SBGGR8 bayer pattern:
+        * 
+        * BGBGBGBGBG
+        * GRGRGRGRGR
+        * BGBGBGBGBG
+        * GRGRGRGRGR
+        * 
+        * SGBRG8 bayer pattern:
+        * 
+        * GBGBGBGBGB
+        * RGRGRGRGRG
+        * GBGBGBGBGB
+        * RGRGRGRGRG
+        *
+        * SGRBG8 bayer pattern:
+        *
+        * GRGRGRGRGR
+        * BGBGBGBGBG
+        * GRGRGRGRGR
+        * BGBGBGBGBG
+       */
+       
+       while(i-- > 0)
+       {
+               uint8_t *p[8];
+               uint8_t hn, vn, di;
+               uint8_t r, g, b;
+               int mode;
+               
+               /* Setup pointers to this pixel's neighbours. */
+               p[0] = img - w - 1;
+               p[1] = img - w;
+               p[2] = img - w + 1;
+               p[3] = img - 1;
+               p[4] = img + 1;
+               p[5] = img + w - 1;
+               p[6] = img + w;
+               p[7] = img + w + 1;
+               
+               /* Juggle pointers if they are out of bounds. */
+               if(!y)              { p[0]=p[5]; p[1]=p[6]; p[2]=p[7]; }
+               else if(y == h - 1) { p[5]=p[0]; p[6]=p[1]; p[7]=p[2]; }
+               if(!x)              { p[0]=p[2]; p[3]=p[4]; p[5]=p[7]; }
+               else if(x == w - 1) { p[2]=p[0]; p[4]=p[3]; p[7]=p[5]; }
+               
+               /* Average matching neighbours. */
+               hn = (*p[3] + *p[4]) / 2;
+               vn = (*p[1] + *p[6]) / 2;
+               di = (*p[0] + *p[2] + *p[5] + *p[7]) / 4;
+               
+               /* Calculate RGB */
+               if(palette == SRC_PAL_BAYER) mode = (x + y) & 0x01;
+               else mode = ~(x + y) & 0x01;
+               
+               if(mode)
+               {
+                       g = *img;
+                       if(y & 0x01) { r = hn; b = vn; }
+                       else         { r = vn; b = hn; }
+               }
+               else if(y & 0x01) { r = *img; g = (vn + hn) / 2; b = di; }
+               else              { b = *img; g = (vn + hn) / 2; r = di; }
+               
+               if(palette == SRC_PAL_SGRBG8)
+               {
+                       uint8_t t = r;
+                       r = b;
+                       b = t;
+               }
+               
+               *(dst++) += r;
+               *(dst++) += g;
+               *(dst++) += b;
+               
+               /* Move to the next pixel (or line) */
+               if(++x == w) { x = 0; y++; }
+               img++;
+       }
+       
+       return(0);
+}
+
diff --git a/src/v4l/dec_grey.c b/src/v4l/dec_grey.c
new file mode 100644 (file)
index 0000000..28cfbfd
--- /dev/null
@@ -0,0 +1,51 @@
+/* fswebcam - Small and simple webcam for *nix                */
+/*============================================================*/
+/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
+/*                                                            */
+/* This program is distributed under the terms of the GNU     */
+/* General Public License, version 2. You may use, modify,    */
+/* and redistribute it under the terms of this license. A     */
+/* copy should be included with this source.                  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+
+#include "src.h"
+
+int fswc_add_image_y16(src_t *src, avgbmp_t *abitmap)
+{
+       uint16_t *bitmap = (uint16_t *) src->img;
+       uint32_t i = src->width * src->height;
+       
+       if(src->length < i) return(-1);
+       
+       while(i-- > 0)
+       {
+               *(abitmap++) += *bitmap >> 8;
+               *(abitmap++) += *bitmap >> 8;
+               *(abitmap++) += *(bitmap++) >> 8;
+       }
+       
+       return(0);
+}
+
+int fswc_add_image_grey(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *bitmap = (uint8_t *) src->img;
+       uint32_t i = src->width * src->height;
+       
+       if(src->length < i) return(-1);
+       
+       while(i-- > 0)
+       {
+               *(abitmap++) += *bitmap;
+               *(abitmap++) += *bitmap;
+               *(abitmap++) += *(bitmap++);
+       }
+       
+       return(0);
+}
+
diff --git a/src/v4l/dec_jpeg.c b/src/v4l/dec_jpeg.c
new file mode 100644 (file)
index 0000000..2d94d8e
--- /dev/null
@@ -0,0 +1,109 @@
+/* fswebcam - Small and simple webcam for *nix                */
+/*============================================================*/
+/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
+/*                                                            */
+/* This program is distributed under the terms of the GNU     */
+/* General Public License, version 2. You may use, modify,    */
+/* and redistribute it under the terms of this license. A     */
+/* copy should be included with this source.                  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <gd.h>
+#include "src.h"
+
+int verify_jpeg_dht(uint8_t *src,  uint32_t lsrc,
+                    uint8_t **dst, uint32_t *ldst)
+{
+       /* This function is based on a patch provided by Scott J. Bertin. */
+       
+       static unsigned char dht[] =
+       {
+               0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
+               0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+               0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
+               0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
+               0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
+               0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
+               0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
+               0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+               0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+               0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
+               0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
+               0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+               0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
+               0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
+               0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+               0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+               0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+               0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+               0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+               0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+               0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
+               0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+               0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+               0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
+               0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
+               0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
+               0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+               0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
+               0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
+               0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
+               0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+               0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+               0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
+               0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
+               0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+               0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+               0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+               0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+               0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+               0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
+       };
+       uint8_t *p, *i = NULL;
+       
+       /* By default we simply return the source image. */
+       *dst = src;
+       *ldst = lsrc;
+       
+       /* Scan for an existing DHT segment or the first SOS segment. */
+       for(p = src + 2; p - src < lsrc - 3 && i == NULL; )
+       {
+               if(*(p++) != 0xFF) continue;
+               
+               if(*p == 0xD9) break;           /* JPEG_EOI */
+               if(*p == 0xC4) return(0);       /* JPEG_DHT */
+               if(*p == 0xDA && !i) i = p - 1; /* JPEG_SOS */
+               
+               /* Move to next segment. */
+               p += (p[1] << 8) + p[2];
+       }
+       
+       /* If no SOS was found, insert the DHT directly after the SOI. */
+       if(i == NULL) i = src + 2;
+       
+       
+       *ldst = lsrc + sizeof(dht);
+       *dst  = malloc(*ldst);
+       if(!*dst)
+       {
+               return(-1);
+       }
+       
+       /* Copy the JPEG data, inserting the DHT segment. */
+       memcpy((p  = *dst), src, i - src);
+       memcpy((p += i - src), dht, sizeof(dht));
+       memcpy((p += sizeof(dht)), i, lsrc - (i - src));
+       
+       return(1);
+}
+
+
+
diff --git a/src/v4l/dec_rgb.c b/src/v4l/dec_rgb.c
new file mode 100644 (file)
index 0000000..ab76857
--- /dev/null
@@ -0,0 +1,133 @@
+/* fswebcam - Small and simple webcam for *nix                */
+/*============================================================*/
+/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
+/*                                                            */
+/* This program is distributed under the terms of the GNU     */
+/* General Public License, version 2. You may use, modify,    */
+/* and redistribute it under the terms of this license. A     */
+/* copy should be included with this source.                  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include "src.h"
+
+int fswc_add_image_rgb32(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *img = (uint8_t *) src->img;
+       uint32_t i = src->width * src->height;
+       
+       if(src->length << 2 < i) return(-1);
+       
+       while(i-- > 0)
+       {
+               *(abitmap++) += *(img++);
+               *(abitmap++) += *(img++);
+               *(abitmap++) += *(img++);
+               img++;
+       }
+       
+       return(0);
+}
+
+int fswc_add_image_bgr32(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *img = (uint8_t *) src->img;
+       uint32_t p, i = src->width * src->height;
+       
+       if(src->length << 2 < i) return(-1);
+       
+       for(p = 0; p < i; p += 4)
+       {
+               abitmap[0] += img[2];
+               abitmap[1] += img[1];
+               abitmap[2] += img[0];
+               abitmap += 3;
+               img += 4;
+       }
+       
+       return(0);
+}
+
+int fswc_add_image_rgb24(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *img = (uint8_t *) src->img;
+       uint32_t i = src->width * src->height * 3;
+       
+       if(src->length < i) return(-1);
+       while(i-- > 0) *(abitmap++) += *(img++);
+       
+       return(0);
+}
+
+int fswc_add_image_bgr24(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *img = (uint8_t *) src->img;
+       uint32_t p, i = src->width * src->height * 3;
+       
+       if(src->length < i) return(-1);
+       
+       for(p = 0; p < src->length; p += 3)
+       {
+               abitmap[0] += img[2];
+               abitmap[1] += img[1];
+               abitmap[2] += img[0];
+               abitmap += 3;
+               img += 3;
+       }
+       
+       return(0);
+}
+
+int fswc_add_image_rgb565(src_t *src, avgbmp_t *abitmap)
+{
+       uint16_t *img = (uint16_t *) src->img;
+       uint32_t i = src->width * src->height;
+       
+       if(src->length >> 1 < i) return(-1);
+       
+       while(i-- > 0)
+       {
+               uint8_t r, g, b;
+               
+               r = (*img & 0xF800) >> 8;
+               g = (*img &  0x7E0) >> 3;
+               b = (*img &   0x1F) << 3;
+               
+               *(abitmap++) += r + (r >> 5);
+               *(abitmap++) += g + (g >> 6);
+               *(abitmap++) += b + (b >> 5);
+               
+               img++;
+       }
+       
+       return(0);
+}
+
+int fswc_add_image_rgb555(src_t *src, avgbmp_t *abitmap)
+{
+       uint16_t *img = (uint16_t *) src->img;
+       uint32_t i = src->width * src->height;
+       
+       if(src->length >> 1 < i) return(-1);
+       
+       while(i-- > 0)
+       {
+               uint8_t r, g, b;
+               
+               r = (*img & 0x7C00) >> 7;
+               g = (*img &  0x3E0) >> 2;
+               b = (*img &   0x1F) << 3;
+               
+               *(abitmap++) += r + (r >> 5);
+               *(abitmap++) += g + (g >> 5);
+               *(abitmap++) += b + (b >> 5);
+               
+               img++;
+       }
+       
+       return(0);
+}
+
diff --git a/src/v4l/dec_s561.c b/src/v4l/dec_s561.c
new file mode 100644 (file)
index 0000000..ae1bc4f
--- /dev/null
@@ -0,0 +1,908 @@
+/* Spca561decoder (C) 2005 Andrzej Szombierski [qq@kuku.eu.org] */
+/*==============================================================*/
+/* This program is distributed under the terms of the GNU       */
+/* General Public License, version 2. You may use, modify,      */
+/* and redistribute it under the terms of this license. A       */
+/* copy should be included with this source.                    */
+
+/*
+ *     Decoder for compressed spca561 images
+ *     It was developed for "Labtec WebCam Elch 2(SPCA561A)" (046d:0929)
+ *     but it might work with other spca561 cameras
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "src.h"
+#include "dec.h"
+
+/*fixme: not reentrant */
+static unsigned int bit_bucket;
+static const unsigned char *input_ptr;
+
+static void refill(int *bitfill)
+{
+       if (*bitfill < 8) {
+               bit_bucket = (bit_bucket << 8) | *(input_ptr++);
+               *bitfill += 8;
+       }
+}
+
+static int nbits(int *bitfill, int n)
+{
+       bit_bucket = (bit_bucket << 8) | *(input_ptr++);
+       *bitfill -= n;
+       return (bit_bucket >> (*bitfill & 0xff)) & ((1 << n) - 1);
+}
+
+static int _nbits(int *bitfill, int n)
+{
+       *bitfill -= n;
+       return (bit_bucket >> (*bitfill & 0xff)) & ((1 << n) - 1);
+}
+
+static int fun_A(int *bitfill)
+{
+       int ret;
+       static int tab[] = {
+               12, 13, 14, 15, 16, 17, 18, 19, -12, -13, -14, -15,
+               -16, -17, -18, -19, -19
+       };
+
+       ret = tab[nbits(bitfill, 4)];
+
+       refill(bitfill);
+       return ret;
+}
+static int fun_B(int *bitfill)
+{
+       static int tab1[] =
+           { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31, 31,
+               31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+                   16, 17,
+               18,
+               19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
+       };
+       static int tab[] =
+           { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -5,
+               -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17,
+                   -18, -19
+       };
+       unsigned int tmp;
+
+       tmp = nbits(bitfill, 7) - 68;
+       refill(bitfill);
+       if (tmp > 47)
+               return 0xff;
+       return tab[tab1[tmp]];
+}
+static int fun_C(int *bitfill, int gkw)
+{
+       static int tab1[] =
+           { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 23, 23, 23, 23, 23, 23,
+               23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+                   12, 13,
+               14,
+               15, 16, 17, 18, 19, 20, 21, 22
+       };
+       static int tab[] =
+           { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -9, -10, -11,
+               -12, -13, -14, -15, -16, -17, -18, -19
+       };
+       unsigned int tmp;
+
+       if (gkw == 0xfe) {
+               if (nbits(bitfill, 1) == 0)
+                       return 7;
+               else
+                       return -8;
+       }
+
+       if (gkw != 0xff)
+               return 0xff;
+
+       tmp = nbits(bitfill, 7) - 72;
+       if (tmp > 43)
+               return 0xff;
+
+       refill(bitfill);
+       return tab[tab1[tmp]];
+}
+static int fun_D(int *bitfill, int gkw)
+{
+       if (gkw == 0xfd) {
+               if (nbits(bitfill, 1) == 0)
+                       return 12;
+               return -13;
+       }
+
+       if (gkw == 0xfc) {
+               if (nbits(bitfill, 1) == 0)
+                       return 13;
+               return -14;
+       }
+
+       if (gkw == 0xfe) {
+               switch (nbits(bitfill, 2)) {
+               case 0:
+                       return 14;
+               case 1:
+                       return -15;
+               case 2:
+                       return 15;
+               case 3:
+                       return -16;
+               }
+       }
+
+       if (gkw == 0xff) {
+               switch (nbits(bitfill, 3)) {
+               case 4:
+                       return 16;
+               case 5:
+                       return -17;
+               case 6:
+                       return 17;
+               case 7:
+                       return -18;
+               case 2:
+                       return _nbits(bitfill, 1) ? 0xed : 0x12;
+               case 3:
+                       (*bitfill)--;
+                       return 18;
+               }
+               return 0xff;
+       }
+       return gkw;
+}
+
+static int fun_E(int cur_byte, int *bitfill)
+{
+       static int tab0[] = { 0, -1, 1, -2, 2, -3, 3, -4 };
+       static int tab1[] = { 4, -5, 5, -6, 6, -7, 7, -8 };
+       static int tab2[] = { 8, -9, 9, -10, 10, -11, 11, -12 };
+       static int tab3[] = { 12, -13, 13, -14, 14, -15, 15, -16 };
+       static int tab4[] = { 16, -17, 17, -18, 18, -19, 19, -19 };
+
+       if ((cur_byte & 0xf0) >= 0x80) {
+               *bitfill -= 4;
+               return tab0[(cur_byte >> 4) & 7];
+       }
+       if ((cur_byte & 0xc0) == 0x40) {
+               *bitfill -= 5;
+               return tab1[(cur_byte >> 3) & 7];
+
+       }
+       if ((cur_byte & 0xe0) == 0x20) {
+               *bitfill -= 6;
+               return tab2[(cur_byte >> 2) & 7];
+
+       }
+       if ((cur_byte & 0xf0) == 0x10) {
+               *bitfill -= 7;
+               return tab3[(cur_byte >> 1) & 7];
+
+       }
+       if ((cur_byte & 0xf8) == 8) {
+               *bitfill -= 8;
+               return tab4[cur_byte & 7];
+       }
+       return 0xff;
+}
+
+static int fun_F(int cur_byte, int *bitfill)
+{
+       *bitfill -= 5;
+       switch (cur_byte & 0xf8) {
+       case 0x80:
+               return 0;
+       case 0x88:
+               return -1;
+       case 0x90:
+               return 1;
+       case 0x98:
+               return -2;
+       case 0xa0:
+               return 2;
+       case 0xa8:
+               return -3;
+       case 0xb0:
+               return 3;
+       case 0xb8:
+               return -4;
+       case 0xc0:
+               return 4;
+       case 0xc8:
+               return -5;
+       case 0xd0:
+               return 5;
+       case 0xd8:
+               return -6;
+       case 0xe0:
+               return 6;
+       case 0xe8:
+               return -7;
+       case 0xf0:
+               return 7;
+       case 0xf8:
+               return -8;
+       }
+
+       *bitfill -= 1;
+       switch (cur_byte & 0xfc) {
+       case 0x40:
+               return 8;
+       case 0x44:
+               return -9;
+       case 0x48:
+               return 9;
+       case 0x4c:
+               return -10;
+       case 0x50:
+               return 10;
+       case 0x54:
+               return -11;
+       case 0x58:
+               return 11;
+       case 0x5c:
+               return -12;
+       case 0x60:
+               return 12;
+       case 0x64:
+               return -13;
+       case 0x68:
+               return 13;
+       case 0x6c:
+               return -14;
+       case 0x70:
+               return 14;
+       case 0x74:
+               return -15;
+       case 0x78:
+               return 15;
+       case 0x7c:
+               return -16;
+       }
+
+       *bitfill -= 1;
+       switch (cur_byte & 0xfe) {
+       case 0x20:
+               return 16;
+       case 0x22:
+               return -17;
+       case 0x24:
+               return 17;
+       case 0x26:
+               return -18;
+       case 0x28:
+               return 18;
+       case 0x2a:
+               return -19;
+       case 0x2c:
+               return 19;
+       }
+
+       *bitfill += 7;
+       return 0xff;
+}
+
+static int spca561_decode(int width, int height,
+                                  const unsigned char *inbuf,
+                                  unsigned char *outbuf)
+{
+       /* buffers */
+       static int accum[8 * 8 * 8];
+       static int i_hits[8 * 8 * 8];
+
+       const int nbits_A[] =
+           { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+                   5, 5,
+               5, 5, 5, 5, 5,
+               5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+       };
+       const int tab_A[] =
+           { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 11, -11, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+                   10, 10,
+               255, 254, -4,
+               -4, -5, -5, -6, -6, -7, -7, -8, -8, -9, -9, -10, -10, -1,
+                   -1, -1,
+               -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
+                   3, 3, 3,
+               3, 3, 3,
+               -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -3,
+                   -3, 1,
+               1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1,
+               1
+       };
+
+       const int nbits_B[] =
+           { 0, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       };
+       const int tab_B[] =
+           { 0xff, -4, 3, 3, -3, -3, -3, -3, 2, 2, 2, 2, 2, 2, 2, 2, -2,
+               -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+                   1, 1,
+               1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0,
+       };
+
+       const int nbits_C[] =
+           { 0, 0, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
+               5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+                   4, 4,
+               4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, 2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       };
+       const int tab_C[] =
+           { 0xff, 0xfe, 6, -7, 5, 5, -6, -6, 4, 4, 4, 4, -5, -5, -5, -5,
+               3, 3, 3, 3, 3, 3, 3, 3, -4, -4, -4, -4, -4, -4, -4, -4, 2,
+                   2, 2, 2,
+               2, 2, 2,
+               2, 2, 2, 2, 2, 2, 2, 2, 2, -3, -3, -3, -3, -3, -3, -3, -3,
+                   -3, -3,
+               -3, -3, -3,
+               -3, -3, -3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1,
+               1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -2, -2, -2, -2, -2, -2, -2,
+                   -2, -2,
+               -2, -2, -2,
+               -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+                   -2, -2,
+               -2, -2,
+               -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1,
+       };
+
+       const int nbits_D[] =
+           { 0, 0, 0, 0, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5,
+                   5, 5,
+               5, 5, 5, 5, 5,
+               5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4,
+                   4, 4,
+               4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+                   4, 4,
+               4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+                   4, 4,
+               4, 4, 4, 4, 4,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                   3, 3,
+               3, 3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
+       };
+       const int tab_D[] =
+           { 0xff, 0xfe, 0xfd, 0xfc, 10, -11, 11, -12, 8, 8, -9, -9, 9, 9,
+               -10, -10, 6, 6, 6, 6, -7, -7, -7, -7, 7, 7, 7, 7, -8, -8,
+                   -8, -8,
+               4, 4, 4, 4,
+               4, 4, 4, 4, -5, -5, -5, -5, -5, -5, -5, -5, 5, 5, 5, 5, 5,
+                   5, 5, 5,
+               -6, -6,
+               -6, -6, -6, -6, -6, -6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+                   2, 2,
+               2, 2, -3,
+               -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+                   3, 3,
+               3, 3, 3, 3,
+               3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -4, -4, -4, -4, -4, -4, -4,
+                   -4, -4,
+               -4, -4, -4,
+               -4, -4, -4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                   -1, -1,
+               -1, -1,
+               -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                   1, 1, 1,
+               1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, -2, -2, -2, -2, -2, -2, -2, -2,
+                   -2, -2,
+               -2, -2, -2,
+               -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+                   -2, -2,
+               -2, -2
+       };
+
+       /* a_curve[19 + i] = ... [-19..19] => [-160..160] */
+       const int a_curve[] =
+           { -160, -144, -128, -112, -98, -88, -80, -72, -64, -56, -48,
+               -40, -32, -24, -18, -12, -8, -5, -2, 0, 2, 5, 8, 12, 18,
+                   24, 32,
+               40, 48, 56, 64,
+               72, 80, 88, 98, 112, 128, 144, 160
+       };
+       /* clamp0_255[256 + i] = min(max(i,255),0) */
+       const unsigned char clamp0_255[] =
+           { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                   1, 2,
+               3, 4, 5, 6, 7, 8, 9, 10,
+               11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+                   26, 27,
+               28, 29, 30, 31, 32, 33,
+               34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+                   49, 50,
+               51, 52, 53, 54, 55, 56,
+               57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+                   72, 73,
+               74, 75, 76, 77, 78, 79,
+               80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+                   95, 96,
+               97, 98, 99, 100, 101,
+               102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+                   114,
+               115, 116, 117, 118, 119,
+               120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+                   132,
+               133, 134, 135, 136, 137,
+               138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+                   150,
+               151, 152, 153, 154, 155,
+               156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+                   168,
+               169, 170, 171, 172, 173,
+               174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
+                   186,
+               187, 188, 189, 190, 191,
+               192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+                   204,
+               205, 206, 207, 208, 209,
+               210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+                   222,
+               223, 224, 225, 226, 227,
+               228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+                   240,
+               241, 242, 243, 244, 245,
+               246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255, 255, 255, 255, 255,
+               255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+                   255,
+               255
+       };
+       /* abs_clamp15[19 + i] = min(abs(i), 15) */
+       const int abs_clamp15[] =
+           { 15, 15, 15, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3,
+               2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+                   15, 15,
+               15
+       };
+       /* diff_encoding[256 + i] = ... */
+       const int diff_encoding[] =
+           { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+                   7, 7,
+               7, 7, 7, 7, 7, 7, 7,
+               7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5,
+                   5, 5,
+               5, 5, 5, 5, 5, 3, 3,
+               3, 3, 1, 1, 0, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6, 6,
+               6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+                   6, 6,
+               6, 6, 6, 6, 6, 6
+       };
+
+       int block;
+       int bitfill = 0;
+       int xwidth = width + 6;
+       int off_up_right = 2 - 2 * xwidth;
+       int off_up_left = -2 - 2 * xwidth;
+       int pixel_U = 0, saved_pixel_UR = 0;
+       int pixel_x = 0, pixel_y = 2;
+       unsigned char *output_ptr = outbuf;
+
+       memset(i_hits, 0, sizeof(i_hits));
+       memset(accum, 0, sizeof(accum));
+
+       memcpy(outbuf + xwidth * 2 + 3, inbuf + 0x14, width);
+       memcpy(outbuf + xwidth * 3 + 3, inbuf + 0x14 + width, width);
+
+       input_ptr = inbuf + 0x14 + width * 2;
+       output_ptr = outbuf + (xwidth) * 4 + 3;
+
+       bit_bucket = 0;
+
+       for (block = 0; block < ((height - 2) * width) / 32; ++block) {
+               int b_it, var_7 = 0;
+               int cur_byte;
+
+               refill(&bitfill);
+
+               cur_byte = (bit_bucket >> (bitfill & 7)) & 0xff;
+
+               if ((cur_byte & 0x80) == 0) {
+                       var_7 = 0;
+                       bitfill--;
+               } else if ((cur_byte & 0xC0) == 0x80) {
+                       var_7 = 1;
+                       bitfill -= 2;
+               } else if ((cur_byte & 0xc0) == 0xc0) {
+                       var_7 = 2;
+                       bitfill -= 2;
+               }
+
+               for (b_it = 0; b_it < 32; b_it++) {
+                       int index;
+                       int pixel_L, pixel_UR, pixel_UL;
+                       int multiplier;
+                       int dL, dC, dR;
+                       int gkw;        /* God knows what */
+
+                       refill(&bitfill);
+                       cur_byte = bit_bucket >> (bitfill & 7) & 0xff;
+
+                       pixel_L = output_ptr[-2];
+                       pixel_UR = output_ptr[off_up_right];
+                       pixel_UL = output_ptr[off_up_left];
+
+                       dL = diff_encoding[0x100 + pixel_UL - pixel_L];
+                       dC = diff_encoding[0x100 + pixel_U - pixel_UL];
+                       dR = diff_encoding[0x100 + pixel_UR - pixel_U];
+
+                       if (pixel_x < 2) {
+                               pixel_L = pixel_UL = pixel_U =
+                                   output_ptr[-xwidth * 2];
+                               pixel_UR = output_ptr[off_up_right];
+                               dL = dC = 0;
+                               dR = diff_encoding[0x100 + pixel_UR -
+                                                  pixel_U];
+                       } else if (pixel_x > width - 3)
+                               dR = 0;
+
+                       multiplier = 4;
+                       index = dR + dC * 8 + dL * 64;
+
+                       if (pixel_L + pixel_U * 2 <= 144
+                           && (pixel_y & 1) == 0
+                           && (b_it & 3) == 0 && (dR < 5) && (dC < 5)
+                           && (dL < 5)) {
+                               multiplier = 1;
+                       } else if (pixel_L <= 48
+                                  && dL <= 4 && dC <= 4 && dL >= 1
+                                  && dC >= 1) {
+                               multiplier = 2;
+                       } else if (var_7 == 1) {
+                               multiplier = 2;
+                       } else if (dC + dL >= 11 || var_7 == 2) {
+                               multiplier = 8;
+                       }
+
+                       if (i_hits[index] < 7) {
+                               bitfill -= nbits_A[cur_byte];
+                               gkw = tab_A[cur_byte];
+                               if (gkw == 0xfe)
+                                       gkw = fun_A(&bitfill);
+                       } else if (i_hits[index] >= accum[index]) {
+                               bitfill -= nbits_B[cur_byte];
+                               gkw = tab_B[cur_byte];
+                               if (cur_byte == 0)
+                                       gkw = fun_B(&bitfill);
+                       } else if (i_hits[index] * 2 >= accum[index]) {
+                               bitfill -= nbits_C[cur_byte];
+                               gkw = tab_C[cur_byte];
+                               if (cur_byte < 2)
+                                       gkw = fun_C(&bitfill, gkw);
+                       } else if (i_hits[index] * 4 >= accum[index]) {
+                               bitfill -= nbits_D[cur_byte];
+                               gkw = tab_D[cur_byte];
+                               if (cur_byte < 4)
+                                       gkw = fun_D(&bitfill, gkw);
+                       } else if (i_hits[index] * 8 >= accum[index]) {
+                               gkw = fun_E(cur_byte, &bitfill);
+                       } else {
+                               gkw = fun_F(cur_byte, &bitfill);
+                       }
+
+                       if (gkw == 0xff)
+                               return -3;
+
+                       {
+                               int tmp1, tmp2;
+
+                               tmp1 =
+                                   (pixel_U + pixel_L) * 3 - pixel_UL * 2;
+                               tmp1 += (tmp1 < 0) ? 3 : 0;
+                               tmp2 = a_curve[19 + gkw] * multiplier;
+                               tmp2 += (tmp2 < 0) ? 1 : 0;
+
+                               *(output_ptr++) =
+                                   clamp0_255[0x100 + (tmp1 >> 2) -
+                                              (tmp2 >> 1)];
+                       }
+                       pixel_U = saved_pixel_UR;
+                       saved_pixel_UR = pixel_UR;
+
+                       if (++pixel_x == width) {
+                               output_ptr += 6;
+                               pixel_x = 0;
+                               pixel_y++;
+                       }
+
+                       accum[index] += abs_clamp15[19 + gkw];
+
+                       if (i_hits[index]++ == 15) {
+                               i_hits[index] = 8;
+                               accum[index] /= 2;
+                       }
+               }
+       }
+       return 0;
+}
+
+/* FIXME, change spca561_decode not to need the extra border
+   around its dest buffer */
+int fswc_add_image_s561(avgbmp_t *dst, uint8_t *img, uint32_t length, uint32_t width, uint32_t height, int palette)
+{
+       uint x, y;
+       uint8_t *s, *d;
+       unsigned char tmpimg[650 * 490];
+       
+       if(spca561_decode(width, height, img, tmpimg) != 0)
+       {
+               return(-1);
+       }
+       
+       /* Remove buffer border */
+       d = tmpimg;
+       s = tmpimg + 2 * (width + 6) + 3;
+       for(y = 0; y < height; y++)
+       {
+               for(x = 0; x < width; x++) *(d++) = *(s++);
+               s += 6;
+       }
+       
+       fswc_add_image_bayer(dst, tmpimg, width * height, width, height, SRC_PAL_SGBRG8);
+       
+       return(0);
+}
+
diff --git a/src/v4l/dec_yuv.c b/src/v4l/dec_yuv.c
new file mode 100644 (file)
index 0000000..6336ce5
--- /dev/null
@@ -0,0 +1,170 @@
+/* fswebcam - Small and simple webcam for *nix                */
+/*============================================================*/
+/* Copyright (C)2005-2010 Philip Heron <phil@sanslogic.co.uk> */
+/*                                                            */
+/* This program is distributed under the terms of the GNU     */
+/* General Public License, version 2. You may use, modify,    */
+/* and redistribute it under the terms of this license. A     */
+/* copy should be included with this source.                  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+
+#include "src.h"
+
+/* The following YUV functions are based on code by Vincent Hourdin.
+ * http://vinvin.dyndns.org/projects/
+ *
+ * Faster integer maths from camE by Tom Gilbert.
+ * http://linuxbrit.co.uk/camE/
+*/
+
+int fswc_add_image_yuyv(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *ptr;
+       uint32_t x, y, z;
+       
+       if(src->length < (src->width * src->height * 2)) return(-1);
+       
+       /* YUYV and UYVY are very similar and so  *
+        * are both handled by this one function. */
+       
+       ptr = (uint8_t *) src->img;
+       z = 0;
+       
+       for(y = 0; y < src->height; y++)
+       {
+               for(x = 0; x < src->width; x++)
+               {
+                       int r, g, b;
+                       int y, u, v;
+                       
+                       if(src->palette == SRC_PAL_UYVY)
+                       {
+                               if(!z) y = ptr[1] << 8;
+                               else   y = ptr[3] << 8;
+                               
+                               u = ptr[0] - 128;
+                               v = ptr[2] - 128;
+                       }
+                       else /* SRC_PAL_YUYV */
+                       {
+                               if(!z) y = ptr[0] << 8;
+                               else   y = ptr[2] << 8;
+                               
+                               u = ptr[1] - 128;
+                               v = ptr[3] - 128;
+                       }
+                       
+                       r = (y + (359 * v)) >> 8;
+                       g = (y - (88 * u) - (183 * v)) >> 8;
+                       b = (y + (454 * u)) >> 8;
+                       
+                       *(abitmap++) += CLIP(r, 0x00, 0xFF);
+                       *(abitmap++) += CLIP(g, 0x00, 0xFF);
+                       *(abitmap++) += CLIP(b, 0x00, 0xFF);
+                       
+                       if(z++)
+                       {
+                               z = 0;
+                               ptr += 4;
+                       }
+               }
+       }
+       
+        return(0);
+}
+
+int fswc_add_image_yuv420p(src_t *src, avgbmp_t *abitmap)
+{
+       uint8_t *yptr, *uptr, *vptr;
+       uint32_t x, y, p, o;
+       
+       if(src->length < (src->width * src->height * 3) / 2) return(-1);
+       
+       /* Setup pointers to Y, U and V buffers. */
+       yptr = (uint8_t *) src->img;
+       uptr = yptr + (src->width * src->height);
+       vptr = uptr + (src->width * src->height / 4);
+       o = 0;
+       p = 0;
+       
+       for(y = 0; y < src->height; y++)
+       {
+               for(x = 0; x < src->width; x++)
+               {
+                       int r, g, b;
+                       int y, u, v;
+                       
+                       y = *(yptr++) << 8;
+                       u = uptr[p] - 128;
+                       v = vptr[p] - 128;
+                       
+                       r = (y + (359 * v)) >> 8;
+                       g = (y - (88 * u) - (183 * v)) >> 8;
+                       b = (y + (454 * u)) >> 8;
+                       
+                       *(abitmap++) += CLIP(r, 0x00, 0xFF);
+                       *(abitmap++) += CLIP(g, 0x00, 0xFF);
+                       *(abitmap++) += CLIP(b, 0x00, 0xFF);
+                       
+                       if(x & 1) p++;
+               }
+               
+               if(!(y & 1)) p -= src->width / 2;
+       }
+       
+       return(0);
+}
+
+int fswc_add_image_nv12mb(src_t *src, avgbmp_t *abitmap)
+{
+       uint32_t x, y;
+       uint32_t bw;
+       
+       if(src->length != (src->width * src->height * 3) / 2) return(-1);
+       
+       bw = src->width >> 4;
+       
+       for(y = 0; y < src->height; y++)
+       {
+               for(x = 0; x < src->width; x++)
+               {
+                       uint32_t bx, by;
+                       int cy, cu, cv;
+                       int cr, cg, cb;
+                       uint8_t *py, *puv;
+                       
+                       bx = x >> 4;
+                       by = y >> 4;
+                       
+                       py  = src->img;
+                       py += ((by * bw) + bx) * 0x100;
+                       py += ((y - (by << 4)) * 0x10) + (x - (bx << 4));
+                       
+                       by /= 2;
+                       
+                       puv  = (avgbmp_t *)src->img + (src->width * src->height);
+                       puv += ((by * bw) + bx) * 0x100;
+                       puv += (((y / 2) - (by << 4)) * 0x10) + ((x - (bx << 4)) &~ 1);
+                       
+                       cy = *py << 8;
+                       cu = puv[0] - 128;
+                       cv = puv[1] - 128;
+                       
+                       cr = (cy + (359 * cv)) >> 8;
+                       cg = (cy - (88 * cu) - (183 * cv)) >> 8;
+                       cb = (cy + (454 * cu)) >> 8;
+                       
+                       *(abitmap++) += CLIP(cr, 0x00, 0xFF);
+                       *(abitmap++) += CLIP(cg, 0x00, 0xFF);
+                       *(abitmap++) += CLIP(cb, 0x00, 0xFF);
+               }
+       }
+       
+       return(0);
+}
+
index 391b121cfda1e5bbf6b3f5c9abcdc3833c100f79..9cbc27fbc2d1cf5b055fc73c1995e182e227db7a 100644 (file)
@@ -79,10 +79,10 @@ int src_open(src_t *src, char *source)
        return 0;
 }
 
-const char *src_query(src_t *src, char *source, int *width, int *height, char **pixelformat)
+const char *src_query(src_t *src, char *source, uint *width, uint *height, char **pixelformatdescription)
 {
     src->source = source;
-    return src_v4l2.query(src, width, height, pixelformat);
+    return src_v4l2.query(src, width, height, pixelformatdescription);
 }
 
 int src_close(src_t *src)
index ae228a4b23798a84099c3bc9aed6854a9fbaeb18..3ce1d3b2584a736c0a9814c608124a783557d136 100644 (file)
@@ -23,6 +23,11 @@ extern "C" {
 #ifndef INC_SRC_H
 #define INC_SRC_H
 
+typedef unsigned char avgbmp_t;
+
+
+#define CLIP(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
+
 #define SRC_TYPE_NONE   (0)
 #define SRC_TYPE_DEVICE (1 << 0) /* Can capture from a device */
 #define SRC_TYPE_FILE   (1 << 1) /* Can capture from a file */
@@ -119,7 +124,7 @@ typedef struct {
        int (*open)(src_t *);
        int (*close)(src_t *);
        int (*grab)(src_t *);
-       const char *(*query)(src_t *, int*, int*, char **);
+       const char *(*query)(src_t *, uint*, uint*, char **);
        
 } src_mod_t;
 
@@ -207,7 +212,7 @@ typedef struct {
 extern int src_open(src_t *src, char *source);
 extern int src_close(src_t *src);
 extern int src_grab(src_t *src);
-extern const char *src_query(src_t *src, char *source, int *width, int *height, char **pixelformat);
+extern const char *src_query(src_t *src, char *source, uint *width, uint *height, char **pixelformatdescription);
 
 extern int src_set_option(src_option_t ***options, char *name, char *value);
 extern int src_get_option_by_number(src_option_t **opt, int number, char **name, char **value);
index 6c37abdf51e5f0bf98e97ec374ba7cc9da42e0eb..7d1e03f434573e4bcb3ff9ac30d785895a039aac 100644 (file)
@@ -802,7 +802,7 @@ int src_v4l2_set_read(src_t *src)
        return(0);
 }
 
-static const char *src_v4l2_query(src_t *src, int *width, int *height, char **pixelformat)
+static const char *src_v4l2_query(src_t *src, uint *width, uint *height, char **pixelformatdescription)
 {
        if(!src->source)
        {
@@ -836,7 +836,8 @@ static const char *src_v4l2_query(src_t *src, int *width, int *height, char **pi
            fprintf(stderr, "Cannot get capabilities.");
            return NULL;
        }
-       char *res = (char*) s->cap.card;
+       char *res = strdup((char*) s->cap.card);
+       /*strcpy(res, (char*) s->cap.card);*/
        if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
            *width = 0;
            *height = 0;
@@ -858,10 +859,13 @@ static const char *src_v4l2_query(src_t *src, int *width, int *height, char **pi
            fmt.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            if (ioctl(s->fd, VIDIOC_ENUM_FMT, &fmt) != -1)
            {
-               *pixelformat = fmt.description;
+               /*strcpy(*pixelformatdescription, (char *) fmt.description);*/
+               *pixelformatdescription = strdup((char*)fmt.description);
                fprintf(stderr, "format: %s", fmt.description);
            }
-           else *pixelformat = "";
+           else {
+               *pixelformatdescription = '\0';
+           }
        }
        src_v4l2_close(src);
        return res;
index c067a3a2bb766dd8fe95c0dc366157526c37a3fe..53ee5cf06ecdf272eeb303d775113ba3b8b6fb6b 100644 (file)
 
 #include "v4lcapture.h"
 #include "kdenlivesettings.h"
-
+#include "dec.h"
 
 static src_t v4lsrc;
 
+QImage add_image_png(src_t *src)
+{
+    QImage im;
+    im.loadFromData((uchar *)src->img, src->length, "PNG");
+    return im;
+}
+
+QImage add_image_jpeg(src_t *src)
+{
+    uint32_t hlength;
+    uint8_t *himg = NULL;
+    QImage im;
+
+    /* MJPEG data may lack the DHT segment required for decoding... */
+    verify_jpeg_dht((uint8_t *) src->img, src->length, &himg, &hlength);
+
+    im.loadFromData(himg, hlength, "JPG");
+    return im;
+}
+
 class MyDisplay : public QLabel
 {
 public:
@@ -90,6 +110,9 @@ void MyDisplay::setImage(QImage img)
 V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent):
     CaptureHandler(lay, parent)
     , m_update(false)
+    , m_device(KdenliveSettings::video4vdevice())
+    , m_width(-1)
+    , m_height(-1)
 {
     if (lay == NULL) return;
     m_display = new MyDisplay;
@@ -122,8 +145,10 @@ QStringList V4lCaptureHandler::getDeviceName(QString input)
     config->delay = 0;
     config->use_read = 0;
     config->list = 0;
-    config->width = 384;
-    config->height = 288;
+    if (m_width > 0) config->width = m_width;
+    else config->width = 384;
+    if (m_height > 0) config->height = m_height;
+    else config->height = 288;
     config->fps = 0;
     config->frames = 1;
     config->skipframes = 0;
@@ -154,15 +179,25 @@ QStringList V4lCaptureHandler::getDeviceName(QString input)
     v4lsrc.fps        = config->fps;
     v4lsrc.option     = config->option;
     char *source = config->device;
-    int width = 0;
-    int height = 0;
-    char *pixelformat;
-    QString deviceName = src_query(&v4lsrc, source, &width, &height, &pixelformat);
+    uint width = 0;
+    uint height = 0;
+    char *pixelformatdescription;
+    QString deviceName(src_query(&v4lsrc, source, &width, &height, &pixelformatdescription));
     QStringList result;
-    result << (deviceName.isEmpty() ? input : deviceName) << (width == 0 ? QString() : QString("%1x%2").arg(width).arg(height)) << QString(pixelformat);
+    result << (deviceName.isEmpty() ? input : deviceName) << (width == 0 ? QString() : QString("%1x%2").arg(width).arg(height)) << QString(pixelformatdescription);
     return result;
 }
 
+void V4lCaptureHandler::setDevice(const QString input, QString size)
+{
+    m_device = input;
+    if (!size.isEmpty()) {
+        m_width = size.section('x', 0, 0).toInt();
+        m_height = size.section('x', -1).toInt();
+
+    }
+}
+
 void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool)
 {
     m_display->setHidden(false);
@@ -183,15 +218,17 @@ void V4lCaptureHandler::startPreview(int /*deviceId*/, int /*captureMode*/, bool
     config->logfile = NULL;
     config->gmt = 0;
     config->start = 0;
-    config->device = strdup(KdenliveSettings::video4vdevice().toUtf8().constData());
+    config->device = strdup(m_device.toUtf8().constData());
     config->input = NULL;
     config->tuner = 0;
     config->frequency = 0;
     config->delay = 0;
     config->use_read = 0;
     config->list = 0;
-    config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
-    config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
+    if (m_width > 0) config->width = m_width;
+    else config->width = KdenliveSettings::video4size().section("x", 0, 0).toInt();/*384;*/
+    if (m_height > 0) config->height = m_height;
+    else config->height = KdenliveSettings::video4size().section("x", -1).toInt();/*288;*/
     config->fps = 0;
     config->frames = 1;
     config->skipframes = 0;
@@ -237,15 +274,59 @@ void V4lCaptureHandler::slotUpdate()
 {
     if (!m_update) return;
     src_grab(&v4lsrc);
-    uint8_t *img = (uint8_t *) v4lsrc.img;
-    uint32_t i = v4lsrc.width * v4lsrc.height;
-
-    if (v4lsrc.length << 2 < i) return;
+    QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB888);
+    switch (v4lsrc.palette) {
+    case SRC_PAL_PNG:
+        qimg = add_image_png(&v4lsrc);
+        break;
+    case SRC_PAL_JPEG:
+    case SRC_PAL_MJPEG:
+        qimg = add_image_jpeg(&v4lsrc);
+        break;
+    case SRC_PAL_S561:
+        fswc_add_image_s561(qimg.bits(), (uchar *)v4lsrc.img, v4lsrc.length, v4lsrc.width, v4lsrc.height, v4lsrc.palette);
+        break;
+    case SRC_PAL_RGB32:
+        fswc_add_image_rgb32(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_BGR32:
+        fswc_add_image_bgr32(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_RGB24:
+        fswc_add_image_rgb24(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_BGR24:
+        fswc_add_image_bgr24(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_BAYER:
+    case SRC_PAL_SGBRG8:
+    case SRC_PAL_SGRBG8:
+        fswc_add_image_bayer(qimg.bits(), (uchar *)v4lsrc.img, v4lsrc.length, v4lsrc.width, v4lsrc.height, v4lsrc.palette);
+        break;
+    case SRC_PAL_YUYV:
+    case SRC_PAL_UYVY:
+        fswc_add_image_yuyv(&v4lsrc, (avgbmp_t *)qimg.bits());
+        break;
+    case SRC_PAL_YUV420P:
+        fswc_add_image_yuv420p(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_NV12MB:
+        fswc_add_image_nv12mb(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_RGB565:
+        fswc_add_image_rgb565(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_RGB555:
+        fswc_add_image_rgb555(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_Y16:
+        fswc_add_image_y16(&v4lsrc, qimg.bits());
+        break;
+    case SRC_PAL_GREY:
+        fswc_add_image_grey(&v4lsrc, qimg.bits());
+        break;
+    }
 
-    QImage qimg(v4lsrc.width, v4lsrc.height, QImage::Format_RGB32);
-    //Format_ARGB32_Premultiplied
-    //convert from uyvy422 to rgba
-    CaptureHandler::yuv2rgb((uchar *)img, (uchar *)qimg.bits(), v4lsrc.width, v4lsrc.height);
     if (!m_captureFramePath.isEmpty()) {
         qimg.save(m_captureFramePath);
         emit frameSaved(m_captureFramePath);
@@ -292,7 +373,10 @@ void V4lCaptureHandler::hidePreview(bool hide)
 
 void V4lCaptureHandler::stopPreview()
 {
+    m_display->setHidden(true);
     if (!m_update) return;
     m_update = false;
     src_close(&v4lsrc);
 }
+
+
index 464bfa592d7c07c4ac6f65bb957b4ac3075b0668..80ed0d4ea5457575635b8437fc374a651f350aa2 100644 (file)
@@ -45,12 +45,17 @@ public:
     void hideOverlay();
     void hidePreview(bool hide);
     QStringList getDeviceName(QString input);
+    /** @brief Sets the path to the capture devide and optionnaly the width / height of the capture. */
+    void setDevice(const QString input, QString size = QString());
 
 private:
     bool m_update;
     MyDisplay *m_display;
     QString m_captureFramePath;
     QImage m_overlayImage;
+    QString m_device;
+    int m_width;
+    int m_height;
 
 private slots:
     void slotUpdate();