From e2d9e6fe8472f8170c6bb7be61a2e781fefac9ff Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Tue, 26 Oct 2010 20:42:55 +0000 Subject: [PATCH] Basic webcam (video4linux) autodetection svn path=/trunk/kdenlive/; revision=5053 --- src/CMakeLists.txt | 1 + src/blackmagic/capture.cpp | 2 +- src/blackmagic/capture.h | 2 +- src/kdenlivesettingsdialog.cpp | 8 +++- src/stopmotion/capturehandler.h | 2 +- src/stopmotion/stopmotion.cpp | 2 +- src/v4l/src.c | 4 +- src/v4l/src.h | 4 +- src/v4l/src_v4l2.c | 21 ++++++++- src/v4l/v4lcapture.cpp | 5 +- src/v4l/v4lcapture.h | 2 +- src/widgets/wizardcapture_ui.ui | 81 +++++++++++++++++++++++++++++++++ src/wizard.cpp | 65 ++++++++++++++++++++++++-- src/wizard.h | 4 ++ 14 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 src/widgets/wizardcapture_ui.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5d0ecb12..5166e0d3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -89,6 +89,7 @@ kde4_add_ui_files(kdenlive_UI widgets/geometryval_ui.ui widgets/wizardstandard_ui.ui widgets/wizardextra_ui.ui + widgets/wizardcapture_ui.ui widgets/wizardcheck_ui.ui widgets/wizardmltcheck_ui.ui widgets/spacerdialog_ui.ui diff --git a/src/blackmagic/capture.cpp b/src/blackmagic/capture.cpp index 8afb4d25..cb953b82 100644 --- a/src/blackmagic/capture.cpp +++ b/src/blackmagic/capture.cpp @@ -492,7 +492,7 @@ BmdCaptureHandler::BmdCaptureHandler(QVBoxLayout *lay, QWidget *parent): { } -QString BmdCaptureHandler::getDeviceName(QString) +QString BmdCaptureHandler::getDeviceName(QString, int *, int *) { return QString(); } diff --git a/src/blackmagic/capture.h b/src/blackmagic/capture.h index b58b40c1..db716c80 100644 --- a/src/blackmagic/capture.h +++ b/src/blackmagic/capture.h @@ -59,7 +59,7 @@ public: void showOverlay(QImage img, bool transparent = true); void hideOverlay(); void hidePreview(bool hide); - QString getDeviceName(QString); + QString getDeviceName(QString, int *, int *); private: IDeckLinkIterator *deckLinkIterator; diff --git a/src/kdenlivesettingsdialog.cpp b/src/kdenlivesettingsdialog.cpp index 97861f63..f17c9f75 100644 --- a/src/kdenlivesettingsdialog.cpp +++ b/src/kdenlivesettingsdialog.cpp @@ -83,11 +83,15 @@ KdenliveSettingsDialog::KdenliveSettingsDialog(QWidget * parent) : m_configCapture.setupUi(p4); V4lCaptureHandler v4l(NULL); + int width; + int height; // Video 4 Linux device detection for (int i = 0; i < 10; i++) { QString path = "/dev/video" + QString::number(i); if (QFile::exists(path)) { - m_configCapture.kcfg_detectedv4ldevices->addItem(v4l.getDeviceName(path.toUtf8().constData()), path); + QString deviceName = v4l.getDeviceName(path.toUtf8().constData(), &width, &height); + m_configCapture.kcfg_detectedv4ldevices->addItem(deviceName, path); + if (width > 0) m_configCapture.kcfg_detectedv4ldevices->setItemData(m_configCapture.kcfg_detectedv4ldevices->count() - 1, QString("%1x%2").arg(width).arg(height), Qt::UserRole + 1); } } connect(m_configCapture.kcfg_detectedv4ldevices, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatev4lDevice())); @@ -642,6 +646,8 @@ void KdenliveSettingsDialog::slotUpdatev4lDevice() { QString device = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex()).toString(); if (!device.isEmpty()) m_configCapture.kcfg_video4vdevice->setText(device); + QString size = m_configCapture.kcfg_detectedv4ldevices->itemData(m_configCapture.kcfg_detectedv4ldevices->currentIndex(), Qt::UserRole + 1).toString(); + if (!size.isEmpty()) m_configCapture.kcfg_video4size->setText(size); } diff --git a/src/stopmotion/capturehandler.h b/src/stopmotion/capturehandler.h index c91a5d5f..f43fddae 100644 --- a/src/stopmotion/capturehandler.h +++ b/src/stopmotion/capturehandler.h @@ -38,7 +38,7 @@ public: virtual void showOverlay(QImage img, bool transparent = true) = 0; virtual void hideOverlay() = 0; virtual void hidePreview(bool hide) = 0; - virtual QString getDeviceName(QString input) = 0; + virtual QString getDeviceName(QString input, int *width, int *height) = 0; static void yuv2rgb(unsigned char *yuv_buffer, unsigned char *rgb_buffer, int width, int height); protected: diff --git a/src/stopmotion/stopmotion.cpp b/src/stopmotion/stopmotion.cpp index 2094396e..e4e89f05 100644 --- a/src/stopmotion/stopmotion.cpp +++ b/src/stopmotion/stopmotion.cpp @@ -191,7 +191,7 @@ StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * > } if (QFile::exists(KdenliveSettings::video4vdevice())) { if (m_bmCapture == NULL) m_bmCapture = new V4lCaptureHandler(m_layout); - capture_device->addItem(m_bmCapture->getDeviceName(KdenliveSettings::video4vdevice()), "v4l"); + capture_device->addItem(m_bmCapture->getDeviceName(KdenliveSettings::video4vdevice(), 0, 0), "v4l"); } connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString))); diff --git a/src/v4l/src.c b/src/v4l/src.c index 7aadb6cd..96bb64cf 100644 --- a/src/v4l/src.c +++ b/src/v4l/src.c @@ -79,10 +79,10 @@ int src_open(src_t *src, char *source) return 0; } -const char *src_query(src_t *src, char *source) +const char *src_query(src_t *src, char *source, int *width, int *height) { src->source = source; - return src_v4l2.query(src); + return src_v4l2.query(src, width, height); } int src_close(src_t *src) diff --git a/src/v4l/src.h b/src/v4l/src.h index 5f9aba54..011a9519 100644 --- a/src/v4l/src.h +++ b/src/v4l/src.h @@ -119,7 +119,7 @@ typedef struct { int (*open)(src_t *); int (*close)(src_t *); int (*grab)(src_t *); - const char *(*query)(src_t *); + const char *(*query)(src_t *, int*, int*); } src_mod_t; @@ -207,7 +207,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); +extern const char *src_query(src_t *src, char *source, int *width, int *height); 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); diff --git a/src/v4l/src_v4l2.c b/src/v4l/src_v4l2.c index 56c4dbad..641913f6 100644 --- a/src/v4l/src_v4l2.c +++ b/src/v4l/src_v4l2.c @@ -802,7 +802,7 @@ int src_v4l2_set_read(src_t *src) return(0); } -static const char *src_v4l2_query(src_t *src) +static const char *src_v4l2_query(src_t *src, int *width, int *height) { if(!src->source) { @@ -836,7 +836,24 @@ static const char *src_v4l2_query(src_t *src) fprintf(stderr, "Cannot get capabilities."); return NULL; } - char * res = (char*) s->cap.card; + char * res = (char*) s->cap.card; + if(!s->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { + width = 0; + height = 0; + } + else { + struct v4l2_format format; + memset(&format,0,sizeof(format)); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(s->fd,VIDIOC_G_FMT,&format) < 0) { + fprintf(stderr, "Cannot get format."); + } + else { + *width = format.fmt.pix.width; + *height = format.fmt.pix.height; + fprintf(stderr, "Size: %d, %d.", width, height); + } + } src_v4l2_close(src); return res; } diff --git a/src/v4l/v4lcapture.cpp b/src/v4l/v4lcapture.cpp index 8ede6e3f..013a7c80 100644 --- a/src/v4l/v4lcapture.cpp +++ b/src/v4l/v4lcapture.cpp @@ -96,7 +96,7 @@ V4lCaptureHandler::V4lCaptureHandler(QVBoxLayout *lay, QWidget *parent): lay->addWidget(m_display); } -QString V4lCaptureHandler::getDeviceName(QString input) +QString V4lCaptureHandler::getDeviceName(QString input, int *width, int *height) { fswebcam_config_t *config; /* Prepare the configuration structure. */ @@ -154,8 +154,7 @@ QString V4lCaptureHandler::getDeviceName(QString input) v4lsrc.fps = config->fps; v4lsrc.option = config->option; char *source = config->device; - - QString deviceName = src_query(&v4lsrc, source); + QString deviceName = src_query(&v4lsrc, source, width, height); kDebug() << "DEVIE NAME: " << deviceName << "."; return deviceName.isEmpty() ? input : deviceName; } diff --git a/src/v4l/v4lcapture.h b/src/v4l/v4lcapture.h index a1778b3b..ffa35b93 100644 --- a/src/v4l/v4lcapture.h +++ b/src/v4l/v4lcapture.h @@ -44,7 +44,7 @@ public: void showOverlay(QImage img, bool transparent = true); void hideOverlay(); void hidePreview(bool hide); - QString getDeviceName(QString input); + QString getDeviceName(QString input, int *width, int *height); private: bool m_update; diff --git a/src/widgets/wizardcapture_ui.ui b/src/widgets/wizardcapture_ui.ui new file mode 100644 index 00000000..0c151a63 --- /dev/null +++ b/src/widgets/wizardcapture_ui.ui @@ -0,0 +1,81 @@ + + + WizardCapture_UI + + + + 0 + 0 + 273 + 153 + + + + Form + + + + + + Autodetected capture devices + + + + + + + Check + + + + + + + + 0 + 0 + + + + true + + + true + + + + Device Name + + + + + Capacities + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + + + + + + + diff --git a/src/wizard.cpp b/src/wizard.cpp index ea1084d5..ad6a9e11 100644 --- a/src/wizard.cpp +++ b/src/wizard.cpp @@ -20,6 +20,7 @@ #include "wizard.h" #include "kdenlivesettings.h" #include "profilesdialog.h" +#include "v4l/v4lcapture.h" #include "kdenlive-config.h" #include @@ -39,7 +40,7 @@ const double recommendedMltVersion = 510; static const char kdenlive_version[] = VERSION; Wizard::Wizard(bool upgrade, QWidget *parent) : - QWizard(parent) + QWizard(parent) { setWindowTitle(i18n("Config Wizard")); setPixmap(QWizard::WatermarkPixmap, QPixmap(KStandardDirs::locate("appdata", "banner.png"))); @@ -122,6 +123,15 @@ Wizard::Wizard(bool upgrade, QWidget *parent) : slotCheckThumbs(); addPage(page3); + QWizardPage *page6 = new QWizardPage; + page6->setTitle(i18n("Webcam")); + m_capture.setupUi(page6); + connect(m_capture.button_reload, SIGNAL(clicked()), this, SLOT(slotDetectWebcam())); + connect(m_capture.device_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotUpdateCaptureParameters())); + m_capture.button_reload->setIcon(KIcon("view-refresh")); + + addPage(page6); + QWizardPage *page5 = new QWizardPage; page5->setTitle(i18n("Checking system")); @@ -130,10 +140,57 @@ Wizard::Wizard(bool upgrade, QWidget *parent) : listViewDelegate = new WizardDelegate(m_check.programList); m_check.programList->setItemDelegate(listViewDelegate); - + slotDetectWebcam(); QTimer::singleShot(500, this, SLOT(slotCheckMlt())); } +void Wizard::slotDetectWebcam() +{ + m_capture.device_list->clear(); + + // Video 4 Linux device detection + V4lCaptureHandler v4l(NULL); + int width = 0; + int height = 0; + for (int i = 0; i < 10; i++) { + QString path = "/dev/video" + QString::number(i); + if (QFile::exists(path)) { + QString deviceName = v4l.getDeviceName(path.toUtf8().constData(), &width, &height); + QString captureSize; + if (width > 0) captureSize = QString::number(width) + "x" + QString::number(height); + if (!deviceName.isEmpty()) { + QTreeWidgetItem *item = new QTreeWidgetItem(m_capture.device_list, QStringList() << deviceName << captureSize); + item->setData(0, Qt::UserRole, path); + if (!captureSize.isEmpty()) item->setData(0, Qt::UserRole + 1, captureSize); + } + } + } + if (m_capture.device_list->topLevelItemCount() > 0) { + m_capture.v4l_status->setText(i18n("Select your default video4linux device")); + // select default device + bool found = false; + for (int i = 0; i < m_capture.device_list->topLevelItemCount(); i++) { + QTreeWidgetItem * item = m_capture.device_list->topLevelItem(i); + if (item && item->data(0, Qt::UserRole).toString() == KdenliveSettings::video4vdevice()) { + m_capture.device_list->setCurrentItem(item); + found = true; + break; + } + } + if (!found) m_capture.device_list->setCurrentItem(m_capture.device_list->topLevelItem(0)); + } else m_capture.v4l_status->setText(i18n("No device found, plug your webcam and refresh.")); +} + +void Wizard::slotUpdateCaptureParameters() +{ + QTreeWidgetItem * item = m_capture.device_list->currentItem(); + if (!item) return; + QString device = item->data(0, Qt::UserRole).toString(); + if (!device.isEmpty()) KdenliveSettings::setVideo4vdevice(device); + + QString size = item->data(0, Qt::UserRole + 1).toString(); + if (!size.isEmpty()) KdenliveSettings::setVideo4size(size); +} void Wizard::checkMltComponents() { @@ -388,7 +445,7 @@ void Wizard::installExtraMimes(QString baseName, QStringList globs) } else { QStringList extensions = mime->patterns(); QString comment = mime->comment(); - foreach(const QString &glob, globs) { + foreach(const QString & glob, globs) { if (!extensions.contains(glob)) extensions << glob; } kDebug() << "EXTS: " << extensions; @@ -415,7 +472,7 @@ void Wizard::installExtraMimes(QString baseName, QStringList globs) writer.writeEndElement(); // comment } - foreach(const QString& pattern, extensions) { + foreach(const QString & pattern, extensions) { writer.writeStartElement(nsUri, "glob"); writer.writeAttribute("pattern", pattern); writer.writeEndElement(); // glob diff --git a/src/wizard.h b/src/wizard.h index 633ba299..da2a5513 100644 --- a/src/wizard.h +++ b/src/wizard.h @@ -33,6 +33,7 @@ #include "ui_wizardextra_ui.h" #include "ui_wizardcheck_ui.h" #include "ui_wizardmltcheck_ui.h" +#include "ui_wizardcapture_ui.h" class WizardDelegate: public QItemDelegate { @@ -85,6 +86,7 @@ private: Ui::WizardStandard_UI m_standard; Ui::WizardExtra_UI m_extra; Ui::WizardMltCheck_UI m_mltCheck; + Ui::WizardCapture_UI m_capture; Ui::WizardCheck_UI m_check; QVBoxLayout *m_startLayout; bool m_systemCheckIsOk; @@ -102,6 +104,8 @@ private slots: void slotCheckSelectedItem(); void slotCheckMlt(); void slotShowWebInfos(); + void slotDetectWebcam(); + void slotUpdateCaptureParameters(); }; #endif -- 2.39.2