diff options
199 files changed, 3211 insertions, 2167 deletions
diff --git a/.qmake.conf b/.qmake.conf index fec66b73e..b1c22d3b7 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.8.1 +MODULE_VERSION = 5.9.0 diff --git a/examples/multimedia/declarative-camera/CameraListButton.qml b/examples/multimedia/declarative-camera/CameraListButton.qml index 892bb4e2a..b53b57a84 100644 --- a/examples/multimedia/declarative-camera/CameraListButton.qml +++ b/examples/multimedia/declarative-camera/CameraListButton.qml @@ -69,8 +69,6 @@ Item { anchors.top: parent.top visible: opacity > 0 - currentValue: cameraListButton.value - onSelected: popup.toggle() } } diff --git a/examples/multimediawidgets/player/histogramwidget.cpp b/examples/multimediawidgets/player/histogramwidget.cpp index ff8d84e9b..71c243e23 100644 --- a/examples/multimediawidgets/player/histogramwidget.cpp +++ b/examples/multimediawidgets/player/histogramwidget.cpp @@ -40,6 +40,54 @@ #include "histogramwidget.h" #include <QPainter> +#include <QHBoxLayout> + +template <class T> +static QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels); + +class QAudioLevel : public QWidget +{ + Q_OBJECT +public: + explicit QAudioLevel(QWidget *parent = 0); + + // Using [0; 1.0] range + void setLevel(qreal level); + +protected: + void paintEvent(QPaintEvent *event); + +private: + qreal m_level; +}; + +QAudioLevel::QAudioLevel(QWidget *parent) + : QWidget(parent) + , m_level(0.0) +{ + setMinimumHeight(15); + setMaximumHeight(50); +} + +void QAudioLevel::setLevel(qreal level) +{ + if (m_level != level) { + m_level = level; + update(); + } +} + +void QAudioLevel::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + // draw level + qreal widthLevel = m_level * width(); + painter.fillRect(0, 0, widthLevel, height(), Qt::red); + // clear the rest of the control + painter.fillRect(widthLevel, 0, width(), height(), Qt::black); +} HistogramWidget::HistogramWidget(QWidget *parent) : QWidget(parent) @@ -50,6 +98,7 @@ HistogramWidget::HistogramWidget(QWidget *parent) qRegisterMetaType<QVector<qreal> >("QVector<qreal>"); connect(&m_processor, SIGNAL(histogramReady(QVector<qreal>)), SLOT(setHistogram(QVector<qreal>))); m_processorThread.start(QThread::LowestPriority); + setLayout(new QHBoxLayout); } HistogramWidget::~HistogramWidget() @@ -60,7 +109,7 @@ HistogramWidget::~HistogramWidget() void HistogramWidget::processFrame(QVideoFrame frame) { - if (m_isBusy) + if (m_isBusy && frame.isValid()) return; //drop frame m_isBusy = true; @@ -68,6 +117,132 @@ void HistogramWidget::processFrame(QVideoFrame frame) Qt::QueuedConnection, Q_ARG(QVideoFrame, frame), Q_ARG(int, m_levels)); } +// This function returns the maximum possible sample value for a given audio format +qreal getPeakValue(const QAudioFormat& format) +{ + // Note: Only the most common sample formats are supported + if (!format.isValid()) + return qreal(0); + + if (format.codec() != "audio/pcm") + return qreal(0); + + switch (format.sampleType()) { + case QAudioFormat::Unknown: + break; + case QAudioFormat::Float: + if (format.sampleSize() != 32) // other sample formats are not supported + return qreal(0); + return qreal(1.00003); + case QAudioFormat::SignedInt: + if (format.sampleSize() == 32) + return qreal(INT_MAX); + if (format.sampleSize() == 16) + return qreal(SHRT_MAX); + if (format.sampleSize() == 8) + return qreal(CHAR_MAX); + break; + case QAudioFormat::UnSignedInt: + if (format.sampleSize() == 32) + return qreal(UINT_MAX); + if (format.sampleSize() == 16) + return qreal(USHRT_MAX); + if (format.sampleSize() == 8) + return qreal(UCHAR_MAX); + break; + } + + return qreal(0); +} + +// returns the audio level for each channel +QVector<qreal> getBufferLevels(const QAudioBuffer& buffer) +{ + QVector<qreal> values; + + if (!buffer.isValid()) + return values; + + if (!buffer.format().isValid() || buffer.format().byteOrder() != QAudioFormat::LittleEndian) + return values; + + if (buffer.format().codec() != "audio/pcm") + return values; + + int channelCount = buffer.format().channelCount(); + values.fill(0, channelCount); + qreal peak_value = getPeakValue(buffer.format()); + if (qFuzzyCompare(peak_value, qreal(0))) + return values; + + switch (buffer.format().sampleType()) { + case QAudioFormat::Unknown: + case QAudioFormat::UnSignedInt: + if (buffer.format().sampleSize() == 32) + values = getBufferLevels(buffer.constData<quint32>(), buffer.frameCount(), channelCount); + if (buffer.format().sampleSize() == 16) + values = getBufferLevels(buffer.constData<quint16>(), buffer.frameCount(), channelCount); + if (buffer.format().sampleSize() == 8) + values = getBufferLevels(buffer.constData<quint8>(), buffer.frameCount(), channelCount); + for (int i = 0; i < values.size(); ++i) + values[i] = qAbs(values.at(i) - peak_value / 2) / (peak_value / 2); + break; + case QAudioFormat::Float: + if (buffer.format().sampleSize() == 32) { + values = getBufferLevels(buffer.constData<float>(), buffer.frameCount(), channelCount); + for (int i = 0; i < values.size(); ++i) + values[i] /= peak_value; + } + break; + case QAudioFormat::SignedInt: + if (buffer.format().sampleSize() == 32) + values = getBufferLevels(buffer.constData<qint32>(), buffer.frameCount(), channelCount); + if (buffer.format().sampleSize() == 16) + values = getBufferLevels(buffer.constData<qint16>(), buffer.frameCount(), channelCount); + if (buffer.format().sampleSize() == 8) + values = getBufferLevels(buffer.constData<qint8>(), buffer.frameCount(), channelCount); + for (int i = 0; i < values.size(); ++i) + values[i] /= peak_value; + break; + } + + return values; +} + +template <class T> +QVector<qreal> getBufferLevels(const T *buffer, int frames, int channels) +{ + QVector<qreal> max_values; + max_values.fill(0, channels); + + for (int i = 0; i < frames; ++i) { + for (int j = 0; j < channels; ++j) { + qreal value = qAbs(qreal(buffer[i * channels + j])); + if (value > max_values.at(j)) + max_values.replace(j, value); + } + } + + return max_values; +} + +void HistogramWidget::processBuffer(QAudioBuffer buffer) +{ + if (audioLevels.count() != buffer.format().channelCount()) { + qDeleteAll(audioLevels); + audioLevels.clear(); + for (int i = 0; i < buffer.format().channelCount(); ++i) { + QAudioLevel *level = new QAudioLevel(this); + audioLevels.append(level); + layout()->addWidget(level); + } + } + + QVector<qreal> levels = getBufferLevels(buffer); + for (int i = 0; i < levels.count(); ++i) + audioLevels.at(i)->setLevel(levels.at(i)); +} + void HistogramWidget::setHistogram(QVector<qreal> histogram) { m_isBusy = false; @@ -79,6 +254,9 @@ void HistogramWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); + if (!audioLevels.isEmpty()) + return; + QPainter painter(this); if (m_histogram.isEmpty()) { @@ -152,3 +330,5 @@ void FrameProcessor::processFrame(QVideoFrame frame, int levels) emit histogramReady(histogram); } + +#include "histogramwidget.moc" diff --git a/examples/multimediawidgets/player/histogramwidget.h b/examples/multimediawidgets/player/histogramwidget.h index 9462b1c84..a85dd27e1 100644 --- a/examples/multimediawidgets/player/histogramwidget.h +++ b/examples/multimediawidgets/player/histogramwidget.h @@ -43,8 +43,11 @@ #include <QThread> #include <QVideoFrame> +#include <QAudioBuffer> #include <QWidget> +class QAudioLevel; + class FrameProcessor: public QObject { Q_OBJECT @@ -67,6 +70,7 @@ public: public slots: void processFrame(QVideoFrame frame); + void processBuffer(QAudioBuffer buffer); void setHistogram(QVector<qreal> histogram); protected: @@ -78,6 +82,7 @@ private: FrameProcessor m_processor; QThread m_processorThread; bool m_isBusy; + QVector<QAudioLevel *> audioLevels; }; #endif // HISTOGRAMWIDGET_H diff --git a/examples/multimediawidgets/player/player.cpp b/examples/multimediawidgets/player/player.cpp index ab048838a..8f291c501 100644 --- a/examples/multimediawidgets/player/player.cpp +++ b/examples/multimediawidgets/player/player.cpp @@ -47,6 +47,7 @@ #include <QMediaService> #include <QMediaPlaylist> #include <QVideoProbe> +#include <QAudioProbe> #include <QMediaMetaData> #include <QtWidgets> @@ -73,6 +74,7 @@ Player::Player(QWidget *parent) connect(player, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int))); connect(player, SIGNAL(videoAvailableChanged(bool)), this, SLOT(videoAvailableChanged(bool))); connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(displayErrorMessage())); + connect(player, &QMediaPlayer::stateChanged, this, &Player::stateChanged); //! [2] videoWidget = new VideoWidget(this); @@ -96,14 +98,20 @@ Player::Player(QWidget *parent) labelHistogram = new QLabel(this); labelHistogram->setText("Histogram:"); - histogram = new HistogramWidget(this); + videoHistogram = new HistogramWidget(this); + audioHistogram = new HistogramWidget(this); QHBoxLayout *histogramLayout = new QHBoxLayout; histogramLayout->addWidget(labelHistogram); - histogramLayout->addWidget(histogram, 1); + histogramLayout->addWidget(videoHistogram, 1); + histogramLayout->addWidget(audioHistogram, 2); - probe = new QVideoProbe(this); - connect(probe, SIGNAL(videoFrameProbed(QVideoFrame)), histogram, SLOT(processFrame(QVideoFrame))); - probe->setSource(player); + videoProbe = new QVideoProbe(this); + connect(videoProbe, SIGNAL(videoFrameProbed(QVideoFrame)), videoHistogram, SLOT(processFrame(QVideoFrame))); + videoProbe->setSource(player); + + audioProbe = new QAudioProbe(this); + connect(audioProbe, SIGNAL(audioBufferProbed(QAudioBuffer)), audioHistogram, SLOT(processBuffer(QAudioBuffer))); + audioProbe->setSource(player); QPushButton *openButton = new QPushButton(tr("Open"), this); @@ -269,6 +277,7 @@ void Player::jump(const QModelIndex &index) void Player::playlistPositionChanged(int currentItem) { + clearHistogram(); playlistView->setCurrentIndex(playlistModel->index(currentItem, 0)); } @@ -305,6 +314,12 @@ void Player::statusChanged(QMediaPlayer::MediaStatus status) } } +void Player::stateChanged(QMediaPlayer::State state) +{ + if (state == QMediaPlayer::StoppedState) + clearHistogram(); +} + void Player::handleCursor(QMediaPlayer::MediaStatus status) { #ifndef QT_NO_CURSOR @@ -423,3 +438,9 @@ void Player::showColorDialog() } colorDialog->show(); } + +void Player::clearHistogram() +{ + QMetaObject::invokeMethod(videoHistogram, "processFrame", Qt::QueuedConnection, Q_ARG(QVideoFrame, QVideoFrame())); + QMetaObject::invokeMethod(audioHistogram, "processBuffer", Qt::QueuedConnection, Q_ARG(QAudioBuffer, QAudioBuffer())); +} diff --git a/examples/multimediawidgets/player/player.h b/examples/multimediawidgets/player/player.h index ca643bd7d..ff60f8c63 100644 --- a/examples/multimediawidgets/player/player.h +++ b/examples/multimediawidgets/player/player.h @@ -56,6 +56,7 @@ class QPushButton; class QSlider; class QVideoProbe; class QVideoWidget; +class QAudioProbe; QT_END_NAMESPACE class PlaylistModel; @@ -89,6 +90,7 @@ private slots: void playlistPositionChanged(int); void statusChanged(QMediaPlayer::MediaStatus status); + void stateChanged(QMediaPlayer::State state); void bufferingProgress(int progress); void videoAvailableChanged(bool available); @@ -97,6 +99,7 @@ private slots: void showColorDialog(); private: + void clearHistogram(); void setTrackInfo(const QString &info); void setStatusInfo(const QString &info); void handleCursor(QMediaPlayer::MediaStatus status); @@ -113,8 +116,10 @@ private: QDialog *colorDialog; QLabel *labelHistogram; - HistogramWidget *histogram; - QVideoProbe *probe; + HistogramWidget *videoHistogram; + HistogramWidget *audioHistogram; + QVideoProbe *videoProbe; + QAudioProbe *audioProbe; PlaylistModel *playlistModel; QAbstractItemView *playlistView; diff --git a/examples/multimediawidgets/videographicsitem/main.cpp b/examples/multimediawidgets/videographicsitem/main.cpp index 25ac7af06..d5fcdb2d8 100644 --- a/examples/multimediawidgets/videographicsitem/main.cpp +++ b/examples/multimediawidgets/videographicsitem/main.cpp @@ -41,12 +41,33 @@ #include "videoplayer.h" #include <QApplication> +#include <QCommandLineParser> +#include <QCommandLineOption> +#include <QDir> int main(int argc, char **argv) { QApplication app(argc, argv); + QCoreApplication::setApplicationName("Player Example"); + QCoreApplication::setOrganizationName("QtProject"); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + QCommandLineParser parser; + parser.setApplicationDescription("Qt MultiMedia Player QGraphicsView Example"); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("url", "The URL to open."); + parser.process(app); + VideoPlayer player; + + if (!parser.positionalArguments().isEmpty() && player.isPlayerAvailable()) { + const QUrl url = + QUrl::fromUserInput(parser.positionalArguments().constFirst(), + QDir::currentPath(), QUrl::AssumeLocalFile); + player.load(url); + } + player.show(); return app.exec(); diff --git a/examples/multimediawidgets/videographicsitem/videoplayer.cpp b/examples/multimediawidgets/videographicsitem/videoplayer.cpp index fcfe38b26..7f5c4f0bb 100644 --- a/examples/multimediawidgets/videographicsitem/videoplayer.cpp +++ b/examples/multimediawidgets/videographicsitem/videoplayer.cpp @@ -51,8 +51,9 @@ VideoPlayer::VideoPlayer(QWidget *parent) , playButton(0) , positionSlider(0) { + const QRect screenGeometry = QApplication::desktop()->screenGeometry(this); videoItem = new QGraphicsVideoItem; - videoItem->setSize(QSizeF(640, 480)); + videoItem->setSize(QSizeF(screenGeometry.width() / 3, screenGeometry.height() / 2)); QGraphicsScene *scene = new QGraphicsScene(this); QGraphicsView *graphicsView = new QGraphicsView(scene); @@ -60,27 +61,27 @@ VideoPlayer::VideoPlayer(QWidget *parent) scene->addItem(videoItem); QSlider *rotateSlider = new QSlider(Qt::Horizontal); + rotateSlider->setToolTip(tr("Rotate Video")); rotateSlider->setRange(-180, 180); rotateSlider->setValue(0); - connect(rotateSlider, SIGNAL(valueChanged(int)), - this, SLOT(rotateVideo(int))); + connect(rotateSlider, &QAbstractSlider::valueChanged, + this, &VideoPlayer::rotateVideo); QAbstractButton *openButton = new QPushButton(tr("Open...")); - connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); + connect(openButton, &QAbstractButton::clicked, this, &VideoPlayer::openFile); playButton = new QPushButton; playButton->setEnabled(false); playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); - connect(playButton, SIGNAL(clicked()), - this, SLOT(play())); + connect(playButton, &QAbstractButton::clicked, this, &VideoPlayer::play); positionSlider = new QSlider(Qt::Horizontal); positionSlider->setRange(0, 0); - connect(positionSlider, SIGNAL(sliderMoved(int)), - this, SLOT(setPosition(int))); + connect(positionSlider, &QAbstractSlider::sliderMoved, + this, &VideoPlayer::setPosition); QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); @@ -88,34 +89,49 @@ VideoPlayer::VideoPlayer(QWidget *parent) controlLayout->addWidget(playButton); controlLayout->addWidget(positionSlider); - QBoxLayout *layout = new QVBoxLayout; + QBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(graphicsView); layout->addWidget(rotateSlider); layout->addLayout(controlLayout); - setLayout(layout); - mediaPlayer.setVideoOutput(videoItem); - connect(&mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), - this, SLOT(mediaStateChanged(QMediaPlayer::State))); - connect(&mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64))); - connect(&mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64))); + connect(&mediaPlayer, &QMediaPlayer::stateChanged, + this, &VideoPlayer::mediaStateChanged); + connect(&mediaPlayer, &QMediaPlayer::positionChanged, this, &VideoPlayer::positionChanged); + connect(&mediaPlayer, &QMediaPlayer::durationChanged, this, &VideoPlayer::durationChanged); } VideoPlayer::~VideoPlayer() { } +QSize VideoPlayer::sizeHint() const +{ + return (videoItem->size() * qreal(3) / qreal(2)).toSize(); +} -void VideoPlayer::openFile() +bool VideoPlayer::isPlayerAvailable() const { - QString fileName = QFileDialog::getOpenFileName(this, tr("Open Movie"),QDir::homePath()); + return mediaPlayer.isAvailable(); +} - if (!fileName.isEmpty()) { - mediaPlayer.setMedia(QUrl::fromLocalFile(fileName)); +void VideoPlayer::openFile() +{ + QFileDialog fileDialog(this); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setWindowTitle(tr("Open Movie")); + const QStringList supportedMimeTypes = mediaPlayer.supportedMimeTypes(); + if (!supportedMimeTypes.isEmpty()) + fileDialog.setMimeTypeFilters(supportedMimeTypes); + fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath())); + if (fileDialog.exec() == QDialog::Accepted) + load(fileDialog.selectedUrls().constFirst()); +} - playButton->setEnabled(true); - } +void VideoPlayer::load(const QUrl &url) +{ + mediaPlayer.setMedia(url); + playButton->setEnabled(true); } void VideoPlayer::play() diff --git a/examples/multimediawidgets/videographicsitem/videoplayer.h b/examples/multimediawidgets/videographicsitem/videoplayer.h index 17cb8565a..ffccc9a9c 100644 --- a/examples/multimediawidgets/videographicsitem/videoplayer.h +++ b/examples/multimediawidgets/videographicsitem/videoplayer.h @@ -59,7 +59,10 @@ public: VideoPlayer(QWidget *parent = 0); ~VideoPlayer(); - QSize sizeHint() const override { return QSize(800, 600); } + void load(const QUrl &url); + bool isPlayerAvailable() const; + + QSize sizeHint() const override; public slots: void openFile(); diff --git a/src/gsttools/qgstcodecsinfo.cpp b/src/gsttools/qgstcodecsinfo.cpp index edee797ae..230dc581b 100644 --- a/src/gsttools/qgstcodecsinfo.cpp +++ b/src/gsttools/qgstcodecsinfo.cpp @@ -41,62 +41,11 @@ #include "qgstutils_p.h" #include <QtCore/qset.h> -#ifdef QMEDIA_GSTREAMER_CAMERABIN #include <gst/pbutils/pbutils.h> -#include <gst/pbutils/encoding-profile.h> -#endif - QGstCodecsInfo::QGstCodecsInfo(QGstCodecsInfo::ElementType elementType) { - -#if GST_CHECK_VERSION(0,10,31) - - GstElementFactoryListType gstElementType = 0; - switch (elementType) { - case AudioEncoder: - gstElementType = GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER; - break; - case VideoEncoder: - gstElementType = GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER; - break; - case Muxer: - gstElementType = GST_ELEMENT_FACTORY_TYPE_MUXER; - break; - } - - GstCaps *allCaps = supportedElementCaps(gstElementType); - GstCaps *caps = gst_caps_new_empty(); - - uint codecsCount = gst_caps_get_size(allCaps); - for (uint i=0; i<codecsCount; i++) { - gst_caps_append_structure(caps, gst_caps_steal_structure(allCaps, 0)); - gchar * capsString = gst_caps_to_string(caps); - - QString codec = QLatin1String(capsString); - m_codecs.append(codec); - -#ifdef QMEDIA_GSTREAMER_CAMERABIN - gchar *description = gst_pb_utils_get_codec_description(caps); - m_codecDescriptions.insert(codec, QString::fromUtf8(description)); - - if (description) - g_free(description); -#else - m_codecDescriptions.insert(codec, codec); -#endif - - if (capsString) - g_free(capsString); - - gst_caps_remove_structure(caps, 0); - } - - gst_caps_unref(caps); - gst_caps_unref(allCaps); -#else - Q_UNUSED(elementType); -#endif // GST_CHECK_VERSION(0,10,31) + updateCodecs(elementType); } QStringList QGstCodecsInfo::supportedCodecs() const @@ -106,23 +55,49 @@ QStringList QGstCodecsInfo::supportedCodecs() const QString QGstCodecsInfo::codecDescription(const QString &codec) const { - return m_codecDescriptions.value(codec); + return m_codecInfo.value(codec).description; } -#if GST_CHECK_VERSION(0,10,31) +QByteArray QGstCodecsInfo::codecElement(const QString &codec) const -/*! - List all supported caps for all installed elements of type \a elementType. +{ + return m_codecInfo.value(codec).elementName; +} + +QStringList QGstCodecsInfo::codecOptions(const QString &codec) const +{ + QStringList options; + + QByteArray elementName = m_codecInfo.value(codec).elementName; + if (elementName.isEmpty()) + return options; + + GstElement *element = gst_element_factory_make(elementName, NULL); + if (element) { + guint numProperties; + GParamSpec **properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(element), + &numProperties); + for (guint j = 0; j < numProperties; ++j) { + GParamSpec *property = properties[j]; + // ignore some properties + if (strcmp(property->name, "name") == 0 || strcmp(property->name, "parent") == 0) + continue; + + options.append(QLatin1String(property->name)); + } + g_free(properties); + gst_object_unref(element); + } + + return options; +} - Caps are simplified to mime type and a few field necessary to distinguish - different codecs like mpegversion or layer. - */ -GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementType, - GstRank minimumRank, - GstPadDirection padDirection) +void QGstCodecsInfo::updateCodecs(ElementType elementType) { - GList *elements = gst_element_factory_list_get_elements(elementType, minimumRank); - GstCaps *res = gst_caps_new_empty(); + m_codecs.clear(); + m_codecInfo.clear(); + + GList *elements = elementFactories(elementType); QSet<QByteArray> fakeEncoderMimeTypes; fakeEncoderMimeTypes << "unknown/unknown" @@ -143,7 +118,7 @@ GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementT GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data; padTemplates = padTemplates->next; - if (padTemplate->direction == padDirection) { + if (padTemplate->direction == GST_PAD_SRC) { GstCaps *caps = gst_static_caps_get(&padTemplate->static_caps); for (uint i=0; i<gst_caps_get_size(caps); i++) { const GstStructure *structure = gst_caps_get_structure(caps, i); @@ -172,18 +147,101 @@ GstCaps* QGstCodecsInfo::supportedElementCaps(GstElementFactoryListType elementT } } -#if GST_CHECK_VERSION(1,0,0) - res = -#endif - gst_caps_merge_structure(res, newStructure); + GstCaps *newCaps = gst_caps_new_full(newStructure, NULL); + gchar *capsString = gst_caps_to_string(newCaps); + QString codec = QLatin1String(capsString); + if (capsString) + g_free(capsString); + GstRank rank = GstRank(gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(factory))); + + // If two elements provide the same codec, use the highest ranked one + QMap<QString, CodecInfo>::const_iterator it = m_codecInfo.find(codec); + if (it == m_codecInfo.constEnd() || it->rank < rank) { + if (it == m_codecInfo.constEnd()) + m_codecs.append(codec); + + CodecInfo info; + info.elementName = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory)); + + gchar *description = gst_pb_utils_get_codec_description(newCaps); + info.description = QString::fromUtf8(description); + if (description) + g_free(description); + + info.rank = rank; + + m_codecInfo.insert(codec, info); + } + + gst_caps_unref(newCaps); } gst_caps_unref(caps); } } } + gst_plugin_feature_list_free(elements); +} + +#if !GST_CHECK_VERSION(0, 10, 31) +static gboolean element_filter(GstPluginFeature *feature, gpointer user_data) +{ + if (Q_UNLIKELY(!GST_IS_ELEMENT_FACTORY(feature))) + return FALSE; + + const QGstCodecsInfo::ElementType type = *reinterpret_cast<QGstCodecsInfo::ElementType *>(user_data); + + const gchar *klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature)); + if (type == QGstCodecsInfo::AudioEncoder && !(strstr(klass, "Encoder") && strstr(klass, "Audio"))) + return FALSE; + if (type == QGstCodecsInfo::VideoEncoder && !(strstr(klass, "Encoder") && strstr(klass, "Video"))) + return FALSE; + if (type == QGstCodecsInfo::Muxer && !strstr(klass, "Muxer")) + return FALSE; + + guint rank = gst_plugin_feature_get_rank(feature); + if (rank < GST_RANK_MARGINAL) + return FALSE; + + return TRUE; +} + +static gint compare_plugin_func(const void *item1, const void *item2) +{ + GstPluginFeature *f1 = reinterpret_cast<GstPluginFeature *>(const_cast<void *>(item1)); + GstPluginFeature *f2 = reinterpret_cast<GstPluginFeature *>(const_cast<void *>(item2)); - return res; + gint diff = gst_plugin_feature_get_rank(f2) - gst_plugin_feature_get_rank(f1); + if (diff != 0) + return diff; + + return strcmp(gst_plugin_feature_get_name(f1), gst_plugin_feature_get_name (f2)); +} +#endif + +GList *QGstCodecsInfo::elementFactories(ElementType elementType) const +{ +#if GST_CHECK_VERSION(0,10,31) + GstElementFactoryListType gstElementType = 0; + switch (elementType) { + case AudioEncoder: + gstElementType = GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER; + break; + case VideoEncoder: + gstElementType = GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER; + break; + case Muxer: + gstElementType = GST_ELEMENT_FACTORY_TYPE_MUXER; + break; + } + + return gst_element_factory_list_get_elements(gstElementType, GST_RANK_MARGINAL); +#else + GList *result = gst_registry_feature_filter(gst_registry_get_default(), + element_filter, + FALSE, &elementType); + result = g_list_sort(result, compare_plugin_func); + return result; +#endif } -#endif //GST_CHECK_VERSION(0,10,31) diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp index 67f9a8fa7..792df4243 100644 --- a/src/gsttools/qgstreamervideowidget.cpp +++ b/src/gsttools/qgstreamervideowidget.cpp @@ -59,7 +59,7 @@ public: virtual ~QGstreamerVideoWidget() {} - QSize sizeHint() const + QSize sizeHint() const override { return m_nativeSize; } @@ -84,7 +84,7 @@ public: } protected: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { paint_helper(); } diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index 2f8a39d67..96bd09f86 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -41,7 +41,6 @@ #include "qgstutils_p.h" #include <QtCore/qdatetime.h> -#include <QtCore/qtimezone.h> #include <QtCore/qdir.h> #include <QtCore/qbytearray.h> #include <QtCore/qvariant.h> @@ -136,7 +135,9 @@ static void addTagToMap(const GstTagList *list, int minute = gst_date_time_get_minute(dateTime); int second = gst_date_time_get_second(dateTime); float tz = gst_date_time_get_time_zone_offset(dateTime); - map->insert(QByteArray(tag), QDateTime(QDate(year,month,day), QTime(hour, minute, second), QTimeZone(tz * 60 * 60))); + QDateTime dateTime(QDate(year, month, day), QTime(hour, minute, second), + Qt::OffsetFromUTC, tz * 60 * 60); + map->insert(QByteArray(tag), dateTime); } else if (year > 0 && month > 0 && day > 0) { map->insert(QByteArray(tag), QDate(year,month,day)); } @@ -1430,6 +1431,40 @@ QPair<qreal, qreal> QGstUtils::structureFrameRateRange(const GstStructure *s) return rate; } +typedef QMap<QString, QString> FileExtensionMap; +Q_GLOBAL_STATIC(FileExtensionMap, fileExtensionMap) + +QString QGstUtils::fileExtensionForMimeType(const QString &mimeType) +{ + if (fileExtensionMap->isEmpty()) { + //extension for containers hard to guess from mimetype + fileExtensionMap->insert("video/x-matroska", "mkv"); + fileExtensionMap->insert("video/quicktime", "mov"); + fileExtensionMap->insert("video/x-msvideo", "avi"); + fileExtensionMap->insert("video/msvideo", "avi"); + fileExtensionMap->insert("audio/mpeg", "mp3"); + fileExtensionMap->insert("application/x-shockwave-flash", "swf"); + fileExtensionMap->insert("application/x-pn-realmedia", "rm"); + } + + //for container names like avi instead of video/x-msvideo, use it as extension + if (!mimeType.contains('/')) + return mimeType; + + QString format = mimeType.left(mimeType.indexOf(',')); + QString extension = fileExtensionMap->value(format); + + if (!extension.isEmpty() || format.isEmpty()) + return extension; + + QRegExp rx("[-/]([\\w]+)$"); + + if (rx.indexIn(format) != -1) + extension = rx.cap(1); + + return extension; +} + void qt_gst_object_ref_sink(gpointer object) { #if GST_CHECK_VERSION(0,10,24) diff --git a/src/imports/audioengine/audioengine.cpp b/src/imports/audioengine/audioengine.cpp index a132af49a..f97928f9d 100644 --- a/src/imports/audioengine/audioengine.cpp +++ b/src/imports/audioengine/audioengine.cpp @@ -67,7 +67,7 @@ class QAudioEngineDeclarativeModule : public QQmlExtensionPlugin public: QAudioEngineDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) override { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtAudioEngine")); diff --git a/src/imports/audioengine/qaudioengine_openal_p.h b/src/imports/audioengine/qaudioengine_openal_p.h index 088cb3f22..c1dbf6aa2 100644 --- a/src/imports/audioengine/qaudioengine_openal_p.h +++ b/src/imports/audioengine/qaudioengine_openal_p.h @@ -123,28 +123,28 @@ public: QSoundSourcePrivate(QObject *parent); ~QSoundSourcePrivate(); - void play(); - void pause(); - void stop(); + void play() override; + void pause() override; + void stop() override; - QSoundSource::State state() const; + QSoundSource::State state() const override; bool isLooping() const; - void setLooping(bool looping); - void setPosition(const QVector3D& position); - void setDirection(const QVector3D& direction); - void setVelocity(const QVector3D& velocity); + void setLooping(bool looping) override; + void setPosition(const QVector3D& position) override; + void setDirection(const QVector3D& direction) override; + void setVelocity(const QVector3D& velocity) override; - QVector3D velocity() const; - QVector3D position() const; - QVector3D direction() const; + QVector3D velocity() const override; + QVector3D position() const override; + QVector3D direction() const override; - void setGain(qreal gain); - void setPitch(qreal pitch); - void setCone(qreal innerAngle, qreal outerAngle, qreal outerGain); + void setGain(qreal gain) override; + void setPitch(qreal pitch) override; + void setCone(qreal innerAngle, qreal outerAngle, qreal outerGain) override; - void bindBuffer(QSoundBuffer*); - void unbindBuffer(); + void bindBuffer(QSoundBuffer*) override; + void unbindBuffer() override; void checkState(); diff --git a/src/imports/audioengine/qdeclarative_attenuationmodel_p.h b/src/imports/audioengine/qdeclarative_attenuationmodel_p.h index b50ed2ff5..1cec3f4ab 100644 --- a/src/imports/audioengine/qdeclarative_attenuationmodel_p.h +++ b/src/imports/audioengine/qdeclarative_attenuationmodel_p.h @@ -97,9 +97,9 @@ public: qreal endDistance() const; void setEndDistance(qreal endDist); - qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const; + qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const override; - void setEngine(QDeclarativeAudioEngine *engine); + void setEngine(QDeclarativeAudioEngine *engine) override; private: Q_DISABLE_COPY(QDeclarativeAttenuationModelLinear); @@ -126,9 +126,9 @@ public: qreal rolloffFactor() const; void setRolloffFactor(qreal rolloffFactor); - qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const; + qreal calculateGain(const QVector3D &listenerPosition, const QVector3D &sourcePosition) const override; - void setEngine(QDeclarativeAudioEngine *engine); + void setEngine(QDeclarativeAudioEngine *engine) override; private: Q_DISABLE_COPY(QDeclarativeAttenuationModelInverse); diff --git a/src/imports/audioengine/qdeclarative_audioengine_p.h b/src/imports/audioengine/qdeclarative_audioengine_p.h index abb379894..fd049e629 100644 --- a/src/imports/audioengine/qdeclarative_audioengine_p.h +++ b/src/imports/audioengine/qdeclarative_audioengine_p.h @@ -90,8 +90,8 @@ public: QDeclarativeAudioEngine(QObject *parent = 0); ~QDeclarativeAudioEngine(); - void classBegin(); - void componentComplete(); + void classBegin() override; + void componentComplete() override; //This is used for tracking all objects declared inside AudioEngine //see appendFunction diff --git a/src/imports/multimedia/Video.qml b/src/imports/multimedia/Video.qml index b3fee7495..66b86c74b 100644 --- a/src/imports/multimedia/Video.qml +++ b/src/imports/multimedia/Video.qml @@ -38,7 +38,7 @@ ****************************************************************************/ import QtQuick 2.0 -import QtMultimedia 5.6 +import QtMultimedia 5.9 /*! \qmltype Video @@ -384,6 +384,34 @@ Item { property alias autoPlay: player.autoPlay /*! + \qmlproperty int Video::notifyInterval + + The interval at which notifiable properties will update. + + The notifiable properties are \l position and \l bufferProgress. + + The interval is expressed in milliseconds, the default value is 1000. + + \since 5.9 + */ + property alias notifyInterval: player.notifyInterval + + /*! + \qmlproperty int Video::loops + + This property holds the number of times the media is played. A value of \c 0 or \c 1 means + the media will be played only once; set to \c MediaPlayer.Infinite to enable infinite looping. + + The value can be changed while the media is playing, in which case it will update + the remaining loops to the new value. + + The default is \c 1. + + \since 5.9 + */ + property alias loops: player.loops + + /*! \qmlsignal Video::paused() This signal is emitted when playback is paused. diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp index b7ab473c7..6a316a298 100644 --- a/src/imports/multimedia/multimedia.cpp +++ b/src/imports/multimedia/multimedia.cpp @@ -85,7 +85,7 @@ class QMultimediaDeclarativeModule : public QQmlExtensionPlugin public: QMultimediaDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) override { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtMultimedia")); @@ -143,11 +143,19 @@ public: // 5.8 types (nothing new, re-register one of the types) qmlRegisterType<QSoundEffect>(uri, 5, 8, "SoundEffect"); + // 5.9 types + qmlRegisterType<QDeclarativeAudio, 2>(uri, 5, 9, "Audio"); + qmlRegisterType<QDeclarativeAudio, 2>(uri, 5, 9, "MediaPlayer"); + qmlRegisterUncreatableType<QDeclarativeCameraCapture, 1>(uri, 5, 9, "CameraCapture", + trUtf8("CameraCapture is provided by Camera")); + qmlRegisterUncreatableType<QDeclarativeCameraFlash, 1>(uri, 5, 9, "CameraFlash", + trUtf8("CameraFlash is provided by Camera")); + qmlRegisterType<QDeclarativeMediaMetaData>(); qmlRegisterType<QAbstractVideoFilter>(); } - void initializeEngine(QQmlEngine *engine, const char *uri) + void initializeEngine(QQmlEngine *engine, const char *uri) override { Q_UNUSED(uri); engine->addImageProvider("camera", new QDeclarativeCameraPreviewProvider); diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp index 5a065072c..fc13323e8 100644 --- a/src/imports/multimedia/qdeclarativeaudio.cpp +++ b/src/imports/multimedia/qdeclarativeaudio.cpp @@ -119,6 +119,7 @@ QDeclarativeAudio::QDeclarativeAudio(QObject *parent) , m_status(QMediaPlayer::NoMedia) , m_error(QMediaPlayer::ServiceMissingError) , m_player(0) + , m_notifyInterval(1000) { } @@ -201,6 +202,34 @@ void QDeclarativeAudio::setAudioRole(QDeclarativeAudio::AudioRole audioRole) } /*! + \qmlproperty int QtMultimedia::Audio::notifyInterval + + The interval at which notifiable properties will update. + + The notifiable properties are \l position and \l bufferProgress. + + The interval is expressed in milliseconds, the default value is 1000. + + \since 5.9 +*/ +int QDeclarativeAudio::notifyInterval() const +{ + return m_complete ? m_player->notifyInterval() : m_notifyInterval; +} + +void QDeclarativeAudio::setNotifyInterval(int value) +{ + if (notifyInterval() == value) + return; + if (m_complete) { + m_player->setNotifyInterval(value); + return; + } + m_notifyInterval = value; + emit notifyIntervalChanged(); +} + +/*! \qmlmethod list<int> QtMultimedia::Audio::supportedAudioRoles() Returns a list of supported audio roles. @@ -400,7 +429,7 @@ qreal QDeclarativeAudio::volume() const void QDeclarativeAudio::setVolume(qreal volume) { if (volume < 0 || volume > 1) { - qmlInfo(this) << tr("volume should be between 0.0 and 1.0"); + qmlWarning(this) << tr("volume should be between 0.0 and 1.0"); return; } @@ -821,6 +850,8 @@ void QDeclarativeAudio::classBegin() this, SIGNAL(hasVideoChanged())); connect(m_player, SIGNAL(audioRoleChanged(QAudio::Role)), this, SIGNAL(audioRoleChanged())); + connect(m_player, SIGNAL(notifyIntervalChanged(int)), + this, SIGNAL(notifyIntervalChanged())); m_error = m_player->availability() == QMultimedia::ServiceMissing ? QMediaPlayer::ServiceMissingError : QMediaPlayer::NoError; @@ -845,6 +876,8 @@ void QDeclarativeAudio::componentComplete() m_player->setPlaybackRate(m_playbackRate); if (m_audioRole != UnknownRole) m_player->setAudioRole(QAudio::Role(m_audioRole)); + if (m_notifyInterval != m_player->notifyInterval()) + m_player->setNotifyInterval(m_notifyInterval); if (!m_content.isNull() && (m_autoLoad || m_autoPlay)) { m_player->setMedia(m_content, 0); @@ -1165,6 +1198,18 @@ void QDeclarativeAudio::_q_mediaChanged(const QMediaContent &media) */ /*! + \qmlproperty int QtMultimedia::MediaPlayer::notifyInterval + + The interval at which notifiable properties will update. + + The notifiable properties are \l position and \l bufferProgress. + + The interval is expressed in milliseconds, the default value is 1000. + + \since 5.9 +*/ + +/*! \qmlmethod QtMultimedia::MediaPlayer::play() Starts playback of the media. diff --git a/src/imports/multimedia/qdeclarativeaudio_p.h b/src/imports/multimedia/qdeclarativeaudio_p.h index 48c8704e9..4e2b94300 100644 --- a/src/imports/multimedia/qdeclarativeaudio_p.h +++ b/src/imports/multimedia/qdeclarativeaudio_p.h @@ -95,6 +95,7 @@ class QDeclarativeAudio : public QObject, public QQmlParserStatus Q_PROPERTY(QObject *mediaObject READ mediaObject NOTIFY mediaObjectChanged SCRIPTABLE false DESIGNABLE false) Q_PROPERTY(Availability availability READ availability NOTIFY availabilityChanged) Q_PROPERTY(AudioRole audioRole READ audioRole WRITE setAudioRole NOTIFY audioRoleChanged REVISION 1) + Q_PROPERTY(int notifyInterval READ notifyInterval WRITE setNotifyInterval NOTIFY notifyIntervalChanged REVISION 2) Q_ENUMS(Status) Q_ENUMS(Error) Q_ENUMS(Loop) @@ -169,8 +170,8 @@ public: PlaybackState playbackState() const; void setPlaybackState(QMediaPlayer::State playbackState); - void classBegin(); - void componentComplete(); + void classBegin() override; + void componentComplete() override; QObject *mediaObject() { return m_player; } @@ -214,6 +215,8 @@ public: bool autoPlay() const; void setAutoPlay(bool autoplay); + int notifyInterval() const; + void setNotifyInterval(int); public Q_SLOTS: void play(); @@ -260,6 +263,7 @@ Q_SIGNALS: void error(QDeclarativeAudio::Error error, const QString &errorString); void mediaObjectChanged(); + Q_REVISION(2) void notifyIntervalChanged(); private Q_SLOTS: void _q_error(QMediaPlayer::Error); @@ -294,6 +298,7 @@ private: QScopedPointer<QDeclarativeMediaMetaData> m_metaData; QMediaPlayer *m_player; + int m_notifyInterval; friend class QDeclarativeMediaBaseAnimation; }; diff --git a/src/imports/multimedia/qdeclarativecamera_p.h b/src/imports/multimedia/qdeclarativecamera_p.h index 964d30117..97afa5b53 100644 --- a/src/imports/multimedia/qdeclarativecamera_p.h +++ b/src/imports/multimedia/qdeclarativecamera_p.h @@ -336,8 +336,8 @@ private Q_SLOTS: void _q_availabilityChanged(QMultimedia::AvailabilityStatus); protected: - void classBegin(); - void componentComplete(); + void classBegin() override; + void componentComplete() override; private: Q_DISABLE_COPY(QDeclarativeCamera) diff --git a/src/imports/multimedia/qdeclarativecameracapture.cpp b/src/imports/multimedia/qdeclarativecameracapture.cpp index 32f3cfc37..22d87ec22 100644 --- a/src/imports/multimedia/qdeclarativecameracapture.cpp +++ b/src/imports/multimedia/qdeclarativecameracapture.cpp @@ -112,6 +112,9 @@ QDeclarativeCameraCapture::QDeclarativeCameraCapture(QCamera *camera, QObject *p connect(m_capture, SIGNAL(error(int,QCameraImageCapture::Error,QString)), this, SLOT(_q_captureFailed(int,QCameraImageCapture::Error,QString))); + connect(m_camera, SIGNAL(statusChanged(QCamera::Status)), + this, SLOT(_q_cameraStatusChanged(QCamera::Status))); + QMediaService *service = camera->service(); m_metadataWriterControl = service ? service->requestControl<QMetaDataWriterControl*>() : 0; } @@ -239,6 +242,15 @@ void QDeclarativeCameraCapture::_q_captureFailed(int id, QCameraImageCapture::Er qWarning() << "QCameraImageCapture error:" << message; emit captureFailed(id, message); } + +void QDeclarativeCameraCapture::_q_cameraStatusChanged(QCamera::Status status) +{ + if (status != QCamera::UnloadedStatus && status != QCamera::LoadedStatus && + status != QCamera::ActiveStatus) + return; + + emit supportedResolutionsChanged(); +} /*! \property QDeclarativeCameraCapture::resolution @@ -251,6 +263,8 @@ void QDeclarativeCameraCapture::_q_captureFailed(int id, QCameraImageCapture::Er This property holds the resolution/size of the image to be captured. If empty, the system chooses the appropriate resolution. + + \sa supportedResolutions */ QSize QDeclarativeCameraCapture::resolution() @@ -289,6 +303,24 @@ QString QDeclarativeCameraCapture::errorString() const } /*! + \qmlproperty list<size> QtMultimedia::CameraCapture::supportedResolutions + + This property holds a list of resolutions which are supported for capturing. + The information can be used to set a valid \e resolution. If the camera isn't + loaded, the list will be empty. + + \since 5.9 + \sa resolution + */ +QVariantList QDeclarativeCameraCapture::supportedResolutions() +{ + QVariantList supportedResolutions; + for (const QSize &res : m_capture->supportedResolutions()) + supportedResolutions.append(QVariant(res)); + return supportedResolutions; +} + +/*! \qmlmethod QtMultimedia::CameraCapture::setMetadata(key, value) diff --git a/src/imports/multimedia/qdeclarativecameracapture_p.h b/src/imports/multimedia/qdeclarativecameracapture_p.h index 06cb1b8f1..1b8066a4e 100644 --- a/src/imports/multimedia/qdeclarativecameracapture_p.h +++ b/src/imports/multimedia/qdeclarativecameracapture_p.h @@ -69,6 +69,7 @@ class QDeclarativeCameraCapture : public QObject Q_PROPERTY(QString capturedImagePath READ capturedImagePath NOTIFY imageSaved) Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY captureFailed) + Q_PROPERTY(QVariantList supportedResolutions READ supportedResolutions NOTIFY supportedResolutionsChanged REVISION 1) public: ~QDeclarativeCameraCapture(); @@ -80,6 +81,7 @@ public: QString capturedImagePath() const; QCameraImageCapture::Error error() const; QString errorString() const; + QVariantList supportedResolutions(); public Q_SLOTS: int capture(); @@ -99,12 +101,14 @@ Q_SIGNALS: void captureFailed(int requestId, const QString &message); void resolutionChanged(const QSize &); + void supportedResolutionsChanged(); private slots: void _q_imageCaptured(int, const QImage&); void _q_imageSaved(int, const QString&); void _q_imageMetadataAvailable(int, const QString &, const QVariant &); void _q_captureFailed(int, QCameraImageCapture::Error, const QString&); + void _q_cameraStatusChanged(QCamera::Status status); private: friend class QDeclarativeCamera; diff --git a/src/imports/multimedia/qdeclarativecameraflash.cpp b/src/imports/multimedia/qdeclarativecameraflash.cpp index f8adc5e71..551b88aef 100644 --- a/src/imports/multimedia/qdeclarativecameraflash.cpp +++ b/src/imports/multimedia/qdeclarativecameraflash.cpp @@ -73,11 +73,13 @@ QT_BEGIN_NAMESPACE /*! Construct a declarative camera flash object using \a parent object. */ -QDeclarativeCameraFlash::QDeclarativeCameraFlash(QCamera *camera, QObject *parent) : - QObject(parent) +QDeclarativeCameraFlash::QDeclarativeCameraFlash(QCamera *camera, QObject *parent) + : QObject(parent) { m_exposure = camera->exposure(); connect(m_exposure, SIGNAL(flashReady(bool)), this, SIGNAL(flashReady(bool))); + connect(camera, SIGNAL(statusChanged(QCamera::Status)), + this, SLOT(_q_cameraStatusChanged(QCamera::Status))); } QDeclarativeCameraFlash::~QDeclarativeCameraFlash() @@ -133,6 +135,51 @@ void QDeclarativeCameraFlash::setFlashMode(QDeclarativeCameraFlash::FlashMode mo } } +void QDeclarativeCameraFlash::_q_cameraStatusChanged(QCamera::Status status) +{ + if (status != QCamera::UnloadedStatus && status != QCamera::LoadedStatus && + status != QCamera::ActiveStatus) + return; + + emit supportedModesChanged(); +} + +/*! + \qmlproperty list<FlashMode> QtMultimedia::CameraFlash::supportedModes + + This property holds the supported flash modes of the camera. If the list + only contains Camera.FlashOff, no flash is supported. + + \code + Camera { + id: camera + flash { + onSupportedModesChanged { + if (flash.supportedModes.length == 1) { + // no flash supported + } else { + // some flash is supported + } + } + } + } + \endcode + + \since 5.9 + \sa mode + */ +QVariantList QDeclarativeCameraFlash::supportedModes() const +{ + QVariantList supportedModes; + + for (int i=1; i <= (int) QCameraExposure::FlashManual; i = (i << 1)) { + if (m_exposure->isFlashModeSupported((QCameraExposure::FlashMode) i)) + supportedModes.append(QVariant(i)); + } + + return supportedModes; +} + /*! \qmlsignal QtMultimedia::CameraFlash::flashModeChanged(int) This signal is emitted when the \c flashMode property is changed. diff --git a/src/imports/multimedia/qdeclarativecameraflash_p.h b/src/imports/multimedia/qdeclarativecameraflash_p.h index 9247c7202..df037c4d6 100644 --- a/src/imports/multimedia/qdeclarativecameraflash_p.h +++ b/src/imports/multimedia/qdeclarativecameraflash_p.h @@ -63,6 +63,7 @@ class QDeclarativeCameraFlash : public QObject Q_OBJECT Q_PROPERTY(bool ready READ isFlashReady NOTIFY flashReady) Q_PROPERTY(FlashMode mode READ flashMode WRITE setFlashMode NOTIFY flashModeChanged) + Q_PROPERTY(QVariantList supportedModes READ supportedModes NOTIFY supportedModesChanged REVISION 1) Q_ENUMS(FlashMode) public: @@ -83,6 +84,7 @@ public: FlashMode flashMode() const; bool isFlashReady() const; + QVariantList supportedModes() const; public Q_SLOTS: void setFlashMode(FlashMode); @@ -90,6 +92,10 @@ public Q_SLOTS: Q_SIGNALS: void flashReady(bool status); void flashModeChanged(FlashMode); + void supportedModesChanged(); + +private slots: + void _q_cameraStatusChanged(QCamera::Status status); private: friend class QDeclarativeCamera; diff --git a/src/imports/multimedia/qdeclarativecamerafocus_p.h b/src/imports/multimedia/qdeclarativecamerafocus_p.h index 707102bff..16a48de53 100644 --- a/src/imports/multimedia/qdeclarativecamerafocus_p.h +++ b/src/imports/multimedia/qdeclarativecamerafocus_p.h @@ -131,8 +131,8 @@ public: FocusZonesModel(QObject *parent = 0); - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; public slots: void setFocusZones(const QCameraFocusZoneList &zones); diff --git a/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h b/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h index b9ac29b1e..cf5f0644c 100644 --- a/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h +++ b/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h @@ -61,7 +61,7 @@ public: QDeclarativeCameraPreviewProvider(); ~QDeclarativeCameraPreviewProvider(); - virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize); + QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) override; static void registerPreview(const QString &id, const QImage &preview); }; diff --git a/src/imports/multimedia/qdeclarativeplaylist_p.h b/src/imports/multimedia/qdeclarativeplaylist_p.h index 22c853605..fa221a05b 100644 --- a/src/imports/multimedia/qdeclarativeplaylist_p.h +++ b/src/imports/multimedia/qdeclarativeplaylist_p.h @@ -126,12 +126,12 @@ public: QString errorString() const; QMediaPlaylist *mediaPlaylist() const { return m_playlist; } - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - QHash<int, QByteArray> roleNames() const; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash<int, QByteArray> roleNames() const override; - void classBegin(); - void componentComplete(); + void classBegin() override; + void componentComplete() override; QQmlListProperty<QDeclarativePlaylistItem> items() { return QQmlListProperty<QDeclarativePlaylistItem>( diff --git a/src/multimedia/audio/qaudiobuffer.cpp b/src/multimedia/audio/qaudiobuffer.cpp index 3768fd196..e4918edf2 100644 --- a/src/multimedia/audio/qaudiobuffer.cpp +++ b/src/multimedia/audio/qaudiobuffer.cpp @@ -140,15 +140,15 @@ public: free(mBuffer); } - void release() {delete this;} - QAudioFormat format() const {return mFormat;} - qint64 startTime() const {return mStartTime;} - int frameCount() const {return mFrameCount;} + void release() override {delete this;} + QAudioFormat format() const override {return mFormat;} + qint64 startTime() const override {return mStartTime;} + int frameCount() const override {return mFrameCount;} - void *constData() const {return mBuffer;} + void *constData() const override {return mBuffer;} - void *writableData() {return mBuffer;} - QAbstractAudioBuffer *clone() const + void *writableData() override {return mBuffer;} + QAbstractAudioBuffer *clone() const override { return new QMemoryAudioBufferProvider(mBuffer, mFrameCount, mFormat, mStartTime); } diff --git a/src/multimedia/audio/qaudiodecoder.h b/src/multimedia/audio/qaudiodecoder.h index a63a6836f..85e0b75f7 100644 --- a/src/multimedia/audio/qaudiodecoder.h +++ b/src/multimedia/audio/qaudiodecoder.h @@ -120,8 +120,8 @@ Q_SIGNALS: void durationChanged(qint64 duration); public: - virtual bool bind(QObject *); - virtual void unbind(QObject *); + bool bind(QObject *) override; + void unbind(QObject *) override; private: Q_DISABLE_COPY(QAudioDecoder) diff --git a/src/multimedia/audio/qaudiodevicefactory.cpp b/src/multimedia/audio/qaudiodevicefactory.cpp index c3e4929b3..b1788f28a 100644 --- a/src/multimedia/audio/qaudiodevicefactory.cpp +++ b/src/multimedia/audio/qaudiodevicefactory.cpp @@ -61,64 +61,64 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, audioLoader, class QNullDeviceInfo : public QAbstractAudioDeviceInfo { public: - QAudioFormat preferredFormat() const { qWarning()<<"using null deviceinfo, none available"; return QAudioFormat(); } - bool isFormatSupported(const QAudioFormat& ) const { return false; } + QAudioFormat preferredFormat() const override { qWarning()<<"using null deviceinfo, none available"; return QAudioFormat(); } + bool isFormatSupported(const QAudioFormat& ) const override { return false; } QAudioFormat nearestFormat(const QAudioFormat& ) const { return QAudioFormat(); } - QString deviceName() const { return QString(); } - QStringList supportedCodecs() { return QStringList(); } - QList<int> supportedSampleRates() { return QList<int>(); } - QList<int> supportedChannelCounts() { return QList<int>(); } - QList<int> supportedSampleSizes() { return QList<int>(); } - QList<QAudioFormat::Endian> supportedByteOrders() { return QList<QAudioFormat::Endian>(); } - QList<QAudioFormat::SampleType> supportedSampleTypes() { return QList<QAudioFormat::SampleType>(); } + QString deviceName() const override { return QString(); } + QStringList supportedCodecs() override { return QStringList(); } + QList<int> supportedSampleRates() override { return QList<int>(); } + QList<int> supportedChannelCounts() override { return QList<int>(); } + QList<int> supportedSampleSizes() override { return QList<int>(); } + QList<QAudioFormat::Endian> supportedByteOrders() override { return QList<QAudioFormat::Endian>(); } + QList<QAudioFormat::SampleType> supportedSampleTypes() override { return QList<QAudioFormat::SampleType>(); } }; class QNullInputDevice : public QAbstractAudioInput { public: - void start(QIODevice*) { qWarning()<<"using null input device, none available";} - QIODevice* start() { qWarning()<<"using null input device, none available"; return 0; } - void stop() {} - void reset() {} - void suspend() {} - void resume() {} - int bytesReady() const { return 0; } - int periodSize() const { return 0; } - void setBufferSize(int ) {} - int bufferSize() const { return 0; } - void setNotifyInterval(int ) {} - int notifyInterval() const { return 0; } - qint64 processedUSecs() const { return 0; } - qint64 elapsedUSecs() const { return 0; } - QAudio::Error error() const { return QAudio::OpenError; } - QAudio::State state() const { return QAudio::StoppedState; } - void setFormat(const QAudioFormat&) {} - QAudioFormat format() const { return QAudioFormat(); } - void setVolume(qreal) {} - qreal volume() const {return 1.0f;} + void start(QIODevice*) override { qWarning()<<"using null input device, none available";} + QIODevice* start() override { qWarning()<<"using null input device, none available"; return 0; } + void stop() override {} + void reset() override {} + void suspend() override {} + void resume() override {} + int bytesReady() const override { return 0; } + int periodSize() const override { return 0; } + void setBufferSize(int ) override {} + int bufferSize() const override { return 0; } + void setNotifyInterval(int ) override {} + int notifyInterval() const override { return 0; } + qint64 processedUSecs() const override { return 0; } + qint64 elapsedUSecs() const override { return 0; } + QAudio::Error error() const override { return QAudio::OpenError; } + QAudio::State state() const override { return QAudio::StoppedState; } + void setFormat(const QAudioFormat&) override {} + QAudioFormat format() const override { return QAudioFormat(); } + void setVolume(qreal) override {} + qreal volume() const override {return 1.0f;} }; class QNullOutputDevice : public QAbstractAudioOutput { public: - void start(QIODevice*) {qWarning()<<"using null output device, none available";} - QIODevice* start() { qWarning()<<"using null output device, none available"; return 0; } - void stop() {} - void reset() {} - void suspend() {} - void resume() {} - int bytesFree() const { return 0; } - int periodSize() const { return 0; } - void setBufferSize(int ) {} - int bufferSize() const { return 0; } - void setNotifyInterval(int ) {} - int notifyInterval() const { return 0; } - qint64 processedUSecs() const { return 0; } - qint64 elapsedUSecs() const { return 0; } - QAudio::Error error() const { return QAudio::OpenError; } - QAudio::State state() const { return QAudio::StoppedState; } - void setFormat(const QAudioFormat&) {} - QAudioFormat format() const { return QAudioFormat(); } + void start(QIODevice*) override {qWarning()<<"using null output device, none available";} + QIODevice* start() override { qWarning()<<"using null output device, none available"; return 0; } + void stop() override {} + void reset() override {} + void suspend() override {} + void resume() override {} + int bytesFree() const override { return 0; } + int periodSize() const override { return 0; } + void setBufferSize(int ) override {} + int bufferSize() const override { return 0; } + void setNotifyInterval(int ) override {} + int notifyInterval() const override { return 0; } + qint64 processedUSecs() const override { return 0; } + qint64 elapsedUSecs() const override { return 0; } + QAudio::Error error() const override { return QAudio::OpenError; } + QAudio::State state() const override { return QAudio::StoppedState; } + void setFormat(const QAudioFormat&) override {} + QAudioFormat format() const override { return QAudioFormat(); } }; QList<QAudioDeviceInfo> QAudioDeviceFactory::availableDevices(QAudio::Mode mode) diff --git a/src/multimedia/audio/qaudiosystem.cpp b/src/multimedia/audio/qaudiosystem.cpp index 549b06373..b11993e55 100644 --- a/src/multimedia/audio/qaudiosystem.cpp +++ b/src/multimedia/audio/qaudiosystem.cpp @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE \ingroup multimedia \ingroup multimedia_audio \inmodule QtMultimedia - \internal This class implements the audio functionality for QAudioDeviceInfo, i.e., QAudioDeviceInfo keeps a @@ -112,7 +111,6 @@ QT_BEGIN_NAMESPACE \ingroup multimedia \inmodule QtMultimedia - \internal QAbstractAudioOutput implements audio functionality for QAudioOutput, i.e., QAudioOutput routes function calls to @@ -252,7 +250,6 @@ QT_BEGIN_NAMESPACE \ingroup multimedia \inmodule QtMultimedia - \internal QAudioDeviceInput keeps an instance of QAbstractAudioInput and routes calls to functions of the same name to QAbstractAudioInput. diff --git a/src/multimedia/audio/qaudiosystemplugin.cpp b/src/multimedia/audio/qaudiosystemplugin.cpp index 636b614d4..6a255cf11 100644 --- a/src/multimedia/audio/qaudiosystemplugin.cpp +++ b/src/multimedia/audio/qaudiosystemplugin.cpp @@ -58,7 +58,6 @@ QAudioSystemPluginExtension::~QAudioSystemPluginExtension() \ingroup multimedia \ingroup multimedia_audio \inmodule QtMultimedia - \internal Writing a audio plugin is achieved by subclassing this base class, reimplementing the pure virtual functions availableDevices(), diff --git a/src/multimedia/audio/qaudiosystemplugin.h b/src/multimedia/audio/qaudiosystemplugin.h index 3368c9b98..e304f1c46 100644 --- a/src/multimedia/audio/qaudiosystemplugin.h +++ b/src/multimedia/audio/qaudiosystemplugin.h @@ -81,10 +81,10 @@ public: explicit QAudioSystemPlugin(QObject *parent = Q_NULLPTR); ~QAudioSystemPlugin(); - virtual QList<QByteArray> availableDevices(QAudio::Mode) const = 0; - virtual QAbstractAudioInput* createInput(const QByteArray& device) = 0; - virtual QAbstractAudioOutput* createOutput(const QByteArray& device) = 0; - virtual QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) = 0; + QList<QByteArray> availableDevices(QAudio::Mode) const override = 0; + QAbstractAudioInput* createInput(const QByteArray& device) override = 0; + QAbstractAudioOutput* createOutput(const QByteArray& device) override = 0; + QAbstractAudioDeviceInfo* createDeviceInfo(const QByteArray& device, QAudio::Mode mode) override = 0; }; QT_END_NAMESPACE diff --git a/src/multimedia/audio/qsoundeffect_qaudio_p.h b/src/multimedia/audio/qsoundeffect_qaudio_p.h index d8c416fdb..6fc3ae8d5 100644 --- a/src/multimedia/audio/qsoundeffect_qaudio_p.h +++ b/src/multimedia/audio/qsoundeffect_qaudio_p.h @@ -69,8 +69,8 @@ public: PrivateSoundSource(QSoundEffectPrivate* s); ~PrivateSoundSource() {} - qint64 readData( char* data, qint64 len); - qint64 writeData(const char* data, qint64 len); + qint64 readData( char* data, qint64 len) override; + qint64 writeData(const char* data, qint64 len) override; private Q_SLOTS: void sampleReady(); diff --git a/src/multimedia/audio/qwavedecoder_p.h b/src/multimedia/audio/qwavedecoder_p.h index 1cd20e07f..0f1cef599 100644 --- a/src/multimedia/audio/qwavedecoder_p.h +++ b/src/multimedia/audio/qwavedecoder_p.h @@ -70,9 +70,9 @@ public: QAudioFormat audioFormat() const; int duration() const; - qint64 size() const; - bool isSequential() const; - qint64 bytesAvailable() const; + qint64 size() const override; + bool isSequential() const override; + qint64 bytesAvailable() const override; Q_SIGNALS: void formatKnown(); @@ -82,8 +82,8 @@ private Q_SLOTS: void handleData(); private: - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); + qint64 readData(char *data, qint64 maxlen) override; + qint64 writeData(const char *data, qint64 len) override; bool enoughDataAvailable(); bool findChunk(const char *chunkId); diff --git a/src/multimedia/camera/qcamera.h b/src/multimedia/camera/qcamera.h index 180760728..685298905 100644 --- a/src/multimedia/camera/qcamera.h +++ b/src/multimedia/camera/qcamera.h @@ -176,7 +176,7 @@ public: QT_DEPRECATED static QString deviceDescription(const QByteArray &device); #endif - QMultimedia::AvailabilityStatus availability() const; + QMultimedia::AvailabilityStatus availability() const override; State state() const; Status status() const; diff --git a/src/multimedia/camera/qcamerafocus.cpp b/src/multimedia/camera/qcamerafocus.cpp index 9da48e257..848b33df8 100644 --- a/src/multimedia/camera/qcamerafocus.cpp +++ b/src/multimedia/camera/qcamerafocus.cpp @@ -68,15 +68,15 @@ public: QCameraFocusFakeZoomControl(QObject *parent) : QCameraZoomControl(parent) {} - qreal maximumOpticalZoom() const { return 1.0; } - qreal maximumDigitalZoom() const { return 1.0; } + qreal maximumOpticalZoom() const override { return 1.0; } + qreal maximumDigitalZoom() const override { return 1.0; } - qreal requestedOpticalZoom() const { return 1.0; } - qreal requestedDigitalZoom() const { return 1.0; } - qreal currentOpticalZoom() const { return 1.0; } - qreal currentDigitalZoom() const { return 1.0; } + qreal requestedOpticalZoom() const override { return 1.0; } + qreal requestedDigitalZoom() const override { return 1.0; } + qreal currentOpticalZoom() const override { return 1.0; } + qreal currentDigitalZoom() const override { return 1.0; } - void zoomTo(qreal, qreal) { qWarning("The camera doesn't support zooming."); } + void zoomTo(qreal, qreal) override { qWarning("The camera doesn't support zooming."); } }; class QCameraFocusFakeFocusControl : public QCameraFocusControl @@ -85,17 +85,17 @@ public: QCameraFocusFakeFocusControl(QObject *parent) : QCameraFocusControl(parent) {} - QCameraFocus::FocusModes focusMode() const { return QCameraFocus::AutoFocus; } - void setFocusMode(QCameraFocus::FocusModes) { qWarning("Focus mode selection is not supported"); } - bool isFocusModeSupported(QCameraFocus::FocusModes) const { return false; } + QCameraFocus::FocusModes focusMode() const override { return QCameraFocus::AutoFocus; } + void setFocusMode(QCameraFocus::FocusModes) override { qWarning("Focus mode selection is not supported"); } + bool isFocusModeSupported(QCameraFocus::FocusModes) const override { return false; } - QCameraFocus::FocusPointMode focusPointMode() const { return QCameraFocus::FocusPointAuto; } - void setFocusPointMode(QCameraFocus::FocusPointMode) { qWarning("Focus points mode selection is not supported"); } - bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const { return false; } - QPointF customFocusPoint() const { return QPointF(0.5,0.5); } - void setCustomFocusPoint(const QPointF &) { qWarning("Focus points selection is not supported"); } + QCameraFocus::FocusPointMode focusPointMode() const override { return QCameraFocus::FocusPointAuto; } + void setFocusPointMode(QCameraFocus::FocusPointMode) override { qWarning("Focus points mode selection is not supported"); } + bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const override { return false; } + QPointF customFocusPoint() const override { return QPointF(0.5,0.5); } + void setCustomFocusPoint(const QPointF &) override { qWarning("Focus points selection is not supported"); } - QCameraFocusZoneList focusZones() const { return QCameraFocusZoneList(); } + QCameraFocusZoneList focusZones() const override { return QCameraFocusZoneList(); } }; diff --git a/src/multimedia/camera/qcameraimagecapture.h b/src/multimedia/camera/qcameraimagecapture.h index 3f3c6bd26..12feb9eec 100644 --- a/src/multimedia/camera/qcameraimagecapture.h +++ b/src/multimedia/camera/qcameraimagecapture.h @@ -93,7 +93,7 @@ public: bool isAvailable() const; QMultimedia::AvailabilityStatus availability() const; - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; Error error() const; QString errorString() const; @@ -135,7 +135,7 @@ Q_SIGNALS: void imageSaved(int id, const QString &fileName); protected: - bool setMediaObject(QMediaObject *); + bool setMediaObject(QMediaObject *) override; QCameraImageCapturePrivate *d_ptr; private: diff --git a/src/multimedia/camera/qcameraimageprocessing.cpp b/src/multimedia/camera/qcameraimageprocessing.cpp index 431e3202d..91ba1d566 100644 --- a/src/multimedia/camera/qcameraimageprocessing.cpp +++ b/src/multimedia/camera/qcameraimageprocessing.cpp @@ -101,10 +101,10 @@ public: QCameraImageProcessingControl(parent) {} - bool isParameterSupported(ProcessingParameter) const { return false; } - bool isParameterValueSupported(ProcessingParameter, const QVariant &) const { return false; } - QVariant parameter(ProcessingParameter) const { return QVariant(); } - void setParameter(ProcessingParameter, const QVariant &) {} + bool isParameterSupported(ProcessingParameter) const override { return false; } + bool isParameterValueSupported(ProcessingParameter, const QVariant &) const override { return false; } + QVariant parameter(ProcessingParameter) const override { return QVariant(); } + void setParameter(ProcessingParameter, const QVariant &) override {} }; diff --git a/src/multimedia/configure.json b/src/multimedia/configure.json index e7758f0c8..4f0532ad4 100644 --- a/src/multimedia/configure.json +++ b/src/multimedia/configure.json @@ -179,7 +179,7 @@ "features": { "alsa": { "label": "ALSA", - "condition": "config.unix && libs.alsa", + "condition": "config.unix && !config.qnx && libs.alsa", "output": [ "feature", "privateFeature" ] }, "avfoundation": { @@ -225,20 +225,17 @@ }, "gstreamer_app": { "label": "GStreamer App", - "condition": "(features.gstreamer_1_0 && libs.gstreamer_app_1_0) - || (features.gstreamer_0_10 && libs.gstreamer_app_0_10)", + "condition": "(features.gstreamer_1_0 && libs.gstreamer_app_1_0) || (features.gstreamer_0_10 && libs.gstreamer_app_0_10)", "output": [ "privateFeature" ] }, "gstreamer_encodingprofiles": { "label": "GStreamer encoding-profile.h", - "condition": "(features.gstreamer_1_0 && tests.gstreamer_encodingprofiles_1_0) - || (features.gstreamer_0_10 && tests.gstreamer_encodingprofiles_0_10)", + "condition": "(features.gstreamer_1_0 && tests.gstreamer_encodingprofiles_1_0) || (features.gstreamer_0_10 && tests.gstreamer_encodingprofiles_0_10)", "output": [ "privateFeature" ] }, "gstreamer_photography": { "label": "GStreamer Photography", - "condition": "(features.gstreamer_1_0 && libs.gstreamer_photography_1_0) - || (features.gstreamer_0_10 && libs.gstreamer_photography_0_10)", + "condition": "(features.gstreamer_1_0 && libs.gstreamer_photography_1_0) || (features.gstreamer_0_10 && libs.gstreamer_photography_0_10)", "output": [ "privateFeature" ] }, "gpu_vivante": { @@ -275,7 +272,6 @@ }, "wasapi": { "label": "Windows Audio Services", - "autoDetect": "false", "condition": "config.win32 && tests.wasapi", "output": [ "privateFeature" ] }, @@ -319,6 +315,7 @@ "resourcepolicy", "mmrenderer", "avfoundation", + "wasapi", "directshow", "wmf", { diff --git a/src/multimedia/doc/src/platform-notes-ios.qdoc b/src/multimedia/doc/src/platform-notes-ios.qdoc new file mode 100644 index 000000000..81e9ea0c5 --- /dev/null +++ b/src/multimedia/doc/src/platform-notes-ios.qdoc @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\page qtmultimedia-ios.html +\title Qt Multimedia on iOS +\brief Platform notes for iOS + +This page covers the availability of Qt Multimedia features on iOS. + +\section1 Limitations + +Since Qt Multimedia for iOS uses the camera, the \c Info.plist assigned to +QMAKE_INFO_PLIST in the project file must contain the key +\c NSCameraUsageDescription. Otherwise the application will +abort on startup. See Info.plist documentation from Apple for more information +regarding this key. + +*/ diff --git a/src/multimedia/doc/src/qtmultimedia-index.qdoc b/src/multimedia/doc/src/qtmultimedia-index.qdoc index 553732fd1..dfc9c3f15 100644 --- a/src/multimedia/doc/src/qtmultimedia-index.qdoc +++ b/src/multimedia/doc/src/qtmultimedia-index.qdoc @@ -158,6 +158,7 @@ \list \li \l{Qt Multimedia on Windows}{Windows} + \li \l{Qt Multimedia on iOS}{iOS} \endlist \section2 Reference diff --git a/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h b/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h index 768f9c30d..e03da1ab5 100644 --- a/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h +++ b/src/multimedia/gsttools_headers/qgstbufferpoolinterface_p.h @@ -96,11 +96,11 @@ public: explicit QGstBufferPoolPlugin(QObject *parent = 0); virtual ~QGstBufferPoolPlugin() {} - virtual bool isFormatSupported(const QVideoSurfaceFormat &format) const = 0; - virtual GstBuffer *takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps) = 0; - virtual void clear() = 0; + bool isFormatSupported(const QVideoSurfaceFormat &format) const override = 0; + GstBuffer *takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps) override = 0; + void clear() override = 0; - virtual QAbstractVideoBuffer::HandleType handleType() const = 0; + QAbstractVideoBuffer::HandleType handleType() const override = 0; /*! Build an QAbstractVideoBuffer instance from compatible GstBuffer. @@ -108,7 +108,7 @@ public: This method is called from gstreamer video sink thread. */ - virtual QAbstractVideoBuffer *prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine) = 0; + QAbstractVideoBuffer *prepareVideoBuffer(GstBuffer *buffer, int bytesPerLine) override = 0; }; QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h b/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h index 64e9ac21f..af1a4486f 100644 --- a/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h +++ b/src/multimedia/gsttools_headers/qgstcodecsinfo_p.h @@ -63,22 +63,28 @@ class QGstCodecsInfo public: enum ElementType { AudioEncoder, VideoEncoder, Muxer }; + struct CodecInfo { + QString description; + QByteArray elementName; + GstRank rank; + }; + QGstCodecsInfo(ElementType elementType); QStringList supportedCodecs() const; QString codecDescription(const QString &codec) const; - -#if GST_CHECK_VERSION(0,10,31) - static GstCaps* supportedElementCaps(GstElementFactoryListType elementType, - GstRank minimumRank = GST_RANK_MARGINAL, - GstPadDirection padDirection = GST_PAD_SRC); -#endif + QByteArray codecElement(const QString &codec) const; + QStringList codecOptions(const QString &codec) const; private: + void updateCodecs(ElementType elementType); + GList *elementFactories(ElementType elementType) const; + QStringList m_codecs; - QMap<QString,QString> m_codecDescriptions; + QMap<QString, CodecInfo> m_codecInfo; }; +Q_DECLARE_TYPEINFO(QGstCodecsInfo::CodecInfo, Q_MOVABLE_TYPE); QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h b/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h index 9c5ce3052..1a961c6d9 100644 --- a/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h +++ b/src/multimedia/gsttools_headers/qgstreameraudioinputselector_p.h @@ -63,13 +63,13 @@ public: QGstreamerAudioInputSelector(QObject *parent); ~QGstreamerAudioInputSelector(); - QList<QString> availableInputs() const; - QString inputDescription(const QString& name) const; - QString defaultInput() const; - QString activeInput() const; + QList<QString> availableInputs() const override; + QString inputDescription(const QString &name) const override; + QString defaultInput() const override; + QString activeInput() const override; public Q_SLOTS: - void setActiveInput(const QString& name); + void setActiveInput(const QString &name) override; private: void update(); diff --git a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h index d3062c5ad..bacf8c71d 100644 --- a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h @@ -72,8 +72,8 @@ public: virtual ~QGstreamerAudioProbeControl(); protected: - void probeCaps(GstCaps *caps); - bool probeBuffer(GstBuffer *buffer); + void probeCaps(GstCaps *caps) override; + bool probeBuffer(GstBuffer *buffer) override; private slots: void bufferProbed(); diff --git a/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h index bc3d6703e..e1ac453c7 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h @@ -67,19 +67,19 @@ public: QGstreamerVideoInputDeviceControl(GstElementFactory *factory, QObject *parent); ~QGstreamerVideoInputDeviceControl(); - int deviceCount() const; + int deviceCount() const override; - QString deviceName(int index) const; - QString deviceDescription(int index) const; + QString deviceName(int index) const override; + QString deviceDescription(int index) const override; - int defaultDevice() const; - int selectedDevice() const; + int defaultDevice() const override; + int selectedDevice() const override; static QString primaryCamera() { return tr("Main camera"); } static QString secondaryCamera() { return tr("Front camera"); } public Q_SLOTS: - void setSelectedDevice(int index); + void setSelectedDevice(int index) override; private: GstElementFactory *m_factory; diff --git a/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h b/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h index bed411475..f3066fad8 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideooverlay_p.h @@ -94,8 +94,8 @@ public: int saturation() const; void setSaturation(int saturation); - bool processSyncMessage(const QGstreamerMessage &message); - bool processBusMessage(const QGstreamerMessage &message); + bool processSyncMessage(const QGstreamerMessage &message) override; + bool processBusMessage(const QGstreamerMessage &message) override; Q_SIGNALS: void nativeVideoSizeChanged(); @@ -109,7 +109,7 @@ private: GstElement *findBestVideoSink() const; void setWindowHandle_helper(WId id); void updateIsActive(); - void probeCaps(GstCaps *caps); + void probeCaps(GstCaps *caps) override; static void showPrerollFrameChanged(GObject *, GParamSpec *, QGstreamerVideoOverlay *); GstElement *m_videoSink; diff --git a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h index 7520b7424..b599b0e78 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h @@ -72,8 +72,8 @@ public: explicit QGstreamerVideoProbeControl(QObject *parent); virtual ~QGstreamerVideoProbeControl(); - void probeCaps(GstCaps *caps); - bool probeBuffer(GstBuffer *buffer); + void probeCaps(GstCaps *caps) override; + bool probeBuffer(GstBuffer *buffer) override; void startFlushing(); void stopFlushing(); diff --git a/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h b/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h index 6dba54fe4..1d22e1125 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideorenderer_p.h @@ -67,13 +67,13 @@ public: QGstreamerVideoRenderer(QObject *parent = 0); virtual ~QGstreamerVideoRenderer(); - QAbstractVideoSurface *surface() const; - void setSurface(QAbstractVideoSurface *surface); + QAbstractVideoSurface *surface() const override; + void setSurface(QAbstractVideoSurface *surface) override; - GstElement *videoSink(); + GstElement *videoSink() override; - void stopRenderer(); - bool isReady() const { return m_surface != 0; } + void stopRenderer() override; + bool isReady() const override { return m_surface != 0; } signals: void sinkChanged(); diff --git a/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h b/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h index f0a76c152..b2dfece60 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowidget_p.h @@ -73,31 +73,31 @@ public: explicit QGstreamerVideoWidgetControl(QObject *parent = 0, const QByteArray &elementName = QByteArray()); virtual ~QGstreamerVideoWidgetControl(); - GstElement *videoSink(); + GstElement *videoSink() override; - QWidget *videoWidget(); + QWidget *videoWidget() override; - void stopRenderer(); + void stopRenderer() override; - Qt::AspectRatioMode aspectRatioMode() const; - void setAspectRatioMode(Qt::AspectRatioMode mode); + Qt::AspectRatioMode aspectRatioMode() const override; + void setAspectRatioMode(Qt::AspectRatioMode mode) override; - bool isFullScreen() const; - void setFullScreen(bool fullScreen); + bool isFullScreen() const override; + void setFullScreen(bool fullScreen) override; - int brightness() const; - void setBrightness(int brightness); + int brightness() const override; + void setBrightness(int brightness) override; - int contrast() const; - void setContrast(int contrast); + int contrast() const override; + void setContrast(int contrast) override; - int hue() const; - void setHue(int hue); + int hue() const override; + void setHue(int hue) override; - int saturation() const; - void setSaturation(int saturation); + int saturation() const override; + void setSaturation(int saturation) override; - bool eventFilter(QObject *object, QEvent *event); + bool eventFilter(QObject *object, QEvent *event) override; signals: void sinkChanged(); @@ -111,8 +111,8 @@ private: void createVideoWidget(); void updateWidgetAttributes(); - bool processSyncMessage(const QGstreamerMessage &message); - bool processBusMessage(const QGstreamerMessage &message); + bool processSyncMessage(const QGstreamerMessage &message) override; + bool processBusMessage(const QGstreamerMessage &message) override; QGstreamerVideoOverlay m_videoOverlay; QGstreamerVideoWidget *m_widget; diff --git a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h index 949a18773..b489650f9 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h @@ -73,41 +73,41 @@ public: explicit QGstreamerVideoWindow(QObject *parent = 0, const QByteArray &elementName = QByteArray()); ~QGstreamerVideoWindow(); - WId winId() const; - void setWinId(WId id); + WId winId() const override; + void setWinId(WId id) override; - QRect displayRect() const; - void setDisplayRect(const QRect &rect); + QRect displayRect() const override; + void setDisplayRect(const QRect &rect) override; - bool isFullScreen() const; - void setFullScreen(bool fullScreen); + bool isFullScreen() const override; + void setFullScreen(bool fullScreen) override; - QSize nativeSize() const; + QSize nativeSize() const override; - Qt::AspectRatioMode aspectRatioMode() const; - void setAspectRatioMode(Qt::AspectRatioMode mode); + Qt::AspectRatioMode aspectRatioMode() const override; + void setAspectRatioMode(Qt::AspectRatioMode mode) override; - void repaint(); + void repaint() override; - int brightness() const; - void setBrightness(int brightness); + int brightness() const override; + void setBrightness(int brightness) override; - int contrast() const; - void setContrast(int contrast); + int contrast() const override; + void setContrast(int contrast) override; - int hue() const; - void setHue(int hue); + int hue() const override; + void setHue(int hue) override; - int saturation() const; - void setSaturation(int saturation); + int saturation() const override; + void setSaturation(int saturation) override; QAbstractVideoSurface *surface() const; - GstElement *videoSink(); + GstElement *videoSink() override; - bool processSyncMessage(const QGstreamerMessage &message); - bool processBusMessage(const QGstreamerMessage &message); - bool isReady() const { return m_windowId != 0; } + bool processSyncMessage(const QGstreamerMessage &message) override; + bool processBusMessage(const QGstreamerMessage &message) override; + bool isReady() const override { return m_windowId != 0; } signals: void sinkChanged(); diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index 68c9ecda1..8b7de3661 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -146,6 +146,7 @@ namespace QGstUtils { QSize structurePixelAspectRatio(const GstStructure *s); QPair<qreal, qreal> structureFrameRateRange(const GstStructure *s); + QString fileExtensionForMimeType(const QString &mimeType); } void qt_gst_object_ref_sink(gpointer object); diff --git a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h index 92128b92e..d2802d9a2 100644 --- a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h +++ b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h @@ -77,17 +77,17 @@ public: ~QGstVideoBuffer(); - MapMode mapMode() const; + MapMode mapMode() const override; #if GST_CHECK_VERSION(1,0,0) - int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]); + int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) override; #else - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; #endif - void unmap(); + void unmap() override; - QVariant handle() const { return m_handle; } + QVariant handle() const override { return m_handle; } private: #if GST_CHECK_VERSION(1,0,0) GstVideoInfo m_videoInfo; diff --git a/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h b/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h index 433cdf8e5..6a0c4c6bd 100644 --- a/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h +++ b/src/multimedia/gsttools_headers/qgstvideorendererplugin_p.h @@ -100,7 +100,7 @@ public: explicit QGstVideoRendererPlugin(QObject *parent = 0); virtual ~QGstVideoRendererPlugin() {} - virtual QGstVideoRenderer *createRenderer() = 0; + QGstVideoRenderer *createRenderer() override = 0; }; diff --git a/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h b/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h index ff59810bc..3971c959d 100644 --- a/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h +++ b/src/multimedia/gsttools_headers/qgstvideorenderersink_p.h @@ -76,14 +76,14 @@ public: QGstDefaultVideoRenderer(); ~QGstDefaultVideoRenderer(); - GstCaps *getCaps(QAbstractVideoSurface *surface); - bool start(QAbstractVideoSurface *surface, GstCaps *caps); - void stop(QAbstractVideoSurface *surface); + GstCaps *getCaps(QAbstractVideoSurface *surface) override; + bool start(QAbstractVideoSurface *surface, GstCaps *caps) override; + void stop(QAbstractVideoSurface *surface) override; - bool proposeAllocation(GstQuery *query); + bool proposeAllocation(GstQuery *query) override; - bool present(QAbstractVideoSurface *surface, GstBuffer *buffer); - void flush(QAbstractVideoSurface *surface); + bool present(QAbstractVideoSurface *surface, GstBuffer *buffer) override; + void flush(QAbstractVideoSurface *surface) override; private: QVideoSurfaceFormat m_format; @@ -109,7 +109,7 @@ public: GstFlowReturn render(GstBuffer *buffer); - bool event(QEvent *event); + bool event(QEvent *event) override; private slots: bool handleEvent(QMutexLocker *locker); diff --git a/src/multimedia/playback/playback.pri b/src/multimedia/playback/playback.pri index 3bbb8ce15..cc55fc1b0 100644 --- a/src/multimedia/playback/playback.pri +++ b/src/multimedia/playback/playback.pri @@ -12,7 +12,7 @@ PRIVATE_HEADERS += \ playback/qmediaplaylistioplugin_p.h \ playback/qmediaplaylistnavigator_p.h \ playback/qmedianetworkplaylistprovider_p.h \ - playback/playlistfileparser_p.h + playback/qplaylistfileparser_p.h SOURCES += \ playback/qmedianetworkplaylistprovider.cpp \ @@ -23,4 +23,4 @@ SOURCES += \ playback/qmediaplaylistnavigator.cpp \ playback/qmediaplaylistprovider.cpp \ playback/qmediaresource.cpp \ - playback/playlistfileparser.cpp + playback/qplaylistfileparser.cpp diff --git a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp index 7de90d9a1..a4ad97251 100644 --- a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp +++ b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp @@ -41,7 +41,7 @@ #include "qmediaplaylistprovider_p.h" #include "qmediacontent.h" #include "qmediaobject_p.h" -#include "playlistfileparser_p.h" +#include "qplaylistfileparser_p.h" QT_BEGIN_NAMESPACE @@ -62,8 +62,8 @@ public: bool QMediaNetworkPlaylistProviderPrivate::load(const QNetworkRequest &request) { - parser.stop(); - parser.start(request, false); + parser.abort(); + parser.start(request); return true; } @@ -83,12 +83,14 @@ void QMediaNetworkPlaylistProviderPrivate::_q_handleParserError(QPlaylistFilePar case QPlaylistFileParser::FormatNotSupportedError: playlistError = QMediaPlaylist::FormatNotSupportedError; break; + case QPlaylistFileParser::ResourceError: + // fall through case QPlaylistFileParser::NetworkError: playlistError = QMediaPlaylist::NetworkError; break; } - parser.stop(); + parser.abort(); emit q->loadFailed(playlistError, errorMessage); } diff --git a/src/multimedia/playback/qmedianetworkplaylistprovider_p.h b/src/multimedia/playback/qmedianetworkplaylistprovider_p.h index 94595751b..3d1ffe66a 100644 --- a/src/multimedia/playback/qmedianetworkplaylistprovider_p.h +++ b/src/multimedia/playback/qmedianetworkplaylistprovider_p.h @@ -62,26 +62,26 @@ class Q_MULTIMEDIA_EXPORT QMediaNetworkPlaylistProvider : public QMediaPlaylistP Q_OBJECT public: QMediaNetworkPlaylistProvider(QObject *parent=0); - virtual ~QMediaNetworkPlaylistProvider(); + ~QMediaNetworkPlaylistProvider(); - virtual bool load(const QNetworkRequest &request, const char *format = 0); + bool load(const QNetworkRequest &request, const char *format = 0) override; - virtual int mediaCount() const; - virtual QMediaContent media(int pos) const; + int mediaCount() const override; + QMediaContent media(int pos) const override; - virtual bool isReadOnly() const; + bool isReadOnly() const override; - virtual bool addMedia(const QMediaContent &content); - virtual bool addMedia(const QList<QMediaContent> &items); - virtual bool insertMedia(int pos, const QMediaContent &content); - virtual bool insertMedia(int pos, const QList<QMediaContent> &items); - virtual bool moveMedia(int from, int to); - virtual bool removeMedia(int pos); - virtual bool removeMedia(int start, int end); - virtual bool clear(); + bool addMedia(const QMediaContent &content) override; + bool addMedia(const QList<QMediaContent> &items) override; + bool insertMedia(int pos, const QMediaContent &content) override; + bool insertMedia(int pos, const QList<QMediaContent> &items) override; + bool moveMedia(int from, int to) override; + bool removeMedia(int pos) override; + bool removeMedia(int start, int end) override; + bool clear() override; public Q_SLOTS: - virtual void shuffle(); + void shuffle() override; private: Q_DISABLE_COPY(QMediaNetworkPlaylistProvider) diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index f8d91b999..f23a94104 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -157,7 +157,7 @@ public: QNetworkConfiguration currentNetworkConfiguration() const; - QMultimedia::AvailabilityStatus availability() const; + QMultimedia::AvailabilityStatus availability() const override; QAudio::Role audioRole() const; void setAudioRole(QAudio::Role audioRole); @@ -205,8 +205,8 @@ Q_SIGNALS: void networkConfigurationChanged(const QNetworkConfiguration &configuration); public: - virtual bool bind(QObject *); - virtual void unbind(QObject *); + bool bind(QObject *) override; + void unbind(QObject *) override; private: Q_DISABLE_COPY(QMediaPlayer) diff --git a/src/multimedia/playback/qmediaplaylist.h b/src/multimedia/playback/qmediaplaylist.h index 05ab8f42e..b16e734f8 100644 --- a/src/multimedia/playback/qmediaplaylist.h +++ b/src/multimedia/playback/qmediaplaylist.h @@ -70,7 +70,7 @@ public: explicit QMediaPlaylist(QObject *parent = Q_NULLPTR); virtual ~QMediaPlaylist(); - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; PlaybackMode playbackMode() const; void setPlaybackMode(PlaybackMode mode); @@ -129,7 +129,7 @@ Q_SIGNALS: void loadFailed(); protected: - bool setMediaObject(QMediaObject *object); + bool setMediaObject(QMediaObject *object) override; QMediaPlaylistPrivate *d_ptr; private: diff --git a/src/multimedia/playback/qmediaplaylist_p.h b/src/multimedia/playback/qmediaplaylist_p.h index 0c3375ba7..8e081dd67 100644 --- a/src/multimedia/playback/qmediaplaylist_p.h +++ b/src/multimedia/playback/qmediaplaylist_p.h @@ -141,26 +141,26 @@ public: connect(m_navigator, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode))); } - virtual ~QMediaNetworkPlaylistControl() {}; + ~QMediaNetworkPlaylistControl() {} - QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); } - bool setPlaylistProvider(QMediaPlaylistProvider *mediaPlaylist) + QMediaPlaylistProvider* playlistProvider() const override { return m_navigator->playlist(); } + bool setPlaylistProvider(QMediaPlaylistProvider *mediaPlaylist) override { m_navigator->setPlaylist(mediaPlaylist); emit playlistProviderChanged(); return true; } - int currentIndex() const { return m_navigator->currentIndex(); } - void setCurrentIndex(int position) { m_navigator->jump(position); } - int nextIndex(int steps) const { return m_navigator->nextIndex(steps); } - int previousIndex(int steps) const { return m_navigator->previousIndex(steps); } + int currentIndex() const override { return m_navigator->currentIndex(); } + void setCurrentIndex(int position) override { m_navigator->jump(position); } + int nextIndex(int steps) const override { return m_navigator->nextIndex(steps); } + int previousIndex(int steps) const override { return m_navigator->previousIndex(steps); } - void next() { m_navigator->next(); } - void previous() { m_navigator->previous(); } + void next() override { m_navigator->next(); } + void previous() override { m_navigator->previous(); } - QMediaPlaylist::PlaybackMode playbackMode() const { return m_navigator->playbackMode(); } - void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) { m_navigator->setPlaybackMode(mode); } + QMediaPlaylist::PlaybackMode playbackMode() const override { return m_navigator->playbackMode(); } + void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) override { m_navigator->setPlaybackMode(mode); } private: QMediaPlaylistNavigator *m_navigator; diff --git a/src/multimedia/playback/qmediaplaylistioplugin_p.h b/src/multimedia/playback/qmediaplaylistioplugin_p.h index 73281b2bf..1e157d135 100644 --- a/src/multimedia/playback/qmediaplaylistioplugin_p.h +++ b/src/multimedia/playback/qmediaplaylistioplugin_p.h @@ -107,17 +107,17 @@ Q_OBJECT Q_INTERFACES(QMediaPlaylistIOInterface) public: explicit QMediaPlaylistIOPlugin(QObject *parent = 0); - virtual ~QMediaPlaylistIOPlugin(); + ~QMediaPlaylistIOPlugin(); - virtual bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const = 0; - virtual bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const = 0; + bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const override = 0; + bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const override = 0; - virtual bool canWrite(QIODevice *device, const QByteArray &format) const = 0; + bool canWrite(QIODevice *device, const QByteArray &format) const override = 0; - virtual QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray()) = 0; - virtual QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray()) = 0; + QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray()) override = 0; + QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray()) override = 0; - virtual QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format) = 0; + QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format) override = 0; }; QT_END_NAMESPACE diff --git a/src/multimedia/playback/qmediaplaylistnavigator.cpp b/src/multimedia/playback/qmediaplaylistnavigator.cpp index 1da7329ec..192fd463c 100644 --- a/src/multimedia/playback/qmediaplaylistnavigator.cpp +++ b/src/multimedia/playback/qmediaplaylistnavigator.cpp @@ -50,9 +50,9 @@ class QMediaPlaylistNullProvider : public QMediaPlaylistProvider { public: QMediaPlaylistNullProvider() :QMediaPlaylistProvider() {} - virtual ~QMediaPlaylistNullProvider() {} - virtual int mediaCount() const {return 0;} - virtual QMediaContent media(int) const { return QMediaContent(); } + ~QMediaPlaylistNullProvider() {} + int mediaCount() const override {return 0;} + QMediaContent media(int) const override { return QMediaContent(); } }; Q_GLOBAL_STATIC(QMediaPlaylistNullProvider, _q_nullMediaPlaylist) diff --git a/src/multimedia/playback/playlistfileparser.cpp b/src/multimedia/playback/qplaylistfileparser.cpp index 237e417a6..d0617d2cf 100644 --- a/src/multimedia/playback/playlistfileparser.cpp +++ b/src/multimedia/playback/qplaylistfileparser.cpp @@ -37,31 +37,48 @@ ** ****************************************************************************/ -#include "playlistfileparser_p.h" +#include "qplaylistfileparser_p.h" #include <qfileinfo.h> #include <QtCore/QDebug> +#include <QtCore/qiodevice.h> #include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkRequest> +#include "qmediaplayer.h" #include "qmediaobject_p.h" -#include <private/qobject_p.h> #include "qmediametadata.h" +#include "qmediacontent.h" +#include "qmediaresource.h" QT_BEGIN_NAMESPACE namespace { -class ParserBase : public QObject + +class ParserBase { - Q_OBJECT public: - ParserBase(QObject *parent) - : QObject(parent) + explicit ParserBase(QPlaylistFileParser *parent) + : m_parent(parent) + , m_aborted(false) + { + Q_ASSERT(m_parent); + } + + bool parseLine(int lineIndex, const QString& line, const QUrl& root) { + if (m_aborted) + return false; + + const bool ok = parseLineImpl(lineIndex, line, root); + return ok && !m_aborted; } - virtual void parseLine(int lineIndex, const QString& line, const QUrl& root) = 0; + virtual void abort() { m_aborted = true; } + virtual ~ParserBase() { } protected: - QUrl expandToFullPath(const QUrl &root, const QString &line) + virtual bool parseLineImpl(int lineIndex, const QString& line, const QUrl& root) = 0; + + static QUrl expandToFullPath(const QUrl &root, const QString &line) { // On Linux, backslashes are not converted to forward slashes :/ if (line.startsWith(QLatin1String("//")) || line.startsWith(QLatin1String("\\\\"))) { @@ -84,22 +101,22 @@ protected: return url; } -Q_SIGNALS: - void newItem(const QVariant& content); - void finished(); - void error(QPlaylistFileParser::ParserError err, const QString& errorMsg); + void newItemFound(const QVariant& content) { Q_EMIT m_parent->newItem(content); } + +private: + QPlaylistFileParser *m_parent; + bool m_aborted; }; class M3UParser : public ParserBase { public: - M3UParser(QObject *parent) - : ParserBase(parent) + explicit M3UParser(QPlaylistFileParser *q) + : ParserBase(q) , m_extendedFormat(false) { } - /* * Extended M3U directives @@ -117,7 +134,7 @@ public: C:\Documents and Settings\I\My Music\Greatest Hits\Example.ogg */ - void parseLine(int lineIndex, const QString& line, const QUrl& root) + bool parseLineImpl(int lineIndex, const QString& line, const QUrl& root) override { if (line[0] == '#' ) { if (m_extendedFormat) { @@ -149,9 +166,11 @@ public: } } else { m_extraInfo[QLatin1String("url")] = expandToFullPath(root, line); - emit newItem(QVariant(m_extraInfo)); + newItemFound(QVariant(m_extraInfo)); m_extraInfo.clear(); } + + return true; } int getSplitIndex(const QString& line, int startPos) @@ -172,16 +191,15 @@ public: } private: - bool m_extendedFormat; QVariantMap m_extraInfo; + bool m_extendedFormat; }; class PLSParser : public ParserBase { - Q_OBJECT public: - PLSParser(QObject *parent) - : ParserBase(parent) + explicit PLSParser(QPlaylistFileParser *q) + : ParserBase(q) { } @@ -223,17 +241,19 @@ NumberOfEntries=2 Version=2 */ - void parseLine(int, const QString &line, const QUrl &root) + bool parseLineImpl(int, const QString &line, const QUrl &root) override { // We ignore everything but 'File' entries, since that's the only thing we care about. if (!line.startsWith(QLatin1String("File"))) - return; + return true; QString value = getValue(line); if (value.isEmpty()) - return; + return true; - emit newItem(expandToFullPath(root, value)); + newItemFound(expandToFullPath(root, value)); + + return true; } QString getValue(const QString& line) { @@ -247,75 +267,84 @@ Version=2 ///////////////////////////////////////////////////////////////////////////////////////////////// -class QPlaylistFileParserPrivate : public QObjectPrivate +class QPlaylistFileParserPrivate { Q_DECLARE_PUBLIC(QPlaylistFileParser) public: - QPlaylistFileParserPrivate() - : m_source(0) + QPlaylistFileParserPrivate(QPlaylistFileParser *q) + : q_ptr(q) + , m_stream(0) + , m_type(QPlaylistFileParser::UNKNOWN) , m_scanIndex(0) - , m_utf8(false) , m_lineIndex(-1) - , m_type(QPlaylistFileParser::UNKNOWN) - , m_currentParser(0) + , m_utf8(false) + , m_aborted(false) { } - void _q_handleData(); - void _q_handleError(); - void _q_handleParserError(QPlaylistFileParser::ParserError err, const QString& errorMsg); - void _q_handleParserFinished(); + void handleData(); + void handleParserFinished(); + void abort(); + void reset(); - QNetworkReply *m_source; + QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> m_source; + QScopedPointer<ParserBase> m_currentParser; QByteArray m_buffer; - int m_scanIndex; QUrl m_root; - bool m_utf8; - int m_lineIndex; - QPlaylistFileParser::FileType m_type; - ParserBase *m_currentParser; QNetworkAccessManager m_mgr; + QString m_mimeType; + QPlaylistFileParser *q_ptr; + QIODevice *m_stream; + QPlaylistFileParser::FileType m_type; + struct ParserJob + { + QIODevice *m_stream; + QMediaResource m_resource; + bool isValid() const { return m_stream || !m_resource.isNull(); } + void reset() { m_stream = 0; m_resource = QMediaResource(); } + } m_pendingJob; + int m_scanIndex; + int m_lineIndex; + bool m_utf8; + bool m_aborted; private: - void processLine(int startIndex, int length); + bool processLine(int startIndex, int length); }; #define LINE_LIMIT 4096 #define READ_LIMIT 64 -void QPlaylistFileParserPrivate::processLine(int startIndex, int length) +bool QPlaylistFileParserPrivate::processLine(int startIndex, int length) { Q_Q(QPlaylistFileParser); m_lineIndex++; if (!m_currentParser) { - Q_ASSERT(!m_currentParser); - - QString mimeType = m_source->header(QNetworkRequest::ContentTypeHeader).toString(); - m_type = QPlaylistFileParser::findPlaylistType(m_root.toString(), mimeType, m_buffer.constData(), m_buffer.size()); + const QString urlString = m_root.toString(); + const QString &suffix = !urlString.isEmpty() ? QFileInfo(urlString).suffix() : urlString; + const QString &mimeType = m_source->header(QNetworkRequest::ContentTypeHeader).toString(); + m_type = QPlaylistFileParser::findPlaylistType(suffix, !mimeType.isEmpty() ? mimeType : m_mimeType, m_buffer.constData(), quint32(m_buffer.size())); switch (m_type) { case QPlaylistFileParser::UNKNOWN: emit q->error(QPlaylistFileParser::FormatError, QPlaylistFileParser::tr("%1 playlist type is unknown").arg(m_root.toString())); - q->stop(); - return; + q->abort(); + return false; case QPlaylistFileParser::M3U: - m_currentParser = new M3UParser(q); + m_currentParser.reset(new M3UParser(q)); break; case QPlaylistFileParser::M3U8: - m_currentParser = new M3UParser(q); + m_currentParser.reset(new M3UParser(q)); m_utf8 = true; break; case QPlaylistFileParser::PLS: - m_currentParser = new PLSParser(q); + m_currentParser.reset(new PLSParser(q)); break; } - Q_ASSERT(m_currentParser); - QObject::connect(m_currentParser, SIGNAL(newItem(QVariant)), q, SIGNAL(newItem(QVariant))); - QObject::connect(m_currentParser, SIGNAL(finished()), q, SLOT(_q_handleParserFinished())); - QObject::connect(m_currentParser, SIGNAL(error(QPlaylistFileParser::ParserError,QString)), - q, SLOT(_q_handleParserError(QPlaylistFileParser::ParserError,QString))); + + Q_ASSERT(!m_currentParser.isNull()); } QString line; @@ -326,26 +355,28 @@ void QPlaylistFileParserPrivate::processLine(int startIndex, int length) line = QString::fromLatin1(m_buffer.constData() + startIndex, length).trimmed(); } if (line.isEmpty()) - return; + return true; Q_ASSERT(m_currentParser); - m_currentParser->parseLine(m_lineIndex, line, m_root); + return m_currentParser->parseLine(m_lineIndex, line, m_root); } -void QPlaylistFileParserPrivate::_q_handleData() +void QPlaylistFileParserPrivate::handleData() { Q_Q(QPlaylistFileParser); - while (m_source->bytesAvailable()) { + while (m_source->bytesAvailable() && !m_aborted) { int expectedBytes = qMin(READ_LIMIT, int(qMin(m_source->bytesAvailable(), qint64(LINE_LIMIT - m_buffer.size())))); m_buffer.push_back(m_source->read(expectedBytes)); int processedBytes = 0; - while (m_scanIndex < m_buffer.length()) { + while (m_scanIndex < m_buffer.length() && !m_aborted) { char s = m_buffer[m_scanIndex]; if (s == '\r' || s == '\n') { int l = m_scanIndex - processedBytes; - if (l > 0) - processLine(processedBytes, l); + if (l > 0) { + if (!processLine(processedBytes, l)) + break; + } processedBytes = m_scanIndex + 1; if (!m_source) { //some error happened, so exit parsing @@ -355,11 +386,13 @@ void QPlaylistFileParserPrivate::_q_handleData() m_scanIndex++; } + if (m_aborted) + break; + if (m_buffer.length() - processedBytes >= LINE_LIMIT) { - qWarning() << "error parsing playlist["<< m_root << "] with line content >= 4096 bytes."; emit q->error(QPlaylistFileParser::FormatError, QPlaylistFileParser::tr("invalid line in playlist file")); - q->stop(); - return; + q->abort(); + break; } if (m_source->isFinished() && !m_source->bytesAvailable()) { @@ -382,143 +415,226 @@ void QPlaylistFileParserPrivate::_q_handleData() m_scanIndex = 0; } - if (m_source->isFinished()) { - _q_handleParserFinished(); - } + handleParserFinished(); } -void QPlaylistFileParserPrivate::_q_handleError() +QPlaylistFileParser::QPlaylistFileParser(QObject *parent) + : QObject(parent) + , d_ptr(new QPlaylistFileParserPrivate(this)) { - Q_Q(QPlaylistFileParser); - emit q->error(QPlaylistFileParser::NetworkError, m_source->errorString()); - q->stop(); + } -void QPlaylistFileParserPrivate::_q_handleParserError(QPlaylistFileParser::ParserError err, const QString& errorMsg) +QPlaylistFileParser::~QPlaylistFileParser() { - Q_Q(QPlaylistFileParser); - emit q->error(err, errorMsg); + } -void QPlaylistFileParserPrivate::_q_handleParserFinished() +QPlaylistFileParser::FileType QPlaylistFileParser::findByMimeType(const QString &mime) { - Q_Q(QPlaylistFileParser); - bool isParserValid = (m_currentParser != 0); - if (!isParserValid) - emit q->error(QPlaylistFileParser::FormatNotSupportedError, QPlaylistFileParser::tr("Empty file provided")); + if (mime == QLatin1String("text/uri-list") || mime == QLatin1String("audio/x-mpegurl") || mime == QLatin1String("audio/mpegurl")) + return QPlaylistFileParser::M3U; - q->stop(); + if (mime == QLatin1String("application/x-mpegURL") || mime == QLatin1String("application/vnd.apple.mpegurl")) + return QPlaylistFileParser::M3U8; - if (isParserValid) - emit q->finished(); -} + if (mime == QLatin1String("audio/x-scpls")) + return QPlaylistFileParser::PLS; + return QPlaylistFileParser::UNKNOWN; +} -QPlaylistFileParser::QPlaylistFileParser(QObject *parent) - : QObject(*new QPlaylistFileParserPrivate, parent) +QPlaylistFileParser::FileType QPlaylistFileParser::findBySuffixType(const QString &suffix) { + const QString &s = suffix.toLower(); + + if (s == QLatin1String("m3u")) + return QPlaylistFileParser::M3U; + + if (s == QLatin1String("m3u8")) + return QPlaylistFileParser::M3U8; + if (s == QLatin1String("pls")) + return QPlaylistFileParser::PLS; + + return QPlaylistFileParser::UNKNOWN; } -QPlaylistFileParser::FileType QPlaylistFileParser::findPlaylistType(const QString& uri, const QString& mime, const void *data, quint32 size) +QPlaylistFileParser::FileType QPlaylistFileParser::findByDataHeader(const char *data, quint32 size) { - if (!data || !size) - return UNKNOWN; - - FileType uriType = UNKNOWN; - QString suffix = QFileInfo(uri).suffix().toLower(); - if (suffix == QLatin1String("m3u")) - uriType = M3U; - else if (suffix == QLatin1String("m3u8")) - uriType = M3U8; - else if (suffix == QLatin1String("pls")) - uriType = PLS; - - FileType mimeType = UNKNOWN; - if (mime == QLatin1String("text/uri-list") || mime == QLatin1String("audio/x-mpegurl") || mime == QLatin1String("audio/mpegurl")) - mimeType = QPlaylistFileParser::M3U; - else if (mime == QLatin1String("application/x-mpegURL") || mime == QLatin1String("application/vnd.apple.mpegurl")) - mimeType = QPlaylistFileParser::M3U8; - else if (mime == QLatin1String("audio/x-scpls")) - mimeType = QPlaylistFileParser::PLS; - - FileType bufferType = UNKNOWN; - if (size >= 7 && strncmp((const char*)data, "#EXTM3U", 7) == 0) - bufferType = M3U; - else if (size >= 10 && strncmp((const char*)data, "[playlist]", 10) == 0) - bufferType = PLS; - else { - // Make sure every line is a text string - quint32 n; - for (n = 0; n < size; n++) - if (!QChar(QLatin1Char(((const char*)data)[n])).isPrint()) - break; - if (n == size) - bufferType = M3U; - } + if (!data || size == 0) + return QPlaylistFileParser::UNKNOWN; - if (bufferType == M3U && (uriType == M3U8 || mimeType == M3U8)) - bufferType = M3U8; + if (size >= 7 && strncmp(data, "#EXTM3U", 7) == 0) + return QPlaylistFileParser::M3U; + + if (size >= 10 && strncmp(data, "[playlist]", 10) == 0) + return QPlaylistFileParser::PLS; + + return QPlaylistFileParser::UNKNOWN; +} - if (bufferType != UNKNOWN) - return bufferType; +QPlaylistFileParser::FileType QPlaylistFileParser::findPlaylistType(const QString& suffix, + const QString& mime, + const char *data, + quint32 size) +{ - if (uriType != UNKNOWN) - return uriType; + FileType dataHeaderType = findByDataHeader(data, size); + if (dataHeaderType != UNKNOWN) + return dataHeaderType; + FileType mimeType = findByMimeType(mime); if (mimeType != UNKNOWN) return mimeType; + FileType suffixType = findBySuffixType(suffix); + if (suffixType != UNKNOWN) + return suffixType; + return UNKNOWN; } -void QPlaylistFileParser::start(const QNetworkRequest& request, bool utf8) +/* + * Delegating + */ +void QPlaylistFileParser::start(const QMediaContent &media, QIODevice *stream) +{ + const QMediaResource &mediaResource = media.canonicalResource(); + const QString &mimeType = mediaResource.mimeType(); + + if (stream) { + start(stream, mediaResource.mimeType()); + } else { + const QNetworkRequest &request = mediaResource.request(); + const QUrl &url = mediaResource.url(); + + if (request.url().isValid()) + start(request, mimeType); + else + start(QNetworkRequest(url), mimeType); + } +} + +void QPlaylistFileParser::start(QIODevice *stream, const QString &mimeType) { Q_D(QPlaylistFileParser); - stop(); + const bool validStream = stream ? (stream->isOpen() && stream->isReadable()) : false; + + if (!validStream) { + Q_EMIT error(ResourceError, tr("Invalid stream")); + return; + } + + if (!d->m_currentParser.isNull()) { + abort(); + d->m_pendingJob = { stream, QMediaResource(QUrl(), mimeType) }; + return; + } + + d->reset(); + d->m_mimeType = mimeType; + d->m_stream = stream; + connect(d->m_stream, SIGNAL(readyRead()), this, SLOT(_q_handleData())); + d->handleData(); +} - d->m_type = UNKNOWN; - d->m_utf8 = utf8; - d->m_root = request.url(); +void QPlaylistFileParser::start(const QNetworkRequest& request, const QString &mimeType) +{ + Q_D(QPlaylistFileParser); + const QUrl &url = request.url(); - if (d->m_root.isLocalFile() && !QFile::exists(d->m_root.toLocalFile())) { - emit error(NetworkError, QString(tr("%1 does not exist")).arg(d->m_root.toString())); + if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) { + emit error(ResourceError, QString(tr("%1 does not exist")).arg(url.toString())); return; } - d->m_source = d->m_mgr.get(request); + if (!d->m_currentParser.isNull()) { + abort(); + d->m_pendingJob = { Q_NULLPTR, QMediaResource(request, mimeType) }; + return; + } - connect(d->m_source, SIGNAL(readyRead()), this, SLOT(_q_handleData())); - connect(d->m_source, SIGNAL(finished()), this, SLOT(_q_handleData())); - connect(d->m_source, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(_q_handleError())); + d->reset(); + d->m_root = url; + d->m_mimeType = mimeType; + d->m_source.reset(d->m_mgr.get(request)); + connect(d->m_source.data(), SIGNAL(readyRead()), this, SLOT(handleData())); + connect(d->m_source.data(), SIGNAL(finished()), this, SLOT(handleData())); + connect(d->m_source.data(), SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError())); - d->_q_handleData(); + d->handleData(); } -void QPlaylistFileParser::stop() +void QPlaylistFileParser::abort() { Q_D(QPlaylistFileParser); - if (d->m_currentParser) { - disconnect(d->m_currentParser, SIGNAL(newItem(QVariant)), this, SIGNAL(newItem(QVariant))); - disconnect(d->m_currentParser, SIGNAL(finished()), this, SLOT(_q_handleParserFinished())); - disconnect(d->m_currentParser, SIGNAL(error(QPlaylistFileParser::ParserError,QString)), - this, SLOT(_q_handleParserError(QPlaylistFileParser::ParserError,QString))); - d->m_currentParser->deleteLater(); - d->m_currentParser = 0; - } + d->abort(); + + if (d->m_source) + d->m_source->disconnect(); - d->m_buffer.clear(); - d->m_scanIndex = 0; - d->m_lineIndex = -1; - if (d->m_source) { - disconnect(d->m_source, SIGNAL(readyRead()), this, SLOT(_q_handleData())); - disconnect(d->m_source, SIGNAL(finished()), this, SLOT(_q_handleData())); - disconnect(d->m_source, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(_q_handleError())); - d->m_source->deleteLater(); - d->m_source = 0; + if (d->m_stream) + disconnect(d->m_stream, SIGNAL(readyRead()), this, SLOT(handleData())); +} + +void QPlaylistFileParser::handleData() +{ + Q_D(QPlaylistFileParser); + d->handleData(); +} + +void QPlaylistFileParserPrivate::handleParserFinished() +{ + Q_Q(QPlaylistFileParser); + const bool isParserValid = !m_currentParser.isNull(); + if (!isParserValid && !m_aborted) + emit q->error(QPlaylistFileParser::FormatNotSupportedError, QPlaylistFileParser::tr("Empty file provided")); + + if (isParserValid && !m_aborted) { + m_currentParser.reset(); + emit q->finished(); } + + if (!m_aborted) + q->abort(); + + if (!m_source.isNull()) + m_source.reset(); + + if (m_pendingJob.isValid()) + q->start(m_pendingJob.m_resource, m_pendingJob.m_stream); +} + +void QPlaylistFileParserPrivate::abort() +{ + m_aborted = true; + if (!m_currentParser.isNull()) + m_currentParser->abort(); +} + +void QPlaylistFileParserPrivate::reset() +{ + Q_ASSERT(m_currentParser.isNull()); + Q_ASSERT(m_source.isNull()); + m_buffer.clear(); + m_root.clear(); + m_mimeType.clear(); + m_stream = 0; + m_type = QPlaylistFileParser::UNKNOWN; + m_scanIndex = 0; + m_lineIndex = -1; + m_utf8 = false; + m_aborted = false; + m_pendingJob.reset(); +} + +void QPlaylistFileParser::handleError() +{ + Q_D(QPlaylistFileParser); + const QString &errorString = d->m_source->errorString(); + Q_EMIT error(QPlaylistFileParser::NetworkError, errorString); + abort(); } -#include "moc_playlistfileparser_p.cpp" -#include "playlistfileparser.moc" QT_END_NAMESPACE diff --git a/src/multimedia/playback/playlistfileparser_p.h b/src/multimedia/playback/qplaylistfileparser_p.h index bdf95fe7a..927dbb739 100644 --- a/src/multimedia/playback/playlistfileparser_p.h +++ b/src/multimedia/playback/qplaylistfileparser_p.h @@ -52,10 +52,14 @@ // #include "qtmultimediaglobal.h" -#include <QtNetwork/QNetworkRequest> +#include <QtCore/qobject.h> QT_BEGIN_NAMESPACE +class QIODevice; +class QMediaContent; +class QNetworkRequest; + class QPlaylistFileParserPrivate; class Q_MULTIMEDIA_EXPORT QPlaylistFileParser : public QObject @@ -63,6 +67,7 @@ class Q_MULTIMEDIA_EXPORT QPlaylistFileParser : public QObject Q_OBJECT public: QPlaylistFileParser(QObject *parent = 0); + ~QPlaylistFileParser(); enum FileType { @@ -77,26 +82,39 @@ public: NoError, FormatError, FormatNotSupportedError, + ResourceError, NetworkError }; - static FileType findPlaylistType(const QString& uri, const QString& mime, const void *data, quint32 size); - - void start(const QNetworkRequest &request, bool utf8 = false); - void stop(); + void start(const QMediaContent &media, QIODevice *stream = 0); + void start(const QNetworkRequest &request, const QString &mimeType = QString()); + void abort(); Q_SIGNALS: void newItem(const QVariant& content); void finished(); void error(QPlaylistFileParser::ParserError err, const QString& errorMsg); +private Q_SLOTS: + void handleData(); + void handleError(); + private: + void start(QIODevice *stream, const QString &mimeType = QString()); + + static FileType findByMimeType(const QString &mime); + static FileType findBySuffixType(const QString &suffix); + static FileType findByDataHeader(const char *data, quint32 size); + static FileType findPlaylistType(QIODevice *device, + const QString& mime); + static FileType findPlaylistType(const QString &suffix, + const QString& mime, + const char *data = 0, + quint32 size = 0); + Q_DISABLE_COPY(QPlaylistFileParser) Q_DECLARE_PRIVATE(QPlaylistFileParser) - Q_PRIVATE_SLOT(d_func(), void _q_handleData()) - Q_PRIVATE_SLOT(d_func(), void _q_handleError()) - Q_PRIVATE_SLOT(d_func(), void _q_handleParserError(QPlaylistFileParser::ParserError err, const QString& errorMsg)) - Q_PRIVATE_SLOT(d_func(), void _q_handleParserFinished()) + QScopedPointer<QPlaylistFileParserPrivate> d_ptr; }; QT_END_NAMESPACE diff --git a/src/multimedia/qmediaresourcepolicy_p.cpp b/src/multimedia/qmediaresourcepolicy_p.cpp index 8c9ea8264..1577f11af 100644 --- a/src/multimedia/qmediaresourcepolicy_p.cpp +++ b/src/multimedia/qmediaresourcepolicy_p.cpp @@ -51,24 +51,24 @@ namespace { { } - bool isVideoEnabled() const + bool isVideoEnabled() const override { return true; } - bool isGranted() const + bool isGranted() const override { return true; } - bool isAvailable() const + bool isAvailable() const override { return true; } - void acquire() {} - void release() {} - void setVideoEnabled(bool) {} + void acquire() override {} + void release() override {} + void setVideoEnabled(bool) override {} }; } diff --git a/src/multimedia/qmediaserviceprovider.cpp b/src/multimedia/qmediaserviceprovider.cpp index 5d470d6bd..b0783fba6 100644 --- a/src/multimedia/qmediaserviceprovider.cpp +++ b/src/multimedia/qmediaserviceprovider.cpp @@ -315,7 +315,7 @@ class QPluginServiceProvider : public QMediaServiceProvider QMap<const QMediaService*, MediaServiceData> mediaServiceData; public: - QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) + QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) override { QString key(QLatin1String(type.constData())); @@ -440,7 +440,7 @@ public: return 0; } - void releaseService(QMediaService *service) + void releaseService(QMediaService *service) override { if (service != 0) { MediaServiceData d = mediaServiceData.take(service); @@ -450,7 +450,7 @@ public: } } - QMediaServiceProviderHint::Features supportedFeatures(const QMediaService *service) const + QMediaServiceProviderHint::Features supportedFeatures(const QMediaService *service) const override { if (service) { MediaServiceData d = mediaServiceData.value(service); @@ -470,7 +470,7 @@ public: QMultimedia::SupportEstimate hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, - int flags) const + int flags) const override { const QList<QObject*> instances = loader()->instances(QLatin1String(serviceType)); @@ -522,7 +522,7 @@ public: return supportEstimate; } - QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const + QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const override { const QList<QObject*> instances = loader()->instances(QLatin1String(serviceType)); @@ -569,7 +569,7 @@ public: return supportedTypes; } - QByteArray defaultDevice(const QByteArray &serviceType) const + QByteArray defaultDevice(const QByteArray &serviceType) const override { const auto instances = loader()->instances(QLatin1String(serviceType)); for (QObject *obj : instances) { @@ -589,7 +589,7 @@ public: return QByteArray(); } - QList<QByteArray> devices(const QByteArray &serviceType) const + QList<QByteArray> devices(const QByteArray &serviceType) const override { QList<QByteArray> res; @@ -606,7 +606,7 @@ public: return res; } - QString deviceDescription(const QByteArray &serviceType, const QByteArray &device) + QString deviceDescription(const QByteArray &serviceType, const QByteArray &device) override { const auto instances = loader()->instances(QLatin1String(serviceType)); for (QObject *obj : instances) { @@ -622,7 +622,7 @@ public: return QString(); } - QCamera::Position cameraPosition(const QByteArray &device) const + QCamera::Position cameraPosition(const QByteArray &device) const override { const QByteArray serviceType(Q_MEDIASERVICE_CAMERA); const auto instances = loader()->instances(QString::fromLatin1(serviceType)); @@ -642,7 +642,7 @@ public: return QCamera::UnspecifiedPosition; } - int cameraOrientation(const QByteArray &device) const + int cameraOrientation(const QByteArray &device) const override { const QByteArray serviceType(Q_MEDIASERVICE_CAMERA); const auto instances = loader()->instances(QString::fromLatin1(serviceType)); diff --git a/src/multimedia/qmediaserviceproviderplugin.h b/src/multimedia/qmediaserviceproviderplugin.h index 43fe55d43..6447e319a 100644 --- a/src/multimedia/qmediaserviceproviderplugin.h +++ b/src/multimedia/qmediaserviceproviderplugin.h @@ -195,8 +195,8 @@ class Q_MULTIMEDIA_EXPORT QMediaServiceProviderPlugin : public QObject, public Q Q_INTERFACES(QMediaServiceProviderFactoryInterface) public: - virtual QMediaService* create(const QString& key) = 0; - virtual void release(QMediaService *service) = 0; + QMediaService* create(const QString& key) override = 0; + void release(QMediaService *service) override = 0; }; /*! diff --git a/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h b/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h index 54282cad4..465821cb1 100644 --- a/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h +++ b/src/multimedia/qtmultimediaquicktools_headers/qdeclarativevideooutput_p.h @@ -134,10 +134,10 @@ Q_SIGNALS: void contentRectChanged(); protected: - QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); - void itemChange(ItemChange change, const ItemChangeData &changeData); - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); - void releaseResources(); + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override; + void itemChange(ItemChange change, const ItemChangeData &changeData) override; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void releaseResources() override; private Q_SLOTS: void _q_updateMediaObject(); diff --git a/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h b/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h index ab7c5aa23..c094bed1f 100644 --- a/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h +++ b/src/multimedia/qtmultimediaquicktools_headers/qsgvideonode_p.h @@ -101,8 +101,8 @@ class Q_MULTIMEDIAQUICK_EXPORT QSGVideoNodeFactoryPlugin : public QObject, publi Q_OBJECT Q_INTERFACES(QSGVideoNodeFactoryInterface) public: - virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const = 0; - virtual QSGVideoNode *createNode(const QVideoSurfaceFormat &format) = 0; + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const override = 0; + QSGVideoNode *createNode(const QVideoSurfaceFormat &format) override = 0; }; QT_END_NAMESPACE diff --git a/src/multimedia/radio/qradiodata.h b/src/multimedia/radio/qradiodata.h index a5cc09900..826c652ff 100644 --- a/src/multimedia/radio/qradiodata.h +++ b/src/multimedia/radio/qradiodata.h @@ -87,7 +87,7 @@ public: QMultimedia::AvailabilityStatus availability() const; - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; QString stationId() const; ProgramType programType() const; @@ -113,7 +113,7 @@ Q_SIGNALS: void error(QRadioData::Error error); protected: - bool setMediaObject(QMediaObject *); + bool setMediaObject(QMediaObject *) override; QRadioDataPrivate *d_ptr; private: diff --git a/src/multimedia/radio/qradiotuner.h b/src/multimedia/radio/qradiotuner.h index a9de6416d..7952a2e6c 100644 --- a/src/multimedia/radio/qradiotuner.h +++ b/src/multimedia/radio/qradiotuner.h @@ -81,7 +81,7 @@ public: explicit QRadioTuner(QObject *parent = Q_NULLPTR); ~QRadioTuner(); - QMultimedia::AvailabilityStatus availability() const; + QMultimedia::AvailabilityStatus availability() const override; State state() const; diff --git a/src/multimedia/recording/qmediarecorder.h b/src/multimedia/recording/qmediarecorder.h index 3ac25129b..a12bcd632 100644 --- a/src/multimedia/recording/qmediarecorder.h +++ b/src/multimedia/recording/qmediarecorder.h @@ -109,7 +109,7 @@ public: explicit QMediaRecorder(QMediaObject *mediaObject, QObject *parent = Q_NULLPTR); ~QMediaRecorder(); - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; bool isAvailable() const; QMultimedia::AvailabilityStatus availability() const; @@ -194,7 +194,7 @@ Q_SIGNALS: protected: QMediaRecorder(QMediaRecorderPrivate &dd, QMediaObject *mediaObject, QObject *parent = Q_NULLPTR); - bool setMediaObject(QMediaObject *object); + bool setMediaObject(QMediaObject *object) override; QMediaRecorderPrivate *d_ptr; private: diff --git a/src/multimedia/video/qabstractvideobuffer.h b/src/multimedia/video/qabstractvideobuffer.h index dcefdf7bc..2352c0f3d 100644 --- a/src/multimedia/video/qabstractvideobuffer.h +++ b/src/multimedia/video/qabstractvideobuffer.h @@ -107,7 +107,7 @@ public: QAbstractPlanarVideoBuffer(HandleType type); virtual ~QAbstractPlanarVideoBuffer(); - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; virtual int map(MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) = 0; protected: diff --git a/src/multimedia/video/qabstractvideobuffer_p.h b/src/multimedia/video/qabstractvideobuffer_p.h index 6fbd75a30..9e3ced9b5 100644 --- a/src/multimedia/video/qabstractvideobuffer_p.h +++ b/src/multimedia/video/qabstractvideobuffer_p.h @@ -85,7 +85,7 @@ public: QAbstractPlanarVideoBufferPrivate() {} - int map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]); + int map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4]) override; private: Q_DECLARE_PUBLIC(QAbstractPlanarVideoBuffer) diff --git a/src/multimedia/video/qimagevideobuffer_p.h b/src/multimedia/video/qimagevideobuffer_p.h index 6fa742c88..f2b88dd9b 100644 --- a/src/multimedia/video/qimagevideobuffer_p.h +++ b/src/multimedia/video/qimagevideobuffer_p.h @@ -67,10 +67,10 @@ public: QImageVideoBuffer(const QImage &image); ~QImageVideoBuffer(); - MapMode mapMode() const; + MapMode mapMode() const override; - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); - void unmap(); + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; + void unmap() override; }; QT_END_NAMESPACE diff --git a/src/multimedia/video/qmemoryvideobuffer_p.h b/src/multimedia/video/qmemoryvideobuffer_p.h index 132f9367c..e1b1f83a9 100644 --- a/src/multimedia/video/qmemoryvideobuffer_p.h +++ b/src/multimedia/video/qmemoryvideobuffer_p.h @@ -65,10 +65,10 @@ public: QMemoryVideoBuffer(const QByteArray &data, int bytesPerLine); ~QMemoryVideoBuffer(); - MapMode mapMode() const; + MapMode mapMode() const override; - uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); - void unmap(); + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) override; + void unmap() override; }; QT_END_NAMESPACE diff --git a/src/multimedia/video/qvideosurfaceoutput_p.h b/src/multimedia/video/qvideosurfaceoutput_p.h index bca288191..a1b24abbf 100644 --- a/src/multimedia/video/qvideosurfaceoutput_p.h +++ b/src/multimedia/video/qvideosurfaceoutput_p.h @@ -70,12 +70,12 @@ public: QVideoSurfaceOutput(QObject*parent = 0); ~QVideoSurfaceOutput(); - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; void setVideoSurface(QAbstractVideoSurface *surface); protected: - bool setMediaObject(QMediaObject *object); + bool setMediaObject(QMediaObject *object) override; private: QPointer<QAbstractVideoSurface> m_surface; diff --git a/src/multimediawidgets/multimediawidgets.pro b/src/multimediawidgets/multimediawidgets.pro index c37868933..8e4a78278 100644 --- a/src/multimediawidgets/multimediawidgets.pro +++ b/src/multimediawidgets/multimediawidgets.pro @@ -11,17 +11,21 @@ PRIVATE_HEADERS += \ PUBLIC_HEADERS += \ qtmultimediawidgetdefs.h \ qcameraviewfinder.h \ - qgraphicsvideoitem.h \ qvideowidgetcontrol.h \ qvideowidget.h SOURCES += \ qcameraviewfinder.cpp \ - qgraphicsvideoitem.cpp \ qpaintervideosurface.cpp \ qvideowidgetcontrol.cpp \ qvideowidget.cpp +qtConfig(graphicsview) { + SOURCES += qgraphicsvideoitem.cpp + PUBLIC_HEADERS += qgraphicsvideoitem.h +} + + HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS load(qt_module) diff --git a/src/multimediawidgets/qcameraviewfinder.h b/src/multimediawidgets/qcameraviewfinder.h index 2bd49fe83..57f20809a 100644 --- a/src/multimediawidgets/qcameraviewfinder.h +++ b/src/multimediawidgets/qcameraviewfinder.h @@ -64,10 +64,10 @@ public: explicit QCameraViewfinder(QWidget *parent = Q_NULLPTR); ~QCameraViewfinder(); - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; protected: - bool setMediaObject(QMediaObject *object); + bool setMediaObject(QMediaObject *object) override; private: Q_DISABLE_COPY(QCameraViewfinder) diff --git a/src/multimediawidgets/qgraphicsvideoitem.h b/src/multimediawidgets/qgraphicsvideoitem.h index 89de3397a..4a86d4412 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.h +++ b/src/multimediawidgets/qgraphicsvideoitem.h @@ -45,13 +45,11 @@ #include <QtMultimediaWidgets/qvideowidget.h> #include <QtMultimedia/qmediabindableinterface.h> -QT_BEGIN_NAMESPACE - -class QVideoSurfaceFormat; -QT_END_NAMESPACE +#if QT_CONFIG(graphicsview) QT_BEGIN_NAMESPACE +class QVideoSurfaceFormat; class QGraphicsVideoItemPrivate; class Q_MULTIMEDIAWIDGETS_EXPORT QGraphicsVideoItem : public QGraphicsObject, public QMediaBindableInterface { @@ -66,7 +64,7 @@ public: explicit QGraphicsVideoItem(QGraphicsItem *parent = Q_NULLPTR); ~QGraphicsVideoItem(); - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; Qt::AspectRatioMode aspectRatioMode() const; void setAspectRatioMode(Qt::AspectRatioMode mode); @@ -79,18 +77,18 @@ public: QSizeF nativeSize() const; - QRectF boundingRect() const; + QRectF boundingRect() const override; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) override; Q_SIGNALS: void nativeSizeChanged(const QSizeF &size); protected: - void timerEvent(QTimerEvent *event); - QVariant itemChange(GraphicsItemChange change, const QVariant &value); + void timerEvent(QTimerEvent *event) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; - bool setMediaObject(QMediaObject *object); + bool setMediaObject(QMediaObject *object) override; QGraphicsVideoItemPrivate *d_ptr; @@ -103,5 +101,6 @@ private: QT_END_NAMESPACE +#endif // QT_CONFIG(graphicsview) -#endif +#endif // QGRAPHICSVIDEOITEM_H diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp index 9a6ad11ed..214e5ec7e 100644 --- a/src/multimediawidgets/qpaintervideosurface.cpp +++ b/src/multimediawidgets/qpaintervideosurface.cpp @@ -72,19 +72,19 @@ public: QVideoSurfaceGenericPainter(); QList<QVideoFrame::PixelFormat> supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType) const; + QAbstractVideoBuffer::HandleType handleType) const override; - bool isFormatSupported(const QVideoSurfaceFormat &format) const; + bool isFormatSupported(const QVideoSurfaceFormat &format) const override; - QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); - void stop(); + QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) override; + void stop() override; - QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); + QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) override; QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRectF &source); + const QRectF &target, QPainter *painter, const QRectF &source) override; - void updateColors(int brightness, int contrast, int hue, int saturation); + void updateColors(int brightness, int contrast, int hue, int saturation) override; private: QList<QVideoFrame::PixelFormat> m_imagePixelFormats; @@ -252,19 +252,19 @@ public: QVideoSurfaceGLPainter(QGLContext *context); ~QVideoSurfaceGLPainter(); QList<QVideoFrame::PixelFormat> supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType) const; + QAbstractVideoBuffer::HandleType handleType) const override; - bool isFormatSupported(const QVideoSurfaceFormat &format) const; + bool isFormatSupported(const QVideoSurfaceFormat &format) const override; - void stop(); + void stop() override; - QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); + QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) override; QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRectF &source); + const QRectF &target, QPainter *painter, const QRectF &source) override; - void updateColors(int brightness, int contrast, int hue, int saturation); - void viewportDestroyed(); + void updateColors(int brightness, int contrast, int hue, int saturation) override; + void viewportDestroyed() override; protected: void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size); @@ -667,11 +667,11 @@ class QVideoSurfaceArbFpPainter : public QVideoSurfaceGLPainter public: QVideoSurfaceArbFpPainter(QGLContext *context); - QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); - void stop(); + QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) override; + void stop() override; QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRectF &source); + const QRectF &target, QPainter *painter, const QRectF &source) override; private: typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *); @@ -1066,11 +1066,11 @@ class QVideoSurfaceGlslPainter : public QVideoSurfaceGLPainter public: QVideoSurfaceGlslPainter(QGLContext *context); - QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); - void stop(); + QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) override; + void stop() override; QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRectF &source); + const QRectF &target, QPainter *painter, const QRectF &source) override; private: QGLShaderProgram m_program; diff --git a/src/multimediawidgets/qpaintervideosurface_p.h b/src/multimediawidgets/qpaintervideosurface_p.h index 2e89393e9..bf0a0ac5c 100644 --- a/src/multimediawidgets/qpaintervideosurface_p.h +++ b/src/multimediawidgets/qpaintervideosurface_p.h @@ -99,14 +99,14 @@ public: ~QPainterVideoSurface(); QList<QVideoFrame::PixelFormat> supportedPixelFormats( - QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const override; - bool isFormatSupported(const QVideoSurfaceFormat &format) const; + bool isFormatSupported(const QVideoSurfaceFormat &format) const override; - bool start(const QVideoSurfaceFormat &format); - void stop(); + bool start(const QVideoSurfaceFormat &format) override; + void stop() override; - bool present(const QVideoFrame &frame); + bool present(const QVideoFrame &frame) override; int brightness() const; void setBrightness(int brightness); diff --git a/src/multimediawidgets/qvideowidget.cpp b/src/multimediawidgets/qvideowidget.cpp index 60a968813..c43f7a006 100644 --- a/src/multimediawidgets/qvideowidget.cpp +++ b/src/multimediawidgets/qvideowidget.cpp @@ -51,7 +51,6 @@ #include <qapplication.h> #include <qevent.h> -#include <qdialog.h> #include <qboxlayout.h> #include <qnamespace.h> diff --git a/src/multimediawidgets/qvideowidget.h b/src/multimediawidgets/qvideowidget.h index 9aca9d3a4..c8474288b 100644 --- a/src/multimediawidgets/qvideowidget.h +++ b/src/multimediawidgets/qvideowidget.h @@ -67,7 +67,7 @@ public: explicit QVideoWidget(QWidget *parent = Q_NULLPTR); ~QVideoWidget(); - QMediaObject *mediaObject() const; + QMediaObject *mediaObject() const override; #ifdef Q_QDOC bool isFullScreen() const; @@ -80,7 +80,7 @@ public: int hue() const; int saturation() const; - QSize sizeHint() const; + QSize sizeHint() const override; public Q_SLOTS: void setFullScreen(bool fullScreen); @@ -98,14 +98,14 @@ Q_SIGNALS: void saturationChanged(int saturation); protected: - bool event(QEvent *event); - void showEvent(QShowEvent *event); - void hideEvent(QHideEvent *event); - void resizeEvent(QResizeEvent *event); - void moveEvent(QMoveEvent *event); - void paintEvent(QPaintEvent *event); - - bool setMediaObject(QMediaObject *object); + bool event(QEvent *event) override; + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void moveEvent(QMoveEvent *event) override; + void paintEvent(QPaintEvent *event) override; + + bool setMediaObject(QMediaObject *object) override; #if defined(Q_WS_WIN) bool winEvent(MSG *message, long *result); diff --git a/src/multimediawidgets/qvideowidget_p.h b/src/multimediawidgets/qvideowidget_p.h index 039ace24e..48b08e093 100644 --- a/src/multimediawidgets/qvideowidget_p.h +++ b/src/multimediawidgets/qvideowidget_p.h @@ -106,15 +106,15 @@ public: void releaseControl(); - void setBrightness(int brightness); - void setContrast(int contrast); - void setHue(int hue); - void setSaturation(int saturation); + void setBrightness(int brightness) override; + void setContrast(int contrast) override; + void setHue(int hue) override; + void setSaturation(int saturation) override; - void setFullScreen(bool fullScreen); + void setFullScreen(bool fullScreen) override; - Qt::AspectRatioMode aspectRatioMode() const; - void setAspectRatioMode(Qt::AspectRatioMode mode); + Qt::AspectRatioMode aspectRatioMode() const override; + void setAspectRatioMode(Qt::AspectRatioMode mode) override; private: QMediaService *m_service; @@ -134,23 +134,23 @@ public: void releaseControl(); void clearSurface(); - void setBrightness(int brightness); - void setContrast(int contrast); - void setHue(int hue); - void setSaturation(int saturation); + void setBrightness(int brightness) override; + void setContrast(int contrast) override; + void setHue(int hue) override; + void setSaturation(int saturation) override; - void setFullScreen(bool fullScreen); + void setFullScreen(bool fullScreen) override; - Qt::AspectRatioMode aspectRatioMode() const; - void setAspectRatioMode(Qt::AspectRatioMode mode); + Qt::AspectRatioMode aspectRatioMode() const override; + void setAspectRatioMode(Qt::AspectRatioMode mode) override; - QSize sizeHint() const; + QSize sizeHint() const override; - void showEvent(); - void hideEvent(QHideEvent *event); - void resizeEvent(QResizeEvent *event); - void moveEvent(QMoveEvent *event); - void paintEvent(QPaintEvent *event); + void showEvent() override; + void hideEvent(QHideEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void moveEvent(QMoveEvent *event) override; + void paintEvent(QPaintEvent *event) override; Q_SIGNALS: void fullScreenChanged(bool fullScreen); @@ -188,23 +188,23 @@ public: void releaseControl(); - void setBrightness(int brightness); - void setContrast(int contrast); - void setHue(int hue); - void setSaturation(int saturation); + void setBrightness(int brightness) override; + void setContrast(int contrast) override; + void setHue(int hue) override; + void setSaturation(int saturation) override; - void setFullScreen(bool fullScreen); + void setFullScreen(bool fullScreen) override; - Qt::AspectRatioMode aspectRatioMode() const; - void setAspectRatioMode(Qt::AspectRatioMode mode); + Qt::AspectRatioMode aspectRatioMode() const override; + void setAspectRatioMode(Qt::AspectRatioMode mode) override; - QSize sizeHint() const; + QSize sizeHint() const override; - void showEvent(); - void hideEvent(QHideEvent *event); - void resizeEvent(QResizeEvent *event); - void moveEvent(QMoveEvent *event); - void paintEvent(QPaintEvent *event); + void showEvent() override; + void hideEvent(QHideEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void moveEvent(QMoveEvent *event) override; + void paintEvent(QPaintEvent *event) override; #if defined(Q_WS_WIN) bool winEvent(MSG *message, long *result); diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm index a1213be3b..7fd04250e 100644 --- a/src/plugins/avfoundation/camera/avfcameraservice.mm +++ b/src/plugins/avfoundation/camera/avfcameraservice.mm @@ -37,9 +37,9 @@ ** ****************************************************************************/ +#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qvariant.h> #include <QtCore/qdebug.h> -#include <QtCore/qsysinfo.h> #include "avfcameraservice.h" #include "avfcameracontrol.h" @@ -96,7 +96,7 @@ AVFCameraService::AVFCameraService(QObject *parent): m_cameraFocusControl = new AVFCameraFocusControl(this); m_cameraExposureControl = 0; #if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) m_cameraExposureControl = new AVFCameraExposureControl(this); #endif diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm index c32b072ef..0b7c0e9d8 100644 --- a/src/plugins/avfoundation/camera/avfcamerasession.mm +++ b/src/plugins/avfoundation/camera/avfcamerasession.mm @@ -432,18 +432,12 @@ void AVFCameraSession::removeProbe(AVFMediaVideoProbeControl *probe) FourCharCode AVFCameraSession::defaultCodec() { if (!m_defaultCodec) { -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - if (AVCaptureDevice *device = videoCaptureDevice()) { - AVCaptureDeviceFormat *format = device.activeFormat; - if (!format || !format.formatDescription) - return m_defaultCodec; - m_defaultCodec = CMVideoFormatDescriptionGetCodecType(format.formatDescription); - } + if (AVCaptureDevice *device = videoCaptureDevice()) { + AVCaptureDeviceFormat *format = device.activeFormat; + if (!format || !format.formatDescription) + return m_defaultCodec; + m_defaultCodec = CMVideoFormatDescriptionGetCodecType(format.formatDescription); } -#else - // TODO: extract media subtype. -#endif } return m_defaultCodec; } diff --git a/src/plugins/avfoundation/camera/avfcamerautility.h b/src/plugins/avfoundation/camera/avfcamerautility.h index 4da5f751e..ba1bd3861 100644 --- a/src/plugins/avfoundation/camera/avfcamerautility.h +++ b/src/plugins/avfoundation/camera/avfcamerautility.h @@ -40,7 +40,6 @@ #ifndef AVFCAMERAUTILITY_H #define AVFCAMERAUTILITY_H -#include <QtCore/qsysinfo.h> #include <QtCore/qglobal.h> #include <QtCore/qvector.h> #include <QtCore/qdebug.h> @@ -152,23 +151,9 @@ private: Q_DISABLE_COPY(AVFScopedPointer); }; -inline QSysInfo::MacVersion qt_OS_limit(QSysInfo::MacVersion osxVersion, - QSysInfo::MacVersion iosVersion) -{ -#ifdef Q_OS_OSX - Q_UNUSED(iosVersion) - return osxVersion; -#else - Q_UNUSED(osxVersion) - return iosVersion; -#endif -} - typedef QPair<qreal, qreal> AVFPSRange; AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection); -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - QVector<AVCaptureDeviceFormat *> qt_unique_device_formats(AVCaptureDevice *captureDevice, FourCharCode preferredFormat); QSize qt_device_format_resolution(AVCaptureDeviceFormat *format); @@ -185,8 +170,6 @@ AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *forma bool qt_formats_are_equal(AVCaptureDeviceFormat *f1, AVCaptureDeviceFormat *f2); bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat *format, bool preserveFps); -#endif - AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection); void qt_set_framerate_limits(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS); diff --git a/src/plugins/avfoundation/camera/avfcamerautility.mm b/src/plugins/avfoundation/camera/avfcamerautility.mm index 279642e4f..872075e0f 100644 --- a/src/plugins/avfoundation/camera/avfcamerautility.mm +++ b/src/plugins/avfoundation/camera/avfcamerautility.mm @@ -40,6 +40,7 @@ #include "avfcamerautility.h" #include "avfcameradebug.h" +#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qvector.h> #include <QtCore/qpair.h> #include <private/qmultimediautils_p.h> @@ -66,26 +67,17 @@ AVFPSRange qt_connection_framerates(AVCaptureConnection *videoConnection) } } -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0) -#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9) -#endif - { - if (videoConnection.supportsVideoMaxFrameDuration) { - const CMTime cmMax = videoConnection.videoMaxFrameDuration; - if (CMTimeCompare(cmMax, kCMTimeInvalid)) { - if (const Float64 maxSeconds = CMTimeGetSeconds(cmMax)) - newRange.first = 1. / maxSeconds; - } + if (videoConnection.supportsVideoMaxFrameDuration) { + const CMTime cmMax = videoConnection.videoMaxFrameDuration; + if (CMTimeCompare(cmMax, kCMTimeInvalid)) { + if (const Float64 maxSeconds = CMTimeGetSeconds(cmMax)) + newRange.first = 1. / maxSeconds; } } -#endif return newRange; } -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - namespace { inline bool qt_area_sane(const QSize &size) @@ -189,7 +181,7 @@ QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format) Q_ASSERT(format); QSize res; #if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { const CMVideoDimensions hrDim(format.highResolutionStillImageDimensions); res.setWidth(hrDim.width); res.setHeight(hrDim.height); @@ -436,8 +428,6 @@ bool qt_set_active_format(AVCaptureDevice *captureDevice, AVCaptureDeviceFormat return true; } -#endif // SDK - void qt_set_framerate_limits(AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS) { Q_ASSERT(videoConnection); @@ -458,32 +448,17 @@ void qt_set_framerate_limits(AVCaptureConnection *videoConnection, qreal minFPS, if (videoConnection.supportsVideoMinFrameDuration) videoConnection.videoMinFrameDuration = minDuration; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0) -#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_9) { - if (minFPS > 0.) + CMTime maxDuration = kCMTimeInvalid; + if (minFPS > 0.) { + if (!videoConnection.supportsVideoMaxFrameDuration) qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported"; - } else -#endif - { - CMTime maxDuration = kCMTimeInvalid; - if (minFPS > 0.) { - if (!videoConnection.supportsVideoMaxFrameDuration) - qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported"; - else - maxDuration = CMTimeMake(1, minFPS); - } - if (videoConnection.supportsVideoMaxFrameDuration) - videoConnection.videoMaxFrameDuration = maxDuration; + else + maxDuration = CMTimeMake(1, minFPS); } -#else - if (minFPS > 0.) - qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported"; -#endif + if (videoConnection.supportsVideoMaxFrameDuration) + videoConnection.videoMaxFrameDuration = maxDuration; } -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - CMTime qt_adjusted_frame_duration(AVFrameRateRange *range, qreal fps) { Q_ASSERT(range); @@ -549,7 +524,7 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice, qreal minFPS, qreal #ifdef Q_OS_IOS [captureDevice setActiveVideoMinFrameDuration:minFrameDuration]; [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration]; -#else // Q_OS_OSX +#elif defined(Q_OS_MACOS) if (CMTimeCompare(minFrameDuration, kCMTimeInvalid) == 0 && CMTimeCompare(maxFrameDuration, kCMTimeInvalid) == 0) { AVFrameRateRange *range = captureDevice.activeFormat.videoSupportedFrameRateRanges.firstObject; @@ -560,32 +535,16 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice, qreal minFPS, qreal if (CMTimeCompare(minFrameDuration, kCMTimeInvalid)) [captureDevice setActiveVideoMinFrameDuration:minFrameDuration]; -#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) -#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9) -#endif - { - if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid)) - [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration]; - } -#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) -#endif // Q_OS_OSX + if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid)) + [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration]; +#endif // Q_OS_MACOS } -#endif // Platform SDK >= 10.9, >= 7.0. - void qt_set_framerate_limits(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS) { Q_ASSERT(captureDevice); -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0)) - qt_set_framerate_limits(captureDevice, minFPS, maxFPS); - else -#endif - if (videoConnection) - qt_set_framerate_limits(videoConnection, minFPS, maxFPS); - + qt_set_framerate_limits(captureDevice, minFPS, maxFPS); } AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection) @@ -593,33 +552,16 @@ AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnec Q_ASSERT(captureDevice); AVFPSRange fps; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - const CMTime minDuration = captureDevice.activeVideoMinFrameDuration; - if (CMTimeCompare(minDuration, kCMTimeInvalid)) { - if (const Float64 minSeconds = CMTimeGetSeconds(minDuration)) - fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration. - } - -#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) -#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9) -#endif - { - const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration; - if (CMTimeCompare(maxDuration, kCMTimeInvalid)) { - if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration)) - fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration. - } - } -#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) + const CMTime minDuration = captureDevice.activeVideoMinFrameDuration; + if (CMTimeCompare(minDuration, kCMTimeInvalid)) { + if (const Float64 minSeconds = CMTimeGetSeconds(minDuration)) + fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration. + } - } else { -#else // OSX < 10.7 or iOS < 7.0 - { -#endif // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (videoConnection) - fps = qt_connection_framerates(videoConnection); + const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration; + if (CMTimeCompare(maxDuration, kCMTimeInvalid)) { + if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration)) + fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration. } return fps; diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm index 23dd2a4aa..0054a8d01 100644 --- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm +++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm @@ -47,7 +47,6 @@ #include <QtMultimedia/qabstractvideosurface.h> #include <QtCore/qvariant.h> -#include <QtCore/qsysinfo.h> #include <QtCore/qvector.h> #include <QtCore/qdebug.h> #include <QtCore/qlist.h> @@ -97,57 +96,36 @@ QList<QCameraViewfinderSettings> AVFCameraViewfinderSettingsControl2::supportedV if (!pixelFormats.size()) pixelFormats << QVideoFrame::Format_Invalid; // The default value. -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - if (!captureDevice.formats || !captureDevice.formats.count) { - qDebugCamera() << Q_FUNC_INFO << "no capture device formats found"; - return supportedSettings; - } + if (!captureDevice.formats || !captureDevice.formats.count) { + qDebugCamera() << Q_FUNC_INFO << "no capture device formats found"; + return supportedSettings; + } - const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice, - m_service->session()->defaultCodec())); - for (int i = 0; i < formats.size(); ++i) { - AVCaptureDeviceFormat *format = formats[i]; - - const QSize res(qt_device_format_resolution(format)); - if (res.isNull() || !res.isValid()) - continue; - const QSize par(qt_device_format_pixel_aspect_ratio(format)); - if (par.isNull() || !par.isValid()) - continue; - - framerates = qt_device_format_framerates(format); - if (!framerates.size()) - framerates << AVFPSRange(); // The default value. - - for (int i = 0; i < pixelFormats.size(); ++i) { - for (int j = 0; j < framerates.size(); ++j) { - QCameraViewfinderSettings newSet; - newSet.setResolution(res); - newSet.setPixelAspectRatio(par); - newSet.setPixelFormat(pixelFormats[i]); - newSet.setMinimumFrameRate(framerates[j].first); - newSet.setMaximumFrameRate(framerates[j].second); - supportedSettings << newSet; - } - } - } - } else { -#else - { -#endif - AVCaptureConnection *connection = videoConnection(); - if (connection) { - // TODO: resolution and PAR. - framerates << qt_connection_framerates(connection); - for (int i = 0; i < pixelFormats.size(); ++i) { - for (int j = 0; j < framerates.size(); ++j) { - QCameraViewfinderSettings newSet; - newSet.setPixelFormat(pixelFormats[i]); - newSet.setMinimumFrameRate(framerates[j].first); - newSet.setMaximumFrameRate(framerates[j].second); - supportedSettings << newSet; - } + const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice, + m_service->session()->defaultCodec())); + for (int i = 0; i < formats.size(); ++i) { + AVCaptureDeviceFormat *format = formats[i]; + + const QSize res(qt_device_format_resolution(format)); + if (res.isNull() || !res.isValid()) + continue; + const QSize par(qt_device_format_pixel_aspect_ratio(format)); + if (par.isNull() || !par.isValid()) + continue; + + framerates = qt_device_format_framerates(format); + if (!framerates.size()) + framerates << AVFPSRange(); // The default value. + + for (int i = 0; i < pixelFormats.size(); ++i) { + for (int j = 0; j < framerates.size(); ++j) { + QCameraViewfinderSettings newSet; + newSet.setResolution(res); + newSet.setPixelAspectRatio(par); + newSet.setPixelFormat(pixelFormats[i]); + newSet.setMinimumFrameRate(framerates[j].first); + newSet.setMaximumFrameRate(framerates[j].second); + supportedSettings << newSet; } } } @@ -170,25 +148,21 @@ QCameraViewfinderSettings AVFCameraViewfinderSettingsControl2::viewfinderSetting return settings; } -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - if (!captureDevice.activeFormat) { - qDebugCamera() << Q_FUNC_INFO << "no active capture device format"; - return settings; - } - - const QSize res(qt_device_format_resolution(captureDevice.activeFormat)); - const QSize par(qt_device_format_pixel_aspect_ratio(captureDevice.activeFormat)); - if (res.isNull() || !res.isValid() || par.isNull() || !par.isValid()) { - qDebugCamera() << Q_FUNC_INFO << "failed to obtain resolution/pixel aspect ratio"; - return settings; - } + if (!captureDevice.activeFormat) { + qDebugCamera() << Q_FUNC_INFO << "no active capture device format"; + return settings; + } - settings.setResolution(res); - settings.setPixelAspectRatio(par); + const QSize res(qt_device_format_resolution(captureDevice.activeFormat)); + const QSize par(qt_device_format_pixel_aspect_ratio(captureDevice.activeFormat)); + if (res.isNull() || !res.isValid() || par.isNull() || !par.isValid()) { + qDebugCamera() << Q_FUNC_INFO << "failed to obtain resolution/pixel aspect ratio"; + return settings; } -#endif - // TODO: resolution and PAR before 7.0. + + settings.setResolution(res); + settings.setPixelAspectRatio(par); + const AVFPSRange fps = qt_current_framerates(captureDevice, videoConnection()); settings.setMinimumFrameRate(fps.first); settings.setMaximumFrameRate(fps.second); @@ -285,35 +259,30 @@ AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch( if (!captureDevice || settings.isNull()) return nil; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - - const QSize &resolution = settings.resolution(); - if (!resolution.isNull() && resolution.isValid()) { - // Either the exact match (including high resolution for images on iOS) - // or a format with a resolution close to the requested one. - return qt_find_best_resolution_match(captureDevice, resolution, - m_service->session()->defaultCodec()); - } - - // No resolution requested, what about framerates? - if (!qt_framerates_sane(settings)) { - qDebugCamera() << Q_FUNC_INFO << "invalid framerate requested (min/max):" - << settings.minimumFrameRate() << settings.maximumFrameRate(); - return nil; - } + const QSize &resolution = settings.resolution(); + if (!resolution.isNull() && resolution.isValid()) { + // Either the exact match (including high resolution for images on iOS) + // or a format with a resolution close to the requested one. + return qt_find_best_resolution_match(captureDevice, resolution, + m_service->session()->defaultCodec()); + } - const qreal minFPS(settings.minimumFrameRate()); - const qreal maxFPS(settings.maximumFrameRate()); - if (minFPS || maxFPS) - return qt_find_best_framerate_match(captureDevice, - m_service->session()->defaultCodec(), - maxFPS ? maxFPS : minFPS); - // Ignore PAR for the moment (PAR without resolution can - // pick a format with really bad resolution). - // No need to test pixel format, just return settings. + // No resolution requested, what about framerates? + if (!qt_framerates_sane(settings)) { + qDebugCamera() << Q_FUNC_INFO << "invalid framerate requested (min/max):" + << settings.minimumFrameRate() << settings.maximumFrameRate(); + return nil; } -#endif + + const qreal minFPS(settings.minimumFrameRate()); + const qreal maxFPS(settings.maximumFrameRate()); + if (minFPS || maxFPS) + return qt_find_best_framerate_match(captureDevice, + m_service->session()->defaultCodec(), + maxFPS ? maxFPS : minFPS); + // Ignore PAR for the moment (PAR without resolution can + // pick a format with really bad resolution). + // No need to test pixel format, just return settings. return nil; } @@ -395,7 +364,6 @@ bool AVFCameraViewfinderSettingsControl2::applySettings(const QCameraViewfinderS bool activeFormatChanged = false; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) AVCaptureDeviceFormat *match = findBestFormatMatch(settings); if (match) { activeFormatChanged = qt_set_active_format(captureDevice, match, false); @@ -403,7 +371,6 @@ bool AVFCameraViewfinderSettingsControl2::applySettings(const QCameraViewfinderS qDebugCamera() << Q_FUNC_INFO << "matching device format not found"; // We still can update the pixel format at least. } -#endif AVCaptureVideoDataOutput *videoOutput = m_service->videoOutput() ? m_service->videoOutput()->videoDataOutput() : 0; if (videoOutput) { diff --git a/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm b/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm index 2662793f8..47dc736a1 100644 --- a/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm +++ b/src/plugins/avfoundation/camera/avfcamerazoomcontrol.mm @@ -44,7 +44,6 @@ #include "avfcameracontrol.h" #include "avfcameradebug.h" -#include <QtCore/qsysinfo.h> #include <QtCore/qglobal.h> #include <QtCore/qdebug.h> @@ -98,9 +97,6 @@ void AVFCameraZoomControl::zoomTo(qreal optical, qreal digital) { Q_UNUSED(optical) Q_UNUSED(digital) -#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) - return; if (qFuzzyCompare(CGFloat(digital), m_requestedZoomFactor)) return; @@ -109,15 +105,10 @@ void AVFCameraZoomControl::zoomTo(qreal optical, qreal digital) Q_EMIT requestedDigitalZoomChanged(digital); zoomToRequestedDigital(); -#endif } void AVFCameraZoomControl::cameraStateChanged() { -#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) - return; - const QCamera::State state = m_session->state(); if (state != QCamera::ActiveState) { if (state == QCamera::UnloadedState && m_maxZoomFactor > 1.) { @@ -146,15 +137,10 @@ void AVFCameraZoomControl::cameraStateChanged() } zoomToRequestedDigital(); -#endif } void AVFCameraZoomControl::zoomToRequestedDigital() { -#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) - return; - AVCaptureDevice *captureDevice = m_session->videoCaptureDevice(); if (!captureDevice || !captureDevice.activeFormat) return; @@ -186,7 +172,6 @@ void AVFCameraZoomControl::zoomToRequestedDigital() m_zoomFactor = clampedZoom; Q_EMIT currentDigitalZoomChanged(clampedZoom); } -#endif } QT_END_NAMESPACE diff --git a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm index e5aa8a4c2..8384ce6ae 100644 --- a/src/plugins/avfoundation/camera/avfimageencodercontrol.mm +++ b/src/plugins/avfoundation/camera/avfimageencodercontrol.mm @@ -48,7 +48,7 @@ #include <QtMultimedia/qmediaencodersettings.h> -#include <QtCore/qsysinfo.h> +#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qdebug.h> #include <AVFoundation/AVFoundation.h> @@ -84,36 +84,28 @@ QList<QSize> AVFImageEncoderControl::supportedResolutions(const QImageEncoderSet if (!videoCaptureDeviceIsValid()) return resolutions; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); - const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice, - m_service->session()->defaultCodec())); + AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); + const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(captureDevice, + m_service->session()->defaultCodec())); - for (int i = 0; i < formats.size(); ++i) { - AVCaptureDeviceFormat *format = formats[i]; + for (int i = 0; i < formats.size(); ++i) { + AVCaptureDeviceFormat *format = formats[i]; - const QSize res(qt_device_format_resolution(format)); - if (!res.isNull() && res.isValid()) - resolutions << res; + const QSize res(qt_device_format_resolution(format)); + if (!res.isNull() && res.isValid()) + resolutions << res; #if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { - // From Apple's docs (iOS): - // By default, AVCaptureStillImageOutput emits images with the same dimensions as - // its source AVCaptureDevice instance’s activeFormat.formatDescription. However, - // if you set this property to YES, the receiver emits still images at the capture - // device’s highResolutionStillImageDimensions value. - const QSize hrRes(qt_device_format_high_resolution(format)); - if (!hrRes.isNull() && hrRes.isValid()) - resolutions << res; - } -#endif + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { + // From Apple's docs (iOS): + // By default, AVCaptureStillImageOutput emits images with the same dimensions as + // its source AVCaptureDevice instance’s activeFormat.formatDescription. However, + // if you set this property to YES, the receiver emits still images at the capture + // device’s highResolutionStillImageDimensions value. + const QSize hrRes(qt_device_format_high_resolution(format)); + if (!hrRes.isNull() && hrRes.isValid()) + resolutions << res; } - } else { -#else - { #endif - // TODO: resolutions without AVCaptureDeviceFormat ... } if (continuous) @@ -134,40 +126,32 @@ QImageEncoderSettings AVFImageEncoderControl::imageSettings() const if (!videoCaptureDeviceIsValid()) return settings; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); - if (!captureDevice.activeFormat) { - qDebugCamera() << Q_FUNC_INFO << "no active format"; - return settings; - } + AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); + if (!captureDevice.activeFormat) { + qDebugCamera() << Q_FUNC_INFO << "no active format"; + return settings; + } - QSize res(qt_device_format_resolution(captureDevice.activeFormat)); + QSize res(qt_device_format_resolution(captureDevice.activeFormat)); #if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { - if (!m_service->imageCaptureControl() || !m_service->imageCaptureControl()->stillImageOutput()) { - qDebugCamera() << Q_FUNC_INFO << "no still image output"; - return settings; - } - - AVCaptureStillImageOutput *stillImageOutput = m_service->imageCaptureControl()->stillImageOutput(); - if (stillImageOutput.highResolutionStillImageOutputEnabled) - res = qt_device_format_high_resolution(captureDevice.activeFormat); - } -#endif - if (res.isNull() || !res.isValid()) { - qDebugCamera() << Q_FUNC_INFO << "failed to exctract the image resolution"; + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { + if (!m_service->imageCaptureControl() || !m_service->imageCaptureControl()->stillImageOutput()) { + qDebugCamera() << Q_FUNC_INFO << "no still image output"; return settings; } - settings.setResolution(res); - } else { -#else - { + AVCaptureStillImageOutput *stillImageOutput = m_service->imageCaptureControl()->stillImageOutput(); + if (stillImageOutput.highResolutionStillImageOutputEnabled) + res = qt_device_format_high_resolution(captureDevice.activeFormat); + } #endif - // TODO: resolution without AVCaptureDeviceFormat. + if (res.isNull() || !res.isValid()) { + qDebugCamera() << Q_FUNC_INFO << "failed to exctract the image resolution"; + return settings; } + settings.setResolution(res); + settings.setCodec(QLatin1String("jpeg")); return settings; @@ -222,34 +206,26 @@ bool AVFImageEncoderControl::applySettings() bool activeFormatChanged = false; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); - AVCaptureDeviceFormat *match = qt_find_best_resolution_match(captureDevice, res, - m_service->session()->defaultCodec()); + AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice(); + AVCaptureDeviceFormat *match = qt_find_best_resolution_match(captureDevice, res, + m_service->session()->defaultCodec()); - if (!match) { - qDebugCamera() << Q_FUNC_INFO << "unsupported resolution:" << res; - return false; - } + if (!match) { + qDebugCamera() << Q_FUNC_INFO << "unsupported resolution:" << res; + return false; + } - activeFormatChanged = qt_set_active_format(captureDevice, match, true); + activeFormatChanged = qt_set_active_format(captureDevice, match, true); #if defined(Q_OS_IOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { - AVCaptureStillImageOutput *imageOutput = m_service->imageCaptureControl()->stillImageOutput(); - if (res == qt_device_format_high_resolution(captureDevice.activeFormat)) - imageOutput.highResolutionStillImageOutputEnabled = YES; - else - imageOutput.highResolutionStillImageOutputEnabled = NO; - } -#endif - } else { -#else - { -#endif - // TODO: resolution without capture device format ... + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { + AVCaptureStillImageOutput *imageOutput = m_service->imageCaptureControl()->stillImageOutput(); + if (res == qt_device_format_high_resolution(captureDevice.activeFormat)) + imageOutput.highResolutionStillImageOutputEnabled = YES; + else + imageOutput.highResolutionStillImageOutputEnabled = NO; } +#endif return activeFormatChanged; } diff --git a/src/plugins/avfoundation/camera/avfmediaassetwriter.mm b/src/plugins/avfoundation/camera/avfmediaassetwriter.mm index 28735bc6a..5a1257f6c 100644 --- a/src/plugins/avfoundation/camera/avfmediaassetwriter.mm +++ b/src/plugins/avfoundation/camera/avfmediaassetwriter.mm @@ -47,7 +47,6 @@ #include "avfmediacontainercontrol.h" #include <QtCore/qmetaobject.h> -#include <QtCore/qsysinfo.h> QT_USE_NAMESPACE diff --git a/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm b/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm index b478ba321..bbb16e709 100644 --- a/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm +++ b/src/plugins/avfoundation/camera/avfvideoencodersettingscontrol.mm @@ -56,7 +56,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QStringList, supportedCodecs, (QStringList() << QLatin #endif )) -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) static bool format_supports_framerate(AVCaptureDeviceFormat *format, qreal fps) { if (format && fps > qreal(0)) { @@ -74,7 +73,6 @@ static bool format_supports_framerate(AVCaptureDeviceFormat *format, qreal fps) return false; } -#endif static bool real_list_contains(const QList<qreal> &list, qreal value) { @@ -107,24 +105,20 @@ QList<QSize> AVFVideoEncoderSettingsControl::supportedResolutions(const QVideoEn QList<QSize> resolutions; resolutions.append(QSize(32, 32)); -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - AVCaptureDevice *device = m_service->session()->videoCaptureDevice(); - if (device) { - int maximumWidth = 0; - const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(device, - m_service->session()->defaultCodec())); - for (int i = 0; i < formats.size(); ++i) { - const QSize res(qt_device_format_resolution(formats[i])); - if (res.width() > maximumWidth) - maximumWidth = res.width(); - } - - if (maximumWidth > 0) - resolutions.append(QSize(maximumWidth, maximumWidth)); + AVCaptureDevice *device = m_service->session()->videoCaptureDevice(); + if (device) { + int maximumWidth = 0; + const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(device, + m_service->session()->defaultCodec())); + for (int i = 0; i < formats.size(); ++i) { + const QSize res(qt_device_format_resolution(formats[i])); + if (res.width() > maximumWidth) + maximumWidth = res.width(); } + + if (maximumWidth > 0) + resolutions.append(QSize(maximumWidth, maximumWidth)); } -#endif if (resolutions.count() == 1) resolutions.append(QSize(3840, 3840)); @@ -135,45 +129,39 @@ QList<QSize> AVFVideoEncoderSettingsControl::supportedResolutions(const QVideoEn QList<qreal> AVFVideoEncoderSettingsControl::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const { -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) QList<qreal> uniqueFrameRates; - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) { - AVCaptureDevice *device = m_service->session()->videoCaptureDevice(); - if (!device) - return uniqueFrameRates; + AVCaptureDevice *device = m_service->session()->videoCaptureDevice(); + if (!device) + return uniqueFrameRates; - if (continuous) - *continuous = false; + if (continuous) + *continuous = false; - QVector<AVFPSRange> allRates; + QVector<AVFPSRange> allRates; - if (!settings.resolution().isValid()) { - const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(device, 0)); - for (int i = 0; i < formats.size(); ++i) { - AVCaptureDeviceFormat *format = formats.at(i); - allRates += qt_device_format_framerates(format); - } - } else { - AVCaptureDeviceFormat *format = qt_find_best_resolution_match(device, - settings.resolution(), - m_service->session()->defaultCodec()); - if (format) - allRates = qt_device_format_framerates(format); + if (!settings.resolution().isValid()) { + const QVector<AVCaptureDeviceFormat *> formats(qt_unique_device_formats(device, 0)); + for (int i = 0; i < formats.size(); ++i) { + AVCaptureDeviceFormat *format = formats.at(i); + allRates += qt_device_format_framerates(format); } + } else { + AVCaptureDeviceFormat *format = qt_find_best_resolution_match(device, + settings.resolution(), + m_service->session()->defaultCodec()); + if (format) + allRates = qt_device_format_framerates(format); + } - for (int j = 0; j < allRates.size(); ++j) { - if (!real_list_contains(uniqueFrameRates, allRates[j].first)) - uniqueFrameRates.append(allRates[j].first); - if (!real_list_contains(uniqueFrameRates, allRates[j].second)) - uniqueFrameRates.append(allRates[j].second); - } + for (int j = 0; j < allRates.size(); ++j) { + if (!real_list_contains(uniqueFrameRates, allRates[j].first)) + uniqueFrameRates.append(allRates[j].first); + if (!real_list_contains(uniqueFrameRates, allRates[j].second)) + uniqueFrameRates.append(allRates[j].second); } return uniqueFrameRates; -#else - return QList<qreal>(); -#endif } QStringList AVFVideoEncoderSettingsControl::supportedVideoCodecs() const @@ -243,7 +231,6 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection int w = m_requestedSettings.resolution().width(); int h = m_requestedSettings.resolution().height(); -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) if (AVCaptureDeviceFormat *currentFormat = device.activeFormat) { CMFormatDescriptionRef formatDesc = currentFormat.formatDescription; CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDesc); @@ -300,7 +287,6 @@ NSDictionary *AVFVideoEncoderSettingsControl::applySettings(AVCaptureConnection h = qMin(h, dim.height); } } -#endif if (w > 0 && h > 0) { // Width and height must be divisible by 2 @@ -382,13 +368,11 @@ void AVFVideoEncoderSettingsControl::unapplySettings(AVCaptureConnection *connec const bool needFpsChanged = m_restoreFps.first || m_restoreFps.second; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0) if (m_restoreFormat) { qt_set_active_format(device, m_restoreFormat, !needFpsChanged); [m_restoreFormat release]; m_restoreFormat = nil; } -#endif if (needFpsChanged) { qt_set_framerate_limits(device, connection, m_restoreFps.first, m_restoreFps.second); diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro index 9d2f07656..4b960ed5a 100644 --- a/src/plugins/avfoundation/camera/camera.pro +++ b/src/plugins/avfoundation/camera/camera.pro @@ -5,13 +5,16 @@ CONFIG += no_keywords QT += multimedia-private network -LIBS += -framework AudioToolbox \ +LIBS += -framework CoreFoundation \ + -framework Foundation \ + -framework AudioToolbox \ -framework CoreAudio \ -framework QuartzCore \ -framework CoreMedia osx:LIBS += -framework AppKit \ -framework AudioUnit -ios:LIBS += -framework CoreVideo +ios:LIBS += -framework CoreGraphics \ + -framework CoreVideo QMAKE_USE += avfoundation diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.h index b18862b55..4460a4867 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.h @@ -63,7 +63,6 @@ private: AVFMediaPlayerControl *m_control; QMediaControl *m_videoOutput; AVFMediaPlayerMetaDataControl *m_playerMetaDataControl; - bool m_enableRenderControl; }; QT_END_NAMESPACE diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm index 526c36cc6..6218401b3 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayerservice.mm @@ -48,32 +48,19 @@ #endif #include "avfvideowindowcontrol.h" -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_6_0) #import <AVFoundation/AVFoundation.h> -#endif QT_USE_NAMESPACE AVFMediaPlayerService::AVFMediaPlayerService(QObject *parent) : QMediaService(parent) , m_videoOutput(0) - , m_enableRenderControl(true) { m_session = new AVFMediaPlayerSession(this); m_control = new AVFMediaPlayerControl(this); m_control->setSession(m_session); m_playerMetaDataControl = new AVFMediaPlayerMetaDataControl(m_session, this); -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_6_0) - // AVPlayerItemVideoOutput is available in SDK - #if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_8, __IPHONE_6_0) - // might not be available at runtime - #if defined(Q_OS_IOS) || defined(Q_OS_TVOS) - m_enableRenderControl = [AVPlayerItemVideoOutput class] != 0; - #endif - #endif -#endif - connect(m_control, SIGNAL(mediaChanged(QMediaContent)), m_playerMetaDataControl, SLOT(updateTags())); } @@ -98,7 +85,7 @@ QMediaControl *AVFMediaPlayerService::requestControl(const char *name) return m_playerMetaDataControl; - if (m_enableRenderControl && (qstrcmp(name, QVideoRendererControl_iid) == 0)) { + if (qstrcmp(name, QVideoRendererControl_iid) == 0) { if (!m_videoOutput) m_videoOutput = new AVFVideoRendererControl(this); diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h index f0cb46aaa..5696faf15 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h @@ -86,8 +86,6 @@ public: qreal playbackRate() const; - inline bool isVolumeSupported() const { return m_volumeSupported; } - public Q_SLOTS: void setPlaybackRate(qreal rate); @@ -169,7 +167,6 @@ private: QMediaContent m_resources; ResourceHandler m_resourceHandler; - const bool m_volumeSupported; bool m_muted; bool m_tryingAsync; int m_volume; diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 473a18884..e15c2e44a 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -233,7 +233,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe [m_player retain]; //Set the initial volume on new player object - if (self.session && self.session->isVolumeSupported()) { + if (self.session) { [m_player setVolume:m_session->volume() / 100.0f]; [m_player setMuted:m_session->isMuted()]; } @@ -380,11 +380,6 @@ AVFMediaPlayerSession::AVFMediaPlayerSession(AVFMediaPlayerService *service, QOb , m_state(QMediaPlayer::StoppedState) , m_mediaStatus(QMediaPlayer::NoMedia) , m_mediaStream(0) -#ifdef Q_OS_IOS - , m_volumeSupported(QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) -#else - , m_volumeSupported(true) -#endif , m_muted(false) , m_tryingAsync(false) , m_volume(100) @@ -749,11 +744,6 @@ void AVFMediaPlayerSession::setVolume(int volume) qDebug() << Q_FUNC_INFO << volume; #endif - if (!m_volumeSupported) { - qWarning("%s not implemented, requires iOS 7 or later", Q_FUNC_INFO); - return; - } - if (m_volume == volume) return; @@ -772,11 +762,6 @@ void AVFMediaPlayerSession::setMuted(bool muted) qDebug() << Q_FUNC_INFO << muted; #endif - if (!m_volumeSupported) { - qWarning("%s not implemented, requires iOS 7 or later", Q_FUNC_INFO); - return; - } - if (m_muted == muted) return; diff --git a/src/plugins/coreaudio/coreaudiosessionmanager.mm b/src/plugins/coreaudio/coreaudiosessionmanager.mm index d381b82c0..923a1942f 100644 --- a/src/plugins/coreaudio/coreaudiosessionmanager.mm +++ b/src/plugins/coreaudio/coreaudiosessionmanager.mm @@ -42,10 +42,6 @@ #import <AVFoundation/AVAudioSession.h> #import <Foundation/Foundation.h> -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) -#include <AudioToolbox/AudioToolbox.h> -#endif - QT_BEGIN_NAMESPACE @interface CoreAudioSessionObserver : NSObject @@ -81,24 +77,19 @@ QT_BEGIN_NAMESPACE self->m_sessionManager = sessionManager; self->m_audioSession = [AVAudioSession sharedInstance]; -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0) -#endif - { - //Set up observers - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(audioSessionInterruption:) - name:AVAudioSessionInterruptionNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(audioSessionMediaServicesWereReset:) - name:AVAudioSessionMediaServicesWereResetNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(audioSessionRouteChange:) - name:AVAudioSessionRouteChangeNotification - object:self->m_audioSession]; - } + //Set up observers + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioSessionInterruption:) + name:AVAudioSessionInterruptionNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioSessionMediaServicesWereReset:) + name:AVAudioSessionMediaServicesWereResetNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioSessionRouteChange:) + name:AVAudioSessionRouteChangeNotification + object:self->m_audioSession]; return self; } @@ -109,20 +100,15 @@ QT_BEGIN_NAMESPACE qDebug() << Q_FUNC_INFO; #endif -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0) -#endif - { - [[NSNotificationCenter defaultCenter] removeObserver:self - name:AVAudioSessionInterruptionNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:AVAudioSessionMediaServicesWereResetNotification - object:self->m_audioSession]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:AVAudioSessionRouteChangeNotification - object:self->m_audioSession]; - } + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVAudioSessionInterruptionNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVAudioSessionMediaServicesWereResetNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVAudioSessionRouteChangeNotification + object:self->m_audioSession]; [super dealloc]; } @@ -285,9 +271,6 @@ bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionC #endif break; case CoreAudioSessionManager::MultiRoute: -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0) -#endif targetCategory = AVAudioSessionCategoryMultiRoute; break; } @@ -295,16 +278,9 @@ bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionC if (targetCategory == nil) return false; -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_6_0) { - return [[m_sessionObserver audioSession] setCategory:targetCategory error:nil]; - } else -#endif - { - return [[m_sessionObserver audioSession] setCategory:targetCategory - withOptions:(AVAudioSessionCategoryOptions)options - error:nil]; - } + return [[m_sessionObserver audioSession] setCategory:targetCategory + withOptions:(AVAudioSessionCategoryOptions)options + error:nil]; } bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes mode) @@ -327,9 +303,6 @@ bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes targetMode = AVAudioSessionModeMeasurement; break; case CoreAudioSessionManager::MoviePlayback: -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0) -#endif targetMode = AVAudioSessionModeMoviePlayback; break; } @@ -360,11 +333,7 @@ CoreAudioSessionManager::AudioSessionCategorys CoreAudioSessionManager::category } else if (category == AVAudioSessionCategoryAudioProcessing) { localCategory = AudioProcessing; #endif - } else if ( -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0 && -#endif - category == AVAudioSessionCategoryMultiRoute) { + } else if (category == AVAudioSessionCategoryMultiRoute) { localCategory = MultiRoute; } @@ -386,11 +355,7 @@ CoreAudioSessionManager::AudioSessionModes CoreAudioSessionManager::mode() localMode = VideoRecording; } else if (mode == AVAudioSessionModeMeasurement) { localMode = Measurement; - } else if ( -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_6_0 && -#endif - mode == AVAudioSessionModeMoviePlayback) { + } else if (mode == AVAudioSessionModeMoviePlayback) { localMode = MoviePlayback; } @@ -419,32 +384,12 @@ QList<QByteArray> CoreAudioSessionManager::outputDevices() float CoreAudioSessionManager::currentIOBufferDuration() { -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_6_0) { - Float32 duration; - UInt32 size = sizeof(duration); - AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size, &duration); - return duration; - } else -#endif - { - return [[m_sessionObserver audioSession] IOBufferDuration]; - } + return [[m_sessionObserver audioSession] IOBufferDuration]; } float CoreAudioSessionManager::preferredSampleRate() { -#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_6_0) { - Float64 sampleRate; - UInt32 size = sizeof(sampleRate); - AudioSessionGetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, &size, &sampleRate); - return sampleRate; - } else -#endif - { - return [[m_sessionObserver audioSession] preferredSampleRate]; - } + return [[m_sessionObserver audioSession] preferredSampleRate]; } #ifdef QT_DEBUG_COREAUDIO diff --git a/src/plugins/directshow/camera/directshowcameraglobal.h b/src/plugins/directshow/camera/directshowcameraglobal.h index 75112a090..8df387b4a 100644 --- a/src/plugins/directshow/camera/directshowcameraglobal.h +++ b/src/plugins/directshow/camera/directshowcameraglobal.h @@ -44,9 +44,6 @@ #include <dshow.h> -DEFINE_GUID(MEDIASUBTYPE_I420, - 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); - extern const GUID MEDIASUBTYPE_RGB24; extern const GUID MEDIASUBTYPE_RGB32; extern const GUID MEDIASUBTYPE_YUY2; diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index 5587b479c..40e54a94d 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -47,148 +47,13 @@ #include "dscamerasession.h" #include "dsvideorenderer.h" +#include "directshowsamplegrabber.h" #include "directshowcameraglobal.h" +#include "directshowmediatype.h" +#include "directshowutils.h" QT_BEGIN_NAMESPACE - -namespace { -// DirectShow helper implementation -void _CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource) -{ - *pmtTarget = *pmtSource; - if (pmtTarget->cbFormat != 0) { - pmtTarget->pbFormat = reinterpret_cast<BYTE *>(CoTaskMemAlloc(pmtTarget->cbFormat)); - if (pmtTarget->pbFormat) - memcpy(pmtTarget->pbFormat, pmtSource->pbFormat, pmtTarget->cbFormat); - } - if (pmtTarget->pUnk != NULL) { - // pUnk should not be used. - pmtTarget->pUnk->AddRef(); - } -} - -void _FreeMediaType(AM_MEDIA_TYPE& mt) -{ - if (mt.cbFormat != 0) { - CoTaskMemFree((PVOID)mt.pbFormat); - mt.cbFormat = 0; - mt.pbFormat = NULL; - } - if (mt.pUnk != NULL) { - // pUnk should not be used. - mt.pUnk->Release(); - mt.pUnk = NULL; - } -} -} // end namespace - -static HRESULT getPin(IBaseFilter *filter, PIN_DIRECTION pinDir, IPin **pin); - - -class SampleGrabberCallbackPrivate : public ISampleGrabberCB -{ -public: - explicit SampleGrabberCallbackPrivate(DSCameraSession *session) - : m_ref(1) - , m_session(session) - { } - - virtual ~SampleGrabberCallbackPrivate() { } - - STDMETHODIMP_(ULONG) AddRef() - { - return InterlockedIncrement(&m_ref); - } - - STDMETHODIMP_(ULONG) Release() - { - ULONG ref = InterlockedDecrement(&m_ref); - if (ref == 0) - delete this; - return ref; - } - - STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) - { - if (NULL == ppvObject) - return E_POINTER; - if (riid == IID_IUnknown /*__uuidof(IUnknown) */ ) { - *ppvObject = static_cast<IUnknown*>(this); - return S_OK; - } - if (riid == IID_ISampleGrabberCB /*__uuidof(ISampleGrabberCB)*/ ) { - *ppvObject = static_cast<ISampleGrabberCB*>(this); - return S_OK; - } - return E_NOTIMPL; - } - - STDMETHODIMP SampleCB(double Time, IMediaSample *pSample) - { - Q_UNUSED(Time) - Q_UNUSED(pSample) - return E_NOTIMPL; - } - - STDMETHODIMP BufferCB(double time, BYTE *pBuffer, long bufferLen) - { - // We display frames as they arrive, the presentation time is - // irrelevant - Q_UNUSED(time); - - if (m_session) { - m_session->onFrameAvailable(reinterpret_cast<const char *>(pBuffer), - bufferLen); - } - - return S_OK; - } - -private: - ULONG m_ref; - DSCameraSession *m_session; -}; - -QVideoFrame::PixelFormat pixelFormatFromMediaSubtype(GUID uid) -{ - if (uid == MEDIASUBTYPE_ARGB32) - return QVideoFrame::Format_ARGB32; - else if (uid == MEDIASUBTYPE_RGB32) - return QVideoFrame::Format_RGB32; - else if (uid == MEDIASUBTYPE_RGB24) - return QVideoFrame::Format_RGB24; - else if (uid == MEDIASUBTYPE_RGB565) - return QVideoFrame::Format_RGB565; - else if (uid == MEDIASUBTYPE_RGB555) - return QVideoFrame::Format_RGB555; - else if (uid == MEDIASUBTYPE_AYUV) - return QVideoFrame::Format_AYUV444; - else if (uid == MEDIASUBTYPE_I420 || uid == MEDIASUBTYPE_IYUV) - return QVideoFrame::Format_YUV420P; - else if (uid == MEDIASUBTYPE_YV12) - return QVideoFrame::Format_YV12; - else if (uid == MEDIASUBTYPE_UYVY) - return QVideoFrame::Format_UYVY; - else if (uid == MEDIASUBTYPE_YUYV || uid == MEDIASUBTYPE_YUY2) - return QVideoFrame::Format_YUYV; - else if (uid == MEDIASUBTYPE_NV12) - return QVideoFrame::Format_NV12; - else if (uid == MEDIASUBTYPE_MJPG) - return QVideoFrame::Format_Jpeg; - else if (uid == MEDIASUBTYPE_IMC1) - return QVideoFrame::Format_IMC1; - else if (uid == MEDIASUBTYPE_IMC2) - return QVideoFrame::Format_IMC2; - else if (uid == MEDIASUBTYPE_IMC3) - return QVideoFrame::Format_IMC3; - else if (uid == MEDIASUBTYPE_IMC4) - return QVideoFrame::Format_IMC4; - else - return QVideoFrame::Format_Invalid; -} - - DSCameraSession::DSCameraSession(QObject *parent) : QObject(parent) , m_graphBuilder(Q_NULLPTR) @@ -196,7 +61,6 @@ DSCameraSession::DSCameraSession(QObject *parent) , m_sourceDeviceName(QLatin1String("default")) , m_sourceFilter(Q_NULLPTR) , m_needsHorizontalMirroring(false) - , m_previewFilter(Q_NULLPTR) , m_previewSampleGrabber(Q_NULLPTR) , m_nullRendererFilter(Q_NULLPTR) , m_previewStarted(false) @@ -207,8 +71,6 @@ DSCameraSession::DSCameraSession(QObject *parent) , m_currentImageId(-1) , m_status(QCamera::UnloadedStatus) { - ZeroMemory(&m_sourceFormat, sizeof(m_sourceFormat)); - connect(this, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(updateReadyForCapture())); } @@ -497,14 +359,13 @@ bool DSCameraSession::unload() setStatus(QCamera::UnloadingStatus); + m_previewSampleGrabber->deleteLater(); + m_previewSampleGrabber = nullptr; + m_needsHorizontalMirroring = false; m_supportedViewfinderSettings.clear(); - for (AM_MEDIA_TYPE f : qAsConst(m_supportedFormats)) - _FreeMediaType(f); m_supportedFormats.clear(); SAFE_RELEASE(m_sourceFilter); - SAFE_RELEASE(m_previewSampleGrabber); - SAFE_RELEASE(m_previewFilter); SAFE_RELEASE(m_nullRendererFilter); SAFE_RELEASE(m_filterGraph); SAFE_RELEASE(m_graphBuilder); @@ -571,6 +432,9 @@ bool DSCameraSession::stopPreview() setStatus(QCamera::StoppingStatus); + if (m_previewSampleGrabber) + m_previewSampleGrabber->stop(); + IMediaControl* pControl = 0; HRESULT hr = m_filterGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); if (FAILED(hr)) { @@ -587,8 +451,7 @@ bool DSCameraSession::stopPreview() disconnectGraph(); - _FreeMediaType(m_sourceFormat); - ZeroMemory(&m_sourceFormat, sizeof(m_sourceFormat)); + m_sourceFormat.clear(); m_previewStarted = false; setStatus(QCamera::LoadedStatus); @@ -646,12 +509,12 @@ int DSCameraSession::captureImage(const QString &fileName) return m_imageIdCounter; } -void DSCameraSession::onFrameAvailable(const char *frameData, long len) +void DSCameraSession::onFrameAvailable(double time, quint8 *buffer, long len) { // !!! Not called on the main thread - + Q_UNUSED(time); // Deep copy, the data might be modified or freed after the callback returns - QByteArray data(frameData, len); + QByteArray data(reinterpret_cast<const char *>(buffer), len); m_presentMutex.lock(); @@ -688,7 +551,7 @@ void DSCameraSession::presentFrame() m_presentMutex.unlock(); QImage captureImage; - int captureId; + const int captureId = m_currentImageId; m_captureMutex.lock(); @@ -705,8 +568,6 @@ void DSCameraSession::presentFrame() m_capturedFrame.unmap(); - captureId = m_currentImageId; - QtConcurrent::run(this, &DSCameraSession::saveCapturedImage, m_currentImageId, captureImage, m_imageCaptureFileName); @@ -737,8 +598,6 @@ void DSCameraSession::saveCapturedImage(int id, const QImage &image, const QStri bool DSCameraSession::createFilterGraph() { // Previously containered in <qedit.h>. - static const IID iID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } }; - static const CLSID cLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; static const CLSID cLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; HRESULT hr; @@ -840,26 +699,12 @@ bool DSCameraSession::createFilterGraph() } // Sample grabber filter - hr = CoCreateInstance(cLSID_SampleGrabber, NULL,CLSCTX_INPROC, - IID_IBaseFilter, (void**)&m_previewFilter); - if (FAILED(hr)) { - qWarning() << "failed to create sample grabber"; - goto failed; + if (!m_previewSampleGrabber) { + m_previewSampleGrabber = new DirectShowSampleGrabber; + connect(m_previewSampleGrabber, &DirectShowSampleGrabber::bufferAvailable, + this, &DSCameraSession::onFrameAvailable); } - hr = m_previewFilter->QueryInterface(iID_ISampleGrabber, (void**)&m_previewSampleGrabber); - if (FAILED(hr)) { - qWarning() << "failed to get sample grabber"; - goto failed; - } - - { - SampleGrabberCallbackPrivate *callback = new SampleGrabberCallbackPrivate(this); - m_previewSampleGrabber->SetCallback(callback, 1); - m_previewSampleGrabber->SetOneShot(FALSE); - m_previewSampleGrabber->SetBufferSamples(FALSE); - callback->Release(); - } // Null renderer. Input connected to the sample grabber's output. Simply // discard the samples it receives. @@ -877,8 +722,6 @@ bool DSCameraSession::createFilterGraph() failed: m_needsHorizontalMirroring = false; SAFE_RELEASE(m_sourceFilter); - SAFE_RELEASE(m_previewSampleGrabber); - SAFE_RELEASE(m_previewFilter); SAFE_RELEASE(m_nullRendererFilter); SAFE_RELEASE(m_filterGraph); SAFE_RELEASE(m_graphBuilder); @@ -910,11 +753,11 @@ bool DSCameraSession::configurePreviewFormat() m_actualViewfinderSettings = resolvedViewfinderSettings; - _CopyMediaType(&m_sourceFormat, &m_supportedFormats[settingsIndex]); + m_sourceFormat = m_supportedFormats[settingsIndex]; // Set frame rate. // We don't care about the minimumFrameRate, DirectShow only allows to set an // average frame rate, so set that to the maximumFrameRate. - VIDEOINFOHEADER *videoInfo = reinterpret_cast<VIDEOINFOHEADER*>(m_sourceFormat.pbFormat); + VIDEOINFOHEADER *videoInfo = reinterpret_cast<VIDEOINFOHEADER*>(m_sourceFormat->pbFormat); videoInfo->AvgTimePerFrame = 10000000 / resolvedViewfinderSettings.maximumFrameRate(); // We only support RGB32, if the capture source doesn't support @@ -955,16 +798,11 @@ bool DSCameraSession::configurePreviewFormat() } // Set sample grabber format (always RGB32) - AM_MEDIA_TYPE grabberFormat; - ZeroMemory(&grabberFormat, sizeof(grabberFormat)); - grabberFormat.majortype = MEDIATYPE_Video; - grabberFormat.subtype = MEDIASUBTYPE_RGB32; - grabberFormat.formattype = FORMAT_VideoInfo; - hr = m_previewSampleGrabber->SetMediaType(&grabberFormat); - if (FAILED(hr)) { - qWarning() << "Failed to set video format on grabber"; + static const AM_MEDIA_TYPE grabberFormat { MEDIATYPE_Video, MEDIASUBTYPE_RGB32, 0, 0, 0, FORMAT_VideoInfo, nullptr, 0, nullptr}; + if (!m_previewSampleGrabber->setMediaType(&grabberFormat)) return false; - } + + m_previewSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB); return true; } @@ -1052,8 +890,7 @@ bool DSCameraSession::connectGraph() return false; } - hr = m_filterGraph->AddFilter(m_previewFilter, L"Sample Grabber"); - if (FAILED(hr)) { + if (FAILED(m_filterGraph->AddFilter(m_previewSampleGrabber->filter(), L"Sample Grabber"))) { qWarning() << "failed to add sample grabber to graph"; return false; } @@ -1066,7 +903,7 @@ bool DSCameraSession::connectGraph() hr = m_graphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_sourceFilter, - m_previewFilter, + m_previewSampleGrabber->filter(), m_nullRendererFilter); if (FAILED(hr)) { qWarning() << "Graph failed to connect filters" << hr; @@ -1078,40 +915,10 @@ bool DSCameraSession::connectGraph() void DSCameraSession::disconnectGraph() { - IPin *pPin = 0; - HRESULT hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin); - if (SUCCEEDED(hr)) { - m_filterGraph->Disconnect(pPin); - pPin->Release(); - pPin = NULL; - } - - hr = getPin(m_previewFilter, PINDIR_INPUT, &pPin); - if (SUCCEEDED(hr)) { - m_filterGraph->Disconnect(pPin); - pPin->Release(); - pPin = NULL; - } - - hr = getPin(m_previewFilter, PINDIR_OUTPUT, &pPin); - if (SUCCEEDED(hr)) { - m_filterGraph->Disconnect(pPin); - pPin->Release(); - pPin = NULL; - } - - hr = getPin(m_nullRendererFilter, PINDIR_INPUT, &pPin); - if (SUCCEEDED(hr)) { - m_filterGraph->Disconnect(pPin); - pPin->Release(); - pPin = NULL; - } - // To avoid increasing the memory usage every time the graph is re-connected it's // important that all filters are released; also the ones added by the "Intelligent Connect". IEnumFilters *enumFilters = NULL; - hr = m_filterGraph->EnumFilters(&enumFilters); - if (SUCCEEDED(hr)) { + if (SUCCEEDED(m_filterGraph->EnumFilters(&enumFilters))) { IBaseFilter *filter = NULL; while (enumFilters->Next(1, &filter, NULL) == S_OK) { m_filterGraph->RemoveFilter(filter); @@ -1137,8 +944,6 @@ void DSCameraSession::updateSourceCapabilities() m_supportedViewfinderSettings.clear(); m_needsHorizontalMirroring = false; - for (AM_MEDIA_TYPE f : qAsConst(m_supportedFormats)) - _FreeMediaType(f); m_supportedFormats.clear(); m_imageProcessingParametersInfos.clear(); @@ -1150,8 +955,7 @@ void DSCameraSession::updateSourceCapabilities() qWarning() << "Failed to get the video control"; } else { IPin *pPin = 0; - hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin); - if (FAILED(hr)) { + if (!DirectShowUtils::getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin, &hr)) { qWarning() << "Failed to get the pin for the video control"; } else { long supportedModes; @@ -1190,7 +994,7 @@ void DSCameraSession::updateSourceCapabilities() for (int iIndex = 0; iIndex < iCount; ++iIndex) { hr = pConfig->GetStreamCaps(iIndex, &pmt, reinterpret_cast<BYTE*>(&scc)); if (hr == S_OK) { - QVideoFrame::PixelFormat pixelFormat = pixelFormatFromMediaSubtype(pmt->subtype); + QVideoFrame::PixelFormat pixelFormat = DirectShowMediaType::pixelFormatFromType(pmt); if (pmt->majortype == MEDIATYPE_Video && pmt->formattype == FORMAT_VideoInfo @@ -1203,8 +1007,7 @@ void DSCameraSession::updateSourceCapabilities() if (pVideoControl) { IPin *pPin = 0; - hr = getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin); - if (FAILED(hr)) { + if (!DirectShowUtils::getPin(m_sourceFilter, PINDIR_OUTPUT, &pPin, &hr)) { qWarning() << "Failed to get the pin for the video control"; } else { long listSize = 0; @@ -1237,15 +1040,12 @@ void DSCameraSession::updateSourceCapabilities() settings.setPixelFormat(pixelFormat); settings.setPixelAspectRatio(1, 1); m_supportedViewfinderSettings.append(settings); - - AM_MEDIA_TYPE format; - _CopyMediaType(&format, pmt); - m_supportedFormats.append(format); + m_supportedFormats.append(DirectShowMediaType(*pmt)); } } - _FreeMediaType(*pmt); + DirectShowMediaType::deleteType(pmt); } } @@ -1254,30 +1054,4 @@ void DSCameraSession::updateSourceCapabilities() updateImageProcessingParametersInfos(); } -HRESULT getPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin) -{ - *ppPin = 0; - IEnumPins *pEnum = 0; - IPin *pPin = 0; - - HRESULT hr = pFilter->EnumPins(&pEnum); - if (FAILED(hr)) { - return hr; - } - - pEnum->Reset(); - while (pEnum->Next(1, &pPin, NULL) == S_OK) { - PIN_DIRECTION ThisPinDir; - pPin->QueryDirection(&ThisPinDir); - if (ThisPinDir == PinDir) { - pEnum->Release(); - *ppPin = pPin; - return S_OK; - } - pPin->Release(); - } - pEnum->Release(); - return E_FAIL; -} - QT_END_NAMESPACE diff --git a/src/plugins/directshow/camera/dscamerasession.h b/src/plugins/directshow/camera/dscamerasession.h index 61b156d8a..37730736f 100644 --- a/src/plugins/directshow/camera/dscamerasession.h +++ b/src/plugins/directshow/camera/dscamerasession.h @@ -56,6 +56,7 @@ #include <dshow.h> #include <objbase.h> #include <initguid.h> +#include "directshowmediatype.h" #ifdef Q_CC_MSVC # pragma comment(lib, "strmiids.lib") # pragma comment(lib, "ole32.lib") @@ -71,11 +72,10 @@ #define __IDxtKey_INTERFACE_DEFINED__ struct ICaptureGraphBuilder2; -struct ISampleGrabber; QT_BEGIN_NAMESPACE -class SampleGrabberCallbackPrivate; +class DirectShowSampleGrabber; class DSCameraSession : public QObject { @@ -154,7 +154,7 @@ private: void setStatus(QCamera::Status status); - void onFrameAvailable(const char *frameData, long len); + void onFrameAvailable(double time, quint8 *buffer, long len); void saveCapturedImage(int id, const QImage &image, const QString &path); bool createFilterGraph(); @@ -182,14 +182,13 @@ private: QString m_sourceDeviceName; IBaseFilter* m_sourceFilter; bool m_needsHorizontalMirroring; - QList<AM_MEDIA_TYPE> m_supportedFormats; + QList<DirectShowMediaType> m_supportedFormats; QList<QCameraViewfinderSettings> m_supportedViewfinderSettings; - AM_MEDIA_TYPE m_sourceFormat; + DirectShowMediaType m_sourceFormat; QMap<QCameraImageProcessingControl::ProcessingParameter, ImageProcessingParameterInfo> m_imageProcessingParametersInfos; // Preview - IBaseFilter *m_previewFilter; - ISampleGrabber *m_previewSampleGrabber; + DirectShowSampleGrabber *m_previewSampleGrabber; IBaseFilter *m_nullRendererFilter; QVideoFrame m_currentFrame; bool m_previewStarted; diff --git a/src/plugins/directshow/common/common.pri b/src/plugins/directshow/common/common.pri new file mode 100644 index 000000000..9b7c1e3f4 --- /dev/null +++ b/src/plugins/directshow/common/common.pri @@ -0,0 +1,11 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/directshowvideoprobecontrol.h \ + $$PWD/directshowaudioprobecontrol.h \ + $$PWD/directshowsamplegrabber.h + +SOURCES += \ + $$PWD/directshowvideoprobecontrol.cpp \ + $$PWD/directshowaudioprobecontrol.cpp \ + $$PWD/directshowsamplegrabber.cpp diff --git a/src/plugins/directshow/common/directshowaudioprobecontrol.cpp b/src/plugins/directshow/common/directshowaudioprobecontrol.cpp new file mode 100644 index 000000000..55ef70178 --- /dev/null +++ b/src/plugins/directshow/common/directshowaudioprobecontrol.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowaudioprobecontrol.h" +#include "directshowglobal.h" + +QT_BEGIN_NAMESPACE + +DirectShowAudioProbeControl::DirectShowAudioProbeControl(QObject *p) + : QMediaAudioProbeControl(p) +{ + +} + +DirectShowAudioProbeControl::~DirectShowAudioProbeControl() +{ + if (m_ref.deref()) + qCWarning(qtDirectShowPlugin, "QAudioProbe control destroyed while it's still being referenced!!!"); +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowaudioprobecontrol.h b/src/plugins/directshow/common/directshowaudioprobecontrol.h new file mode 100644 index 000000000..553bd1178 --- /dev/null +++ b/src/plugins/directshow/common/directshowaudioprobecontrol.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWAUDIOPROBECONTROL_H +#define DIRECTSHOWAUDIOPROBECONTROL_H + +#include <qmediaaudioprobecontrol.h> + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class DirectShowAudioProbeControl : public QMediaAudioProbeControl +{ + Q_OBJECT +public: + explicit DirectShowAudioProbeControl(QObject *p = nullptr); + ~DirectShowAudioProbeControl(); + + bool ref() { return m_ref.ref(); } + bool deref() { return m_ref.deref(); } +private: + QAtomicInt m_ref; +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWAUDIOPROBECONTROL_H diff --git a/src/plugins/directshow/common/directshowsamplegrabber.cpp b/src/plugins/directshow/common/directshowsamplegrabber.cpp new file mode 100644 index 000000000..b33c3cfc6 --- /dev/null +++ b/src/plugins/directshow/common/directshowsamplegrabber.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowsamplegrabber.h" + +#include "directshowglobal.h" +#include "directshowutils.h" + + +QT_BEGIN_NAMESPACE + +// Previously contained in <qedit.h>. +static const IID iID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } }; +static const CLSID cLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + +class SampleGrabberCallbackPrivate : public ISampleGrabberCB +{ +public: + explicit SampleGrabberCallbackPrivate(DirectShowSampleGrabber *grabber) + : m_ref(1) + , m_grabber(grabber) + { } + + virtual ~SampleGrabberCallbackPrivate() { } + + STDMETHODIMP_(ULONG) AddRef() + { + return InterlockedIncrement(&m_ref); + } + + STDMETHODIMP_(ULONG) Release() + { + ULONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + delete this; + return ref; + } + + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) + { + if (NULL == ppvObject) + return E_POINTER; + + if (riid == IID_IUnknown /*__uuidof(IUnknown) */ ) { + AddRef(); + *ppvObject = static_cast<IUnknown *>(this); + return S_OK; + } else if (riid == IID_ISampleGrabberCB /*__uuidof(ISampleGrabberCB)*/ ) { + AddRef(); + *ppvObject = static_cast<ISampleGrabberCB *>(this); + return S_OK; + } + return E_NOTIMPL; + } + + STDMETHODIMP SampleCB(double time, IMediaSample *mediaSample) + { + if (m_grabber) + Q_EMIT m_grabber->sampleAvailable(time, mediaSample); + + return S_OK; + } + + STDMETHODIMP BufferCB(double time, BYTE *buffer, long bufferLen) + { + if (m_grabber) + Q_EMIT m_grabber->bufferAvailable(time, buffer, bufferLen); + + return S_OK; + } + +private: + ULONG m_ref; + DirectShowSampleGrabber *m_grabber; +}; + +DirectShowSampleGrabber::DirectShowSampleGrabber(QObject *p) + : QObject(p) + , m_sampleGrabber(nullptr) + , m_sampleGabberCb(nullptr) + , m_callbackType(CallbackMethod::BufferCB) +{ + // Create sample grabber filter + HRESULT hr = CoCreateInstance(cLSID_SampleGrabber, NULL, CLSCTX_INPROC, iID_ISampleGrabber, reinterpret_cast<void **>(&m_sampleGrabber)); + + if (FAILED(hr)) { + qCWarning(qtDirectShowPlugin, "Failed to create sample grabber"); + return; + } + + hr = m_sampleGrabber->QueryInterface(IID_IBaseFilter, reinterpret_cast<void **>(&m_filter)); + if (FAILED(hr)) + qCWarning(qtDirectShowPlugin, "Failed to get base filter interface"); +} + +DirectShowSampleGrabber::~DirectShowSampleGrabber() +{ + stop(); + SAFE_RELEASE(m_sampleGabberCb); + SAFE_RELEASE(m_filter); + SAFE_RELEASE(m_sampleGrabber); +} + +void DirectShowSampleGrabber::stop() +{ + if (!m_sampleGrabber) + return; + + if (FAILED(m_sampleGrabber->SetCallback(nullptr, static_cast<long>(m_callbackType)))) { + qCWarning(qtDirectShowPlugin, "Failed to stop sample grabber callback"); + return; + } +} + +bool DirectShowSampleGrabber::getConnectedMediaType(AM_MEDIA_TYPE *mediaType) +{ + Q_ASSERT(mediaType); + + if (!isValid()) + return false; + + if (FAILED(m_sampleGrabber->GetConnectedMediaType(mediaType))) { + qCWarning(qtDirectShowPlugin, "Failed to retrieve the connected media type"); + return false; + } + + return true; +} + +bool DirectShowSampleGrabber::setMediaType(const AM_MEDIA_TYPE *mediaType) +{ + Q_ASSERT(mediaType); + + if (FAILED(m_sampleGrabber->SetMediaType(mediaType))) { + qCWarning(qtDirectShowPlugin, "Failed to set media type"); + return false; + } + + return true; +} + +void DirectShowSampleGrabber::start(DirectShowSampleGrabber::CallbackMethod method, + bool oneShot, + bool bufferSamples) +{ + if (!m_sampleGrabber) + return; + + stop(); + + if (!m_sampleGabberCb) + m_sampleGabberCb = new SampleGrabberCallbackPrivate(this); + + m_callbackType = method; + m_sampleGrabber->SetCallback(m_sampleGabberCb, static_cast<long>(method)); + m_sampleGrabber->SetOneShot(oneShot); + m_sampleGrabber->SetBufferSamples(bufferSamples); +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowsamplegrabber.h b/src/plugins/directshow/common/directshowsamplegrabber.h new file mode 100644 index 000000000..edabae2db --- /dev/null +++ b/src/plugins/directshow/common/directshowsamplegrabber.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWSAMPLEGRABBER_H +#define DIRECTSHOWSAMPLEGRABBER_H + +#include <QtCore/qglobal.h> +#include <QtCore/qobject.h> + +// TODO: Fix this. +#include <directshowcameraglobal.h> + +QT_BEGIN_NAMESPACE + +class SampleGrabberCallbackPrivate; + +class DirectShowSampleGrabber : public QObject +{ + Q_OBJECT +public: + DirectShowSampleGrabber(QObject *p = nullptr); + ~DirectShowSampleGrabber(); + + // 0 = ISampleGrabberCB::SampleCB, 1 = ISampleGrabberCB::BufferCB + enum class CallbackMethod : long + { + SampleCB, + BufferCB + }; + + bool isValid() const { return m_filter && m_sampleGrabber; } + bool getConnectedMediaType(AM_MEDIA_TYPE *mediaType); + bool setMediaType(const AM_MEDIA_TYPE *mediaType); + + void stop(); + void start(CallbackMethod method, bool oneShot = false, bool bufferSamples = false); + + IBaseFilter *filter() const { return m_filter; } + +Q_SIGNALS: + void sampleAvailable(double time, IMediaSample *sample); + void bufferAvailable(double time, quint8 *buffer, long len); + +private: + IBaseFilter *m_filter; + ISampleGrabber *m_sampleGrabber; + SampleGrabberCallbackPrivate *m_sampleGabberCb; + CallbackMethod m_callbackType; +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWSAMPLEGRABBER_H diff --git a/src/plugins/directshow/common/directshowvideoprobecontrol.cpp b/src/plugins/directshow/common/directshowvideoprobecontrol.cpp new file mode 100644 index 000000000..5ec1ff064 --- /dev/null +++ b/src/plugins/directshow/common/directshowvideoprobecontrol.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowvideoprobecontrol.h" +#include "directshowglobal.h" + +QT_BEGIN_NAMESPACE + +DirectShowVideoProbeControl::DirectShowVideoProbeControl(QObject *p) + : QMediaVideoProbeControl(p) +{ + +} + +DirectShowVideoProbeControl::~DirectShowVideoProbeControl() +{ + if (m_ref.deref()) + qCWarning(qtDirectShowPlugin, "QVideoProbe control destroyed while it's still being referenced!!!"); +} + +QT_END_NAMESPACE diff --git a/src/plugins/directshow/common/directshowvideoprobecontrol.h b/src/plugins/directshow/common/directshowvideoprobecontrol.h new file mode 100644 index 000000000..458263234 --- /dev/null +++ b/src/plugins/directshow/common/directshowvideoprobecontrol.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWVIDEOPROBECONTROL_H +#define DIRECTSHOWVIDEOPROBECONTROL_H + +#include <qmediavideoprobecontrol.h> + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class DirectShowVideoProbeControl : public QMediaVideoProbeControl +{ + Q_OBJECT +public: + explicit DirectShowVideoProbeControl(QObject *p = nullptr); + ~DirectShowVideoProbeControl(); + + bool ref() { return m_ref.ref(); } + bool deref() { return m_ref.deref(); } +private: + QAtomicInt m_ref; +}; + +QT_END_NAMESPACE + +#endif // DIRECTSHOWVIDEOPROBECONTROL_H diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro index 8e31527da..35301474f 100644 --- a/src/plugins/directshow/directshow.pro +++ b/src/plugins/directshow/directshow.pro @@ -10,6 +10,7 @@ SOURCES += dsserviceplugin.cpp mingw: DEFINES += NO_DSHOW_STRSAFE +include(common/common.pri) include(helpers/helpers.pri) qtConfig(directshow-player): include(player/player.pri) include(camera/camera.pri) diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp index 6d8f97f52..9060bac7c 100644 --- a/src/plugins/directshow/dsserviceplugin.cpp +++ b/src/plugins/directshow/dsserviceplugin.cpp @@ -44,6 +44,7 @@ #include <QtCore/qdebug.h> #include <QtCore/QFile> +#include "directshowglobal.h" #include "dsserviceplugin.h" #include "dsvideodevicecontrol.h" @@ -72,6 +73,10 @@ extern const CLSID CLSID_VideoInputDeviceCategory; #include <windows.h> #include <ocidl.h> +QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qtDirectShowPlugin, "qt.multimedia.plugins.directshow") +QT_END_NAMESPACE + QT_USE_NAMESPACE static int g_refCount = 0; diff --git a/src/plugins/directshow/helpers/directshowglobal.h b/src/plugins/directshow/helpers/directshowglobal.h index f7890c52b..5f391710e 100644 --- a/src/plugins/directshow/helpers/directshowglobal.h +++ b/src/plugins/directshow/helpers/directshowglobal.h @@ -43,6 +43,13 @@ #include <dshow.h> #include <QtCore/qglobal.h> +#include <QtCore/qloggingcategory.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qtDirectShowPlugin) + +QT_END_NAMESPACE template <typename T> T *com_cast(IUnknown *unknown, const IID &iid) { @@ -77,6 +84,9 @@ template <typename T> T *com_new(const IID &clsid, const IID &iid) : 0; } +DEFINE_GUID(MEDIASUBTYPE_I420, + 0x30323449,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); + #ifndef __IFilterGraph2_INTERFACE_DEFINED__ #define __IFilterGraph2_INTERFACE_DEFINED__ #define INTERFACE IFilterGraph2 diff --git a/src/plugins/directshow/helpers/directshowmediatype.cpp b/src/plugins/directshow/helpers/directshowmediatype.cpp index 60c0ee040..d9ddf8248 100644 --- a/src/plugins/directshow/helpers/directshowmediatype.cpp +++ b/src/plugins/directshow/helpers/directshowmediatype.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "directshowmediatype.h" +#include "directshowglobal.h" namespace { @@ -49,85 +50,168 @@ namespace static const TypeLookup qt_typeLookup[] = { - { QVideoFrame::Format_RGB32, /*MEDIASUBTYPE_RGB32*/ {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} }, - { QVideoFrame::Format_BGR24, /*MEDIASUBTYPE_RGB24*/ {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} }, - { QVideoFrame::Format_RGB565, /*MEDIASUBTYPE_RGB565*/ {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} }, - { QVideoFrame::Format_RGB555, /*MEDIASUBTYPE_RGB555*/ {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}} }, - { QVideoFrame::Format_AYUV444, /*MEDIASUBTYPE_AYUV*/ {0x56555941, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_YUYV, /*MEDIASUBTYPE_YUY2*/ {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_UYVY, /*MEDIASUBTYPE_UYVY*/ {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_IMC1, /*MEDIASUBTYPE_IMC1*/ {0x31434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_IMC2, /*MEDIASUBTYPE_IMC2*/ {0x32434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_IMC3, /*MEDIASUBTYPE_IMC3*/ {0x33434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_IMC4, /*MEDIASUBTYPE_IMC4*/ {0x34434D49, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_YV12, /*MEDIASUBTYPE_YV12*/ {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_NV12, /*MEDIASUBTYPE_NV12*/ {0x3231564E, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_IYUV*/ {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} }, - { QVideoFrame::Format_YUV420P, /*MEDIASUBTYPE_I420*/ {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} } + { QVideoFrame::Format_ARGB32, MEDIASUBTYPE_ARGB32 }, + { QVideoFrame::Format_RGB32, MEDIASUBTYPE_RGB32 }, + { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, + { QVideoFrame::Format_RGB565, MEDIASUBTYPE_RGB565 }, + { QVideoFrame::Format_RGB555, MEDIASUBTYPE_RGB555 }, + { QVideoFrame::Format_AYUV444, MEDIASUBTYPE_AYUV }, + { QVideoFrame::Format_YUYV, MEDIASUBTYPE_YUY2 }, + { QVideoFrame::Format_UYVY, MEDIASUBTYPE_UYVY }, + { QVideoFrame::Format_IMC1, MEDIASUBTYPE_IMC1 }, + { QVideoFrame::Format_IMC2, MEDIASUBTYPE_IMC2 }, + { QVideoFrame::Format_IMC3, MEDIASUBTYPE_IMC3 }, + { QVideoFrame::Format_IMC4, MEDIASUBTYPE_IMC4 }, + { QVideoFrame::Format_YV12, MEDIASUBTYPE_YV12 }, + { QVideoFrame::Format_NV12, MEDIASUBTYPE_NV12 }, + { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_IYUV }, + { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_I420 }, + { QVideoFrame::Format_Jpeg, MEDIASUBTYPE_MJPG } }; } -bool DirectShowMediaType::isPartiallySpecified() const +bool DirectShowMediaType::isPartiallySpecified(const AM_MEDIA_TYPE *mediaType) { - return majortype == GUID_NULL || formattype == GUID_NULL; + return mediaType->majortype == GUID_NULL || mediaType->formattype == GUID_NULL; } -bool DirectShowMediaType::isCompatibleWith(const DirectShowMediaType *type) const +DirectShowMediaType::DirectShowMediaType() + : mediaType({ GUID_NULL, GUID_NULL, TRUE, FALSE, 1, GUID_NULL, nullptr, 0, nullptr}) { - if (type->majortype != GUID_NULL && majortype != type->majortype) - return false; +} - if (type->subtype != GUID_NULL && subtype != type->subtype) - return false; +DirectShowMediaType::DirectShowMediaType(const AM_MEDIA_TYPE &type) + : DirectShowMediaType() +{ + copy(&mediaType, &type); +} - if (type->formattype != GUID_NULL) { - if (formattype != type->formattype) - return false; - if (cbFormat != type->cbFormat) - return false; - if (cbFormat != 0 && memcmp(pbFormat, type->pbFormat, cbFormat) != 0) - return false; - } +DirectShowMediaType::DirectShowMediaType(AM_MEDIA_TYPE &&type) + : DirectShowMediaType() +{ + move(&mediaType, type); +} - return true; +DirectShowMediaType::DirectShowMediaType(const DirectShowMediaType &other) + : DirectShowMediaType() +{ + copy(&mediaType, &other.mediaType); +} + +DirectShowMediaType::DirectShowMediaType(DirectShowMediaType &&other) + : DirectShowMediaType() +{ + move(&mediaType, other.mediaType); +} + +DirectShowMediaType &DirectShowMediaType::operator=(const DirectShowMediaType &other) +{ + copy(&mediaType, &other.mediaType); + return *this; +} + +DirectShowMediaType &DirectShowMediaType::operator=(DirectShowMediaType &&other) +{ + move(&mediaType, other.mediaType); + return *this; } void DirectShowMediaType::init(AM_MEDIA_TYPE *type) { - ZeroMemory((PVOID)type, sizeof(*type)); + Q_ASSERT(type); + SecureZeroMemory(reinterpret_cast<void *>(type), sizeof(AM_MEDIA_TYPE)); type->lSampleSize = 1; type->bFixedSizeSamples = TRUE; } -void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source) +void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source) { - if (!target) + if (!(target && source)) + return; + + if (target == source) return; - *target = source; + clear(*target); - if (source.cbFormat > 0) { - target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source.cbFormat)); - memcpy(target->pbFormat, source.pbFormat, source.cbFormat); + *target = *source; + + if (source->cbFormat > 0) { + target->pbFormat = reinterpret_cast<PBYTE>(CoTaskMemAlloc(source->cbFormat)); + memcpy(target->pbFormat, source->pbFormat, source->cbFormat); } if (target->pUnk) target->pUnk->AddRef(); } +void DirectShowMediaType::move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source) +{ + if (!target || !source || !(*source)) + return; + + if (target == *source) + return; + + clear(*target); + *target = *(*source); + SecureZeroMemory(reinterpret_cast<void *>(*source), sizeof(AM_MEDIA_TYPE)); + *source = nullptr; +} + +void DirectShowMediaType::move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source) +{ + AM_MEDIA_TYPE *srcPtr = &source; + move(target, &srcPtr); +} + +/** + * @brief DirectShowMediaType::deleteType - Used for AM_MEDIA_TYPE structures that have + * been allocated by CoTaskMemAlloc or CreateMediaType. + * @param type + */ void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type) { - freeData(type); + if (!type) + return; + clear(*type); CoTaskMemFree(type); } -void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type) +bool DirectShowMediaType::isCompatible(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + if (b->majortype != GUID_NULL && a->majortype != b->majortype) + return false; + + if (b->subtype != GUID_NULL && a->subtype != b->subtype) + return false; + + if (b->formattype != GUID_NULL) { + if (a->formattype != b->formattype) + return false; + if (a->cbFormat != b->cbFormat) + return false; + if (a->cbFormat != 0 && memcmp(a->pbFormat, b->pbFormat, a->cbFormat) != 0) + return false; + } + + return true; +} + +/** + * @brief DirectShowMediaType::clear - Clears all member data, and releases allocated buffers. + * Use this to release automatic AM_MEDIA_TYPE structures. + * @param type + */ +void DirectShowMediaType::clear(AM_MEDIA_TYPE &type) { - if (type->cbFormat > 0) - CoTaskMemFree(type->pbFormat); + if (type.cbFormat > 0) + CoTaskMemFree(type.pbFormat); + + if (type.pUnk) + type.pUnk->Release(); - if (type->pUnk) - type->pUnk->Release(); + SecureZeroMemory(&type, sizeof(type)); } @@ -142,14 +226,17 @@ GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format) return MEDIASUBTYPE_None; } -QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type) +QVideoSurfaceFormat DirectShowMediaType::videoFormatFromType(const AM_MEDIA_TYPE *type) { + if (!type) + return QVideoSurfaceFormat(); + const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup); for (int i = 0; i < count; ++i) { - if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype) && type.cbFormat > 0) { - if (IsEqualGUID(type.formattype, FORMAT_VideoInfo)) { - VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type.pbFormat); + if (IsEqualGUID(qt_typeLookup[i].mediaType, type->subtype) && type->cbFormat > 0) { + if (IsEqualGUID(type->formattype, FORMAT_VideoInfo)) { + VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER *>(type->pbFormat); QVideoSurfaceFormat format( QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)), @@ -161,8 +248,8 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ format.setScanLineDirection(scanLineDirection(format.pixelFormat(), header->bmiHeader)); return format; - } else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) { - VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type.pbFormat); + } else if (IsEqualGUID(type->formattype, FORMAT_VideoInfo2)) { + VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2 *>(type->pbFormat); QVideoSurfaceFormat format( QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)), @@ -180,12 +267,15 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ return QVideoSurfaceFormat(); } -QVideoFrame::PixelFormat DirectShowMediaType::pixelFormatFromType(const AM_MEDIA_TYPE &type) +QVideoFrame::PixelFormat DirectShowMediaType::pixelFormatFromType(const AM_MEDIA_TYPE *type) { + if (!type) + return QVideoFrame::Format_Invalid; + const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup); for (int i = 0; i < count; ++i) { - if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype)) { + if (IsEqualGUID(qt_typeLookup[i].mediaType, type->subtype)) { return qt_typeLookup[i].pixelFormat; } } @@ -198,6 +288,7 @@ int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format) { switch (format.pixelFormat()) { // 32 bpp packed formats. + case QVideoFrame::Format_ARGB32: case QVideoFrame::Format_RGB32: case QVideoFrame::Format_AYUV444: return format.frameWidth() * 4; @@ -240,8 +331,9 @@ QVideoSurfaceFormat::Direction DirectShowMediaType::scanLineDirection(QVideoFram */ switch (pixelFormat) { + case QVideoFrame::Format_ARGB32: case QVideoFrame::Format_RGB32: - case QVideoFrame::Format_BGR24: + case QVideoFrame::Format_RGB24: case QVideoFrame::Format_RGB565: case QVideoFrame::Format_RGB555: return bmiHeader.biHeight < 0 diff --git a/src/plugins/directshow/helpers/directshowmediatype.h b/src/plugins/directshow/helpers/directshowmediatype.h index b2b074ccc..7849ca9b0 100644 --- a/src/plugins/directshow/helpers/directshowmediatype.h +++ b/src/plugins/directshow/helpers/directshowmediatype.h @@ -45,39 +45,48 @@ #include <qvideosurfaceformat.h> #include <dvdmedia.h> +#include <QtCore/qglobal.h> QT_USE_NAMESPACE -class DirectShowMediaType : public AM_MEDIA_TYPE +class DirectShowMediaType { public: - DirectShowMediaType() { init(this); } - DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); } - DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); } - DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) { - freeData(this); copy(this, type); return *this; } - DirectShowMediaType &operator =(const DirectShowMediaType &other) { - freeData(this); copy(this, other); return *this; } - ~DirectShowMediaType() { freeData(this); } + DirectShowMediaType(); + DirectShowMediaType(const DirectShowMediaType &other); + DirectShowMediaType(DirectShowMediaType &&other); + explicit DirectShowMediaType(const AM_MEDIA_TYPE &type); + explicit DirectShowMediaType(AM_MEDIA_TYPE &&type); + ~DirectShowMediaType() { clear(mediaType); } - void clear() { freeData(this); init(this); } + DirectShowMediaType &operator =(const DirectShowMediaType &other); + DirectShowMediaType &operator =(DirectShowMediaType &&other); - bool isPartiallySpecified() const; - bool isCompatibleWith(const DirectShowMediaType *type) const; + void clear() { clear(mediaType); } + + inline AM_MEDIA_TYPE *operator &() Q_DECL_NOTHROW { return &mediaType; } + inline AM_MEDIA_TYPE *operator ->() Q_DECL_NOTHROW { return &mediaType; } + + inline const AM_MEDIA_TYPE *operator &() const Q_DECL_NOTHROW { return &mediaType; } + inline const AM_MEDIA_TYPE *operator ->() const Q_DECL_NOTHROW { return &mediaType; } static void init(AM_MEDIA_TYPE *type); - static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source); - static void freeData(AM_MEDIA_TYPE *type); + static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE *source); + static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE **source); + static void move(AM_MEDIA_TYPE *target, AM_MEDIA_TYPE &source); + static void clear(AM_MEDIA_TYPE &type); static void deleteType(AM_MEDIA_TYPE *type); - + static bool isPartiallySpecified(const AM_MEDIA_TYPE *mediaType); + static bool isCompatible(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b); static GUID convertPixelFormat(QVideoFrame::PixelFormat format); - static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type); - static QVideoFrame::PixelFormat pixelFormatFromType(const AM_MEDIA_TYPE &type); + static QVideoSurfaceFormat videoFormatFromType(const AM_MEDIA_TYPE *type); + static QVideoFrame::PixelFormat pixelFormatFromType(const AM_MEDIA_TYPE *type); static int bytesPerLine(const QVideoSurfaceFormat &format); + static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader); private: - static QVideoSurfaceFormat::Direction scanLineDirection(QVideoFrame::PixelFormat pixelFormat, const BITMAPINFOHEADER &bmiHeader); + AM_MEDIA_TYPE mediaType; }; Q_DECLARE_TYPEINFO(DirectShowMediaType, Q_MOVABLE_TYPE); diff --git a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp index a1c8b2306..a58993f7f 100644 --- a/src/plugins/directshow/helpers/directshowmediatypeenum.cpp +++ b/src/plugins/directshow/helpers/directshowmediatypeenum.cpp @@ -72,7 +72,7 @@ HRESULT DirectShowMediaTypeEnum::Next(ULONG cMediaTypes, AM_MEDIA_TYPE **ppMedia for (ULONG i = 0; i < count; ++i, ++m_index) { ppMediaTypes[i] = reinterpret_cast<AM_MEDIA_TYPE *>(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); - DirectShowMediaType::copy(ppMediaTypes[i], m_mediaTypes.at(m_index)); + DirectShowMediaType::copy(ppMediaTypes[i], &m_mediaTypes.at(m_index)); } if (pcFetched) diff --git a/src/plugins/directshow/helpers/directshowpin.cpp b/src/plugins/directshow/helpers/directshowpin.cpp index 6cf4da321..f501747f9 100644 --- a/src/plugins/directshow/helpers/directshowpin.cpp +++ b/src/plugins/directshow/helpers/directshowpin.cpp @@ -81,22 +81,20 @@ HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) if (pd == m_direction) return VFW_E_INVALID_DIRECTION; - const DirectShowMediaType *type = reinterpret_cast<const DirectShowMediaType*>(pmt); - - if (type != NULL && !type->isPartiallySpecified()) { + if (pmt != NULL && DirectShowMediaType::isPartiallySpecified(pmt)) { // If the type is fully specified, use it - hr = tryConnect(pReceivePin, type); + hr = tryConnect(pReceivePin, pmt); } else { IEnumMediaTypes *enumMediaTypes = NULL; // First, try the receiving pin's preferred types if (SUCCEEDED(pReceivePin->EnumMediaTypes(&enumMediaTypes))) { - hr = tryMediaTypes(pReceivePin, type, enumMediaTypes); + hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes); enumMediaTypes->Release(); } // Then, try this pin's preferred types if (FAILED(hr) && SUCCEEDED(EnumMediaTypes(&enumMediaTypes))) { - hr = tryMediaTypes(pReceivePin, type, enumMediaTypes); + hr = tryMediaTypes(pReceivePin, pmt, enumMediaTypes); enumMediaTypes->Release(); } } @@ -109,19 +107,19 @@ HRESULT DirectShowPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) return S_OK; } -HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const DirectShowMediaType *partialType, IEnumMediaTypes *enumMediaTypes) +HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *partialType, IEnumMediaTypes *enumMediaTypes) { HRESULT hr = enumMediaTypes->Reset(); if (FAILED(hr)) return hr; - DirectShowMediaType *mediaType = NULL; + AM_MEDIA_TYPE *mediaType = NULL; ULONG mediaCount = 0; HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES; - for (; enumMediaTypes->Next(1, reinterpret_cast<AM_MEDIA_TYPE**>(&mediaType), &mediaCount) == S_OK;) { + for (; enumMediaTypes->Next(1, &mediaType, &mediaCount) == S_OK;) { - if (mediaType && (partialType == NULL || mediaType->isCompatibleWith(partialType))) { + if (mediaType && (partialType == NULL || DirectShowMediaType::isCompatible(mediaType, partialType))) { hr = tryConnect(pin, mediaType); if (FAILED(hr) && (hr != E_FAIL) @@ -141,7 +139,7 @@ HRESULT DirectShowPin::tryMediaTypes(IPin *pin, const DirectShowMediaType *parti return hrFailure; } -HRESULT DirectShowPin::tryConnect(IPin *pin, const DirectShowMediaType *type) +HRESULT DirectShowPin::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type) { if (!isMediaTypeSupported(type)) return VFW_E_TYPE_NOT_ACCEPTED; @@ -189,15 +187,14 @@ HRESULT DirectShowPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE * if (pd == m_direction) return VFW_E_INVALID_DIRECTION; - const DirectShowMediaType *type = reinterpret_cast<const DirectShowMediaType*>(pmt); - if (!isMediaTypeSupported(type)) + if (!isMediaTypeSupported(pmt)) return VFW_E_TYPE_NOT_ACCEPTED; m_peerPin = pConnector; m_peerPin->AddRef(); HRESULT hr; - if (!setMediaType(type)) + if (!setMediaType(pmt)) hr = VFW_E_TYPE_NOT_ACCEPTED; else hr = completeConnection(pConnector); @@ -265,7 +262,7 @@ HRESULT DirectShowPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) DirectShowMediaType::init(pmt); return VFW_E_NOT_CONNECTED; } else { - DirectShowMediaType::copy(pmt, m_mediaType); + DirectShowMediaType::copy(pmt, &m_mediaType); return S_OK; } } @@ -309,7 +306,7 @@ HRESULT DirectShowPin::QueryAccept(const AM_MEDIA_TYPE *pmt) if (!pmt) return E_POINTER; - if (!isMediaTypeSupported(reinterpret_cast<const DirectShowMediaType*>(pmt))) + if (!isMediaTypeSupported(pmt)) return S_FALSE; return S_OK; @@ -370,12 +367,12 @@ QList<DirectShowMediaType> DirectShowPin::supportedMediaTypes() return QList<DirectShowMediaType>(); } -bool DirectShowPin::setMediaType(const DirectShowMediaType *type) +bool DirectShowPin::setMediaType(const AM_MEDIA_TYPE *type) { if (!type) m_mediaType.clear(); else - m_mediaType = *type; + DirectShowMediaType::copy(&m_mediaType, type); return true; } @@ -673,7 +670,7 @@ HRESULT DirectShowInputPin::Receive(IMediaSample *pSample) if (!(m_sampleProperties.dwSampleFlags & AM_SAMPLE_TYPECHANGED)) return S_OK; - if (isMediaTypeSupported(reinterpret_cast<DirectShowMediaType*>(m_sampleProperties.pMediaType))) + if (isMediaTypeSupported(m_sampleProperties.pMediaType)) return S_OK; m_inErrorState = true; diff --git a/src/plugins/directshow/helpers/directshowpin.h b/src/plugins/directshow/helpers/directshowpin.h index 823223956..b8207abae 100644 --- a/src/plugins/directshow/helpers/directshowpin.h +++ b/src/plugins/directshow/helpers/directshowpin.h @@ -55,9 +55,9 @@ public: QString name() const { return m_name; } bool isConnected() const { return m_peerPin != NULL; } - virtual bool isMediaTypeSupported(const DirectShowMediaType *type) = 0; + virtual bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) = 0; virtual QList<DirectShowMediaType> supportedMediaTypes(); - virtual bool setMediaType(const DirectShowMediaType *type); + virtual bool setMediaType(const AM_MEDIA_TYPE *type); virtual HRESULT completeConnection(IPin *pin); virtual HRESULT connectionEnded(); @@ -107,8 +107,8 @@ protected: private: Q_DISABLE_COPY(DirectShowPin) - HRESULT tryMediaTypes(IPin *pin, const DirectShowMediaType *type, IEnumMediaTypes *enumMediaTypes); - HRESULT tryConnect(IPin *pin, const DirectShowMediaType *type); + HRESULT tryMediaTypes(IPin *pin, const AM_MEDIA_TYPE *type, IEnumMediaTypes *enumMediaTypes); + HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type); }; diff --git a/src/plugins/directshow/helpers/directshowutils.cpp b/src/plugins/directshow/helpers/directshowutils.cpp new file mode 100644 index 000000000..d9701fd99 --- /dev/null +++ b/src/plugins/directshow/helpers/directshowutils.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowutils.h" + +/** + * @brief DirectShowUtils::isPinConnected + * @param pin + * @param hrOut + * @return + */ +bool DirectShowUtils::isPinConnected(IPin *pin, HRESULT *hrOut) +{ + IPin *connectedPin = nullptr; + const ScopedSafeRelease<IPin> releasePin { &connectedPin }; + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + *hrOut = pin->ConnectedTo(&connectedPin); + if (*hrOut == VFW_E_NOT_CONNECTED) // Not an error in this case + *hrOut = S_OK; + + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Querying pin connection failed!"); + return false; + } + + return true; +} + +/** + * @brief DirectShowUtils::hasPinDirection + * @param pin + * @param direction + * @param hrOut + * @return + */ +bool DirectShowUtils::hasPinDirection(IPin *pin, PIN_DIRECTION direction, HRESULT *hrOut) +{ + PIN_DIRECTION pinDir; + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + *hrOut = pin->QueryDirection(&pinDir); + + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Querying pin direction failed!"); + return false; + } + + return (pinDir == direction); +} + +/** + * @brief DirectShowUtils::getPin + * @param filter + * @param pinDirection + * @param pin + * @param hrOut + * @return + */ +bool DirectShowUtils::getPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut) +{ + IEnumPins *enumPins = nullptr; + const ScopedSafeRelease<IEnumPins> releaseEnumPins { &enumPins }; + HRESULT hr S_OK; + if (!hrOut) + hrOut = &hr; + + *hrOut = filter->EnumPins(&enumPins); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to retrieve pins from the filter!"); + return false; + } + + enumPins->Reset(); + IPin *nextPin = nullptr; + while (enumPins->Next(1, &nextPin, NULL) == S_OK) { + const ScopedSafeRelease<IPin> releasePin { &nextPin }; + PIN_DIRECTION currentPinDir; + *hrOut = nextPin->QueryDirection(¤tPinDir); + if (currentPinDir == pinDirection) { + *pin = nextPin; + (*pin)->AddRef(); + return true; + } + } + + return false; +} + +/** + * @brief DirectShowUtils::matchPin + * @param pin + * @param pinDirection + * @param shouldBeConnected + * @param hrOut + * @return + */ +bool DirectShowUtils::matchPin(IPin *pin, PIN_DIRECTION pinDirection, BOOL shouldBeConnected, HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + const BOOL isConnected = isPinConnected(pin, hrOut); + if (FAILED(*hrOut)) // Error reason will already be logged, so just return. + return false; + + if (isConnected == shouldBeConnected) + return hasPinDirection(pin, pinDirection, hrOut); + + return SUCCEEDED(*hrOut); +} + +/** + * @brief DirectShowUtils::findUnconnectedPin + * @param filter + * @param pinDirection + * @param pin + * @param hrOut + * @return + */ +bool DirectShowUtils::findUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + IEnumPins *enumPins = nullptr; + const ScopedSafeRelease<IEnumPins> releaseEnumPins { &enumPins }; + *hrOut = filter->EnumPins(&enumPins); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to retrieve pins from the DS filter"); + return false; + } + + IPin *nextPin = nullptr; + while (S_OK == enumPins->Next(1, &nextPin, nullptr)) { + const ScopedSafeRelease<IPin> releaseNextPin { &nextPin }; + if (matchPin(nextPin, pinDirection, FALSE, hrOut)) { + *pin = nextPin; + (*pin)->AddRef(); + return true; + } + + if (FAILED(*hrOut)) + return false; + } + + qCDebug(qtDirectShowPlugin, "No unconnected pins found"); + *hrOut = VFW_E_NOT_FOUND; + + return false; +} + +/** + * @brief DirectShowUtils::connectFilters - Attempts to connect \a outputPin to \a filter + * @param graph + * @param outputPin + * @param filter + * @param hrOut + * @return + */ +bool DirectShowUtils::connectFilters(IGraphBuilder *graph, IPin *outputPin, IBaseFilter *filter, HRESULT *hrOut) +{ + + // Find an input pin on the downstream filter. + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + IPin *inputPin = nullptr; + const ScopedSafeRelease<IPin> releaseInputPin { &inputPin }; + if (!findUnconnectedPin(filter, PINDIR_INPUT, &inputPin, hrOut)) + return false; + + + // Try to connect them. + *hrOut = graph->Connect(outputPin, inputPin); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to connect output pin to filter!"); + return false; + } + + return true; +} + +/** + * @brief DirectShowUtils::connectFilters - Attempts to connect \a filter to \a inputPin. + * @param graph + * @param filter + * @param inputPin + * @param hrOut + * @return + */ +bool DirectShowUtils::connectFilters(IGraphBuilder *graph, IBaseFilter *filter, IPin *inputPin, HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + IPin *outputPin = nullptr; + const ScopedSafeRelease<IPin> releaseOutputPin { &outputPin }; + // Find an output pin on the upstream filter. + if (findUnconnectedPin(filter, PINDIR_OUTPUT, &outputPin, hrOut)) + return false; + + *hrOut = graph->Connect(outputPin, inputPin); + if (FAILED(*hrOut)) { + qCDebug(qtDirectShowPlugin, "Unable to connect filter to input pin!"); + return false; + } + + return true; +} + +/** + * @brief DirectShowUtils::connectFilters - Attempts to connect the \a upstreamFilter to \a downstreamFilter. + * @param graph + * @param upstreamFilter + * @param downstreamFilter + * @param autoConnect - If set to true all filters in the graph will be considered. + * @param hrOut + * @return true if the the filters were connected, false otherwise. + */ +bool DirectShowUtils::connectFilters(IGraphBuilder *graph, + IBaseFilter *upstreamFilter, + IBaseFilter *downstreamFilter, + bool autoConnect, + HRESULT *hrOut) +{ + HRESULT hr = S_OK; + if (!hrOut) + hrOut = &hr; + + const auto findAndConnect = [graph, downstreamFilter, hrOut](IBaseFilter *filter) -> bool { + IPin *outputPin = nullptr; + const ScopedSafeRelease<IPin> releaseOutputPin { &outputPin }; + if (findUnconnectedPin(filter, PINDIR_OUTPUT, &outputPin, hrOut)) + return connectFilters(graph, outputPin, downstreamFilter, hrOut); + + return false; + }; + + // Try to connect to the upstream filter first. + if (findAndConnect(upstreamFilter)) + return S_OK; + + const auto getFilters = [graph, hrOut]() -> IEnumFilters * { + IEnumFilters *f = nullptr; + *hrOut = graph->EnumFilters(&f); + return f; + }; + IEnumFilters *filters = autoConnect ? getFilters() + : nullptr; + const ScopedSafeRelease<IEnumFilters> releaseEnumFilters { &filters }; + if (!filters) { + qCDebug(qtDirectShowPlugin, "No filters found!"); + return false; + } + + IBaseFilter *nextFilter = nullptr; + while (S_OK == filters->Next(1, &nextFilter, 0)) { + const ScopedSafeRelease<IBaseFilter> releaseNextFilter { &nextFilter }; + if (nextFilter && findAndConnect(nextFilter)) + break; + } + + return SUCCEEDED(*hrOut); +} diff --git a/src/plugins/directshow/helpers/directshowutils.h b/src/plugins/directshow/helpers/directshowutils.h new file mode 100644 index 000000000..09c81c257 --- /dev/null +++ b/src/plugins/directshow/helpers/directshowutils.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWUTILS_H +#define DIRECTSHOWUTILS_H + +#include "directshowglobal.h" + +QT_BEGIN_NAMESPACE + +namespace DirectShowUtils +{ +template <typename T> +void safeRelease(T **iface) { + if (!iface) + return; + + if (!*iface) + return; + + (*iface)->Release(); + *iface = nullptr; +} + +template <typename T> +struct ScopedSafeRelease +{ + T **iunknown; + ~ScopedSafeRelease() + { + DirectShowUtils::safeRelease(iunknown); + } +}; + +bool getPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut); +bool isPinConnected(IPin *pin, HRESULT *hrOut = nullptr); +bool hasPinDirection(IPin *pin, PIN_DIRECTION direction, HRESULT *hrOut = nullptr); +bool matchPin(IPin *pin, PIN_DIRECTION pinDirection, BOOL shouldBeConnected, HRESULT *hrOut = nullptr); +bool findUnconnectedPin(IBaseFilter *filter, PIN_DIRECTION pinDirection, IPin **pin, HRESULT *hrOut = nullptr); +bool connectFilters(IGraphBuilder *graph, IPin *outputPin, IBaseFilter *filter, HRESULT *hrOut = nullptr); +bool connectFilters(IGraphBuilder *graph, IBaseFilter *filter, IPin *inputPin, HRESULT *hrOut = nullptr); +bool connectFilters(IGraphBuilder *graph, + IBaseFilter *upstreamFilter, + IBaseFilter *downstreamFilter, + bool autoConnect = false, + HRESULT *hrOut = nullptr); +} + +QT_END_NAMESPACE + +#endif // DIRECTSHOWUTILS_H diff --git a/src/plugins/directshow/helpers/helpers.pri b/src/plugins/directshow/helpers/helpers.pri index b3743a680..ca883eeb8 100644 --- a/src/plugins/directshow/helpers/helpers.pri +++ b/src/plugins/directshow/helpers/helpers.pri @@ -9,7 +9,8 @@ HEADERS += \ $$PWD/directshowobject.h \ $$PWD/directshowpin.h \ $$PWD/directshowpinenum.h \ - $$PWD/directshowvideobuffer.h + $$PWD/directshowvideobuffer.h \ + $$PWD/directshowutils.h SOURCES += \ $$PWD/directshowbasefilter.cpp \ @@ -19,4 +20,5 @@ SOURCES += \ $$PWD/directshowobject.cpp \ $$PWD/directshowpin.cpp \ $$PWD/directshowpinenum.cpp \ - $$PWD/directshowvideobuffer.cpp + $$PWD/directshowvideobuffer.cpp \ + $$PWD/directshowutils.cpp diff --git a/src/plugins/directshow/player/directshowiosource.cpp b/src/plugins/directshow/player/directshowiosource.cpp index 3c44dd1ed..96b4b14bf 100644 --- a/src/plugins/directshow/player/directshowiosource.cpp +++ b/src/plugins/directshow/player/directshowiosource.cpp @@ -82,7 +82,7 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) // The filter works in pull mode, the downstream filter is responsible for requesting // samples from this one. // - AM_MEDIA_TYPE type = + AM_MEDIA_TYPE type { MEDIATYPE_Stream, // majortype MEDIASUBTYPE_NULL, // subtype @@ -99,7 +99,7 @@ DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) for (int i = 0; i < count; ++i) { type.subtype = directshow_subtypes[i]; - m_supportedMediaTypes.append(type); + m_supportedMediaTypes.append(DirectShowMediaType(type)); } } @@ -371,12 +371,12 @@ HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) hr = pReceivePin->ReceiveConnection(this, pmt); // Update the media type for the current connection. if (SUCCEEDED(hr)) - m_connectionMediaType = *pmt; + DirectShowMediaType::copy(&m_connectionMediaType, pmt); } else if (pmt && pmt->subtype == MEDIATYPE_NULL) { // - Partial type (Stream, but no subtype specified). - m_connectionMediaType = *pmt; + DirectShowMediaType::copy(&m_connectionMediaType, pmt); // Check if the receiving pin accepts any of the streaming subtypes. for (const DirectShowMediaType &t : qAsConst(m_supportedMediaTypes)) { - m_connectionMediaType.subtype = t.subtype; + m_connectionMediaType->subtype = t->subtype; hr = pReceivePin->ReceiveConnection(this, &m_connectionMediaType); if (SUCCEEDED(hr)) break; @@ -477,7 +477,7 @@ HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt) return VFW_E_NOT_CONNECTED; } else { - DirectShowMediaType::copy(pmt, m_connectionMediaType); + DirectShowMediaType::copy(pmt, &m_connectionMediaType); return S_OK; } diff --git a/src/plugins/directshow/player/directshowplayercontrol.cpp b/src/plugins/directshow/player/directshowplayercontrol.cpp index fce488af2..2d0ee2d59 100644 --- a/src/plugins/directshow/player/directshowplayercontrol.cpp +++ b/src/plugins/directshow/player/directshowplayercontrol.cpp @@ -200,7 +200,7 @@ qreal DirectShowPlayerControl::playbackRate() const void DirectShowPlayerControl::setPlaybackRate(qreal rate) { - if (m_playbackRate != rate) { + if (!qFuzzyCompare(m_playbackRate, rate)) { m_service->setRate(rate); emit playbackRateChanged(m_playbackRate = rate); @@ -370,7 +370,7 @@ void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, void DirectShowPlayerControl::updatePlaybackRate(qreal rate) { - if (m_playbackRate != rate) { + if (!qFuzzyCompare(m_playbackRate, rate)) { m_playbackRate = rate; scheduleUpdate(PlaybackRateProperty); diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp index 1554d194d..5fbb6ef05 100644 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ b/src/plugins/directshow/player/directshowplayerservice.cpp @@ -629,13 +629,13 @@ int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { PIN_DIRECTION direction; if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) { - AM_MEDIA_TYPE connectionType; + DirectShowMediaType connectionType; if (SUCCEEDED(pin->ConnectionMediaType(&connectionType))) { IPin *peer = 0; - if (connectionType.majortype == MEDIATYPE_Audio) { + if (connectionType->majortype == MEDIATYPE_Audio) { streamTypes |= AudioStream; - } else if (connectionType.majortype == MEDIATYPE_Video) { + } else if (connectionType->majortype == MEDIATYPE_Video) { streamTypes |= VideoStream; } else if (SUCCEEDED(pin->ConnectedTo(&peer))) { PIN_INFO peerInfo; diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h index b8d30e79a..d933bd660 100644 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ b/src/plugins/directshow/player/directshowplayerservice.h @@ -186,6 +186,7 @@ private: int m_pendingTasks; int m_executingTask; int m_executedTasks; + int m_streamTypes; HANDLE m_taskHandle; HANDLE m_eventHandle; GraphStatus m_graphStatus; @@ -195,20 +196,19 @@ private: IBaseFilter *m_source; IBaseFilter *m_audioOutput; IBaseFilter *m_videoOutput; - int m_streamTypes; qreal m_rate; qint64 m_position; qint64 m_seekPosition; qint64 m_duration; - bool m_buffering; - bool m_seekable; - bool m_atEnd; - bool m_dontCacheNextSeekResult; QMediaTimeRange m_playbackRange; QUrl m_url; QMediaResourceList m_resources; QString m_errorString; QMutex m_mutex; + bool m_buffering; + bool m_seekable; + bool m_atEnd; + bool m_dontCacheNextSeekResult; friend class DirectShowPlayerServiceThread; }; diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp index 4cb97be39..13f767a85 100644 --- a/src/plugins/directshow/player/videosurfacefilter.cpp +++ b/src/plugins/directshow/player/videosurfacefilter.cpp @@ -63,8 +63,8 @@ public: VideoSurfaceInputPin(VideoSurfaceFilter *filter); // DirectShowPin - bool isMediaTypeSupported(const DirectShowMediaType *type); - bool setMediaType(const DirectShowMediaType *type); + bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) override; + bool setMediaType(const AM_MEDIA_TYPE *type) override; HRESULT completeConnection(IPin *pin); HRESULT connectionEnded(); @@ -90,12 +90,12 @@ VideoSurfaceInputPin::VideoSurfaceInputPin(VideoSurfaceFilter *filter) { } -bool VideoSurfaceInputPin::isMediaTypeSupported(const DirectShowMediaType *type) +bool VideoSurfaceInputPin::isMediaTypeSupported(const AM_MEDIA_TYPE *type) { return m_videoSurfaceFilter->isMediaTypeSupported(type); } -bool VideoSurfaceInputPin::setMediaType(const DirectShowMediaType *type) +bool VideoSurfaceInputPin::setMediaType(const AM_MEDIA_TYPE *type) { if (!DirectShowInputPin::setMediaType(type)) return false; @@ -282,7 +282,7 @@ void VideoSurfaceFilter::supportedFormatsChanged() } } -bool VideoSurfaceFilter::isMediaTypeSupported(const DirectShowMediaType *type) +bool VideoSurfaceFilter::isMediaTypeSupported(const AM_MEDIA_TYPE *type) { if (type->majortype != MEDIATYPE_Video || type->bFixedSizeSamples == FALSE) return false; @@ -297,7 +297,7 @@ bool VideoSurfaceFilter::isMediaTypeSupported(const DirectShowMediaType *type) return false; } -bool VideoSurfaceFilter::setMediaType(const DirectShowMediaType *type) +bool VideoSurfaceFilter::setMediaType(const AM_MEDIA_TYPE *type) { if (!type) { qCDebug(qLcRenderFilter, "clear media type"); @@ -305,7 +305,7 @@ bool VideoSurfaceFilter::setMediaType(const DirectShowMediaType *type) m_bytesPerLine = 0; return true; } else { - m_surfaceFormat = DirectShowMediaType::formatFromType(*type); + m_surfaceFormat = DirectShowMediaType::videoFormatFromType(type); m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat); qCDebug(qLcRenderFilter) << "setMediaType -->" << m_surfaceFormat; return m_surfaceFormat.isValid(); @@ -478,7 +478,7 @@ HRESULT VideoSurfaceFilter::Receive(IMediaSample *pMediaSample) // If the format dynamically changed, the sample contains information about the new format. // We need to reset the format and restart the QAbstractVideoSurface. if (m_pin->currentSampleProperties()->pMediaType - && (!m_pin->setMediaType(reinterpret_cast<const DirectShowMediaType *>(m_pin->currentSampleProperties()->pMediaType)) + && (!m_pin->setMediaType(m_pin->currentSampleProperties()->pMediaType) || !restartSurface())) { qCWarning(qLcRenderFilter, " dynamic format change failed, aborting rendering"); NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0); diff --git a/src/plugins/directshow/player/videosurfacefilter.h b/src/plugins/directshow/player/videosurfacefilter.h index 581e33c70..6d6cc7593 100644 --- a/src/plugins/directshow/player/videosurfacefilter.h +++ b/src/plugins/directshow/player/videosurfacefilter.h @@ -83,8 +83,8 @@ public: STDMETHODIMP_(ULONG) GetMiscFlags(); // DirectShowPin (delegate) - bool isMediaTypeSupported(const DirectShowMediaType *type); - bool setMediaType(const DirectShowMediaType *type); + bool isMediaTypeSupported(const AM_MEDIA_TYPE *type); + bool setMediaType(const AM_MEDIA_TYPE *type); HRESULT completeConnection(IPin *pin); HRESULT connectionEnded(); diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h index c9c5c70e3..f5e26e553 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodercontrol.h @@ -64,25 +64,25 @@ public: QGstreamerAudioDecoderControl(QGstreamerAudioDecoderSession *session, QObject *parent = 0); ~QGstreamerAudioDecoderControl(); - QAudioDecoder::State state() const; + QAudioDecoder::State state() const override; - QString sourceFilename() const; - void setSourceFilename(const QString &fileName); + QString sourceFilename() const override; + void setSourceFilename(const QString &fileName) override; - QIODevice* sourceDevice() const; - void setSourceDevice(QIODevice *device); + QIODevice* sourceDevice() const override; + void setSourceDevice(QIODevice *device) override; - void start(); - void stop(); + void start() override; + void stop() override; - QAudioFormat audioFormat() const; - void setAudioFormat(const QAudioFormat &format); + QAudioFormat audioFormat() const override; + void setAudioFormat(const QAudioFormat &format) override; - QAudioBuffer read(); - bool bufferAvailable() const; + QAudioBuffer read() override; + bool bufferAvailable() const override; - qint64 position() const; - qint64 duration() const; + qint64 position() const override; + qint64 duration() const override; private: // Stuff goes here diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h index df54d39f4..6e52b9d87 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderservice.h @@ -56,8 +56,8 @@ public: QGstreamerAudioDecoderService(QObject *parent = 0); ~QGstreamerAudioDecoderService(); - QMediaControl *requestControl(const char *name); - void releaseControl(QMediaControl *control); + QMediaControl *requestControl(const char *name) override; + void releaseControl(QMediaControl *control) override; private: QGstreamerAudioDecoderControl *m_control; diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.h index a5ae56637..d1b96043b 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.h +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.h @@ -55,11 +55,11 @@ class QGstreamerAudioDecoderServicePlugin Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "audiodecoder.json") public: - QMediaService* create(QString const& key); - void release(QMediaService *service); + QMediaService* create(const QString &key) override; + void release(QMediaService *service) override; - QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const; - QStringList supportedMimeTypes() const; + QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList &codecs) const override; + QStringList supportedMimeTypes() const override; private: void updateSupportedMimeTypes() const; diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h index 3d0e9a2b0..385908cbd 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.h @@ -74,7 +74,7 @@ public: QAudioDecoder::State state() const { return m_state; } QAudioDecoder::State pendingState() const { return m_pendingState; } - bool processBusMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message) override; #if QT_CONFIG(gstreamer_app) QGstAppSrc *appsrc() const { return m_appSrc; } diff --git a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h index 943ef19b0..b8091c8ca 100644 --- a/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinaudioencoder.h @@ -67,20 +67,20 @@ public: CameraBinAudioEncoder(QObject *parent); virtual ~CameraBinAudioEncoder(); - QStringList supportedAudioCodecs() const; - QString codecDescription(const QString &codecName) const; + QStringList supportedAudioCodecs() const override; + QString codecDescription(const QString &codecName) const override; QStringList supportedEncodingOptions(const QString &codec) const; QVariant encodingOption(const QString &codec, const QString &name) const; void setEncodingOption(const QString &codec, const QString &name, const QVariant &value); QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(), - bool *isContinuous = 0) const; + bool *isContinuous = 0) const override; QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const; QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const; - QAudioEncoderSettings audioSettings() const; - void setAudioSettings(const QAudioEncoderSettings&); + QAudioEncoderSettings audioSettings() const override; + void setAudioSettings(const QAudioEncoderSettings &) override; QAudioEncoderSettings actualAudioSettings() const; void setActualAudioSettings(const QAudioEncoderSettings&); diff --git a/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h index 96af6c7fb..a6cdc5297 100644 --- a/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h +++ b/src/plugins/gstreamer/camerabin/camerabincapturebufferformat.h @@ -59,10 +59,10 @@ public: CameraBinCaptureBufferFormat(CameraBinSession *session); virtual ~CameraBinCaptureBufferFormat(); - QList<QVideoFrame::PixelFormat> supportedBufferFormats() const; + QList<QVideoFrame::PixelFormat> supportedBufferFormats() const override; - QVideoFrame::PixelFormat bufferFormat() const; - void setBufferFormat(QVideoFrame::PixelFormat format); + QVideoFrame::PixelFormat bufferFormat() const override; + void setBufferFormat(QVideoFrame::PixelFormat format) override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabincapturedestination.h b/src/plugins/gstreamer/camerabin/camerabincapturedestination.h index 0ee40e7ba..460fd1aa3 100644 --- a/src/plugins/gstreamer/camerabin/camerabincapturedestination.h +++ b/src/plugins/gstreamer/camerabin/camerabincapturedestination.h @@ -56,9 +56,9 @@ public: CameraBinCaptureDestination(CameraBinSession *session); virtual ~CameraBinCaptureDestination(); - bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const; - QCameraImageCapture::CaptureDestinations captureDestination() const; - void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination); + bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const override; + QCameraImageCapture::CaptureDestinations captureDestination() const override; + void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp index 1479b4ba6..0fc51611e 100644 --- a/src/plugins/gstreamer/camerabin/camerabincontainer.cpp +++ b/src/plugins/gstreamer/camerabin/camerabincontainer.cpp @@ -40,6 +40,7 @@ #include <QtMultimedia/private/qtmultimediaglobal_p.h> #include "camerabincontainer.h" #include <QtCore/qregexp.h> +#include <private/qgstutils_p.h> #include <QtCore/qdebug.h> @@ -51,14 +52,6 @@ CameraBinContainer::CameraBinContainer(QObject *parent) , m_supportedContainers(QGstCodecsInfo::Muxer) #endif { - //extension for containers hard to guess from mimetype - m_fileExtensions["video/x-matroska"] = "mkv"; - m_fileExtensions["video/quicktime"] = "mov"; - m_fileExtensions["video/x-msvideo"] = "avi"; - m_fileExtensions["video/msvideo"] = "avi"; - m_fileExtensions["audio/mpeg"] = "mp3"; - m_fileExtensions["application/x-shockwave-flash"] = "swf"; - m_fileExtensions["application/x-pn-realmedia"] = "rm"; } QStringList CameraBinContainer::supportedContainers() const @@ -128,9 +121,9 @@ GstEncodingContainerProfile *CameraBinContainer::createProfile() //if format is not in the list of supported gstreamer mime types, //try to find the mime type with matching extension if (!supportedFormats.contains(format)) { - QString extension = suggestedFileExtension(m_actualFormat); + QString extension = QGstUtils::fileExtensionForMimeType(m_actualFormat); for (const QString &formatCandidate : supportedFormats) { - if (suggestedFileExtension(formatCandidate) == extension) { + if (QGstUtils::fileExtensionForMimeType(formatCandidate) == extension) { format = formatCandidate; break; } @@ -153,27 +146,4 @@ GstEncodingContainerProfile *CameraBinContainer::createProfile() #endif -/*! - Suggest file extension for current container mimetype. - */ -QString CameraBinContainer::suggestedFileExtension(const QString &containerFormat) const -{ - //for container names like avi instead of video/x-msvideo, use it as extension - if (!containerFormat.contains('/')) - return containerFormat; - - QString format = containerFormat.left(containerFormat.indexOf(',')); - QString extension = m_fileExtensions.value(format); - - if (!extension.isEmpty() || format.isEmpty()) - return extension; - - QRegExp rx("[-/]([\\w]+)$"); - - if (rx.indexIn(format) != -1) - extension = rx.cap(1); - - return extension; -} - QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabincontainer.h b/src/plugins/gstreamer/camerabin/camerabincontainer.h index 25de50095..738e55e2a 100644 --- a/src/plugins/gstreamer/camerabin/camerabincontainer.h +++ b/src/plugins/gstreamer/camerabin/camerabincontainer.h @@ -63,18 +63,16 @@ public: CameraBinContainer(QObject *parent); virtual ~CameraBinContainer() {} - virtual QStringList supportedContainers() const; - virtual QString containerDescription(const QString &formatMimeType) const; + QStringList supportedContainers() const override; + QString containerDescription(const QString &formatMimeType) const override; - virtual QString containerFormat() const; - virtual void setContainerFormat(const QString &format); + QString containerFormat() const override; + void setContainerFormat(const QString &format) override; QString actualContainerFormat() const; void setActualContainerFormat(const QString &containerFormat); void resetActualContainerFormat(); - QString suggestedFileExtension(const QString &containerFormat) const; - #if QT_CONFIG(gstreamer_encodingprofiles) GstEncodingContainerProfile *createProfile(); #endif @@ -85,7 +83,6 @@ Q_SIGNALS: private: QString m_format; QString m_actualFormat; - QMap<QString, QString> m_fileExtensions; #if QT_CONFIG(gstreamer_encodingprofiles) QGstCodecsInfo m_supportedContainers; diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.h b/src/plugins/gstreamer/camerabin/camerabincontrol.h index a4d052afb..56c02dad4 100644 --- a/src/plugins/gstreamer/camerabin/camerabincontrol.h +++ b/src/plugins/gstreamer/camerabin/camerabincontrol.h @@ -59,16 +59,16 @@ public: bool isValid() const { return true; } - QCamera::State state() const; - void setState(QCamera::State state); + QCamera::State state() const override; + void setState(QCamera::State state) override; - QCamera::Status status() const; + QCamera::Status status() const override; - QCamera::CaptureModes captureMode() const; - void setCaptureMode(QCamera::CaptureModes mode); + QCamera::CaptureModes captureMode() const override; + void setCaptureMode(QCamera::CaptureModes mode) override; - bool isCaptureModeSupported(QCamera::CaptureModes mode) const; - bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const; + bool isCaptureModeSupported(QCamera::CaptureModes mode) const override; + bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const override; bool viewfinderColorSpaceConversion() const; CamerabinResourcePolicy *resourcePolicy() { return m_resourcePolicy; } diff --git a/src/plugins/gstreamer/camerabin/camerabinexposure.h b/src/plugins/gstreamer/camerabin/camerabinexposure.h index 0435569d4..c30da25ad 100644 --- a/src/plugins/gstreamer/camerabin/camerabinexposure.h +++ b/src/plugins/gstreamer/camerabin/camerabinexposure.h @@ -58,12 +58,12 @@ public: CameraBinExposure(CameraBinSession *session); virtual ~CameraBinExposure(); - bool isParameterSupported(ExposureParameter parameter) const; - QVariantList supportedParameterRange(ExposureParameter parameter, bool *continuous) const; + bool isParameterSupported(ExposureParameter parameter) const override; + QVariantList supportedParameterRange(ExposureParameter parameter, bool *continuous) const override; - QVariant requestedValue(ExposureParameter parameter) const; - QVariant actualValue(ExposureParameter parameter) const; - bool setValue(ExposureParameter parameter, const QVariant& value); + QVariant requestedValue(ExposureParameter parameter) const override; + QVariant actualValue(ExposureParameter parameter) const override; + bool setValue(ExposureParameter parameter, const QVariant &value) override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabinflash.h b/src/plugins/gstreamer/camerabin/camerabinflash.h index 0bcfef1b9..84177f122 100644 --- a/src/plugins/gstreamer/camerabin/camerabinflash.h +++ b/src/plugins/gstreamer/camerabin/camerabinflash.h @@ -57,11 +57,11 @@ public: CameraBinFlash(CameraBinSession *session); virtual ~CameraBinFlash(); - QCameraExposure::FlashModes flashMode() const; - void setFlashMode(QCameraExposure::FlashModes mode); - bool isFlashModeSupported(QCameraExposure::FlashModes mode) const; + QCameraExposure::FlashModes flashMode() const override; + void setFlashMode(QCameraExposure::FlashModes mode) override; + bool isFlashModeSupported(QCameraExposure::FlashModes mode) const override; - bool isFlashReady() const; + bool isFlashReady() const override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabinfocus.h b/src/plugins/gstreamer/camerabin/camerabinfocus.h index 2b510a987..72a5006f9 100644 --- a/src/plugins/gstreamer/camerabin/camerabinfocus.h +++ b/src/plugins/gstreamer/camerabin/camerabinfocus.h @@ -68,17 +68,17 @@ public: CameraBinFocus(CameraBinSession *session); virtual ~CameraBinFocus(); - QCameraFocus::FocusModes focusMode() const; - void setFocusMode(QCameraFocus::FocusModes mode); - bool isFocusModeSupported(QCameraFocus::FocusModes mode) const; + QCameraFocus::FocusModes focusMode() const override; + void setFocusMode(QCameraFocus::FocusModes mode) override; + bool isFocusModeSupported(QCameraFocus::FocusModes mode) const override; - QCameraFocus::FocusPointMode focusPointMode() const; - void setFocusPointMode(QCameraFocus::FocusPointMode mode) ; - bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const; - QPointF customFocusPoint() const; - void setCustomFocusPoint(const QPointF &point); + QCameraFocus::FocusPointMode focusPointMode() const override; + void setFocusPointMode(QCameraFocus::FocusPointMode mode) override; + bool isFocusPointModeSupported(QCameraFocus::FocusPointMode) const override; + QPointF customFocusPoint() const override; + void setCustomFocusPoint(const QPointF &point) override; - QCameraFocusZoneList focusZones() const; + QCameraFocusZoneList focusZones() const override; void handleFocusMessage(GstMessage*); QCamera::LockStatus focusStatus() const { return m_focusStatus; } @@ -94,7 +94,7 @@ public Q_SLOTS: #if GST_CHECK_VERSION(1,0,0) protected: - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event) override; #endif private Q_SLOTS: @@ -111,7 +111,7 @@ private: void updateRegionOfInterest(const QVector<QRect> &rectangles); #if GST_CHECK_VERSION(1,0,0) - bool probeBuffer(GstBuffer *buffer); + bool probeBuffer(GstBuffer *buffer) override; #endif CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h index a8a55bb06..5e00ab6d5 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimagecapture.h +++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.h @@ -62,14 +62,14 @@ public: CameraBinImageCapture(CameraBinSession *session); virtual ~CameraBinImageCapture(); - QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; } - void setDriveMode(QCameraImageCapture::DriveMode) {} + QCameraImageCapture::DriveMode driveMode() const override { return QCameraImageCapture::SingleImageCapture; } + void setDriveMode(QCameraImageCapture::DriveMode) override {} - bool isReadyForCapture() const; - int capture(const QString &fileName); - void cancelCapture(); + bool isReadyForCapture() const override; + int capture(const QString &fileName) override; + void cancelCapture() override; - bool processBusMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message) override; private slots: void updateState(); @@ -85,8 +85,8 @@ private: { public: EncoderProbe(CameraBinImageCapture *capture) : capture(capture) {} - void probeCaps(GstCaps *caps); - bool probeBuffer(GstBuffer *buffer); + void probeCaps(GstCaps *caps) override; + bool probeBuffer(GstBuffer *buffer) override; private: CameraBinImageCapture * const capture; @@ -96,8 +96,8 @@ private: { public: MuxerProbe(CameraBinImageCapture *capture) : capture(capture) {} - void probeCaps(GstCaps *caps); - bool probeBuffer(GstBuffer *buffer); + void probeCaps(GstCaps *caps) override; + bool probeBuffer(GstBuffer *buffer) override; private: CameraBinImageCapture * const capture; diff --git a/src/plugins/gstreamer/camerabin/camerabinimageencoder.h b/src/plugins/gstreamer/camerabin/camerabinimageencoder.h index 8c777b9cd..96f7ae7aa 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimageencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinimageencoder.h @@ -58,13 +58,13 @@ public: virtual ~CameraBinImageEncoder(); QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = 0) const override; - QStringList supportedImageCodecs() const; - QString imageCodecDescription(const QString &formatName) const; + QStringList supportedImageCodecs() const override; + QString imageCodecDescription(const QString &formatName) const override; - QImageEncoderSettings imageSettings() const; - void setImageSettings(const QImageEncoderSettings &settings); + QImageEncoderSettings imageSettings() const override; + void setImageSettings(const QImageEncoderSettings &settings) override; Q_SIGNALS: void settingsChanged(); diff --git a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h index b09c8d52b..259138e91 100644 --- a/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h +++ b/src/plugins/gstreamer/camerabin/camerabinimageprocessing.h @@ -75,10 +75,10 @@ public: bool setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode); bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const; - bool isParameterSupported(ProcessingParameter) const; - bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const; - QVariant parameter(ProcessingParameter parameter) const; - void setParameter(ProcessingParameter parameter, const QVariant &value); + bool isParameterSupported(ProcessingParameter) const override; + bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const override; + QVariant parameter(ProcessingParameter parameter) const override; + void setParameter(ProcessingParameter parameter, const QVariant &value) override; #if QT_CONFIG(gstreamer_photography) void lockWhiteBalance(); diff --git a/src/plugins/gstreamer/camerabin/camerabininfocontrol.h b/src/plugins/gstreamer/camerabin/camerabininfocontrol.h index c5029dc0a..9c801e804 100644 --- a/src/plugins/gstreamer/camerabin/camerabininfocontrol.h +++ b/src/plugins/gstreamer/camerabin/camerabininfocontrol.h @@ -53,8 +53,8 @@ public: CameraBinInfoControl(GstElementFactory *sourceFactory, QObject *parent); ~CameraBinInfoControl(); - QCamera::Position cameraPosition(const QString &deviceName) const; - int cameraOrientation(const QString &deviceName) const; + QCamera::Position cameraPosition(const QString &deviceName) const override; + int cameraOrientation(const QString &deviceName) const override; private: GstElementFactory * const m_sourceFactory; diff --git a/src/plugins/gstreamer/camerabin/camerabinlocks.h b/src/plugins/gstreamer/camerabin/camerabinlocks.h index c90675615..cd592ffd2 100644 --- a/src/plugins/gstreamer/camerabin/camerabinlocks.h +++ b/src/plugins/gstreamer/camerabin/camerabinlocks.h @@ -61,16 +61,16 @@ public: CameraBinLocks(CameraBinSession *session); virtual ~CameraBinLocks(); - QCamera::LockTypes supportedLocks() const; + QCamera::LockTypes supportedLocks() const override; - QCamera::LockStatus lockStatus(QCamera::LockType lock) const; + QCamera::LockStatus lockStatus(QCamera::LockType lock) const override; - void searchAndLock(QCamera::LockTypes locks); - void unlock(QCamera::LockTypes locks); + void searchAndLock(QCamera::LockTypes locks) override; + void unlock(QCamera::LockTypes locks) override; protected: #if GST_CHECK_VERSION(1, 2, 0) - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event) override; #endif private slots: diff --git a/src/plugins/gstreamer/camerabin/camerabinmetadata.h b/src/plugins/gstreamer/camerabin/camerabinmetadata.h index 67d3bf46e..5fef7e388 100644 --- a/src/plugins/gstreamer/camerabin/camerabinmetadata.h +++ b/src/plugins/gstreamer/camerabin/camerabinmetadata.h @@ -52,12 +52,12 @@ public: virtual ~CameraBinMetaData() {} - bool isMetaDataAvailable() const { return true; } - bool isWritable() const { return true; } + bool isMetaDataAvailable() const override { return true; } + bool isWritable() const override { return true; } - QVariant metaData(const QString &key) const; - void setMetaData(const QString &key, const QVariant &value); - QStringList availableMetaData() const; + QVariant metaData(const QString &key) const override; + void setMetaData(const QString &key, const QVariant &value) override; + QStringList availableMetaData() const override; Q_SIGNALS: void metaDataChanged(const QMap<QByteArray, QVariant>&); diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.h b/src/plugins/gstreamer/camerabin/camerabinrecorder.h index 86aa2fb94..8bd922fb8 100644 --- a/src/plugins/gstreamer/camerabin/camerabinrecorder.h +++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.h @@ -59,27 +59,27 @@ public: CameraBinRecorder(CameraBinSession *session); virtual ~CameraBinRecorder(); - QUrl outputLocation() const; - bool setOutputLocation(const QUrl &sink); + QUrl outputLocation() const override; + bool setOutputLocation(const QUrl &sink) override; - QMediaRecorder::State state() const; - QMediaRecorder::Status status() const; + QMediaRecorder::State state() const override; + QMediaRecorder::Status status() const override; - qint64 duration() const; + qint64 duration() const override; - bool isMuted() const; - qreal volume() const; + bool isMuted() const override; + qreal volume() const override; - void applySettings(); + void applySettings() override; #if QT_CONFIG(gstreamer_encodingprofiles) GstEncodingContainerProfile *videoProfile(); #endif public slots: - void setState(QMediaRecorder::State state); - void setMuted(bool); - void setVolume(qreal volume); + void setState(QMediaRecorder::State state) override; + void setMuted(bool) override; + void setVolume(qreal volume) override; void updateStatus(); diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.h b/src/plugins/gstreamer/camerabin/camerabinservice.h index 9069c3d5c..44afef25f 100644 --- a/src/plugins/gstreamer/camerabin/camerabinservice.h +++ b/src/plugins/gstreamer/camerabin/camerabinservice.h @@ -71,8 +71,8 @@ public: CameraBinService(GstElementFactory *sourceFactory, QObject *parent = 0); virtual ~CameraBinService(); - QMediaControl *requestControl(const char *name); - void releaseControl(QMediaControl *); + QMediaControl *requestControl(const char *name) override; + void releaseControl(QMediaControl *) override; static bool isCameraBinAvailable(); diff --git a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h index 9b16c0eca..b31e44459 100644 --- a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h +++ b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h @@ -65,18 +65,18 @@ public: CameraBinServicePlugin(); ~CameraBinServicePlugin(); - QMediaService* create(QString const& key); - void release(QMediaService *service); + QMediaService* create(const QString &key) override; + void release(QMediaService *service) override; - QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const; + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const override; - QByteArray defaultDevice(const QByteArray &service) const; - QList<QByteArray> devices(const QByteArray &service) const; - QString deviceDescription(const QByteArray &service, const QByteArray &device); + QByteArray defaultDevice(const QByteArray &service) const override; + QList<QByteArray> devices(const QByteArray &service) const override; + QString deviceDescription(const QByteArray &service, const QByteArray &device) override; QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property); - QCamera::Position cameraPosition(const QByteArray &device) const; - int cameraOrientation(const QByteArray &device) const; + QCamera::Position cameraPosition(const QByteArray &device) const override; + int cameraOrientation(const QByteArray &device) const override; private: GstElementFactory *sourceFactory() const; diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index b0a11bb44..ab0bea24a 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -1114,7 +1114,7 @@ void CameraBinSession::recordVideo() : m_sink.toString(), QMediaStorageLocation::Movies, QLatin1String("clip_"), - m_mediaContainerControl->suggestedFileExtension(format)); + QGstUtils::fileExtensionForMimeType(format)); m_recordingActive = true; m_actualSink = QUrl::fromLocalFile(actualFileName); diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h index 8966a2ece..d5c2d7822 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.h +++ b/src/plugins/gstreamer/camerabin/camerabinsession.h @@ -162,8 +162,8 @@ public: QString device() const { return m_inputDevice; } - bool processSyncMessage(const QGstreamerMessage &message); - bool processBusMessage(const QGstreamerMessage &message); + bool processSyncMessage(const QGstreamerMessage &message) override; + bool processBusMessage(const QGstreamerMessage &message) override; QGstreamerVideoProbeControl *videoProbe(); diff --git a/src/plugins/gstreamer/camerabin/camerabinv4limageprocessing.h b/src/plugins/gstreamer/camerabin/camerabinv4limageprocessing.h index 2cc9f925c..a38dc78da 100644 --- a/src/plugins/gstreamer/camerabin/camerabinv4limageprocessing.h +++ b/src/plugins/gstreamer/camerabin/camerabinv4limageprocessing.h @@ -55,10 +55,10 @@ public: CameraBinV4LImageProcessing(CameraBinSession *session); virtual ~CameraBinV4LImageProcessing(); - bool isParameterSupported(ProcessingParameter) const; - bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const; - QVariant parameter(ProcessingParameter parameter) const; - void setParameter(ProcessingParameter parameter, const QVariant &value); + bool isParameterSupported(ProcessingParameter) const override; + bool isParameterValueSupported(ProcessingParameter parameter, const QVariant &value) const override; + QVariant parameter(ProcessingParameter parameter) const override; + void setParameter(ProcessingParameter parameter, const QVariant &value) override; public slots: void updateParametersInfo(QCamera::Status cameraStatus); diff --git a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h index 922b6f464..24013ceab 100644 --- a/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h +++ b/src/plugins/gstreamer/camerabin/camerabinvideoencoder.h @@ -67,18 +67,18 @@ public: virtual ~CameraBinVideoEncoder(); QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = 0) const override; QList< qreal > supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = 0) const override; QPair<int,int> rateAsRational(qreal) const; - QStringList supportedVideoCodecs() const; - QString videoCodecDescription(const QString &codecName) const; + QStringList supportedVideoCodecs() const override; + QString videoCodecDescription(const QString &codecName) const override; - QVideoEncoderSettings videoSettings() const; - void setVideoSettings(const QVideoEncoderSettings &settings); + QVideoEncoderSettings videoSettings() const override; + void setVideoSettings(const QVideoEncoderSettings &settings) override; QVideoEncoderSettings actualVideoSettings() const; void setActualVideoSettings(const QVideoEncoderSettings&); diff --git a/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h index 7a03a065c..59a0ca8a9 100644 --- a/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h +++ b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings.h @@ -54,9 +54,9 @@ public: CameraBinViewfinderSettings(CameraBinSession *session); ~CameraBinViewfinderSettings(); - bool isViewfinderParameterSupported(ViewfinderParameter parameter) const; - QVariant viewfinderParameter(ViewfinderParameter parameter) const; - void setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value); + bool isViewfinderParameterSupported(ViewfinderParameter parameter) const override; + QVariant viewfinderParameter(ViewfinderParameter parameter) const override; + void setViewfinderParameter(ViewfinderParameter parameter, const QVariant &value) override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabinviewfindersettings2.h b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings2.h index 36349b2de..5e03b007a 100644 --- a/src/plugins/gstreamer/camerabin/camerabinviewfindersettings2.h +++ b/src/plugins/gstreamer/camerabin/camerabinviewfindersettings2.h @@ -53,10 +53,10 @@ public: CameraBinViewfinderSettings2(CameraBinSession *session); ~CameraBinViewfinderSettings2(); - QList<QCameraViewfinderSettings> supportedViewfinderSettings() const; + QList<QCameraViewfinderSettings> supportedViewfinderSettings() const override; - QCameraViewfinderSettings viewfinderSettings() const; - void setViewfinderSettings(const QCameraViewfinderSettings &settings); + QCameraViewfinderSettings viewfinderSettings() const override; + void setViewfinderSettings(const QCameraViewfinderSettings &settings) override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/camerabin/camerabinzoom.h b/src/plugins/gstreamer/camerabin/camerabinzoom.h index e009de3b7..8ad4764b2 100644 --- a/src/plugins/gstreamer/camerabin/camerabinzoom.h +++ b/src/plugins/gstreamer/camerabin/camerabinzoom.h @@ -53,15 +53,15 @@ public: CameraBinZoom(CameraBinSession *session); virtual ~CameraBinZoom(); - qreal maximumOpticalZoom() const; - qreal maximumDigitalZoom() const; + qreal maximumOpticalZoom() const override; + qreal maximumDigitalZoom() const override; - qreal requestedOpticalZoom() const; - qreal requestedDigitalZoom() const; - qreal currentOpticalZoom() const; - qreal currentDigitalZoom() const; + qreal requestedOpticalZoom() const override; + qreal requestedDigitalZoom() const override; + qreal currentOpticalZoom() const override; + qreal currentDigitalZoom() const override; - void zoomTo(qreal optical, qreal digital); + void zoomTo(qreal optical, qreal digital) override; private: CameraBinSession *m_session; diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp index abb58c963..40294214a 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp @@ -48,52 +48,18 @@ QGstreamerAudioEncode::QGstreamerAudioEncode(QObject *parent) :QAudioEncoderSettingsControl(parent) + , m_codecs(QGstCodecsInfo::AudioEncoder) { - QList<QByteArray> codecCandidates; - - codecCandidates << "audio/mpeg" << "audio/vorbis" << "audio/speex" << "audio/GSM" - << "audio/PCM" << "audio/AMR" << "audio/AMR-WB" << "audio/FLAC"; - - m_elementNames["audio/mpeg"] = "lamemp3enc"; - m_elementNames["audio/AMR"] = "amrnbenc"; - m_elementNames["audio/AMR-WB"] = "amrwbenc"; - - m_elementNames["audio/vorbis"] = "vorbisenc"; - m_elementNames["audio/speex"] = "speexenc"; - m_elementNames["audio/PCM"] = "audioresample"; - m_elementNames["audio/FLAC"] = "flacenc"; - m_elementNames["audio/GSM"] = "gsmenc"; - - m_codecOptions["audio/vorbis"] = QStringList() << "min-bitrate" << "max-bitrate"; - m_codecOptions["audio/mpeg"] = QStringList() << "mode"; - m_codecOptions["audio/speex"] = QStringList() << "mode" << "vbr" << "vad" << "dtx"; - m_codecOptions["audio/GSM"] = QStringList(); - m_codecOptions["audio/PCM"] = QStringList(); - m_codecOptions["audio/AMR"] = QStringList(); - m_codecOptions["audio/AMR-WB"] = QStringList(); - - for (const QByteArray& codecName : qAsConst(codecCandidates)) { - QByteArray elementName = m_elementNames[codecName]; - GstElementFactory *factory = gst_element_factory_find(elementName.constData()); + for (const QString& codecName : m_codecs.supportedCodecs()) { + GstElementFactory *factory = gst_element_factory_find(m_codecs.codecElement(codecName).constData()); if (factory) { - m_codecs.append(codecName); - const gchar *descr = gst_element_factory_get_description(factory); - - if (codecName == QByteArray("audio/PCM")) - m_codecDescriptions.insert(codecName, tr("Raw PCM audio")); - else - m_codecDescriptions.insert(codecName, QString::fromUtf8(descr)); - m_streamTypes.insert(codecName, QGstreamerMediaContainerControl::supportedStreamTypes(factory, GST_PAD_SRC)); gst_object_unref(GST_OBJECT(factory)); } } - - //if (!m_codecs.isEmpty()) - // m_audioSettings.setCodec(m_codecs[0]); } QGstreamerAudioEncode::~QGstreamerAudioEncode() @@ -102,17 +68,17 @@ QGstreamerAudioEncode::~QGstreamerAudioEncode() QStringList QGstreamerAudioEncode::supportedAudioCodecs() const { - return m_codecs; + return m_codecs.supportedCodecs(); } QString QGstreamerAudioEncode::codecDescription(const QString &codecName) const { - return m_codecDescriptions.value(codecName); + return m_codecs.codecDescription(codecName); } QStringList QGstreamerAudioEncode::supportedEncodingOptions(const QString &codec) const { - return m_codecOptions.value(codec); + return m_codecs.codecOptions(codec); } QVariant QGstreamerAudioEncode::encodingOption( @@ -148,24 +114,24 @@ void QGstreamerAudioEncode::setAudioSettings(const QAudioEncoderSettings &settin GstElement *QGstreamerAudioEncode::createEncoder() { QString codec = m_audioSettings.codec(); - GstElement *encoderElement = gst_element_factory_make(m_elementNames.value(codec).constData(), NULL); + GstElement *encoderElement = gst_element_factory_make(m_codecs.codecElement(codec).constData(), NULL); if (!encoderElement) return 0; GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin")); - GstElement *capsFilter = gst_element_factory_make("capsfilter", NULL); + GstElement *sinkCapsFilter = gst_element_factory_make("capsfilter", NULL); + GstElement *srcCapsFilter = gst_element_factory_make("capsfilter", NULL); - gst_bin_add(encoderBin, capsFilter); - gst_bin_add(encoderBin, encoderElement); - gst_element_link(capsFilter, encoderElement); + gst_bin_add_many(encoderBin, sinkCapsFilter, encoderElement, srcCapsFilter, NULL); + gst_element_link_many(sinkCapsFilter, encoderElement, srcCapsFilter, NULL); // add ghostpads - GstPad *pad = gst_element_get_static_pad(capsFilter, "sink"); + GstPad *pad = gst_element_get_static_pad(sinkCapsFilter, "sink"); gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad)); gst_object_unref(GST_OBJECT(pad)); - pad = gst_element_get_static_pad(encoderElement, "src"); + pad = gst_element_get_static_pad(srcCapsFilter, "src"); gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad)); gst_object_unref(GST_OBJECT(pad)); @@ -181,18 +147,23 @@ GstElement *QGstreamerAudioEncode::createEncoder() gst_caps_append_structure(caps,structure); - //qDebug() << "set caps filter:" << gst_caps_to_string(caps); - - g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL); + g_object_set(G_OBJECT(sinkCapsFilter), "caps", caps, NULL); gst_caps_unref(caps); } + // Some encoders support several codecs. Setting a caps filter downstream with the desired + // codec (which is actually a string representation of the caps) will make sure we use the + // correct codec. + GstCaps *caps = gst_caps_from_string(codec.toUtf8().constData()); + g_object_set(G_OBJECT(srcCapsFilter), "caps", caps, NULL); + gst_caps_unref(caps); + if (encoderElement) { if (m_audioSettings.encodingMode() == QMultimedia::ConstantQualityEncoding) { QMultimedia::EncodingQuality qualityValue = m_audioSettings.quality(); - if (codec == QLatin1String("audio/vorbis")) { + if (codec == QLatin1String("audio/x-vorbis")) { double qualityTable[] = { 0.1, //VeryLow 0.3, //Low @@ -211,7 +182,7 @@ GstElement *QGstreamerAudioEncode::createEncoder() 9 //VeryHigh }; g_object_set(G_OBJECT(encoderElement), "quality", quality[qualityValue], NULL); - } else if (codec == QLatin1String("audio/speex")) { + } else if (codec == QLatin1String("audio/x-speex")) { //0-10 range with default 8 double qualityTable[] = { 2, //VeryLow diff --git a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h index 8474aa1a0..04de602ad 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h +++ b/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.h @@ -49,6 +49,7 @@ #include <gst/gst.h> #include <qaudioformat.h> +#include <private/qgstcodecsinfo_p.h> QT_BEGIN_NAMESPACE @@ -61,30 +62,27 @@ public: QGstreamerAudioEncode(QObject *parent); virtual ~QGstreamerAudioEncode(); - QStringList supportedAudioCodecs() const; - QString codecDescription(const QString &codecName) const; + QStringList supportedAudioCodecs() const override; + QString codecDescription(const QString &codecName) const override; QStringList supportedEncodingOptions(const QString &codec) const; QVariant encodingOption(const QString &codec, const QString &name) const; void setEncodingOption(const QString &codec, const QString &name, const QVariant &value); QList<int> supportedSampleRates(const QAudioEncoderSettings &settings = QAudioEncoderSettings(), - bool *isContinuous = 0) const; + bool *isContinuous = 0) const override; QList<int> supportedChannelCounts(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const; QList<int> supportedSampleSizes(const QAudioEncoderSettings &settings = QAudioEncoderSettings()) const; - QAudioEncoderSettings audioSettings() const; - void setAudioSettings(const QAudioEncoderSettings&); + QAudioEncoderSettings audioSettings() const override; + void setAudioSettings(const QAudioEncoderSettings &) override; GstElement *createEncoder(); QSet<QString> supportedStreamTypes(const QString &codecName) const; private: - QStringList m_codecs; - QMap<QString,QByteArray> m_elementNames; - QMap<QString,QString> m_codecDescriptions; - QMap<QString,QStringList> m_codecOptions; + QGstCodecsInfo m_codecs; QMap<QString, QMap<QString, QVariant> > m_options; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h index 55d85ce6f..0e53f0890 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercameracontrol.h @@ -56,22 +56,22 @@ public: bool isValid() const { return true; } - QCamera::State state() const; - void setState(QCamera::State state); + QCamera::State state() const override; + void setState(QCamera::State state) override; - QCamera::Status status() const { return m_status; } + QCamera::Status status() const override { return m_status; } - QCamera::CaptureModes captureMode() const { return m_captureMode; } - void setCaptureMode(QCamera::CaptureModes mode); + QCamera::CaptureModes captureMode() const override { return m_captureMode; } + void setCaptureMode(QCamera::CaptureModes mode) override; - bool isCaptureModeSupported(QCamera::CaptureModes mode) const; + bool isCaptureModeSupported(QCamera::CaptureModes mode) const override; QCamera::LockTypes supportedLocks() const { return QCamera::NoLock; } - bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const; + bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const override; public slots: void reloadLater(); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h index aa114535f..6839bbe68 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.h @@ -49,15 +49,15 @@ class QGstreamerCaptureMetaDataControl : public QMetaDataWriterControl Q_OBJECT public: QGstreamerCaptureMetaDataControl(QObject *parent); - virtual ~QGstreamerCaptureMetaDataControl() {}; + ~QGstreamerCaptureMetaDataControl() {} - bool isMetaDataAvailable() const { return true; } - bool isWritable() const { return true; } + bool isMetaDataAvailable() const override { return true; } + bool isWritable() const override { return true; } - QVariant metaData(const QString &key) const; - void setMetaData(const QString &key, const QVariant &value); - QStringList availableMetaData() const; + QVariant metaData(const QString &key) const override; + void setMetaData(const QString &key, const QVariant &value) override; + QStringList availableMetaData() const override; Q_SIGNALS: void metaDataChanged(const QMap<QByteArray, QVariant>&); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h index dc731d810..aba98d495 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureservice.h @@ -70,8 +70,8 @@ public: QGstreamerCaptureService(const QString &service, QObject *parent = 0); virtual ~QGstreamerCaptureService(); - QMediaControl *requestControl(const char *name); - void releaseControl(QMediaControl *); + QMediaControl *requestControl(const char *name) override; + void releaseControl(QMediaControl *) override; private: void setAudioPreview(GstElement *); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h index 1af9cdc90..d8b7e9768 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h @@ -69,20 +69,20 @@ class QGstreamerCaptureServicePlugin Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mediacapture.json") #endif public: - QMediaService* create(QString const& key); - void release(QMediaService *service); + QMediaService* create(const QString &key) override; + void release(QMediaService *service) override; #if defined(USE_GSTREAMER_CAMERA) - QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const; + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const override; - QByteArray defaultDevice(const QByteArray &service) const; - QList<QByteArray> devices(const QByteArray &service) const; - QString deviceDescription(const QByteArray &service, const QByteArray &device); + QByteArray defaultDevice(const QByteArray &service) const override; + QList<QByteArray> devices(const QByteArray &service) const override; + QString deviceDescription(const QByteArray &service, const QByteArray &device) override; QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property); #endif - QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const; - QStringList supportedMimeTypes() const; + QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList &codecs) const override; + QStringList supportedMimeTypes() const override; private: void updateSupportedMimeTypes() const; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h index 79203224b..e0c9107a7 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.h @@ -138,7 +138,7 @@ public: bool isReady() const; - bool processBusMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message) override; void addProbe(QGstreamerAudioProbeControl* probe); void removeProbe(QGstreamerAudioProbeControl* probe); @@ -166,8 +166,8 @@ public slots: void setVolume(qreal volume); private: - void probeCaps(GstCaps *caps); - bool probeBuffer(GstBuffer *buffer); + void probeCaps(GstCaps *caps) override; + bool probeBuffer(GstBuffer *buffer) override; enum PipelineMode { EmptyPipeline, PreviewPipeline, RecordingPipeline, PreviewAndRecordingPipeline }; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h index 7d4145ae1..f58cf09c5 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamerimagecapturecontrol.h @@ -53,12 +53,12 @@ public: QGstreamerImageCaptureControl(QGstreamerCaptureSession *session); virtual ~QGstreamerImageCaptureControl(); - QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; } - void setDriveMode(QCameraImageCapture::DriveMode) {} + QCameraImageCapture::DriveMode driveMode() const override { return QCameraImageCapture::SingleImageCapture; } + void setDriveMode(QCameraImageCapture::DriveMode) override {} - bool isReadyForCapture() const; - int capture(const QString &fileName); - void cancelCapture(); + bool isReadyForCapture() const override; + int capture(const QString &fileName) override; + void cancelCapture() override; private slots: void updateState(); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h b/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h index d56a739f1..f3ebd3e90 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamerimageencode.h @@ -59,13 +59,13 @@ public: virtual ~QGstreamerImageEncode(); QList<QSize> supportedResolutions(const QImageEncoderSettings &settings = QImageEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = 0) const override; - QStringList supportedImageCodecs() const; - QString imageCodecDescription(const QString &codecName) const; + QStringList supportedImageCodecs() const override; + QString imageCodecDescription(const QString &codecName) const override; - QImageEncoderSettings imageSettings() const; - void setImageSettings(const QImageEncoderSettings &settings); + QImageEncoderSettings imageSettings() const override; + void setImageSettings(const QImageEncoderSettings &settings) override; Q_SIGNALS: void settingsChanged(); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp index 4e07b35bd..05f1c8af5 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.cpp @@ -39,53 +39,19 @@ #include "qgstreamermediacontainercontrol.h" +#include <private/qgstutils_p.h> #include <QtCore/qdebug.h> QGstreamerMediaContainerControl::QGstreamerMediaContainerControl(QObject *parent) :QMediaContainerControl(parent) + , m_containers(QGstCodecsInfo::Muxer) { - QList<QByteArray> formatCandidates; - formatCandidates << "matroska" << "ogg" << "mp4" << "wav" << "quicktime" << "avi" << "3gpp"; - formatCandidates << "flv" << "amr" << "asf" << "dv" << "gif"; - formatCandidates << "mpeg" << "vob" << "mpegts" << "3g2" << "3gp"; - formatCandidates << "raw"; - - m_elementNames["matroska"] = "matroskamux"; - m_elementNames["ogg"] = "oggmux"; - m_elementNames["mp4"] = "ffmux_mp4"; - m_elementNames["quicktime"] = "ffmux_mov"; - m_elementNames["avi"] = "avimux"; - m_elementNames["3gpp"] = "gppmux"; - m_elementNames["flv"] = "flvmux"; - m_elementNames["wav"] = "wavenc"; - m_elementNames["amr"] = "ffmux_amr"; - m_elementNames["asf"] = "ffmux_asf"; - m_elementNames["dv"] = "ffmux_dv"; - m_elementNames["gif"] = "ffmux_gif"; - m_elementNames["mpeg"] = "ffmux_mpeg"; - m_elementNames["vob"] = "ffmux_vob"; - m_elementNames["mpegts"] = "ffmux_mpegts"; - m_elementNames["3g2"] = "ffmux_3g2"; - m_elementNames["3gp"] = "ffmux_3gp"; - m_elementNames["raw"] = "identity"; - - m_containerExtensions["matroska"] = "mkv"; - m_containerExtensions["quicktime"] = "mov"; - m_containerExtensions["mpegts"] = "m2t"; - m_containerExtensions["mpeg"] = "mpg"; - QSet<QString> allTypes; - for (const QByteArray& formatName : qAsConst(formatCandidates)) { - QByteArray elementName = m_elementNames[formatName]; - GstElementFactory *factory = gst_element_factory_find(elementName.constData()); + for (const QString& formatName : supportedContainers()) { + GstElementFactory *factory = gst_element_factory_find(m_containers.codecElement(formatName).constData()); if (factory) { - m_supportedContainers.append(formatName); - const gchar *descr = gst_element_factory_get_description(factory); - m_containerDescriptions.insert(formatName, QString::fromUtf8(descr)); - - if (formatName == QByteArray("raw")) { m_streamTypes.insert(formatName, allTypes); } else { @@ -97,9 +63,6 @@ QGstreamerMediaContainerControl::QGstreamerMediaContainerControl(QObject *parent gst_object_unref(GST_OBJECT(factory)); } } - - //if (!m_supportedContainers.isEmpty()) - // setContainerFormat(m_supportedContainers[0]); } QSet<QString> QGstreamerMediaContainerControl::supportedStreamTypes(GstElementFactory *factory, GstPadDirection direction) @@ -129,5 +92,5 @@ QSet<QString> QGstreamerMediaContainerControl::supportedStreamTypes(const QStrin QString QGstreamerMediaContainerControl::containerExtension() const { - return m_containerExtensions.value(m_format, m_format); + return QGstUtils::fileExtensionForMimeType(m_format); } diff --git a/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h index b8e2cc045..5c730b21d 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamermediacontainercontrol.h @@ -45,6 +45,8 @@ #include <QtCore/qstringlist.h> #include <QtCore/qset.h> +#include <private/qgstcodecsinfo_p.h> + #include <gst/gst.h> QT_BEGIN_NAMESPACE @@ -54,15 +56,15 @@ class QGstreamerMediaContainerControl : public QMediaContainerControl Q_OBJECT public: QGstreamerMediaContainerControl(QObject *parent); - virtual ~QGstreamerMediaContainerControl() {}; + ~QGstreamerMediaContainerControl() {} - virtual QStringList supportedContainers() const { return m_supportedContainers; } - virtual QString containerFormat() const { return m_format; } - virtual void setContainerFormat(const QString &formatMimeType) { m_format = formatMimeType; } + QStringList supportedContainers() const override { return m_containers.supportedCodecs(); } + QString containerFormat() const override { return m_format; } + void setContainerFormat(const QString &formatMimeType) override { m_format = formatMimeType; } - virtual QString containerDescription(const QString &formatMimeType) const { return m_containerDescriptions.value(formatMimeType); } + QString containerDescription(const QString &formatMimeType) const override { return m_containers.codecDescription(formatMimeType); } - QByteArray formatElementName() const { return m_elementNames.value(containerFormat()); } + QByteArray formatElementName() const { return m_containers.codecElement(containerFormat()); } QSet<QString> supportedStreamTypes(const QString &container) const; @@ -72,10 +74,7 @@ public: private: QString m_format; - QStringList m_supportedContainers; - QMap<QString,QByteArray> m_elementNames; - QMap<QString, QString> m_containerDescriptions; - QMap<QString, QString> m_containerExtensions; + QGstCodecsInfo m_containers; QMap<QString, QSet<QString> > m_streamTypes; }; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h index 96e263e72..b80716f4c 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamerrecordercontrol.h @@ -56,26 +56,26 @@ public: QGstreamerRecorderControl(QGstreamerCaptureSession *session); virtual ~QGstreamerRecorderControl(); - QUrl outputLocation() const; - bool setOutputLocation(const QUrl &sink); + QUrl outputLocation() const override; + bool setOutputLocation(const QUrl &sink) override; - QMediaRecorder::State state() const; - QMediaRecorder::Status status() const; + QMediaRecorder::State state() const override; + QMediaRecorder::Status status() const override; - qint64 duration() const; + qint64 duration() const override; - bool isMuted() const; - qreal volume() const; + bool isMuted() const override; + qreal volume() const override; - void applySettings(); + void applySettings() override; public slots: - void setState(QMediaRecorder::State state); + void setState(QMediaRecorder::State state) override; void record(); void pause(); void stop(); - void setMuted(bool); - void setVolume(qreal volume); + void setMuted(bool) override; + void setVolume(qreal volume) override; private slots: void updateStatus(); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h index 20e855922..a82c7cf4b 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamerv4l2input.h @@ -56,10 +56,10 @@ public: QGstreamerV4L2Input(QObject *parent = 0); virtual ~QGstreamerV4L2Input(); - GstElement *buildElement(); + GstElement *buildElement() override; - QList<qreal> supportedFrameRates(const QSize &frameSize = QSize()) const; - QList<QSize> supportedResolutions(qreal frameRate = -1) const; + QList<qreal> supportedFrameRates(const QSize &frameSize = QSize()) const override; + QList<QSize> supportedResolutions(qreal frameRate = -1) const override; QByteArray device() const; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp index f0781d831..6b4dbe4b7 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.cpp @@ -47,41 +47,17 @@ QGstreamerVideoEncode::QGstreamerVideoEncode(QGstreamerCaptureSession *session) :QVideoEncoderSettingsControl(session), m_session(session) + , m_codecs(QGstCodecsInfo::VideoEncoder) { - QList<QByteArray> codecCandidates; - codecCandidates << "video/h264" << "video/xvid" << "video/mpeg4" << "video/mpeg1" << "video/mpeg2" << "video/theora"; - - m_elementNames["video/h264"] = "x264enc"; - m_elementNames["video/xvid"] = "xvidenc"; - m_elementNames["video/mpeg4"] = "ffenc_mpeg4"; - m_elementNames["video/mpeg1"] = "ffenc_mpeg1video"; - m_elementNames["video/mpeg2"] = "ffenc_mpeg2video"; - m_elementNames["video/theora"] = "theoraenc"; - - m_codecOptions["video/h264"] = QStringList() << "quantizer"; - m_codecOptions["video/xvid"] = QStringList() << "quantizer" << "profile"; - m_codecOptions["video/mpeg4"] = QStringList() << "quantizer"; - m_codecOptions["video/mpeg1"] = QStringList() << "quantizer"; - m_codecOptions["video/mpeg2"] = QStringList() << "quantizer"; - m_codecOptions["video/theora"] = QStringList(); - - for (const QByteArray& codecName : qAsConst(codecCandidates)) { - QByteArray elementName = m_elementNames[codecName]; - GstElementFactory *factory = gst_element_factory_find(elementName.constData()); + for (const QString& codecName : supportedVideoCodecs()) { + GstElementFactory *factory = gst_element_factory_find(m_codecs.codecElement(codecName).constData()); if (factory) { - m_codecs.append(codecName); - const gchar *descr = gst_element_factory_get_description(factory); - m_codecDescriptions.insert(codecName, QString::fromUtf8(descr)); - m_streamTypes.insert(codecName, QGstreamerMediaContainerControl::supportedStreamTypes(factory, GST_PAD_SRC)); gst_object_unref(GST_OBJECT(factory)); } } - - //if (!m_codecs.isEmpty()) - // m_videoSettings.setCodec(m_codecs[0]); } QGstreamerVideoEncode::~QGstreamerVideoEncode() @@ -106,17 +82,17 @@ QList< qreal > QGstreamerVideoEncode::supportedFrameRates(const QVideoEncoderSet QStringList QGstreamerVideoEncode::supportedVideoCodecs() const { - return m_codecs; + return m_codecs.supportedCodecs(); } QString QGstreamerVideoEncode::videoCodecDescription(const QString &codecName) const { - return m_codecDescriptions.value(codecName); + return m_codecs.codecDescription(codecName); } QStringList QGstreamerVideoEncode::supportedEncodingOptions(const QString &codec) const { - return m_codecOptions.value(codec); + return m_codecs.codecOptions(codec); } QVariant QGstreamerVideoEncode::encodingOption(const QString &codec, const QString &name) const @@ -143,28 +119,28 @@ void QGstreamerVideoEncode::setVideoSettings(const QVideoEncoderSettings &settin GstElement *QGstreamerVideoEncode::createEncoder() { QString codec = m_videoSettings.codec(); - //qDebug() << "create encoder for video codec" << codec; - GstElement *encoderElement = gst_element_factory_make( m_elementNames.value(codec).constData(), "video-encoder"); + GstElement *encoderElement = gst_element_factory_make(m_codecs.codecElement(codec).constData(), "video-encoder"); if (!encoderElement) return 0; GstBin *encoderBin = GST_BIN(gst_bin_new("video-encoder-bin")); - GstElement *capsFilter = gst_element_factory_make("capsfilter", "capsfilter-video"); - gst_bin_add(encoderBin, capsFilter); + GstElement *sinkCapsFilter = gst_element_factory_make("capsfilter", "capsfilter-video"); + GstElement *srcCapsFilter = gst_element_factory_make("capsfilter", "capsfilter-video"); + gst_bin_add_many(encoderBin, sinkCapsFilter, srcCapsFilter, NULL); GstElement *colorspace = gst_element_factory_make(QT_GSTREAMER_COLORCONVERSION_ELEMENT_NAME, NULL); gst_bin_add(encoderBin, colorspace); gst_bin_add(encoderBin, encoderElement); - gst_element_link_many(capsFilter, colorspace, encoderElement, NULL); + gst_element_link_many(sinkCapsFilter, colorspace, encoderElement, srcCapsFilter, NULL); // add ghostpads - GstPad *pad = gst_element_get_static_pad(capsFilter, "sink"); + GstPad *pad = gst_element_get_static_pad(sinkCapsFilter, "sink"); gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("sink", pad)); gst_object_unref(GST_OBJECT(pad)); - pad = gst_element_get_static_pad(encoderElement, "src"); + pad = gst_element_get_static_pad(srcCapsFilter, "src"); gst_element_add_pad(GST_ELEMENT(encoderBin), gst_ghost_pad_new("src", pad)); gst_object_unref(GST_OBJECT(pad)); @@ -172,7 +148,7 @@ GstElement *QGstreamerVideoEncode::createEncoder() if (m_videoSettings.encodingMode() == QMultimedia::ConstantQualityEncoding) { QMultimedia::EncodingQuality qualityValue = m_videoSettings.quality(); - if (codec == QLatin1String("video/h264")) { + if (codec == QLatin1String("video/x-h264")) { //constant quantizer mode g_object_set(G_OBJECT(encoderElement), "pass", 4, NULL); int qualityTable[] = { @@ -183,7 +159,7 @@ GstElement *QGstreamerVideoEncode::createEncoder() 8 //VeryHigh }; g_object_set(G_OBJECT(encoderElement), "quantizer", qualityTable[qualityValue], NULL); - } else if (codec == QLatin1String("video/xvid")) { + } else if (codec == QLatin1String("video/x-xvid")) { //constant quantizer mode g_object_set(G_OBJECT(encoderElement), "pass", 3, NULL); int qualityTable[] = { @@ -195,9 +171,7 @@ GstElement *QGstreamerVideoEncode::createEncoder() }; int quant = qualityTable[qualityValue]; g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL); - } else if (codec == QLatin1String("video/mpeg4") || - codec == QLatin1String("video/mpeg1") || - codec == QLatin1String("video/mpeg2") ) { + } else if (codec.startsWith(QLatin1String("video/mpeg"))) { //constant quantizer mode g_object_set(G_OBJECT(encoderElement), "pass", 2, NULL); //quant from 1 to 30, default ~3 @@ -210,7 +184,7 @@ GstElement *QGstreamerVideoEncode::createEncoder() }; double quant = qualityTable[qualityValue]; g_object_set(G_OBJECT(encoderElement), "quantizer", quant, NULL); - } else if (codec == QLatin1String("video/theora")) { + } else if (codec == QLatin1String("video/x-theora")) { int qualityTable[] = { 8, //VeryLow 16, //Low @@ -278,11 +252,18 @@ GstElement *QGstreamerVideoEncode::createEncoder() //qDebug() << "set video caps filter:" << gst_caps_to_string(caps); - g_object_set(G_OBJECT(capsFilter), "caps", caps, NULL); + g_object_set(G_OBJECT(sinkCapsFilter), "caps", caps, NULL); gst_caps_unref(caps); } + // Some encoders support several codecs. Setting a caps filter downstream with the desired + // codec (which is actually a string representation of the caps) will make sure we use the + // correct codec. + GstCaps *caps = gst_caps_from_string(codec.toUtf8().constData()); + g_object_set(G_OBJECT(srcCapsFilter), "caps", caps, NULL); + gst_caps_unref(caps); + return GST_ELEMENT(encoderBin); } diff --git a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h index f4134b46f..bc6636012 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamervideoencode.h @@ -46,6 +46,8 @@ #include <QtCore/qmap.h> #include <QtCore/qset.h> +#include <private/qgstcodecsinfo_p.h> + #include <gst/gst.h> QT_BEGIN_NAMESPACE @@ -60,18 +62,18 @@ public: virtual ~QGstreamerVideoEncode(); QList<QSize> supportedResolutions(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = 0) const override; QList< qreal > supportedFrameRates(const QVideoEncoderSettings &settings = QVideoEncoderSettings(), - bool *continuous = 0) const; + bool *continuous = 0) const override; QPair<int,int> rateAsRational() const; - QStringList supportedVideoCodecs() const; - QString videoCodecDescription(const QString &codecName) const; + QStringList supportedVideoCodecs() const override; + QString videoCodecDescription(const QString &codecName) const override; - QVideoEncoderSettings videoSettings() const; - void setVideoSettings(const QVideoEncoderSettings &settings); + QVideoEncoderSettings videoSettings() const override; + void setVideoSettings(const QVideoEncoderSettings &settings) override; QStringList supportedEncodingOptions(const QString &codec) const; QVariant encodingOption(const QString &codec, const QString &name) const; @@ -84,10 +86,7 @@ public: private: QGstreamerCaptureSession *m_session; - QStringList m_codecs; - QMap<QString,QString> m_codecDescriptions; - QMap<QString,QByteArray> m_elementNames; - QMap<QString,QStringList> m_codecOptions; + QGstCodecsInfo m_codecs; QVideoEncoderSettings m_videoSettings; QMap<QString, QMap<QString, QVariant> > m_options; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreameravailabilitycontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreameravailabilitycontrol.h index 2c303f5af..78299b608 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreameravailabilitycontrol.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreameravailabilitycontrol.h @@ -51,7 +51,7 @@ class QGStreamerAvailabilityControl : public QMediaAvailabilityControl Q_OBJECT public: QGStreamerAvailabilityControl(QMediaPlayerResourceSetInterface *resources, QObject *parent = 0); - QMultimedia::AvailabilityStatus availability() const; + QMultimedia::AvailabilityStatus availability() const override; private Q_SLOTS: void handleAvailabilityChanged(); diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h index 1bbc5b1a5..bf8f7e842 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.h @@ -53,11 +53,11 @@ public: QGstreamerMetaDataProvider( QGstreamerPlayerSession *session, QObject *parent ); virtual ~QGstreamerMetaDataProvider(); - bool isMetaDataAvailable() const; + bool isMetaDataAvailable() const override; bool isWritable() const; - QVariant metaData(const QString &key) const; - QStringList availableMetaData() const; + QVariant metaData(const QString &key) const override; + QStringList availableMetaData() const override; private slots: void updateTags(); diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h index 9ecf5f499..6067a68fc 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.h @@ -67,42 +67,42 @@ public: QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent = 0); ~QGstreamerPlayerControl(); - QMediaPlayer::State state() const; - QMediaPlayer::MediaStatus mediaStatus() const; + QMediaPlayer::State state() const override; + QMediaPlayer::MediaStatus mediaStatus() const override; - qint64 position() const; - qint64 duration() const; + qint64 position() const override; + qint64 duration() const override; - int bufferStatus() const; + int bufferStatus() const override; - int volume() const; - bool isMuted() const; + int volume() const override; + bool isMuted() const override; - bool isAudioAvailable() const; - bool isVideoAvailable() const; + bool isAudioAvailable() const override; + bool isVideoAvailable() const override; void setVideoOutput(QObject *output); - bool isSeekable() const; - QMediaTimeRange availablePlaybackRanges() const; + bool isSeekable() const override; + QMediaTimeRange availablePlaybackRanges() const override; - qreal playbackRate() const; - void setPlaybackRate(qreal rate); + qreal playbackRate() const override; + void setPlaybackRate(qreal rate) override; - QMediaContent media() const; - const QIODevice *mediaStream() const; - void setMedia(const QMediaContent&, QIODevice *); + QMediaContent media() const override; + const QIODevice *mediaStream() const override; + void setMedia(const QMediaContent&, QIODevice *) override; QMediaPlayerResourceSetInterface* resources() const; public Q_SLOTS: - void setPosition(qint64 pos); + void setPosition(qint64 pos) override; - void play(); - void pause(); - void stop(); + void play() override; + void pause() override; + void stop() override; - void setVolume(int volume); - void setMuted(bool muted); + void setVolume(int volume) override; + void setMuted(bool muted) override; private Q_SLOTS: void updateSessionState(QMediaPlayer::State state); diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h index 423ee9173..ec0c0944b 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.h @@ -69,8 +69,8 @@ public: QGstreamerPlayerService(QObject *parent = 0); ~QGstreamerPlayerService(); - QMediaControl *requestControl(const char *name); - void releaseControl(QMediaControl *control); + QMediaControl *requestControl(const char *name) override; + void releaseControl(QMediaControl *control) override; private: QGstreamerPlayerControl *m_control; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.h index 8e3e8a2af..71eece23e 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.h @@ -58,13 +58,13 @@ class QGstreamerPlayerServicePlugin Q_INTERFACES(QMediaServiceSupportedFormatsInterface) Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mediaplayer.json") public: - QMediaService* create(QString const& key); - void release(QMediaService *service); + QMediaService* create(const QString &key) override; + void release(QMediaService *service) override; - QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const; + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const override; - QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const; - QStringList supportedMimeTypes() const; + QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList &codecs) const override; + QStringList supportedMimeTypes() const override; private: void updateSupportedMimeTypes() const; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 94e818f94..cc7aef367 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -47,7 +47,6 @@ #include <private/gstvideoconnector_p.h> #endif #include <private/qgstutils_p.h> -#include <private/playlistfileparser_p.h> #include <private/qgstutils_p.h> #include <gst/gstvalue.h> @@ -61,59 +60,12 @@ #include <QtCore/qdebug.h> #include <QtCore/qdir.h> #include <QtCore/qstandardpaths.h> -#include <QtCore/qvector.h> -#include <QtCore/qmutex.h> //#define DEBUG_PLAYBIN //#define DEBUG_VO_BIN_DUMP QT_BEGIN_NAMESPACE -class TypefindDelegator -{ -public: - TypefindDelegator() - { - Q_ASSERT(gst_type_find_register(0, "playlist", GST_RANK_MARGINAL, notifySessions, 0, 0, 0, 0) == TRUE); - } - - void add(QGstreamerPlayerSession *session) - { - QMutexLocker locker(&m_mtx); - m_sessions.append(session); - } - - void remove(QGstreamerPlayerSession *session) - { - QMutexLocker locker(&m_mtx); - const int idx = m_sessions.indexOf(session); - if (idx != -1) - m_sessions.remove(idx); - } - -private: - static void notifySessions(GstTypeFind *find, gpointer /* unused */) - { - QMutexLocker locker(&m_mtx); - SessionList::const_iterator it = m_sessions.constBegin(); - SessionList::const_iterator end = m_sessions.constEnd(); - - while (it != end) { - (*it)->playlistTypeFindFunction(find); - ++it; - } - } - - typedef QVector<QGstreamerPlayerSession *> SessionList; - static SessionList m_sessions; - static QMutex m_mtx; -}; - -TypefindDelegator::SessionList TypefindDelegator::m_sessions; -QMutex TypefindDelegator::m_mtx; - -Q_GLOBAL_STATIC(TypefindDelegator, g_typeRegister); - static bool usePlaybinVolume() { static enum { Yes, No, Unknown } status = Unknown; @@ -191,10 +143,8 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) m_displayPrerolledFrame(true), m_sourceType(UnknownSrc), m_everPlayed(false), - m_isLiveSource(false), - m_isPlaylist(false) + m_isLiveSource(false) { - g_typeRegister->add(this); m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, NULL); if (m_playbin) { //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale, @@ -210,7 +160,8 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) } g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL); - GstElement *audioSink = gst_element_factory_make("autoaudiosink", "audiosink"); + const QByteArray envAudioSink = qgetenv("QT_GSTREAMER_PLAYBIN_AUDIOSINK"); + GstElement *audioSink = gst_element_factory_make(envAudioSink.isEmpty() ? "autoaudiosink" : envAudioSink, "audiosink"); if (audioSink) { if (usePlaybinVolume()) { m_audioSink = audioSink; @@ -295,8 +246,6 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) QGstreamerPlayerSession::~QGstreamerPlayerSession() { - g_typeRegister->remove(this); - if (m_playbin) { stop(); @@ -347,7 +296,6 @@ void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIO m_request = request; m_duration = -1; m_lastPosition = 0; - m_isPlaylist = false; if (!m_appSrc) m_appSrc = new QGstAppSrc(this); @@ -377,7 +325,6 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request) m_request = request; m_duration = -1; m_lastPosition = 0; - m_isPlaylist = false; #if QT_CONFIG(gstreamer_app) if (m_appSrc) { @@ -945,13 +892,9 @@ bool QGstreamerPlayerSession::play() if (m_playbin) { m_pendingState = QMediaPlayer::PlayingState; if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { - if (!m_isPlaylist) { - qWarning() << "GStreamer; Unable to play -" << m_request.url().toString(); - m_pendingState = m_state = QMediaPlayer::StoppedState; - emit stateChanged(m_state); - } else { - return true; - } + qWarning() << "GStreamer; Unable to play -" << m_request.url().toString(); + m_pendingState = m_state = QMediaPlayer::StoppedState; + emit stateChanged(m_state); } else { resumeVideoProbes(); return true; @@ -972,13 +915,9 @@ bool QGstreamerPlayerSession::pause() return true; if (gst_element_set_state(m_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { - if (!m_isPlaylist) { - qWarning() << "GStreamer; Unable to pause -" << m_request.url().toString(); - m_pendingState = m_state = QMediaPlayer::StoppedState; - emit stateChanged(m_state); - } else { - return true; - } + qWarning() << "GStreamer; Unable to pause -" << m_request.url().toString(); + m_pendingState = m_state = QMediaPlayer::StoppedState; + emit stateChanged(m_state); } else { resumeVideoProbes(); return true; @@ -1347,7 +1286,7 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND) emit error(int(QMediaPlayer::FormatError), tr("Cannot play stream of type: <unknown>")); // GStreamer shows warning for HTTP playlists - if (!m_isPlaylist) + if (err && err->message) qWarning() << "Warning:" << QString::fromUtf8(err->message); g_error_free(err); g_free(debug); @@ -1356,10 +1295,6 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message gchar *debug; gst_message_parse_error(gm, &err, &debug); - // remember playlist value, - // it could be set to false after call to processInvalidMedia - bool isPlaylist = m_isPlaylist; - // Nearly all errors map to ResourceError QMediaPlayer::Error qerror = QMediaPlayer::ResourceError; if (err->domain == GST_STREAM_ERROR @@ -1368,7 +1303,7 @@ bool QGstreamerPlayerSession::processBusMessage(const QGstreamerMessage &message qerror = QMediaPlayer::AccessDeniedError; } processInvalidMedia(qerror, QString::fromUtf8(err->message)); - if (!isPlaylist) + if (err && err->message) qWarning() << "Error:" << QString::fromUtf8(err->message); g_error_free(err); @@ -1804,14 +1739,9 @@ void QGstreamerPlayerSession::processInvalidMedia(QMediaPlayer::Error errorCode, #ifdef DEBUG_PLAYBIN qDebug() << Q_FUNC_INFO; #endif - if (m_isPlaylist) { - stop(); - emit error(int(QMediaPlayer::MediaIsPlaylist), tr("Media is loaded as a playlist")); - } else { - emit invalidMedia(); - stop(); - emit error(int(errorCode), errorString); - } + emit invalidMedia(); + stop(); + emit error(int(errorCode), errorString); } void QGstreamerPlayerSession::showPrerollFrames(bool enabled) @@ -1936,32 +1866,4 @@ void QGstreamerPlayerSession::resumeVideoProbes() m_videoProbe->stopFlushing(); } -void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find) -{ - gchar *strval = 0; -#if GST_CHECK_VERSION(1,0,0) - g_object_get(G_OBJECT(m_playbin), "current-uri", &strval, NULL); -#else - g_object_get(G_OBJECT(m_playbin), "uri", &strval, NULL); -#endif - const QString uri(QString::fromUtf8(strval)); - g_free(strval); - - guint64 length = gst_type_find_get_length(find); - if (!length) - length = 1024; - else - length = qMin(length, guint64(1024)); - - while (length > 0) { - const guint8 *data = gst_type_find_peek(find, 0, length); - if (data) { - m_isPlaylist = (QPlaylistFileParser::findPlaylistType(uri, 0, data, length) != QPlaylistFileParser::UNKNOWN); - return; - } - length >>= 1; // for HTTP files length is not available, - // so we have to try different buffer sizes - } -} - QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h index 90ec60bc9..7f46e8f41 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -115,7 +115,7 @@ public: int activeStream(QMediaStreamsControl::StreamType streamType) const; void setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber); - bool processBusMessage(const QGstreamerMessage &message); + bool processBusMessage(const QGstreamerMessage &message) override; #if QT_CONFIG(gstreamer_app) QGstAppSrc *appsrc() const { return m_appSrc; } @@ -132,8 +132,6 @@ public: void endOfMediaReset(); - void playlistTypeFindFunction(GstTypeFind *find); - public slots: void loadFromUri(const QNetworkRequest &url); void loadFromStream(const QNetworkRequest &url, QIODevice *stream); @@ -256,7 +254,6 @@ private: bool m_everPlayed; bool m_isLiveSource; - bool m_isPlaylist; gulong pad_probe_id; }; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h index ec9de39f0..6f332c160 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerstreamscontrol.h @@ -53,13 +53,13 @@ public: QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent); virtual ~QGstreamerStreamsControl(); - virtual int streamCount(); - virtual StreamType streamType(int streamNumber); + int streamCount() override; + StreamType streamType(int streamNumber) override; - virtual QVariant metaData(int streamNumber, const QString &key); + QVariant metaData(int streamNumber, const QString &key) override; - virtual bool isActive(int streamNumber); - virtual void setActive(int streamNumber, bool state); + bool isActive(int streamNumber) override; + void setActive(int streamNumber, bool state) override; private: QGstreamerPlayerSession *m_session; diff --git a/src/plugins/qnx-audio/audio/qnxaudioinput.cpp b/src/plugins/qnx-audio/audio/qnxaudioinput.cpp index 35d11597c..b16328892 100644 --- a/src/plugins/qnx-audio/audio/qnxaudioinput.cpp +++ b/src/plugins/qnx-audio/audio/qnxaudioinput.cpp @@ -134,6 +134,8 @@ void QnxAudioInput::reset() void QnxAudioInput::suspend() { + snd_pcm_capture_pause(m_pcmHandle); + if (m_pcmNotifier) m_pcmNotifier->setEnabled(false); @@ -142,6 +144,8 @@ void QnxAudioInput::suspend() void QnxAudioInput::resume() { + snd_pcm_capture_resume(m_pcmHandle); + if (m_pcmNotifier) m_pcmNotifier->setEnabled(true); diff --git a/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp b/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp index d5805c2bd..d08d01e6d 100644 --- a/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp +++ b/src/plugins/qnx-audio/audio/qnxaudiooutput.cpp @@ -125,11 +125,13 @@ void QnxAudioOutput::reset() void QnxAudioOutput::suspend() { m_timer.stop(); + snd_pcm_playback_pause(m_pcmHandle); setState(QAudio::SuspendedState); } void QnxAudioOutput::resume() { + snd_pcm_playback_resume(m_pcmHandle); if (m_pushSource) setState(QAudio::IdleState); else { @@ -223,7 +225,10 @@ void QnxAudioOutput::pullData() if (frames == 0 || bytesAvailable < periodSize()) return; - const int bytesRequested = m_format.bytesForFrames(frames); + // The buffer is placed on the stack so no more than 64K or 1 frame + // whichever is larger. + const int maxFrames = qMax(m_format.framesForBytes(64 * 1024), 1); + const int bytesRequested = m_format.bytesForFrames(qMin(frames, maxFrames)); char buffer[bytesRequested]; const int bytesRead = m_source->read(buffer, bytesRequested); diff --git a/src/plugins/wasapi/qwasapiaudioinput.cpp b/src/plugins/wasapi/qwasapiaudioinput.cpp index 22a77df38..561584e83 100644 --- a/src/plugins/wasapi/qwasapiaudioinput.cpp +++ b/src/plugins/wasapi/qwasapiaudioinput.cpp @@ -143,9 +143,7 @@ qint64 WasapiInputDevicePrivate::writeData(const char* data, qint64 len) QWasapiAudioInput::QWasapiAudioInput(const QByteArray &device) : m_deviceName(device) -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 , m_volumeCache(qreal(1.)) -#endif , m_currentState(QAudio::StoppedState) , m_currentError(QAudio::NoError) , m_bufferFrames(0) @@ -165,7 +163,6 @@ QWasapiAudioInput::~QWasapiAudioInput() void QWasapiAudioInput::setVolume(qreal vol) { qCDebug(lcMmAudioInput) << __FUNCTION__ << vol; -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond m_volumeCache = vol; if (m_volumeControl) { quint32 channelCount; @@ -175,17 +172,12 @@ void QWasapiAudioInput::setVolume(qreal vol) RETURN_VOID_IF_FAILED("Could not set audio volume."); } } -#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 } qreal QWasapiAudioInput::volume() const { qCDebug(lcMmAudioInput) << __FUNCTION__; -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond return m_volumeCache; -#else - return qreal(1.0); -#endif } void QWasapiAudioInput::process() @@ -317,11 +309,9 @@ bool QWasapiAudioInput::initStart(bool pull) hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_capture)); EMIT_RETURN_FALSE_IF_FAILED("Could not acquire render service.", QAudio::OpenError) -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond for WinRT hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_volumeControl)); if (FAILED(hr)) qCDebug(lcMmAudioInput) << "Could not acquire volume control."; -#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 hr = m_interface->m_client->GetBufferSize(&m_bufferFrames); EMIT_RETURN_FALSE_IF_FAILED("Could not access buffer size.", QAudio::OpenError) diff --git a/src/plugins/wasapi/qwasapiaudioinput.h b/src/plugins/wasapi/qwasapiaudioinput.h index 3fd7315c1..34ede06b7 100644 --- a/src/plugins/wasapi/qwasapiaudioinput.h +++ b/src/plugins/wasapi/qwasapiaudioinput.h @@ -97,10 +97,8 @@ private: QByteArray m_deviceName; Microsoft::WRL::ComPtr<AudioInterface> m_interface; Microsoft::WRL::ComPtr<IAudioCaptureClient> m_capture; -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 Microsoft::WRL::ComPtr<IAudioStreamVolume> m_volumeControl; qreal m_volumeCache; -#endif QMutex m_mutex; QAudio::State m_currentState; QAudio::Error m_currentError; diff --git a/src/plugins/wasapi/qwasapiaudiooutput.cpp b/src/plugins/wasapi/qwasapiaudiooutput.cpp index 1b0f64451..79548011c 100644 --- a/src/plugins/wasapi/qwasapiaudiooutput.cpp +++ b/src/plugins/wasapi/qwasapiaudiooutput.cpp @@ -157,9 +157,7 @@ qint64 WasapiOutputDevicePrivate::writeData(const char* data, qint64 len) QWasapiAudioOutput::QWasapiAudioOutput(const QByteArray &device) : m_deviceName(device) -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 , m_volumeCache(qreal(1.)) -#endif , m_currentState(QAudio::StoppedState) , m_currentError(QAudio::NoError) , m_interval(1000) @@ -180,7 +178,6 @@ QWasapiAudioOutput::~QWasapiAudioOutput() void QWasapiAudioOutput::setVolume(qreal vol) { qCDebug(lcMmAudioOutput) << __FUNCTION__ << vol; -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond for WinRT m_volumeCache = vol; if (m_volumeControl) { quint32 channelCount; @@ -190,17 +187,12 @@ void QWasapiAudioOutput::setVolume(qreal vol) RETURN_VOID_IF_FAILED("Could not set audio volume."); } } -#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 } qreal QWasapiAudioOutput::volume() const { qCDebug(lcMmAudioOutput) << __FUNCTION__; -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond for WinRT return m_volumeCache; -#else - return qreal(1.0); -#endif } void QWasapiAudioOutput::process() @@ -316,11 +308,9 @@ bool QWasapiAudioOutput::initStart(bool pull) hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_renderer)); EMIT_RETURN_FALSE_IF_FAILED("Could not acquire render service.", QAudio::OpenError) -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 // Volume is only supported MSVC2015 and beyond hr = m_interface->m_client->GetService(IID_PPV_ARGS(&m_volumeControl)); if (FAILED(hr)) qCDebug(lcMmAudioOutput) << "Could not acquire volume control."; -#endif // defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 hr = m_interface->m_client->GetBufferSize(&m_bufferFrames); EMIT_RETURN_FALSE_IF_FAILED("Could not access buffer size.", QAudio::OpenError) diff --git a/src/plugins/wasapi/qwasapiaudiooutput.h b/src/plugins/wasapi/qwasapiaudiooutput.h index 118731af9..02974071b 100644 --- a/src/plugins/wasapi/qwasapiaudiooutput.h +++ b/src/plugins/wasapi/qwasapiaudiooutput.h @@ -98,10 +98,8 @@ private: QByteArray m_deviceName; Microsoft::WRL::ComPtr<AudioInterface> m_interface; Microsoft::WRL::ComPtr<IAudioRenderClient> m_renderer; -#if defined(CLASSIC_APP_BUILD) || _MSC_VER >= 1900 Microsoft::WRL::ComPtr<IAudioStreamVolume> m_volumeControl; qreal m_volumeCache; -#endif QMutex m_mutex; QAudio::State m_currentState; QAudio::Error m_currentError; diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp index 177a0731c..54f4b103b 100644 --- a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp +++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.cpp @@ -109,15 +109,16 @@ struct CaptureRequest class QWinRTCameraImageCaptureControlPrivate { public: + QWinRTCameraImageCaptureControlPrivate() + : isActive(false) + { + } + QPointer<QWinRTCameraControl> cameraControl; QHash<IAsyncAction *, CaptureRequest> requests; quint16 currentCaptureId; QMediaStorageLocation location; - - void onCameraStateChanged() - { - - } + bool isActive; }; QWinRTCameraImageCaptureControl::QWinRTCameraImageCaptureControl(QWinRTCameraControl *parent) @@ -128,14 +129,14 @@ QWinRTCameraImageCaptureControl::QWinRTCameraImageCaptureControl(QWinRTCameraCon d->cameraControl = parent; connect(d->cameraControl, &QCameraControl::stateChanged, - this, &QWinRTCameraImageCaptureControl::readyForCaptureChanged); + this, &QWinRTCameraImageCaptureControl::onCameraStateChanged); d->currentCaptureId = 0; } bool QWinRTCameraImageCaptureControl::isReadyForCapture() const { Q_D(const QWinRTCameraImageCaptureControl); - return d->cameraControl->state() == QCamera::ActiveState; + return d->isActive; } QCameraImageCapture::DriveMode QWinRTCameraImageCaptureControl::driveMode() const @@ -215,6 +216,17 @@ void QWinRTCameraImageCaptureControl::cancelCapture() emit captureQueueChanged(true); } +void QWinRTCameraImageCaptureControl::onCameraStateChanged(QCamera::State state) +{ + Q_D(QWinRTCameraImageCaptureControl); + const bool newActive = state == QCamera::ActiveState; + if (d->isActive == newActive) + return; + + d->isActive = newActive; + emit readyForCaptureChanged(newActive); +} + HRESULT QWinRTCameraImageCaptureControl::onCaptureCompleted(IAsyncAction *asyncInfo, AsyncStatus status) { qCDebug(lcMMCamera) << __FUNCTION__; diff --git a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h index 177eaf5d7..3820bfaf1 100644 --- a/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h +++ b/src/plugins/winrt/qwinrtcameraimagecapturecontrol.h @@ -40,6 +40,7 @@ #ifndef QWINRTCAMERAIMAGECAPTURECONTROL_H #define QWINRTCAMERAIMAGECAPTURECONTROL_H +#include <QtMultimedia/QCamera> #include <QtMultimedia/QCameraImageCaptureControl> #include <QtCore/qt_windows.h> @@ -71,6 +72,9 @@ public: int capture(const QString &fileName) Q_DECL_OVERRIDE; void cancelCapture() Q_DECL_OVERRIDE; +private slots: + void onCameraStateChanged(QCamera::State state); + signals: void captureQueueChanged(bool isEmpty); diff --git a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp index a4df6306f..9fd48fd76 100644 --- a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp +++ b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp @@ -786,8 +786,12 @@ void QWinRTMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *s if (d->stream) { hr = d->engine->SetSourceFromByteStream(d->streamProvider.Get(), reinterpret_cast<BSTR>(urlString.data())); - if (FAILED(hr)) + if (FAILED(hr)) { emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); + return; + } + if (d->videoRenderer) + d->videoRenderer->ensureReady(); return; } diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h index 666a7cbd3..c84612960 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render_p.h @@ -125,10 +125,10 @@ class QSGVideoItemSurface : public QAbstractVideoSurface public: explicit QSGVideoItemSurface(QDeclarativeVideoRendererBackend *backend, QObject *parent = 0); ~QSGVideoItemSurface(); - QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; - bool start(const QVideoSurfaceFormat &format); - void stop(); - bool present(const QVideoFrame &frame); + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const override; + bool start(const QVideoSurfaceFormat &format) override; + void stop() override; + bool present(const QVideoFrame &frame) override; void scheduleOpenGLContextUpdate(); private slots: diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp index 2126f0cbd..0dfa11ab9 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_rgb.cpp @@ -85,9 +85,9 @@ public: setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo.frag")); } - void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - virtual char const *const *attributeNames() const { + char const *const *attributeNames() const override { static const char *names[] = { "qt_VertexPosition", "qt_VertexTexCoord", @@ -97,7 +97,7 @@ public: } protected: - virtual void initialize() { + void initialize() override { m_id_matrix = program()->uniformLocation("qt_Matrix"); m_id_width = program()->uniformLocation("width"); m_id_rgbTexture = program()->uniformLocation("rgbTexture"); @@ -139,17 +139,17 @@ public: QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_textureId); } - virtual QSGMaterialType *type() const { + QSGMaterialType *type() const override { static QSGMaterialType normalType, swizzleType; return needsSwizzling() ? &swizzleType : &normalType; } - virtual QSGMaterialShader *createShader() const { + QSGMaterialShader *createShader() const override { return needsSwizzling() ? new QSGVideoMaterialShader_RGB_swizzle : new QSGVideoMaterialShader_RGB; } - virtual int compare(const QSGMaterial *other) const { + int compare(const QSGMaterial *other) const override { const QSGVideoMaterial_RGB *m = static_cast<const QSGVideoMaterial_RGB *>(other); if (!m_textureId) diff --git a/src/qtmultimediaquicktools/qsgvideonode_rgb_p.h b/src/qtmultimediaquicktools/qsgvideonode_rgb_p.h index 71b28557d..95b74be0b 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_rgb_p.h +++ b/src/qtmultimediaquicktools/qsgvideonode_rgb_p.h @@ -64,13 +64,13 @@ public: QSGVideoNode_RGB(const QVideoSurfaceFormat &format); ~QSGVideoNode_RGB(); - virtual QVideoFrame::PixelFormat pixelFormat() const { + QVideoFrame::PixelFormat pixelFormat() const override { return m_format.pixelFormat(); } - QAbstractVideoBuffer::HandleType handleType() const { + QAbstractVideoBuffer::HandleType handleType() const override { return QAbstractVideoBuffer::NoHandle; } - void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags); + void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags) override; private: QVideoSurfaceFormat m_format; @@ -80,8 +80,8 @@ private: class QSGVideoNodeFactory_RGB : public QSGVideoNodeFactoryInterface { public: - QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; - QSGVideoNode *createNode(const QVideoSurfaceFormat &format); + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const override; + QSGVideoNode *createNode(const QVideoSurfaceFormat &format) override; }; QT_END_NAMESPACE diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp index 8080f3ec2..a26d59532 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_texture.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_texture.cpp @@ -82,9 +82,9 @@ public: setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/rgbvideo.frag")); } - void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - virtual char const *const *attributeNames() const { + char const *const *attributeNames() const override { static const char *names[] = { "qt_VertexPosition", "qt_VertexTexCoord", @@ -94,7 +94,7 @@ public: } protected: - virtual void initialize() { + void initialize() override { m_id_matrix = program()->uniformLocation("qt_Matrix"); m_id_Texture = program()->uniformLocation("rgbTexture"); m_id_opacity = program()->uniformLocation("opacity"); @@ -132,17 +132,17 @@ public: m_frame = QVideoFrame(); } - virtual QSGMaterialType *type() const { + QSGMaterialType *type() const override { static QSGMaterialType normalType, swizzleType; return needsSwizzling() ? &swizzleType : &normalType; } - virtual QSGMaterialShader *createShader() const { + QSGMaterialShader *createShader() const override { return needsSwizzling() ? new QSGVideoMaterialShader_Texture_swizzle : new QSGVideoMaterialShader_Texture; } - virtual int compare(const QSGMaterial *other) const { + int compare(const QSGMaterial *other) const override { const QSGVideoMaterial_Texture *m = static_cast<const QSGVideoMaterial_Texture *>(other); if (!m_textureId) diff --git a/src/qtmultimediaquicktools/qsgvideonode_texture_p.h b/src/qtmultimediaquicktools/qsgvideonode_texture_p.h index e3b288d6e..12685dd24 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_texture_p.h +++ b/src/qtmultimediaquicktools/qsgvideonode_texture_p.h @@ -64,13 +64,13 @@ public: QSGVideoNode_Texture(const QVideoSurfaceFormat &format); ~QSGVideoNode_Texture(); - virtual QVideoFrame::PixelFormat pixelFormat() const { + QVideoFrame::PixelFormat pixelFormat() const override { return m_format.pixelFormat(); } - QAbstractVideoBuffer::HandleType handleType() const { + QAbstractVideoBuffer::HandleType handleType() const override { return QAbstractVideoBuffer::GLTextureHandle; } - void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags); + void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags) override; private: QVideoSurfaceFormat m_format; @@ -80,8 +80,8 @@ private: class QSGVideoNodeFactory_Texture : public QSGVideoNodeFactoryInterface { public: - QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; - QSGVideoNode *createNode(const QVideoSurfaceFormat &format); + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const override; + QSGVideoNode *createNode(const QVideoSurfaceFormat &format) override; }; QT_END_NAMESPACE diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp index 68e6b456b..38b5af943 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp +++ b/src/qtmultimediaquicktools/qsgvideonode_yuv.cpp @@ -79,9 +79,9 @@ public: setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/biplanaryuvvideo.frag")); } - virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; - virtual char const *const *attributeNames() const { + char const *const *attributeNames() const override { static const char *names[] = { "qt_VertexPosition", "qt_VertexTexCoord", @@ -91,7 +91,7 @@ public: } protected: - virtual void initialize() { + void initialize() override { m_id_matrix = program()->uniformLocation("qt_Matrix"); m_id_plane1Width = program()->uniformLocation("plane1Width"); m_id_plane2Width = program()->uniformLocation("plane2Width"); @@ -181,10 +181,10 @@ public: setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qtmultimediaquicktools/shaders/triplanaryuvvideo.frag")); } - virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); + void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; protected: - virtual void initialize() { + void initialize() override { m_id_plane3Width = program()->uniformLocation("plane3Width"); m_id_plane3Texture = program()->uniformLocation("plane3Texture"); QSGVideoMaterialShader_YUV_BiPlanar::initialize(); @@ -201,7 +201,7 @@ public: QSGVideoMaterial_YUV(const QVideoSurfaceFormat &format); ~QSGVideoMaterial_YUV(); - virtual QSGMaterialType *type() const { + QSGMaterialType *type() const override { static QSGMaterialType biPlanarType, biPlanarSwizzleType, triPlanarType, uyvyType, yuyvType; switch (m_format.pixelFormat()) { @@ -218,7 +218,7 @@ public: } } - virtual QSGMaterialShader *createShader() const { + QSGMaterialShader *createShader() const override { switch (m_format.pixelFormat()) { case QVideoFrame::Format_NV12: return new QSGVideoMaterialShader_YUV_BiPlanar; @@ -233,7 +233,7 @@ public: } } - virtual int compare(const QSGMaterial *other) const { + int compare(const QSGMaterial *other) const override { const QSGVideoMaterial_YUV *m = static_cast<const QSGVideoMaterial_YUV *>(other); if (!m_textureIds[0]) return 1; diff --git a/src/qtmultimediaquicktools/qsgvideonode_yuv_p.h b/src/qtmultimediaquicktools/qsgvideonode_yuv_p.h index 2b7e62277..643f40c71 100644 --- a/src/qtmultimediaquicktools/qsgvideonode_yuv_p.h +++ b/src/qtmultimediaquicktools/qsgvideonode_yuv_p.h @@ -63,13 +63,13 @@ public: QSGVideoNode_YUV(const QVideoSurfaceFormat &format); ~QSGVideoNode_YUV(); - virtual QVideoFrame::PixelFormat pixelFormat() const { + QVideoFrame::PixelFormat pixelFormat() const override { return m_format.pixelFormat(); } - QAbstractVideoBuffer::HandleType handleType() const { + QAbstractVideoBuffer::HandleType handleType() const override { return QAbstractVideoBuffer::NoHandle; } - void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags); + void setCurrentFrame(const QVideoFrame &frame, FrameFlags flags) override; private: void bindTexture(int id, int unit, int w, int h, const uchar *bits); @@ -80,8 +80,8 @@ private: class QSGVideoNodeFactory_YUV : public QSGVideoNodeFactoryInterface { public: - QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const; - QSGVideoNode *createNode(const QVideoSurfaceFormat &format); + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const override; + QSGVideoNode *createNode(const QVideoSurfaceFormat &format) override; }; QT_END_NAMESPACE diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST index e826fc079..8aa622881 100644 --- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST +++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST @@ -1,9 +1,6 @@ # QTBUG-46368 -osx-10.8 -osx-10.9 -osx-10.10 -osx-10.11 +osx windows 32bit developer-build windows 64bit developer-build |