summaryrefslogtreecommitdiffstats
path: root/src/multimedia/platform
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-02-05 14:46:11 +0100
committerLars Knoll <lars.knoll@qt.io>2021-02-09 19:03:56 +0000
commitea27ae88abcf82e4c034d48f5b45e16f0fd29a6b (patch)
tree267af0abf6128c33b7724c588de028303841e92d /src/multimedia/platform
parent177dd889e1f1a046c04770e4afe85d29b1476a84 (diff)
More changes for QMediaFormat handling on the backend
The codecs supported by a certain muxer/demuxer are actually something we need to determine from the backend. So a static mapping in QMediaFormat will not really work. Change-Id: I848c607ed222eba160a7c9c1c7b216b991e5ceba Reviewed-by: Doris Verria <doris.verria@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/multimedia/platform')
-rw-r--r--src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp37
-rw-r--r--src/multimedia/platform/android/qandroidformatsinfo.cpp48
-rw-r--r--src/multimedia/platform/android/qandroidformatsinfo_p.h17
-rw-r--r--src/multimedia/platform/darwin/camera/avfcameradebug_p.h2
-rw-r--r--src/multimedia/platform/darwin/camera/avfmediarecordercontrol.mm17
-rw-r--r--src/multimedia/platform/darwin/qdarwinformatsinfo.mm149
-rw-r--r--src/multimedia/platform/darwin/qdarwinformatsinfo_p.h17
-rw-r--r--src/multimedia/platform/gstreamer/common/common.pri2
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstcodecsinfo.cpp273
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstcodecsinfo_p.h96
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstutils_p.h4
-rw-r--r--src/multimedia/platform/gstreamer/mediacapture/qgstreamercapturesession.cpp40
-rw-r--r--src/multimedia/platform/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp9
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerformatsinfo.cpp367
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerformatsinfo_p.h31
-rw-r--r--src/multimedia/platform/qmediaplatformformatinfo.cpp69
-rw-r--r--src/multimedia/platform/qmediaplatformformatinfo_p.h18
17 files changed, 482 insertions, 714 deletions
diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp
index d39058d6a..5be3f6cfe 100644
--- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp
+++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp
@@ -45,6 +45,7 @@
#include "qandroidmultimediautils_p.h"
#include "qandroidvideooutput_p.h"
#include "qandroidglobal_p.h"
+#include <QtCore/qmimetype.h>
#include <algorithm>
@@ -247,37 +248,7 @@ void QAndroidCaptureSession::start()
m_mediaRecorder->setOrientationHint(m_cameraSession->currentCameraRotation());
}
- const char *extension = "mp4";
- switch(m_encoderSettings.format()) {
- case QMediaFormat::MPEG4:
- break;
- case QMediaFormat::Ogg:
- extension = "ogg";
- break;
- case QMediaFormat::QuickTime:
- extension = "mov";
- break;
- case QMediaFormat::WebM:
- extension = "webm";
- break;
- case QMediaFormat::AAC:
- extension = "aac";
- break;
- case QMediaFormat::MP3:
- extension = "mp3";
- break;
- case QMediaFormat::Mpeg4Audio:
- extension = "m4a";
- break;
- case QMediaFormat::ALAC:
- case QMediaFormat::ASF:
- case QMediaFormat::AVI:
- case QMediaFormat::Matroska:
- case QMediaFormat::FLAC:
- case QMediaFormat::Wave:
- case QMediaFormat::UnspecifiedFormat:
- break;
- }
+ QString extension = m_encoderSettings.mimeType().preferredSuffix();
// Set output file
QString filePath = m_mediaStorageLocation.generateFileName(
@@ -287,7 +258,7 @@ void QAndroidCaptureSession::start()
: QMediaStorageLocation::Sounds,
m_cameraSession ? QLatin1String("VID_")
: QLatin1String("REC_"),
- QString::fromUtf8(extension));
+ extension);
m_usedOutputLocation = QUrl::fromLocalFile(filePath);
m_mediaRecorder->setOutputFile(filePath);
@@ -399,7 +370,7 @@ qint64 QAndroidCaptureSession::duration() const
void QAndroidCaptureSession::setEncoderSettings(const QMediaEncoderSettings &settings)
{
m_encoderSettings = settings;
- m_encoderSettings.resolveFormat(m_cameraSession ? QMediaEncoderSettings::AudioAndVideo : QMediaEncoderSettings::AudioOnly);
+ m_encoderSettings.resolveFormat();
m_encoderSettingsDirty = true;
}
diff --git a/src/multimedia/platform/android/qandroidformatsinfo.cpp b/src/multimedia/platform/android/qandroidformatsinfo.cpp
index b8491492a..1faaca87b 100644
--- a/src/multimedia/platform/android/qandroidformatsinfo.cpp
+++ b/src/multimedia/platform/android/qandroidformatsinfo.cpp
@@ -43,15 +43,15 @@ QT_BEGIN_NAMESPACE
QAndroidFormatInfo::QAndroidFormatInfo()
{
- // ### Properly determine the set of supported codecs, this is a minimal set gathered from the old code base
- m_decodableAudioCodecs << QMediaFormat::AudioCodec::AAC << QMediaFormat::AudioCodec::MP3 << QMediaFormat::AudioCodec::Opus
- << QMediaFormat::AudioCodec::Vorbis;
- m_encodableAudioCodecs = m_decodableAudioCodecs;
- m_decodableVideoCodecs << QMediaFormat::VideoCodec::MPEG4 << QMediaFormat::VideoCodec::H264 << QMediaFormat::VideoCodec::H265;
- m_encodableVideoCodecs = m_decodableVideoCodecs;
- m_decodableFileFormats << QMediaFormat::FileFormat::MPEG4 << QMediaFormat::FileFormat::MP3 << QMediaFormat::AAC
- << QMediaFormat::Ogg << QMediaFormat::WebM;
- m_encodableFileFormats = m_decodableFileFormats;
+ decoders = {
+ { QMediaFormat::AAC, { QMediaFormat::AudioCodec::AAC }, {} },
+ { QMediaFormat::MP3, { QMediaFormat::AudioCodec::MP3}, {} },
+ { QMediaFormat::Ogg, { QMediaFormat::AudioCodec::Opus, QMediaFormat::AudioCodec::Vorbis },
+ { QMediaFormat::VideoCodec::VP8 } },
+ { QMediaFormat::MPEG4, { QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::AAC },
+ { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265 } }
+ };
+ encoders = decoders;
}
QAndroidFormatInfo::~QAndroidFormatInfo()
@@ -59,34 +59,4 @@ QAndroidFormatInfo::~QAndroidFormatInfo()
}
-QList<QMediaFormat::FileFormat> QAndroidFormatInfo::decodableMediaContainers() const
-{
- return m_decodableFileFormats;
-}
-
-QList<QMediaFormat::AudioCodec> QAndroidFormatInfo::decodableAudioCodecs() const
-{
- return m_decodableAudioCodecs;
-}
-
-QList<QMediaFormat::VideoCodec> QAndroidFormatInfo::decodableVideoCodecs() const
-{
- return m_decodableVideoCodecs;
-}
-
-QList<QMediaFormat::FileFormat> QAndroidFormatInfo::encodableMediaContainers() const
-{
- return m_encodableFileFormats;
-}
-
-QList<QMediaFormat::AudioCodec> QAndroidFormatInfo::encodableAudioCodecs() const
-{
- return m_encodableAudioCodecs;
-}
-
-QList<QMediaFormat::VideoCodec> QAndroidFormatInfo::encodableVideoCodecs() const
-{
- return m_encodableVideoCodecs;
-}
-
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/android/qandroidformatsinfo_p.h b/src/multimedia/platform/android/qandroidformatsinfo_p.h
index c3f744ebc..461400ed2 100644
--- a/src/multimedia/platform/android/qandroidformatsinfo_p.h
+++ b/src/multimedia/platform/android/qandroidformatsinfo_p.h
@@ -60,23 +60,6 @@ class QAndroidFormatInfo : public QMediaPlatformFormatInfo
public:
QAndroidFormatInfo();
~QAndroidFormatInfo();
-
- QList<QMediaFormat::FileFormat> decodableMediaContainers() const override;
- QList<QMediaFormat::AudioCodec> decodableAudioCodecs() const override;
- QList<QMediaFormat::VideoCodec> decodableVideoCodecs() const override;
-
- QList<QMediaFormat::FileFormat> encodableMediaContainers() const override;
- QList<QMediaFormat::AudioCodec> encodableAudioCodecs() const override;
- QList<QMediaFormat::VideoCodec> encodableVideoCodecs() const override;
-
-private:
- QList<QMediaFormat::FileFormat> m_decodableFileFormats;
- QList<QMediaFormat::AudioCodec> m_decodableAudioCodecs;
- QList<QMediaFormat::VideoCodec> m_decodableVideoCodecs;
-
- QList<QMediaFormat::FileFormat> m_encodableFileFormats;
- QList<QMediaFormat::AudioCodec> m_encodableAudioCodecs;
- QList<QMediaFormat::VideoCodec> m_encodableVideoCodecs;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/darwin/camera/avfcameradebug_p.h b/src/multimedia/platform/darwin/camera/avfcameradebug_p.h
index 616e53d99..cbb64b316 100644
--- a/src/multimedia/platform/darwin/camera/avfcameradebug_p.h
+++ b/src/multimedia/platform/darwin/camera/avfcameradebug_p.h
@@ -57,7 +57,7 @@
QT_USE_NAMESPACE
-//#define AVF_DEBUG_CAMERA
+#define AVF_DEBUG_CAMERA
#ifdef AVF_DEBUG_CAMERA
#define qDebugCamera qDebug
diff --git a/src/multimedia/platform/darwin/camera/avfmediarecordercontrol.mm b/src/multimedia/platform/darwin/camera/avfmediarecordercontrol.mm
index 721f2c1fa..69c56d402 100644
--- a/src/multimedia/platform/darwin/camera/avfmediarecordercontrol.mm
+++ b/src/multimedia/platform/darwin/camera/avfmediarecordercontrol.mm
@@ -48,6 +48,7 @@
#include "avfcamerautility_p.h"
#include <QtCore/qurl.h>
+#include <QtCore/qmimetype.h>
#include <QtCore/qfileinfo.h>
#include <QtMultimedia/qcameracontrol.h>
#include <CoreAudio/CoreAudio.h>
@@ -469,9 +470,13 @@ void AVFMediaRecorderControl::applySettings()
return;
}
- bool videoEnabled = m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo);
QMediaEncoderSettings resolved = m_settings;
- resolved.resolveFormat(videoEnabled ? QMediaEncoderSettings::AudioAndVideo : QMediaEncoderSettings::AudioOnly);
+ resolved.resolveFormat();
+ qDebug() << "file profile" << QMediaFormat::fileFormatName(resolved.format());
+ qDebug() << "video profile" << QMediaFormat::videoCodecName(resolved.videoCodec());
+ qDebug() << "audio profile" << QMediaFormat::audioCodecName(resolved.audioCodec());
+
+ const AVFConfigurationLock lock(m_session->videoCaptureDevice()); // prevents activeFormat from being overridden
// Configure audio settings
[m_movieOutput setOutputSettings:avfAudioSettings(resolved)
@@ -483,8 +488,6 @@ void AVFMediaRecorderControl::applySettings()
NSDictionary *videoSettings = avfVideoSettings(resolved, captureDevice, videoConnection);
- const AVFConfigurationLock lock(m_session->videoCaptureDevice()); // prevents activeFormat from being overridden
-
[m_movieOutput setOutputSettings:videoSettings forConnection:videoConnection];
}
@@ -540,7 +543,9 @@ void AVFMediaRecorderControl::setState(QMediaRecorder::State state)
QString outputLocationPath = m_outputLocation.scheme() == QLatin1String("file") ?
m_outputLocation.path() : m_outputLocation.toString();
- QString extension = "mov";// ######m_service->mediaContainerControl()->containerFormat();
+ QMediaEncoderSettings resolved = m_settings;
+ resolved.resolveFormat();
+ QString extension = resolved.mimeType().preferredSuffix();
QUrl actualLocation = QUrl::fromLocalFile(
m_storageLocation.generateFileName(outputLocationPath,
@@ -550,7 +555,7 @@ void AVFMediaRecorderControl::setState(QMediaRecorder::State state)
qDebugCamera() << "Video capture location:" << actualLocation.toString();
- applySettings();
+// applySettings();
[m_movieOutput startRecordingToOutputFileURL:actualLocation.toNSURL()
recordingDelegate:m_recorderDelagate];
diff --git a/src/multimedia/platform/darwin/qdarwinformatsinfo.mm b/src/multimedia/platform/darwin/qdarwinformatsinfo.mm
index 16e8458e2..11a458dea 100644
--- a/src/multimedia/platform/darwin/qdarwinformatsinfo.mm
+++ b/src/multimedia/platform/darwin/qdarwinformatsinfo.mm
@@ -62,14 +62,14 @@ static struct {
QMediaFormat::VideoCodec value;
} videoCodecMap[] = {
// See CMVideoCodecType for the four character code names of codecs
- { "video/mp4; codecs=\"mp1v\"", QMediaFormat::VideoCodec::MPEG1 },
- { "video/mp4; codecs=\"mp2v\"", QMediaFormat::VideoCodec::MPEG2 },
- { "video/mp4; codecs=\"mp4v\"", QMediaFormat::VideoCodec::MPEG4 },
- { "video/mp4; codecs=\"avc1\"", QMediaFormat::VideoCodec::H264 },
- { "video/mp4; codecs=\"hvc1\"", QMediaFormat::VideoCodec::H265 },
- { "video/mp4; codecs=\"vp09\"", QMediaFormat::VideoCodec::VP9 },
- { "video/mp4; codecs=\"av01\"", QMediaFormat::VideoCodec::AV1 }, // ### ????
- { "video/mp4; codecs=\"jpeg\"", QMediaFormat::VideoCodec::MotionJPEG },
+ { "; codecs=\"mp1v\"", QMediaFormat::VideoCodec::MPEG1 },
+ { "; codecs=\"mp2v\"", QMediaFormat::VideoCodec::MPEG2 },
+ { "; codecs=\"mp4v\"", QMediaFormat::VideoCodec::MPEG4 },
+ { "; codecs=\"avc1\"", QMediaFormat::VideoCodec::H264 },
+ { "; codecs=\"hvc1\"", QMediaFormat::VideoCodec::H265 },
+ { "; codecs=\"vp09\"", QMediaFormat::VideoCodec::VP9 },
+ { "; codecs=\"av01\"", QMediaFormat::VideoCodec::AV1 }, // ### ????
+ { "; codecs=\"jpeg\"", QMediaFormat::VideoCodec::MotionJPEG },
{ nullptr, QMediaFormat::VideoCodec::Unspecified }
};
@@ -78,11 +78,15 @@ static struct {
QMediaFormat::AudioCodec value;
} audioCodecMap[] = {
// AudioFile.h
- { "audio/mp3", QMediaFormat::AudioCodec::MP3 },
- { "audio/aac", QMediaFormat::AudioCodec::AAC },
- { "video/mp4; codecs=\"ac-3\"", QMediaFormat::AudioCodec::AC3 },
- { "video/mp4; codecs=\"ec-3\"", QMediaFormat::AudioCodec::EAC3 },
- { "audio/flac", QMediaFormat::AudioCodec::FLAC },
+ // ### The next two entries do not work, probably because they contain non a space and period and AVFoundation doesn't like that
+ // We know they are supported on all Apple platforms, so we'll add them manually below
+// { "; codecs=\".mp3\"", QMediaFormat::AudioCodec::MP3 },
+// { "; codecs=\"aac \"", QMediaFormat::AudioCodec::AAC },
+ { "; codecs=\"ac-3\"", QMediaFormat::AudioCodec::AC3 },
+ { "; codecs=\"ec-3\"", QMediaFormat::AudioCodec::EAC3 },
+ { "; codecs=\"flac\"", QMediaFormat::AudioCodec::FLAC },
+ { "; codecs=\"alac\"", QMediaFormat::AudioCodec::FLAC },
+ { "; codecs=\"opus\"", QMediaFormat::AudioCodec::Opus },
{ nullptr, QMediaFormat::AudioCodec::Unspecified },
};
@@ -92,85 +96,86 @@ QDarwinFormatInfo::QDarwinFormatInfo()
for (AVFileType filetype in avtypes) {
auto *m = mediaContainerMap;
while (m->name) {
- if (!strcmp(filetype.UTF8String, m->name)) {
- m_decodableMediaContainers.append(m->value);
- break;
+ if (strcmp(filetype.UTF8String, m->name)) {
+ ++m;
+ continue;
}
- ++m;
- }
- }
- {
- auto *m = videoCodecMap;
- while (m->name) {
- if ([AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:m->name]])
- m_decodableVideoCodecs << m->value;
- ++m;
- }
- }
- {
- auto *m = audioCodecMap;
- while (m->name) {
- qDebug() << "audio" << m->name << [AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:m->name]];
- if ([AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:m->name]])
- m_decodableAudioCodecs << m->value;
+ QList<QMediaFormat::VideoCodec> video;
+ QList<QMediaFormat::AudioCodec> audio;
+// qDebug() << "Media container" << m->name << "supported";
+
+ auto *v = videoCodecMap;
+ while (v->name) {
+ QByteArray extendedMimetype = m->name;
+ extendedMimetype += v->name;
+// qDebug() << "video" << extendedMimetype << [AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:extendedMimetype.constData()]];
+ if ([AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:extendedMimetype.constData()]])
+ video << v->value;
+ ++v;
+ }
+
+ auto *a = audioCodecMap;
+ while (a->name) {
+ QByteArray extendedMimetype = m->name;
+ extendedMimetype += a->name;
+// qDebug() << "audio" << extendedMimetype << [AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:extendedMimetype.constData()]];
+ if ([AVURLAsset isPlayableExtendedMIMEType:[NSString stringWithUTF8String:extendedMimetype.constData()]])
+ audio << a->value;
+ ++a;
+ }
+ // Added manually, see comment in the list above
+ if (m->value <= QMediaFormat::AAC)
+ audio << QMediaFormat::AudioCodec::AAC;
+ if (m->value < QMediaFormat::AAC || m->value == QMediaFormat::MP3)
+ audio << QMediaFormat::AudioCodec::MP3;
+
+ decoders << CodecMap{ m->value, audio, video };
++m;
}
}
- // Audio format seems to be symmetric
- m_encodableAudioCodecs = m_decodableAudioCodecs;
+#if 1
+ // ### Verify that this is correct
+ encoders = decoders;
+#else
// ### Haven't seen a good way to figure this out.
// seems AVFoundation only supports those for encoding
- m_encodableMediaContainers << QMediaFormat::MPEG4 << QMediaFormat::QuickTime;
- // AVCaptureVideoDataOutput.availableVideoCodecTypes does not mention H265 even though it is supported
- m_encodableVideoCodecs << QMediaFormat::VideoCodec::H264 << QMediaFormat::VideoCodec::H265 << QMediaFormat::VideoCodec::MotionJPEG;
+ encoders = {
+ { QMediaFormat::MPEG4,
+ { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3, },
+ { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::MotionJPEG } },
+ { QMediaFormat::QuickTime,
+ { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3, },
+ { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::MotionJPEG } },
+ { QMediaFormat::AAC,
+ { QMediaFormat::AudioCodec::AAC },
+ {} },
+ { QMediaFormat::MP3,
+ { QMediaFormat::AudioCodec::MP3 },
+ {} },
+ { QMediaFormat::FLAC,
+ { QMediaFormat::AudioCodec::FLAC },
+ {} },
+ { QMediaFormat::Mpeg4Audio,
+ { QMediaFormat::AudioCodec::AAC },
+ {} }
+ };
+#endif
}
QDarwinFormatInfo::~QDarwinFormatInfo()
{
}
-QList<QMediaFormat::FileFormat> QDarwinFormatInfo::decodableMediaContainers() const
-{
- return m_decodableMediaContainers;
-}
-
-QList<QMediaFormat::AudioCodec> QDarwinFormatInfo::decodableAudioCodecs() const
-{
- return m_decodableAudioCodecs;
-}
-
-QList<QMediaFormat::VideoCodec> QDarwinFormatInfo::decodableVideoCodecs() const
-{
- return m_decodableVideoCodecs;
-}
-
-QList<QMediaFormat::FileFormat> QDarwinFormatInfo::encodableMediaContainers() const
-{
- return m_encodableMediaContainers;
-}
-
-QList<QMediaFormat::AudioCodec> QDarwinFormatInfo::encodableAudioCodecs() const
-{
- return m_encodableAudioCodecs;
-}
-
-QList<QMediaFormat::VideoCodec> QDarwinFormatInfo::encodableVideoCodecs() const
-{
- return m_encodableVideoCodecs;
-}
-
int QDarwinFormatInfo::audioFormatForCodec(QMediaFormat::AudioCodec codec)
{
int codecId = kAudioFormatMPEG4AAC;
switch (codec) {
case QMediaFormat::AudioCodec::Unspecified:
case QMediaFormat::AudioCodec::DolbyTrueHD:
- case QMediaFormat::AudioCodec::Opus:
case QMediaFormat::AudioCodec::Vorbis:
case QMediaFormat::AudioCodec::Wave:
- case QMediaFormat::AudioCodec::WindowsMediaAudio:
// Unsupported, shouldn't happen. Fall back to AAC
case QMediaFormat::AudioCodec::AAC:
codecId = kAudioFormatMPEG4AAC;
@@ -186,6 +191,10 @@ int QDarwinFormatInfo::audioFormatForCodec(QMediaFormat::AudioCodec codec)
break;
case QMediaFormat::AudioCodec::FLAC:
codecId = kAudioFormatFLAC;
+ case QMediaFormat::AudioCodec::ALAC:
+ codecId = kAudioFormatAppleLossless;
+ case QMediaFormat::AudioCodec::Opus:
+ codecId = kAudioFormatOpus;
break;
}
return codecId;
diff --git a/src/multimedia/platform/darwin/qdarwinformatsinfo_p.h b/src/multimedia/platform/darwin/qdarwinformatsinfo_p.h
index ad53c745b..44e03c5b2 100644
--- a/src/multimedia/platform/darwin/qdarwinformatsinfo_p.h
+++ b/src/multimedia/platform/darwin/qdarwinformatsinfo_p.h
@@ -64,25 +64,8 @@ public:
QDarwinFormatInfo();
~QDarwinFormatInfo();
- QList<QMediaFormat::FileFormat> decodableMediaContainers() const override;
- QList<QMediaFormat::AudioCodec> decodableAudioCodecs() const override;
- QList<QMediaFormat::VideoCodec> decodableVideoCodecs() const override;
-
- QList<QMediaFormat::FileFormat> encodableMediaContainers() const override;
- QList<QMediaFormat::AudioCodec> encodableAudioCodecs() const override;
- QList<QMediaFormat::VideoCodec> encodableVideoCodecs() const override;
-
static int audioFormatForCodec(QMediaFormat::AudioCodec codec);
static NSString *videoFormatForCodec(QMediaFormat::VideoCodec codec);
-
-private:
- QList<QMediaFormat::FileFormat> m_decodableMediaContainers;
- QList<QMediaFormat::AudioCodec> m_decodableAudioCodecs;
- QList<QMediaFormat::VideoCodec> m_decodableVideoCodecs;
-
- QList<QMediaFormat::FileFormat> m_encodableMediaContainers;
- QList<QMediaFormat::AudioCodec> m_encodableAudioCodecs;
- QList<QMediaFormat::VideoCodec> m_encodableVideoCodecs;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/common/common.pri b/src/multimedia/platform/gstreamer/common/common.pri
index b57cf4d00..54167b557 100644
--- a/src/multimedia/platform/gstreamer/common/common.pri
+++ b/src/multimedia/platform/gstreamer/common/common.pri
@@ -7,7 +7,6 @@ HEADERS += \
$$PWD/qgstreamerbufferprobe_p.h \
$$PWD/qgstreamervideorendererinterface_p.h \
$$PWD/qgstreamervideorenderer_p.h \
- $$PWD/qgstcodecsinfo_p.h \
$$PWD/qgstreamervideowindow_p.h \
$$PWD/qgstreamervideooverlay_p.h \
$$PWD/qgstreamerplayersession_p.h \
@@ -24,7 +23,6 @@ SOURCES += \
$$PWD/qgstreamerbufferprobe.cpp \
$$PWD/qgstreamervideorendererinterface.cpp \
$$PWD/qgstreamervideorenderer.cpp \
- $$PWD/qgstcodecsinfo.cpp \
$$PWD/qgstreamervideowindow.cpp \
$$PWD/qgstreamervideooverlay.cpp \
$$PWD/qgstreamerplayersession.cpp \
diff --git a/src/multimedia/platform/gstreamer/common/qgstcodecsinfo.cpp b/src/multimedia/platform/gstreamer/common/qgstcodecsinfo.cpp
deleted file mode 100644
index 06e034198..000000000
--- a/src/multimedia/platform/gstreamer/common/qgstcodecsinfo.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/****************************************************************************
-**
-** 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 "qgstcodecsinfo_p.h"
-#include "qgstutils_p.h"
-#include <QtCore/qset.h>
-
-#include <gst/pbutils/pbutils.h>
-
-static QSet<QString> streamTypes(GstElementFactory *factory, GstPadDirection direction)
-{
- QSet<QString> types;
- const GList *pads = gst_element_factory_get_static_pad_templates(factory);
- for (const GList *pad = pads; pad; pad = g_list_next(pad)) {
- GstStaticPadTemplate *templ = reinterpret_cast<GstStaticPadTemplate *>(pad->data);
- if (templ->direction == direction) {
- GstCaps *caps = gst_static_caps_get(&templ->static_caps);
- for (uint i = 0; i < gst_caps_get_size(caps); ++i) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
- types.insert(QString::fromUtf8(gst_structure_get_name(structure)));
- }
- gst_caps_unref(caps);
- }
- }
-
- return types;
-}
-
-QGstCodecsInfo::QGstCodecsInfo(QGstCodecsInfo::ElementType elementType)
-{
- updateCodecs(elementType);
- for (auto &codec : supportedCodecs()) {
- GstElementFactory *factory = gst_element_factory_find(codecElement(codec).constData());
- if (factory) {
- GstPadDirection direction = elementType == Muxer ? GST_PAD_SINK : GST_PAD_SRC;
- m_streamTypes.insert(codec, streamTypes(factory, direction));
- gst_object_unref(GST_OBJECT(factory));
- }
- }
-}
-
-QStringList QGstCodecsInfo::supportedCodecs() const
-{
- return m_codecs;
-}
-
-QString QGstCodecsInfo::codecDescription(const QString &codec) const
-{
- return m_codecInfo.value(codec).description;
-}
-
-QByteArray QGstCodecsInfo::codecElement(const QString &codec) const
-
-{
- 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, nullptr);
- 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;
-}
-
-void QGstCodecsInfo::updateCodecs(ElementType elementType)
-{
- m_codecs.clear();
- m_codecInfo.clear();
-
- GstPadDirection padDirection = GST_PAD_SRC;
- if (elementType == Demuxer || elementType == AudioDecoder || elementType == VideoDecoder)
- padDirection = GST_PAD_SINK;
-
- GList *elements = elementFactories(elementType);
-
- QSet<QByteArray> fakeEncoderMimeTypes;
- fakeEncoderMimeTypes << "unknown/unknown"
- << "audio/x-raw-int" << "audio/x-raw-float"
- << "video/x-raw-yuv" << "video/x-raw-rgb";
-
- QSet<QByteArray> fieldsToAdd;
- fieldsToAdd << "mpegversion" << "layer" << "layout"
- << "variant";
-
- GList *element = elements;
- while (element) {
- GstElementFactory *factory = (GstElementFactory *)element->data;
- element = element->next;
-
- const GList *padTemplates = gst_element_factory_get_static_pad_templates(factory);
- while (padTemplates) {
- GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
- padTemplates = padTemplates->next;
-
- if (padTemplate->direction == padDirection) {
- 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);
-
- //skip "fake" encoders
- if (fakeEncoderMimeTypes.contains(gst_structure_get_name(structure)))
- continue;
-
- GstStructure *newStructure = qt_gst_structure_new_empty(gst_structure_get_name(structure));
-
- //add structure fields to distinguish between formats with similar mime types,
- //like audio/mpeg
- for (int j=0; j<gst_structure_n_fields(structure); j++) {
- const gchar* fieldName = gst_structure_nth_field_name(structure, j);
- if (fieldsToAdd.contains(fieldName)) {
- const GValue *value = gst_structure_get_value(structure, fieldName);
- GType valueType = G_VALUE_TYPE(value);
-
- //don't add values of range type,
- //gst_pb_utils_get_codec_description complains about not fixed caps
-
- if (valueType != GST_TYPE_INT_RANGE && valueType != GST_TYPE_DOUBLE_RANGE &&
- valueType != GST_TYPE_FRACTION_RANGE && valueType != GST_TYPE_LIST &&
- valueType != GST_TYPE_ARRAY)
- gst_structure_set_value(newStructure, fieldName, value);
- }
- }
-
- GstCaps *newCaps = gst_caps_new_full(newStructure, nullptr);
-
- gchar *capsString = gst_caps_to_string(newCaps);
- QString codec = QLatin1String(capsString);
- if (capsString)
- g_free(capsString);
- // skip stuff that's not really a known audio/video codec
- if (codec.startsWith("application"))
- continue;
- 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.constFind(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);
-}
-
-GList *QGstCodecsInfo::elementFactories(ElementType elementType) const
-{
- GstElementFactoryListType gstElementType = 0;
- switch (elementType) {
- case AudioEncoder:
- gstElementType = GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER;
- break;
- case VideoEncoder:
- // GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER also lists image encoders. We don't want these here.
- gstElementType = (GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_ENCODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO);
- break;
- case Muxer:
- gstElementType = GST_ELEMENT_FACTORY_TYPE_MUXER;
- break;
- case AudioDecoder:
- gstElementType = (GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
- break;
- case VideoDecoder:
- gstElementType = (GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO);
- break;
- case Demuxer:
- gstElementType = GST_ELEMENT_FACTORY_TYPE_DEMUXER;
- break;
- }
-
- GList *list = gst_element_factory_list_get_elements(gstElementType, GST_RANK_MARGINAL);
- if (elementType == AudioEncoder) {
- // Manually add "audioconvert" to the list
- // to allow linking with various containers.
- auto factory = gst_element_factory_find("audioconvert");
- if (factory)
- list = g_list_prepend(list, factory);
- }
-
- return list;
-}
-
-QSet<QString> QGstCodecsInfo::supportedStreamTypes(const QString &codec) const
-{
- return m_streamTypes.value(codec);
-}
-
-QStringList QGstCodecsInfo::supportedCodecs(const QSet<QString> &types) const
-{
- QStringList result;
- for (auto &candidate : supportedCodecs()) {
- auto candidateTypes = supportedStreamTypes(candidate);
- if (candidateTypes.intersects(types))
- result << candidate;
- }
-
- return result;
-}
diff --git a/src/multimedia/platform/gstreamer/common/qgstcodecsinfo_p.h b/src/multimedia/platform/gstreamer/common/qgstcodecsinfo_p.h
deleted file mode 100644
index fb2fb71d9..000000000
--- a/src/multimedia/platform/gstreamer/common/qgstcodecsinfo_p.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** 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 QGSTCODECSINFO_H
-#define QGSTCODECSINFO_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qtmultimediaglobal_p.h>
-#include <QtCore/qmap.h>
-#include <QtCore/qstringlist.h>
-#include <QSet>
-
-#include <gst/gst.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_MULTIMEDIA_EXPORT QGstCodecsInfo
-{
-public:
- enum ElementType { AudioEncoder, VideoEncoder, Muxer, AudioDecoder, VideoDecoder, Demuxer };
-
- struct CodecInfo {
- QString description;
- QByteArray elementName;
- GstRank rank;
- };
-
- QGstCodecsInfo(ElementType elementType);
-
- QStringList supportedCodecs() const;
- QString codecDescription(const QString &codec) const;
- QByteArray codecElement(const QString &codec) const;
- QStringList codecOptions(const QString &codec) const;
- QSet<QString> supportedStreamTypes(const QString &codec) const;
- QStringList supportedCodecs(const QSet<QString> &types) const;
-
-private:
- void updateCodecs(ElementType elementType);
- GList *elementFactories(ElementType elementType) const;
-
- QStringList m_codecs;
- QMap<QString, CodecInfo> m_codecInfo;
- QMap<QString, QSet<QString>> m_streamTypes;
-};
-
-Q_DECLARE_TYPEINFO(QGstCodecsInfo::CodecInfo, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/multimedia/platform/gstreamer/common/qgstutils_p.h b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
index 7b6b6ded1..5cf5035ea 100644
--- a/src/multimedia/platform/gstreamer/common/qgstutils_p.h
+++ b/src/multimedia/platform/gstreamer/common/qgstutils_p.h
@@ -195,6 +195,10 @@ class QGstCaps {
public:
QGstCaps(const GstCaps *c) : caps(c) {}
const GstCaps *caps;
+ void unref() {
+ gst_caps_unref(const_cast<GstCaps *>(caps));
+ caps = nullptr;
+ }
bool isNull() const { return !caps; }
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercapturesession.cpp
index 193ccaa34..131e18e80 100644
--- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercapturesession.cpp
+++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercapturesession.cpp
@@ -129,25 +129,17 @@ GstElement *QGstreamerCaptureSession::buildFileSink()
static GstEncodingContainerProfile *createContainerProfile(const QMediaEncoderSettings &settings)
{
- GstCaps *caps = nullptr;
-
auto *formatInfo = QGstreamerIntegration::instance()->m_formatsInfo;
- if (!formatInfo->encodableMediaContainers().contains(settings.format()))
- return nullptr;
-
- const char *format = formatInfo->nativeFormat(settings.format());
- Q_ASSERT(format);
-
- caps = gst_caps_from_string(format);
+ QGstCaps caps = formatInfo->formatCaps(settings.format());
GstEncodingContainerProfile *profile = (GstEncodingContainerProfile *)gst_encoding_container_profile_new(
"container_profile",
(gchar *)"custom container profile",
- caps,
+ const_cast<GstCaps *>(caps.caps),
NULL); //preset
- gst_caps_unref(caps);
+ caps.unref();
return profile;
}
@@ -156,23 +148,17 @@ static GstEncodingProfile *createVideoProfile(const QMediaEncoderSettings &setti
{
auto *formatInfo = QGstreamerIntegration::instance()->m_formatsInfo;
- if (!formatInfo->encodableVideoCodecs().contains(settings.videoCodec()))
- return nullptr;
-
- const char *codec = formatInfo->nativeFormat(settings.videoCodec());
- Q_ASSERT(codec);
- GstCaps *caps = gst_caps_from_string(codec);
-
- if (!caps)
+ QGstCaps caps = formatInfo->videoCaps(settings);
+ if (caps.isNull())
return nullptr;
GstEncodingVideoProfile *profile = gst_encoding_video_profile_new(
- caps,
+ const_cast<GstCaps *>(caps.caps),
nullptr,
NULL, //restriction
0); //presence
- gst_caps_unref(caps);
+ caps.unref();
gst_encoding_video_profile_set_pass(profile, 0);
gst_encoding_video_profile_set_variableframerate(profile, TRUE);
@@ -184,21 +170,17 @@ static GstEncodingProfile *createAudioProfile(const QMediaEncoderSettings &setti
{
auto *formatInfo = QGstreamerIntegration::instance()->m_formatsInfo;
- if (!formatInfo->encodableAudioCodecs().contains(settings.audioCodec()))
+ QGstCaps caps = formatInfo->audioCaps(settings);
+ if (caps.isNull())
return nullptr;
- const char *codec = formatInfo->nativeFormat(settings.audioCodec());
- Q_ASSERT(codec);
-
- GstCaps *caps = gst_caps_from_string(codec);
-
GstEncodingProfile *profile = (GstEncodingProfile *)gst_encoding_audio_profile_new(
- caps,
+ const_cast<GstCaps *>(caps.caps),
nullptr, //preset
NULL, //restriction
0); //presence
- gst_caps_unref(caps);
+ caps.unref();
return profile;
}
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
index 7c60ed4d1..fabf6cf20 100644
--- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
+++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamerrecordercontrol.cpp
@@ -42,6 +42,7 @@
#include <QtGui/qdesktopservices.h>
#include <QStandardPaths>
#include "qaudiodeviceinfo.h"
+#include <qmimetype.h>
QGstreamerRecorderControl::QGstreamerRecorderControl(QGstreamerCaptureSession *session)
: QMediaRecorderControl(session),
@@ -154,9 +155,9 @@ void QGstreamerRecorderControl::record()
m_state = QMediaRecorder::RecordingState;
if (m_outputLocation.isEmpty()) {
- QString container;// ### = m_session->mediaContainerControl()->containerExtension();
+ QString container = resolvedEncoderSettings().mimeType().preferredSuffix();
if (container.isEmpty())
- container = "raw";
+ container = QString::fromLatin1("raw");
m_session->setOutputLocation(QUrl(generateFileName(defaultDir(), container)));
}
@@ -232,12 +233,10 @@ void QGstreamerRecorderControl::setEncoderSettings(const QMediaEncoderSettings &
QMediaEncoderSettings QGstreamerRecorderControl::resolvedEncoderSettings() const
{
QMediaEncoderSettings f = m_settings;
- f.resolveFormat(m_session->captureMode() & QGstreamerCaptureSession::Video ?
- QMediaEncoderSettings::AudioAndVideo : QMediaEncoderSettings::AudioOnly);
+ f.resolveFormat();
return f;
}
-
bool QGstreamerRecorderControl::isMuted() const
{
return m_session->isMuted();
diff --git a/src/multimedia/platform/gstreamer/qgstreamerformatsinfo.cpp b/src/multimedia/platform/gstreamer/qgstreamerformatsinfo.cpp
index 1e5c41969..b0fd8e53e 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerformatsinfo.cpp
+++ b/src/multimedia/platform/gstreamer/qgstreamerformatsinfo.cpp
@@ -40,135 +40,308 @@
#include "qgstreamerformatsinfo_p.h"
#include "private/qgstutils_p.h"
-#include "private/qgstcodecsinfo_p.h"
QT_BEGIN_NAMESPACE
-static struct {
- const char *name;
- QMediaFormat::FileFormat value;
-} videoFormatsMap[] = {
- { "video/x-ms-asf", QMediaFormat::FileFormat::ASF },
- { "video/x-msvideo", QMediaFormat::FileFormat::AVI },
- { "video/x-matroska", QMediaFormat::FileFormat::Matroska },
- { "video/mpeg", QMediaFormat::FileFormat::MPEG4 },
- { "video/quicktime", QMediaFormat::FileFormat::QuickTime },
- { "video/ogg", QMediaFormat::FileFormat::Ogg },
- { "video/webm", QMediaFormat::FileFormat::WebM },
- { nullptr, QMediaFormat::FileFormat::UnspecifiedFormat }
-};
-
-static struct {
- const char *name;
- QMediaFormat::FileFormat value;
-} audioFormatsMap[] = {
- { "audio/mpeg, mpegversion=(int)1, layer=(int)3", QMediaFormat::FileFormat::MP3 },
- { "audio/mpeg, mpegversion=(int)4", QMediaFormat::FileFormat::AAC },
- { "audio/x-flac", QMediaFormat::FileFormat::FLAC },
- { "audio/x-alac", QMediaFormat::FileFormat::ALAC },
- { nullptr, QMediaFormat::FileFormat::UnspecifiedFormat },
-};
-
-static struct {
- const char *name;
- QMediaFormat::VideoCodec value;
-} videoCodecMap[] = {
- { "video/mpeg, mpegversion=(int)1", QMediaFormat::VideoCodec::MPEG1 },
- { "video/mpeg, mpegversion=(int)2", QMediaFormat::VideoCodec::MPEG2 },
- { "video/mpeg, mpegversion=(int)4", QMediaFormat::VideoCodec::MPEG4 },
- { "video/x-h264", QMediaFormat::VideoCodec::H264 },
- { "video/x-h265", QMediaFormat::VideoCodec::H265 },
- { "video/x-vp8", QMediaFormat::VideoCodec::VP8 },
- { "video/x-vp9", QMediaFormat::VideoCodec::VP9 },
- { "video/x-av1", QMediaFormat::VideoCodec::AV1 },
- { "video/x-theora", QMediaFormat::VideoCodec::Theora },
- { "video/x-jpeg", QMediaFormat::VideoCodec::MotionJPEG },
- { nullptr, QMediaFormat::VideoCodec::Unspecified }
-};
-
-static struct {
- const char *name;
- QMediaFormat::AudioCodec value;
-} audioCodecMap[] = {
- { "audio/mpeg, mpegversion=(int)1, layer=(int)3", QMediaFormat::AudioCodec::MP3 },
- { "audio/mpeg, mpegversion=(int)4", QMediaFormat::AudioCodec::AAC },
- { "audio/x-ac3", QMediaFormat::AudioCodec::AC3 },
- { "audio/x-eac3", QMediaFormat::AudioCodec::EAC3 },
- { "audio/x-flac", QMediaFormat::AudioCodec::FLAC },
- { "audio/x-alac", QMediaFormat::AudioCodec::ALAC },
- { "audio/x-true-hd", QMediaFormat::AudioCodec::DolbyTrueHD },
- { "audio/x-vorbis", QMediaFormat::AudioCodec::Vorbis },
- { nullptr, QMediaFormat::AudioCodec::Unspecified },
-};
-
-template<typename Map, typename Hash>
-static auto getList(QGstCodecsInfo::ElementType type, Map *map, Hash &hash)
+static QMediaFormat::AudioCodec audioCodecForCaps(QGstStructure structure)
{
- using T = decltype(map->value);
- QList<T> list;
- QGstCodecsInfo info(type);
- auto codecs = info.supportedCodecs();
- for (const auto &c : codecs) {
- Map *m = map;
- while (m->name) {
- if (m->name == c.toLatin1()) {
- list.append(m->value);
- hash.insert(m->value, m->name);
- break;
- }
- ++m;
+ const char *name = structure.name();
+
+ if (!name || strncmp(name, "audio/", 6))
+ return QMediaFormat::AudioCodec::Unspecified;
+ name += 6;
+ if (!strcmp(name, "mpeg")) {
+ auto version = structure["mpegversion"].toInt();
+ if (version == 1) {
+ auto layer = structure["layer"].toInt();
+ if (layer == 3)
+ return QMediaFormat::AudioCodec::MP3;
}
+ if (version == 4)
+ return QMediaFormat::AudioCodec::AAC;
+ } else if (!strcmp(name, "x-ac3")) {
+ return QMediaFormat::AudioCodec::AC3;
+ } else if (!strcmp(name, "x-eac3")) {
+ return QMediaFormat::AudioCodec::EAC3;
+ } else if (!strcmp(name, "x-flac")) {
+ return QMediaFormat::AudioCodec::FLAC;
+ } else if (!strcmp(name, "x-alac")) {
+ return QMediaFormat::AudioCodec::ALAC;
+ } else if (!strcmp(name, "x-true-hd")) {
+ return QMediaFormat::AudioCodec::DolbyTrueHD;
+ } else if (!strcmp(name, "x-vorbis")) {
+ return QMediaFormat::AudioCodec::Vorbis;
+ } else if (!strcmp(name, "x-opus")) {
+ return QMediaFormat::AudioCodec::Opus;
+ } else if (!strcmp(name, "x-wav")) {
+ return QMediaFormat::AudioCodec::Wave;
}
- return list;
+ return QMediaFormat::AudioCodec::Unspecified;
}
-QGstreamerFormatsInfo::QGstreamerFormatsInfo()
+static QMediaFormat::VideoCodec videoCodecForCaps(QGstStructure structure)
+{
+ const char *name = structure.name();
+
+ if (!name || strncmp(name, "video/", 6))
+ return QMediaFormat::VideoCodec::Unspecified;
+ name += 6;
+
+ if (!strcmp(name, "mpeg")) {
+ auto version = structure["mpegversion"].toInt();
+ if (version == 1)
+ return QMediaFormat::VideoCodec::MPEG1;
+ else if (version == 2)
+ return QMediaFormat::VideoCodec::MPEG2;
+ else if (version == 4)
+ return QMediaFormat::VideoCodec::MPEG4;
+ } else if (!strcmp(name, "x-h264")) {
+ return QMediaFormat::VideoCodec::H264;
+ } else if (!strcmp(name, "x-h265")) {
+ return QMediaFormat::VideoCodec::H265;
+ } else if (!strcmp(name, "x-vp8")) {
+ return QMediaFormat::VideoCodec::VP8;
+ } else if (!strcmp(name, "x-vp9")) {
+ return QMediaFormat::VideoCodec::VP9;
+ } else if (!strcmp(name, "x-av1")) {
+ return QMediaFormat::VideoCodec::AV1;
+ } else if (!strcmp(name, "x-theora")) {
+ return QMediaFormat::VideoCodec::Theora;
+ } else if (!strcmp(name, "x-jpeg")) {
+ return QMediaFormat::VideoCodec::MotionJPEG;
+ }
+ return QMediaFormat::VideoCodec::Unspecified;
+}
+
+static QMediaFormat::FileFormat fileFormatForCaps(QGstStructure structure)
{
- m_decodableMediaContainers = getList(QGstCodecsInfo::Demuxer, videoFormatsMap, formatToCaps);
- m_decodableMediaContainers.append(getList(QGstCodecsInfo::AudioDecoder, audioFormatsMap, formatToCaps));
- m_decodableAudioCodecs = getList(QGstCodecsInfo::AudioDecoder, audioCodecMap, audioToCaps);
- m_decodableVideoCodecs = getList(QGstCodecsInfo::VideoDecoder, videoCodecMap, videoToCaps);
-
- m_encodableMediaContainers = getList(QGstCodecsInfo::Muxer, videoFormatsMap, formatToCaps);
- m_encodableMediaContainers.append(getList(QGstCodecsInfo::AudioEncoder, audioFormatsMap, formatToCaps));
- m_encodableAudioCodecs = getList(QGstCodecsInfo::AudioEncoder, audioCodecMap, audioToCaps);
- m_encodableVideoCodecs = getList(QGstCodecsInfo::VideoEncoder, videoCodecMap, videoToCaps);
+ const char *name = structure.name();
+
+ if (!strcmp(name, "video/x-ms-asf")) {
+ return QMediaFormat::FileFormat::ASF;
+ } else if (!strcmp(name, "video/x-msvideo")) {
+ return QMediaFormat::FileFormat::AVI;
+ } else if (!strcmp(name, "video/x-matroska")) {
+ return QMediaFormat::FileFormat::Matroska;
+ } else if (!strcmp(name, "video/quicktime")) {
+ auto variant = structure["variant"].toString();
+ if (!variant)
+ return QMediaFormat::FileFormat::QuickTime;
+ else if (!strcmp(variant, "iso"))
+ return QMediaFormat::FileFormat::MPEG4;
+ } else if (!strcmp(name, "video/ogg")) {
+ return QMediaFormat::FileFormat::Ogg;
+ } else if (!strcmp(name, "video/webm")) {
+ return QMediaFormat::FileFormat::WebM;
+ }
+ return QMediaFormat::UnspecifiedFormat;
}
-QGstreamerFormatsInfo::~QGstreamerFormatsInfo()
+static QPair<QList<QMediaFormat::AudioCodec>, QList<QMediaFormat::VideoCodec>> getCodecsList(bool decode)
{
+ QList<QMediaFormat::AudioCodec> audio;
+ QList<QMediaFormat::VideoCodec> video;
+ GstPadDirection padDirection = decode ? GST_PAD_SINK : GST_PAD_SRC;
+
+ GList *elementList = gst_element_factory_list_get_elements(decode ? GST_ELEMENT_FACTORY_TYPE_DECODER : GST_ELEMENT_FACTORY_TYPE_ENCODER,
+ GST_RANK_MARGINAL);
+
+ GList *element = elementList;
+ while (element) {
+ GstElementFactory *factory = (GstElementFactory *)element->data;
+ element = element->next;
+
+ const GList *padTemplates = gst_element_factory_get_static_pad_templates(factory);
+ while (padTemplates) {
+ GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
+ padTemplates = padTemplates->next;
+
+ if (padTemplate->direction == padDirection) {
+ QGstCaps caps = gst_static_caps_get(&padTemplate->static_caps);
+
+ for (int i = 0; i < caps.size(); i++) {
+ QGstStructure structure = caps.at(i);
+ auto a = audioCodecForCaps(structure);
+ if (a != QMediaFormat::AudioCodec::Unspecified)
+ audio.append(a);
+ auto v = videoCodecForCaps(structure);
+ if (v != QMediaFormat::VideoCodec::Unspecified)
+ video.append(v);
+ }
+ caps.unref();
+ }
+ }
+ }
+ gst_plugin_feature_list_free(elementList);
+ return {audio, video};
}
-QList<QMediaFormat::FileFormat> QGstreamerFormatsInfo::decodableMediaContainers() const
+QList<QGstreamerFormatsInfo::CodecMap> QGstreamerFormatsInfo::getMuxerList(bool demuxer,
+ QList<QMediaFormat::AudioCodec> supportedAudioCodecs,
+ QList<QMediaFormat::VideoCodec> supportedVideoCodecs)
+{
+ QList<QGstreamerFormatsInfo::CodecMap> muxers;
+
+ GstPadDirection padDirection = demuxer ? GST_PAD_SINK : GST_PAD_SRC;
+
+ GList *elementList = gst_element_factory_list_get_elements(demuxer ? GST_ELEMENT_FACTORY_TYPE_DEMUXER : GST_ELEMENT_FACTORY_TYPE_MUXER,
+ GST_RANK_MARGINAL);
+ GList *element = elementList;
+ while (element) {
+ GstElementFactory *factory = (GstElementFactory *)element->data;
+ element = element->next;
+
+ QList<QMediaFormat::FileFormat> fileFormats;
+
+ const GList *padTemplates = gst_element_factory_get_static_pad_templates(factory);
+ while (padTemplates) {
+ GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
+ padTemplates = padTemplates->next;
+
+ if (padTemplate->direction == padDirection) {
+ QGstCaps caps = gst_static_caps_get(&padTemplate->static_caps);
+
+ for (int i = 0; i < caps.size(); i++) {
+ QGstStructure structure = caps.at(i);
+ auto fmt = fileFormatForCaps(structure);
+ if (fmt != QMediaFormat::UnspecifiedFormat)
+ fileFormats.append(fmt);
+ }
+ caps.unref();
+ }
+ }
+ if (fileFormats.isEmpty())
+ continue;
+
+ QList<QMediaFormat::AudioCodec> audioCodecs;
+ QList<QMediaFormat::VideoCodec> videoCodecs;
+
+ padTemplates = gst_element_factory_get_static_pad_templates(factory);
+ while (padTemplates) {
+ GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *)padTemplates->data;
+ padTemplates = padTemplates->next;
+
+ // check the other side for supported inputs/outputs
+ if (padTemplate->direction != padDirection) {
+ QGstCaps caps = gst_static_caps_get(&padTemplate->static_caps);
+
+ for (int i = 0; i < caps.size(); i++) {
+ QGstStructure structure = caps.at(i);
+ auto audio = audioCodecForCaps(structure);
+ if (audio != QMediaFormat::AudioCodec::Unspecified && supportedAudioCodecs.contains(audio))
+ audioCodecs.append(audio);
+ auto video = videoCodecForCaps(structure);
+ if (video != QMediaFormat::VideoCodec::Unspecified && supportedVideoCodecs.contains(video))
+ videoCodecs.append(video);
+ }
+ caps.unref();
+ }
+ }
+ if (!audioCodecs.isEmpty() || !videoCodecs.isEmpty()) {
+ for (auto f : qAsConst(fileFormats))
+ muxers.append({f, audioCodecs, videoCodecs});
+ }
+ }
+ gst_plugin_feature_list_free(elementList);
+ return muxers;
+}
+
+#if 0
+static void dumpMuxers(const QList<QGstreamerFormatsInfo::CodecMap> &muxerList)
{
- return m_decodableMediaContainers;
+ for (const auto &m : muxerList) {
+ qDebug() << " " << QMediaFormat::fileFormatName(m.format);
+ qDebug() << " Audio";
+ for (const auto &a : m.audio)
+ qDebug() << " " << QMediaFormat::audioCodecName(a);
+ qDebug() << " Video";
+ for (const auto &v : m.video)
+ qDebug() << " " << QMediaFormat::videoCodecName(v);
+ }
+
}
+#endif
-QList<QMediaFormat::AudioCodec> QGstreamerFormatsInfo::decodableAudioCodecs() const
+QGstreamerFormatsInfo::QGstreamerFormatsInfo()
{
- return m_decodableAudioCodecs;
+ auto codecs = getCodecsList(/*decode = */ true);
+ decoders = getMuxerList(true, codecs.first, codecs.second);
+
+ codecs = getCodecsList(/*decode = */ false);
+ encoders = getMuxerList(/* demuxer = */false, codecs.first, codecs.second);
+ //dumpMuxers(encoders);
}
-QList<QMediaFormat::VideoCodec> QGstreamerFormatsInfo::decodableVideoCodecs() const
+QGstreamerFormatsInfo::~QGstreamerFormatsInfo()
{
- return m_decodableVideoCodecs;
}
-QList<QMediaFormat::FileFormat> QGstreamerFormatsInfo::encodableMediaContainers() const
+QGstCaps QGstreamerFormatsInfo::formatCaps(const QMediaFormat &f) const
{
- return m_encodableMediaContainers;
+ auto format = f.format();
+ Q_ASSERT(format != QMediaFormat::UnspecifiedFormat);
+
+ const char *capsForFormat[QMediaFormat::LastFileFormat + 1] = {
+ "video/x-ms-asf", // ASF
+ "video/x-msvideo", // AVI
+ "video/x-matroska", // Matroska
+ "video/quicktime, variant=(string)iso", // MPEG4
+ "video/ogg", // Ogg
+ "video/quicktime", // QuickTime
+ "video/webm", // WebM
+ "audio/mpeg, mpegversion=(int)4", // AAC
+ "audio/x-flac", // FLAC
+ "audio/mpeg, mpegversion=(int)1, layer=(int)3", // MP3
+ "audio/mpeg, mpegversion=(int)4", // Mpeg4Audio
+ "audio/x-alac", // ALAC
+ "audio/x-wav" // Wave
+
+ };
+ return gst_caps_from_string(capsForFormat[format]);
}
-QList<QMediaFormat::AudioCodec> QGstreamerFormatsInfo::encodableAudioCodecs() const
+QGstCaps QGstreamerFormatsInfo::audioCaps(const QMediaFormat &f) const
{
- return m_encodableAudioCodecs;
+ auto codec = f.audioCodec();
+ if (codec == QMediaFormat::AudioCodec::Unspecified)
+ return nullptr;
+
+ const char *capsForCodec[(int)QMediaFormat::AudioCodec::LastAudioCodec + 1] = {
+ "audio/mpeg, mpegversion=(int)1, layer=(int)3", // MP3
+ "audio/mpeg, mpegversion=(int)4", // AAC
+ "audio/x-ac3", // AC3
+ "audio/x-eac3", // EAC3
+ "audio/x-flac", // FLAC
+ "audio/x-true-hd", // DolbyTrueHD
+ "audio/x-opus", // Opus
+ "audio/x-vorbis", // Vorbis
+ "audio/x-alac", // ALAC
+ "audio/x-wav", // WAVE
+ };
+ return gst_caps_from_string(capsForCodec[(int)codec]);
}
-QList<QMediaFormat::VideoCodec> QGstreamerFormatsInfo::encodableVideoCodecs() const
+QGstCaps QGstreamerFormatsInfo::videoCaps(const QMediaFormat &f) const
{
- return m_encodableVideoCodecs;
+ auto codec = f.videoCodec();
+ if (codec == QMediaFormat::VideoCodec::Unspecified)
+ return nullptr;
+
+ const char *capsForCodec[(int)QMediaFormat::VideoCodec::LastVideoCodec + 1] = {
+ "video/mpeg, mpegversion=(int)1", // MPEG1,
+ "video/mpeg, mpegversion=(int)2", // MPEG2,
+ "video/mpeg, mpegversion=(int)4", // MPEG4,
+ "video/x-h264", // H264,
+ "video/x-h265", // H265,
+ "video/x-vp8", // VP8,
+ "video/x-vp9", // VP9,
+ "video/x-av1", // AV1,
+ "video/x-theora", // Theora,
+ "video/x-jpeg", // MotionJPEG,
+ };
+ return gst_caps_from_string(capsForCodec[(int)codec]);
}
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/gstreamer/qgstreamerformatsinfo_p.h b/src/multimedia/platform/gstreamer/qgstreamerformatsinfo_p.h
index e81319532..cb9d4d880 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerformatsinfo_p.h
+++ b/src/multimedia/platform/gstreamer/qgstreamerformatsinfo_p.h
@@ -54,6 +54,7 @@
#include <private/qmediaplatformformatinfo_p.h>
#include <qhash.h>
#include <qlist.h>
+#include <private/qgstutils_p.h>
QT_BEGIN_NAMESPACE
@@ -63,30 +64,14 @@ public:
QGstreamerFormatsInfo();
~QGstreamerFormatsInfo();
- QList<QMediaFormat::FileFormat> decodableMediaContainers() const override;
- QList<QMediaFormat::AudioCodec> decodableAudioCodecs() const override;
- QList<QMediaFormat::VideoCodec> decodableVideoCodecs() const override;
+ QGstCaps formatCaps(const QMediaFormat &f) const;
+ QGstCaps audioCaps(const QMediaFormat &f) const;
+ QGstCaps videoCaps(const QMediaFormat &f) const;
+ // ###
+// QGstCaps audioEncoderCaps(const QMediaEncoderSettings &f) const;
+// QGstCaps videoEncoderCaps(const QMediaEncoderSettings &f) const;
- QList<QMediaFormat::FileFormat> encodableMediaContainers() const override;
- QList<QMediaFormat::AudioCodec> encodableAudioCodecs() const override;
- QList<QMediaFormat::VideoCodec> encodableVideoCodecs() const override;
-
- const char *nativeFormat(QMediaFormat::FileFormat f) const { return formatToCaps.value(f); }
- const char *nativeFormat(QMediaFormat::AudioCodec c) const { return audioToCaps.value(c); }
- const char *nativeFormat(QMediaFormat::VideoCodec c) const { return videoToCaps.value(c); }
-
-private:
- QList<QMediaFormat::FileFormat> m_decodableMediaContainers;
- QList<QMediaFormat::AudioCodec> m_decodableAudioCodecs;
- QList<QMediaFormat::VideoCodec> m_decodableVideoCodecs;
-
- QList<QMediaFormat::FileFormat> m_encodableMediaContainers;
- QList<QMediaFormat::AudioCodec> m_encodableAudioCodecs;
- QList<QMediaFormat::VideoCodec> m_encodableVideoCodecs;
-
- QHash<QMediaFormat::FileFormat, const char *> formatToCaps;
- QHash<QMediaFormat::AudioCodec, const char *> audioToCaps;
- QHash<QMediaFormat::VideoCodec, const char *> videoToCaps;
+ QList<CodecMap> getMuxerList(bool demuxer, QList<QMediaFormat::AudioCodec> audioCodecs, QList<QMediaFormat::VideoCodec> videoCodecs);
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/qmediaplatformformatinfo.cpp b/src/multimedia/platform/qmediaplatformformatinfo.cpp
index e157a2455..20a5d580c 100644
--- a/src/multimedia/platform/qmediaplatformformatinfo.cpp
+++ b/src/multimedia/platform/qmediaplatformformatinfo.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qmediaplatformformatinfo_p.h"
+#include <qset.h>
QT_BEGIN_NAMESPACE
@@ -45,4 +46,72 @@ QMediaPlatformFormatInfo::QMediaPlatformFormatInfo() = default;
QMediaPlatformFormatInfo::~QMediaPlatformFormatInfo() = default;
+QList<QMediaFormat::FileFormat> QMediaPlatformFormatInfo::supportedFileFormats(const QMediaFormat &constraints, QMediaFormat::ConversionMode m) const
+{
+ QSet<QMediaFormat::FileFormat> formats;
+
+ const auto &codecMap = (m == QMediaFormat::Encode) ? encoders : decoders;
+ for (const auto &m : codecMap) {
+ if (constraints.mode() == QMediaFormat::AudioAndVideo && m.video.isEmpty())
+ continue;
+ if (constraints.audioCodec() != QMediaFormat::AudioCodec::Unspecified && !m.audio.contains(constraints.audioCodec()))
+ continue;
+ if (constraints.videoCodec() != QMediaFormat::VideoCodec::Unspecified && !m.video.contains(constraints.videoCodec()))
+ continue;
+ formats.insert(m.format);
+ }
+ return formats.values();
+}
+
+QList<QMediaFormat::AudioCodec> QMediaPlatformFormatInfo::supportedAudioCodecs(const QMediaFormat &constraints, QMediaFormat::ConversionMode m) const
+{
+ QSet<QMediaFormat::AudioCodec> codecs;
+
+ const auto &codecMap = (m == QMediaFormat::Encode) ? encoders : decoders;
+ for (const auto &m : codecMap) {
+ if (constraints.format() != QMediaFormat::UnspecifiedFormat && m.format != constraints.format())
+ continue;
+ if (constraints.videoCodec() != QMediaFormat::VideoCodec::Unspecified && !m.video.contains(constraints.videoCodec()))
+ continue;
+ for (const auto &c : m.audio)
+ codecs.insert(c);
+ }
+ return codecs.values();
+}
+
+QList<QMediaFormat::VideoCodec> QMediaPlatformFormatInfo::supportedVideoCodecs(const QMediaFormat &constraints, QMediaFormat::ConversionMode m) const
+{
+ if (constraints.mode() == QMediaFormat::AudioOnly)
+ return {};
+
+ QSet<QMediaFormat::VideoCodec> codecs;
+
+ const auto &codecMap = (m == QMediaFormat::Encode) ? encoders : decoders;
+ for (const auto &m : codecMap) {
+ if (constraints.format() != QMediaFormat::UnspecifiedFormat && m.format != constraints.format())
+ continue;
+ if (constraints.audioCodec() != QMediaFormat::AudioCodec::Unspecified && !m.audio.contains(constraints.audioCodec()))
+ continue;
+ for (const auto &c : m.video)
+ codecs.insert(c);
+ }
+ return codecs.values();
+}
+
+bool QMediaPlatformFormatInfo::isSupported(const QMediaFormat &format, QMediaFormat::ConversionMode m) const
+{
+ const auto &codecMap = (m == QMediaFormat::Encode) ? encoders : decoders;
+
+ for (const auto &m : codecMap) {
+ if (m.format != format.format())
+ continue;
+ if (!m.audio.contains(format.audioCodec()))
+ continue;
+ if (format.mode() == QMediaFormat::AudioAndVideo && !m.video.contains(format.videoCodec()))
+ continue;
+ return true;
+ }
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/qmediaplatformformatinfo_p.h b/src/multimedia/platform/qmediaplatformformatinfo_p.h
index 0a3d06cb3..1cba1b086 100644
--- a/src/multimedia/platform/qmediaplatformformatinfo_p.h
+++ b/src/multimedia/platform/qmediaplatformformatinfo_p.h
@@ -62,13 +62,19 @@ public:
QMediaPlatformFormatInfo();
virtual ~QMediaPlatformFormatInfo();
- virtual QList<QMediaFormat::FileFormat> decodableMediaContainers() const = 0;
- virtual QList<QMediaFormat::AudioCodec> decodableAudioCodecs() const = 0;
- virtual QList<QMediaFormat::VideoCodec> decodableVideoCodecs() const = 0;
+ QList<QMediaFormat::FileFormat> supportedFileFormats(const QMediaFormat &constraints, QMediaFormat::ConversionMode m) const;
+ QList<QMediaFormat::AudioCodec> supportedAudioCodecs(const QMediaFormat &constraints, QMediaFormat::ConversionMode m) const;
+ QList<QMediaFormat::VideoCodec> supportedVideoCodecs(const QMediaFormat &constraints, QMediaFormat::ConversionMode m) const;
- virtual QList<QMediaFormat::FileFormat> encodableMediaContainers() const = 0;
- virtual QList<QMediaFormat::AudioCodec> encodableAudioCodecs() const = 0;
- virtual QList<QMediaFormat::VideoCodec> encodableVideoCodecs() const = 0;
+ bool isSupported(const QMediaFormat &format, QMediaFormat::ConversionMode m) const;
+
+ struct CodecMap {
+ QMediaFormat::FileFormat format;
+ QList<QMediaFormat::AudioCodec> audio;
+ QList<QMediaFormat::VideoCodec> video;
+ };
+ QList<CodecMap> encoders;
+ QList<CodecMap> decoders;
};
QT_END_NAMESPACE