The qv4l2 test utility now supports ALSA playback of audio. This allows for PCM playback during capture for supported devices. Signed-off-by: Bård Eirik Winther <bwinther@xxxxxxxxx> --- utils/qv4l2/general-tab.cpp | 296 +++++++++++++++++++++++++++++++++++++++++++- utils/qv4l2/general-tab.h | 38 ++++++ utils/qv4l2/qv4l2.cpp | 141 ++++++++++++++++++++- utils/qv4l2/qv4l2.h | 9 ++ 4 files changed, 480 insertions(+), 4 deletions(-) diff --git a/utils/qv4l2/general-tab.cpp b/utils/qv4l2/general-tab.cpp index 10b14ca..5cfaf07 100644 --- a/utils/qv4l2/general-tab.cpp +++ b/utils/qv4l2/general-tab.cpp @@ -30,6 +30,16 @@ #include <stdio.h> #include <errno.h> +#include <QRegExp> + +bool GeneralTab::m_fullAudioName = false; + +enum audioDeviceAdd { + AUDIO_ADD_NO, + AUDIO_ADD_READ, + AUDIO_ADD_WRITE, + AUDIO_ADD_READWRITE +}; GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) : QGridLayout(parent), @@ -48,12 +58,16 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) m_vidCapFormats(NULL), m_frameSize(NULL), m_vidOutFormats(NULL), - m_vbiMethods(NULL) + m_vbiMethods(NULL), + m_audioInDevice(NULL), + m_audioOutDevice(NULL) { + m_device.append(device); setSpacing(3); setSizeConstraint(QLayout::SetMinimumSize); + if (querycap(m_querycap)) { addLabel("Device:"); addLabel(device + (useWrapper() ? " (wrapped)" : ""), Qt::AlignLeft); @@ -132,6 +146,42 @@ GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) updateAudioOutput(); } + if (hasAlsaAudio()) { + m_audioInDevice = new QComboBox(parent); + m_audioOutDevice = new QComboBox(parent); + m_audioInDevice->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_audioOutDevice->setSizeAdjustPolicy(QComboBox::AdjustToContents); + + if (createAudioDeviceList()) { + addLabel("Audio Input Device"); + connect(m_audioInDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioInDevice); + + addLabel("Audio Output Device"); + connect(m_audioOutDevice, SIGNAL(activated(int)), SLOT(changeAudioDevice())); + addWidget(m_audioOutDevice); + + if (isRadio()) { + setAudioDeviceBufferSize(75); + } else { + v4l2_fract fract; + if (!v4l2::get_interval(fract)) { + // Default values are for 30 FPS + fract.numerator = 33; + fract.denominator = 1000; + } + // Standard capacity is two frames + setAudioDeviceBufferSize((fract.numerator * 2000) / fract.denominator); + } + } else { + fprintf(stderr, "BANNA\n"); + delete m_audioInDevice; + delete m_audioOutDevice; + m_audioInDevice = NULL; + m_audioOutDevice = NULL; + } + } + if (needsStd) { v4l2_std_id tmp; @@ -370,6 +420,180 @@ done: setRowStretch(rowCount() - 1, 1); } +void GeneralTab::showAllAudioDevices(bool use) +{ + QString oldIn(m_audioInDevice->currentText()); + QString oldOut(m_audioOutDevice->currentText()); + + m_fullAudioName = use; + if (oldIn == NULL || oldOut == NULL || !createAudioDeviceList()) + return; + + // Select a similar device as before the listings method change + // check by comparing old selection with any matching in the new list + bool setIn = false, setOut = false; + int listSize = std::max(m_audioInDevice->count(), m_audioOutDevice->count()); + + for (int i = 0; i < listSize; i++) { + QString oldInCmp(oldIn.left(std::min(m_audioInDevice->itemText(i).length(), oldIn.length()))); + QString oldOutCmp(oldOut.left(std::min(m_audioOutDevice->itemText(i).length(), oldOut.length()))); + + if (!setIn && i < m_audioInDevice->count() + && m_audioInDevice->itemText(i).startsWith(oldInCmp)) { + setIn = true; + m_audioInDevice->setCurrentIndex(i); + } + + if (!setOut && i < m_audioOutDevice->count() + && m_audioOutDevice->itemText(i).startsWith(oldOutCmp)) { + setOut = true; + m_audioOutDevice->setCurrentIndex(i); + } + } +} + +bool GeneralTab::filterAudioInDevice(QString &deviceName) +{ + // Removes S/PDIF, front speakers and surround from input devices + // as they are output devices, not input + if (deviceName.contains("surround") + || deviceName.contains("front") + || deviceName.contains("iec958")) + return false; + + // Removes sysdefault too if not full audio mode listings + if (!m_fullAudioName && deviceName.contains("sysdefault")) + return false; + + return true; +} + +bool GeneralTab::filterAudioOutDevice(QString &deviceName) +{ + // Removes advanced options if not full audio mode listings + if (!m_fullAudioName && (deviceName.contains("surround") + || deviceName.contains("front") + || deviceName.contains("iec958") + || deviceName.contains("sysdefault"))) { + return false; + } + + return true; +} + +int GeneralTab::addAudioDevice(void *hint, int deviceNum) +{ + int added = 0; +#ifdef HAVE_ALSA + char *name; + char *iotype; + QString deviceName; + QString listName; + QStringList deviceType; + iotype = snd_device_name_get_hint(hint, "IOID"); + name = snd_device_name_get_hint(hint, "NAME"); + deviceName.append(name); + + snd_card_get_name(deviceNum, &name); + listName.append(name); + + deviceType = deviceName.split(":"); + + // Add device io capability to list name + if (m_fullAudioName) { + listName.append(" "); + + // Makes the surround name more readable + if (deviceName.contains("surround")) + listName.append(QString("surround %1.%2") + .arg(deviceType.value(0)[8]).arg(deviceType.value(0)[9])); + else + listName.append(deviceType.value(0)); + + } else if (!deviceType.value(0).contains("default")) { + listName.append(" ").append(deviceType.value(0)); + } + + // Add device number if it is not 0 + if (deviceName.contains("DEV=")) { + int devNo; + QStringList deviceNo = deviceName.split("DEV="); + devNo = deviceNo.value(1).toInt(); + if (devNo) + listName.append(QString(" %1").arg(devNo)); + } + + if ((iotype == NULL || strncmp(iotype, "Input", 5) == 0) && filterAudioInDevice(deviceName)) { + m_audioInDevice->addItem(listName); + m_audioInDeviceMap[listName] = snd_device_name_get_hint(hint, "NAME"); + added += AUDIO_ADD_READ; + } + + if ((iotype == NULL || strncmp(iotype, "Output", 6) == 0) && filterAudioOutDevice(deviceName)) { + m_audioOutDevice->addItem(listName); + m_audioOutDeviceMap[listName] = snd_device_name_get_hint(hint, "NAME"); + added += AUDIO_ADD_WRITE; + } +#endif + return added; +} + +bool GeneralTab::createAudioDeviceList() +{ +#ifdef HAVE_ALSA + if (m_audioInDevice == NULL || m_audioOutDevice == NULL) + return false; + + m_audioInDevice->clear(); + m_audioOutDevice->clear(); + m_audioInDeviceMap.clear(); + m_audioOutDeviceMap.clear(); + + m_audioInDevice->addItem("None"); + m_audioOutDevice->addItem("Default"); + m_audioInDeviceMap["None"] = "None"; + m_audioOutDeviceMap["Default"] = "default"; + + int deviceNum = -1; + int audioDevices = 0; + int matchDevice = matchAudioDevice(); + int indexDevice = -1; + int indexCount = 0; + + while (snd_card_next(&deviceNum) >= 0) { + if (deviceNum == -1) + break; + + audioDevices++; + if (deviceNum == matchDevice && indexDevice == -1) + indexDevice = indexCount; + + void **hint; + + snd_device_name_hint(deviceNum, "pcm", &hint); + for (int i = 0; hint[i] != NULL; i++) { + int addAs = addAudioDevice(hint[i], deviceNum); + if (addAs == AUDIO_ADD_READ || addAs == AUDIO_ADD_READWRITE) + indexCount++; + } + snd_device_name_free_hint(hint); + } + + snd_config_update_free_global(); + m_audioInDevice->setCurrentIndex(indexDevice + 1); + changeAudioDevice(); + return m_audioInDeviceMap.size() > 1 && m_audioOutDeviceMap.size() > 1 && audioDevices > 1; +#else + return false; +#endif +} + +void GeneralTab::changeAudioDevice() +{ + m_audioOutDevice->setEnabled(getAudioInDevice() != NULL ? getAudioInDevice().compare("None") : false); + emit audioDeviceChanged(); +} + void GeneralTab::addWidget(QWidget *w, Qt::Alignment align) { QGridLayout::addWidget(w, m_row, m_col, align | Qt::AlignVCenter); @@ -932,3 +1156,73 @@ bool GeneralTab::get_interval(struct v4l2_fract &interval) return m_has_interval; } + +QString GeneralTab::getAudioInDevice() +{ + if (m_audioInDevice == NULL) + return NULL; + + return m_audioInDeviceMap[m_audioInDevice->currentText()]; +} + +QString GeneralTab::getAudioOutDevice() +{ + if (m_audioOutDevice == NULL) + return NULL; + + return m_audioOutDeviceMap[m_audioOutDevice->currentText()]; +} + +void GeneralTab::setAudioDeviceBufferSize(int size) +{ + m_audioDeviceBufferSize = size; +} + +int GeneralTab::getAudioDeviceBufferSize() +{ + return m_audioDeviceBufferSize; +} + +#ifdef HAVE_ALSA +int GeneralTab::checkMatchAudioDevice(void *md, const char *vid, const enum device_type type) +{ + const char *devname = NULL; + + while ((devname = get_associated_device(md, devname, type, vid, MEDIA_V4L_VIDEO)) != NULL) { + if (type == MEDIA_SND_CAP) { + QStringList devAddr = QString(devname).split(QRegExp("[:,]")); + return devAddr.value(1).toInt(); + } + } + return -1; +} + +int GeneralTab::matchAudioDevice() +{ + QStringList devPath = m_device.split("/"); + QString curDev = devPath.value(devPath.count() - 1); + + void *media; + const char *video = NULL; + int match; + + media = discover_media_devices(); + + while ((video = get_associated_device(media, video, MEDIA_V4L_VIDEO, NULL, NONE)) != NULL) + if (curDev.compare(video) == 0) + for (int i = 0; i <= MEDIA_SND_HW; i++) + if ((match = checkMatchAudioDevice(media, video, static_cast<device_type>(i))) != -1) + return match; + + return -1; +} +#endif + +bool GeneralTab::hasAlsaAudio() +{ +#ifdef HAVE_ALSA + return !isVbi(); +#else + return false; +#endif +} diff --git a/utils/qv4l2/general-tab.h b/utils/qv4l2/general-tab.h index 5903ed8..6c51016 100644 --- a/utils/qv4l2/general-tab.h +++ b/utils/qv4l2/general-tab.h @@ -21,12 +21,23 @@ #ifndef GENERAL_TAB_H #define GENERAL_TAB_H +#include <config.h> + #include <QSpinBox> #include <sys/time.h> #include <linux/videodev2.h> +#include <map> #include "qv4l2.h" #include "v4l2-api.h" +#ifdef HAVE_ALSA +extern "C" { +#include "../libmedia_dev/get_media_devices.h" +#include "alsa_stream.h" +} +#include <alsa/asoundlib.h> +#endif + class QComboBox; class QCheckBox; class QSpinBox; @@ -41,6 +52,11 @@ public: virtual ~GeneralTab() {} CapMethod capMethod(); + QString getAudioInDevice(); + QString getAudioOutDevice(); + void setAudioDeviceBufferSize(int size); + int getAudioDeviceBufferSize(); + bool hasAlsaAudio(); bool get_interval(struct v4l2_fract &interval); int width() const { return m_width; } int height() const { return m_height; } @@ -69,6 +85,12 @@ public: inline bool streamon() { return v4l2::streamon(m_buftype); } inline bool streamoff() { return v4l2::streamoff(m_buftype); } +public slots: + void showAllAudioDevices(bool use); + +signals: + void audioDeviceChanged(); + private slots: void inputChanged(int); void outputChanged(int); @@ -92,6 +114,7 @@ private slots: void frameIntervalChanged(int); void vidOutFormatChanged(int); void vbiMethodsChanged(int); + void changeAudioDevice(); private: void updateVideoInput(); @@ -108,6 +131,14 @@ private: void updateFrameSize(); void updateFrameInterval(); void updateVidOutFormat(); + int addAudioDevice(void *hint, int deviceNum); + bool filterAudioInDevice(QString &deviceName); + bool filterAudioOutDevice(QString &deviceName); + bool createAudioDeviceList(); +#ifdef HAVE_ALSA + int matchAudioDevice(); + int checkMatchAudioDevice(void *md, const char *vid, const enum device_type type); +#endif void addWidget(QWidget *w, Qt::Alignment align = Qt::AlignLeft); void addLabel(const QString &text, Qt::Alignment align = Qt::AlignRight) @@ -130,6 +161,7 @@ private: bool m_isVbi; __u32 m_buftype; __u32 m_audioModes[5]; + QString m_device; struct v4l2_tuner m_tuner; struct v4l2_modulator m_modulator; struct v4l2_capability m_querycap; @@ -137,6 +169,10 @@ private: __u32 m_width, m_height; struct v4l2_fract m_interval; bool m_has_interval; + int m_audioDeviceBufferSize; + static bool m_fullAudioName; + std::map<QString, QString> m_audioInDeviceMap; + std::map<QString, QString> m_audioOutDeviceMap; // General tab QComboBox *m_videoInput; @@ -163,6 +199,8 @@ private: QComboBox *m_vidOutFormats; QComboBox *m_capMethods; QComboBox *m_vbiMethods; + QComboBox *m_audioInDevice; + QComboBox *m_audioOutDevice; }; #endif diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp index 275b399..5510041 100644 --- a/utils/qv4l2/qv4l2.cpp +++ b/utils/qv4l2/qv4l2.cpp @@ -24,6 +24,12 @@ #include "capture-win-qt.h" #include "capture-win-gl.h" +#ifdef ENABLE_ASLA +extern "C" { +#include "alsa_stream.h" +} +#endif + #include <QToolBar> #include <QToolButton> #include <QMenuBar> @@ -45,15 +51,18 @@ #include <QWhatsThis> #include <QThread> #include <QCloseEvent> +#include <QInputDialog> #include <assert.h> #include <sys/mman.h> +#include <sys/time.h> #include <errno.h> #include <dirent.h> #include <libv4l2.h> ApplicationWindow::ApplicationWindow() : m_capture(NULL), + m_genTab(NULL), m_sigMapper(NULL) { setAttribute(Qt::WA_DeleteOnClose, true); @@ -76,7 +85,7 @@ ApplicationWindow::ApplicationWindow() : openRawAct->setShortcut(Qt::CTRL+Qt::Key_R); connect(openRawAct, SIGNAL(triggered()), this, SLOT(openrawdev())); - m_capStartAct = new QAction(QIcon(":/record.png"), "&Start Capturing", this); + m_capStartAct = new QAction(QIcon(":/record.png"), "Start &Capturing", this); m_capStartAct->setStatusTip("Start capturing"); m_capStartAct->setCheckable(true); m_capStartAct->setDisabled(true); @@ -145,6 +154,21 @@ ApplicationWindow::ApplicationWindow() : m_renderMethod = QV4L2_RENDER_QT; } +#ifdef HAVE_ALSA + captureMenu->addSeparator(); + + m_showAllAudioAct = new QAction("Show All Audio Devices", this); + m_showAllAudioAct->setStatusTip("Show all audio input and output devices if set"); + m_showAllAudioAct->setCheckable(true); + m_showAllAudioAct->setChecked(false); + captureMenu->addAction(m_showAllAudioAct); + + m_audioBufferAct = new QAction("Set Audio Buffer Capacity...", this); + m_audioBufferAct->setStatusTip("Set audio buffer capacity in amout of ms than can be stored"); + connect(m_audioBufferAct, SIGNAL(triggered()), this, SLOT(setAudioBufferSize())); + captureMenu->addAction(m_audioBufferAct); +#endif + QMenu *helpMenu = menuBar()->addMenu("&Help"); helpMenu->addAction("&About", this, SLOT(about()), Qt::Key_F1); @@ -172,8 +196,11 @@ void ApplicationWindow::setDevice(const QString &device, bool rawOpen) m_sigMapper = new QSignalMapper(this); connect(m_sigMapper, SIGNAL(mapped(int)), this, SLOT(ctrlAction(int))); - if (!open(device, !rawOpen)) + if (!open(device, !rawOpen)) { + m_showAllAudioAct->setEnabled(false); + m_audioBufferAct->setEnabled(false); return; + } newCaptureWin(); @@ -181,6 +208,19 @@ void ApplicationWindow::setDevice(const QString &device, bool rawOpen) QWidget *w = new QWidget(m_tabs); m_genTab = new GeneralTab(device, *this, 4, w); + +#ifdef HAVE_ALSA + if (m_genTab->hasAlsaAudio()) { + connect(m_showAllAudioAct, SIGNAL(toggled(bool)), m_genTab, SLOT(showAllAudioDevices(bool))); + connect(m_genTab, SIGNAL(audioDeviceChanged()), this, SLOT(changeAudioDevice())); + m_showAllAudioAct->setEnabled(true); + m_audioBufferAct->setEnabled(true); + } else { + m_showAllAudioAct->setEnabled(false); + m_audioBufferAct->setEnabled(false); + } +#endif + m_tabs->addTab(w, "General"); addTabs(); if (caps() & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)) { @@ -195,7 +235,7 @@ void ApplicationWindow::setDevice(const QString &device, bool rawOpen) m_tabs->show(); m_tabs->setFocus(); m_convertData = v4lconvert_create(fd()); - m_capStartAct->setEnabled(fd() >= 0 && !m_genTab->isRadio()); + m_capStartAct->setEnabled(fd() >= 0); m_ctrlNotifier = new QSocketNotifier(fd(), QSocketNotifier::Exception, m_tabs); connect(m_ctrlNotifier, SIGNAL(activated(int)), this, SLOT(ctrlEvent())); } @@ -235,6 +275,19 @@ void ApplicationWindow::setRenderMethod() newCaptureWin(); } +void ApplicationWindow::setAudioBufferSize() +{ + bool ok; + int buffer = QInputDialog::getInt(this, "Audio Device Buffer Size", "Capacity in ms:", + m_genTab->getAudioDeviceBufferSize(), 1, 65535, 1, &ok); + + if (ok) { + m_genTab->setAudioDeviceBufferSize(buffer); + changeAudioDevice(); + } +} + + void ApplicationWindow::ctrlEvent() { v4l2_event ev; @@ -413,12 +466,19 @@ void ApplicationWindow::capFrame() int s = 0; int err = 0; bool again; +#ifdef HAVE_ALSA + struct timeval tv_alsa; +#endif unsigned char *displaybuf = NULL; switch (m_capMethod) { case methodRead: s = read(m_frameData, m_capSrcFormat.fmt.pix.sizeimage); +#ifdef HAVE_ALSA + alsa_thread_timestamp(&tv_alsa); +#endif + if (s < 0) { if (errno != EAGAIN) { error("read"); @@ -449,6 +509,9 @@ void ApplicationWindow::capFrame() m_capStartAct->setChecked(false); return; } +#ifdef HAVE_ALSA + alsa_thread_timestamp(&tv_alsa); +#endif if (again) return; @@ -475,6 +538,9 @@ void ApplicationWindow::capFrame() m_capStartAct->setChecked(false); return; } +#ifdef HAVE_ALSA + alsa_thread_timestamp(&tv_alsa); +#endif if (again) return; @@ -511,9 +577,22 @@ void ApplicationWindow::capFrame() m_lastFrame = m_frame; m_tv = tv; } + + status = QString("Frame: %1 Fps: %2").arg(++m_frame).arg(m_fps); +#ifdef HAVE_ALSA + if (alsa_thread_is_running()) { + if (tv_alsa.tv_sec || tv_alsa.tv_usec) { + m_totalAudioLatency.tv_sec += buf.timestamp.tv_sec - tv_alsa.tv_sec; + m_totalAudioLatency.tv_usec += buf.timestamp.tv_usec - tv_alsa.tv_usec; + } + status.append(QString(" Average A-V: %3 ms") + .arg((m_totalAudioLatency.tv_sec * 1000 + m_totalAudioLatency.tv_usec / 1000) / m_frame)); + } +#endif if (displaybuf == NULL && m_showFrames) status.append(" Error: Unsupported format."); + if (m_showFrames) m_capture->setFrame(m_capImage->width(), m_capImage->height(), m_capDestFormat.fmt.pix.pixelformat, displaybuf, status); @@ -530,6 +609,11 @@ void ApplicationWindow::capFrame() bool ApplicationWindow::startCapture(unsigned buffer_size) { + startAudio(); + + if (m_genTab->isRadio()) + return true; + __u32 buftype = m_genTab->bufType(); v4l2_requestbuffers req; unsigned int i; @@ -645,6 +729,11 @@ error: void ApplicationWindow::stopCapture() { + stopAudio(); + + if (m_genTab->isRadio()) + return; + __u32 buftype = m_genTab->bufType(); v4l2_requestbuffers reqbufs; v4l2_encoder_cmd cmd; @@ -695,6 +784,42 @@ void ApplicationWindow::stopOutput() { } +void ApplicationWindow::startAudio() +{ +#ifdef HAVE_ALSA + m_totalAudioLatency.tv_sec = 0; + m_totalAudioLatency.tv_usec = 0; + + QString audIn = m_genTab->getAudioInDevice(); + QString audOut = m_genTab->getAudioOutDevice(); + + if (audIn != NULL && audOut != NULL && audIn.compare("None") && audIn.compare(audOut) != 0) { + alsa_thread_startup(audOut.toAscii().data(), audIn.toAscii().data(), + m_genTab->getAudioDeviceBufferSize(), NULL, 0); + + if (m_genTab->isRadio()) + statusBar()->showMessage("Capturing audio"); + } +#endif +} + +void ApplicationWindow::stopAudio() +{ +#ifdef HAVE_ALSA + if (m_genTab != NULL && m_genTab->isRadio()) + statusBar()->showMessage(""); + alsa_thread_stop(); +#endif +} + +void ApplicationWindow::changeAudioDevice() +{ + stopAudio(); + if (m_capStartAct->isChecked()) { + startAudio(); + } +} + void ApplicationWindow::closeCaptureWin() { m_capStartAct->setChecked(false); @@ -702,6 +827,15 @@ void ApplicationWindow::closeCaptureWin() void ApplicationWindow::capStart(bool start) { + if (m_genTab->isRadio()) { + if (start) + startCapture(0); + else + stopCapture(); + + return; + } + QImage::Format dstFmt = QImage::Format_RGB888; struct v4l2_fract interval; v4l2_pix_format &srcPix = m_capSrcFormat.fmt.pix; @@ -821,6 +955,7 @@ void ApplicationWindow::capStart(bool start) void ApplicationWindow::closeDevice() { + stopAudio(); delete m_sigMapper; m_sigMapper = NULL; m_capStartAct->setEnabled(false); diff --git a/utils/qv4l2/qv4l2.h b/utils/qv4l2/qv4l2.h index 2921b16..511a652 100644 --- a/utils/qv4l2/qv4l2.h +++ b/utils/qv4l2/qv4l2.h @@ -20,6 +20,8 @@ #ifndef QV4L2_H #define QV4L2_H +#include <config.h> + #include <QMainWindow> #include <QTabWidget> #include <QSignalMapper> @@ -98,6 +100,8 @@ private: void startOutput(unsigned buffer_size); void stopOutput(); void newCaptureWin(); + void startAudio(); + void stopAudio(); struct buffer *m_buffers; struct v4l2_format m_capSrcFormat; @@ -118,6 +122,7 @@ private slots: void capVbiFrame(); void saveRaw(bool); void setRenderMethod(); + void changeAudioDevice(); // gui private slots: @@ -126,6 +131,7 @@ private slots: void ctrlAction(int); void openRawFile(const QString &s); void rejectedRawFile(); + void setAudioBufferSize(); void about(); @@ -176,6 +182,8 @@ private: QAction *m_saveRawAct; QAction *m_showFramesAct; QAction *m_useGLAct; + QAction *m_showAllAudioAct; + QAction *m_audioBufferAct; QString m_filename; QSignalMapper *m_sigMapper; QTabWidget *m_tabs; @@ -196,6 +204,7 @@ private: unsigned m_lastFrame; unsigned m_fps; struct timeval m_tv; + struct timeval m_totalAudioLatency; QFile m_saveRaw; }; -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html