summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/multimedia/audiorecorder/audiorecorder.cpp4
-rw-r--r--examples/multimediawidgets/camera/camera.cpp6
-rw-r--r--examples/multimediawidgets/camera/videosettings.cpp12
-rw-r--r--src/multimedia/CMakeLists.txt1
-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
-rw-r--r--src/multimedia/qmediaformat.cpp354
-rw-r--r--src/multimedia/qmediaformat.h47
-rw-r--r--src/multimedia/recording/qmediaencodersettings.cpp144
-rw-r--r--src/multimedia/recording/qmediaencodersettings.h7
25 files changed, 700 insertions, 1071 deletions
diff --git a/examples/multimedia/audiorecorder/audiorecorder.cpp b/examples/multimedia/audiorecorder/audiorecorder.cpp
index 3a73dd7f0..93913a23b 100644
--- a/examples/multimedia/audiorecorder/audiorecorder.cpp
+++ b/examples/multimedia/audiorecorder/audiorecorder.cpp
@@ -87,12 +87,12 @@ AudioRecorder::AudioRecorder()
//audio codecs
ui->audioCodecBox->addItem(tr("Default"), QVariant(QString()));
- for (auto &codec : QMediaEncoderInfo::supportedAudioCodecs())
+ for (auto &codec : QMediaFormat().supportedAudioCodecs(QMediaFormat::Encode))
ui->audioCodecBox->addItem(QMediaFormat::audioCodecDescription(codec), QVariant::fromValue(codec));
//containers
ui->containerBox->addItem(tr("Default"), QVariant(QString()));
- for (auto &container : QMediaEncoderInfo::supportedFileFormats()) {
+ for (auto &container : QMediaFormat().supportedFileFormats(QMediaFormat::Encode)) {
if (container < QMediaFormat::AAC) // ### Somewhat hacky, skip video formats
continue;
ui->containerBox->addItem(QMediaFormat::fileFormatDescription(container), QVariant::fromValue(container));
diff --git a/examples/multimediawidgets/camera/camera.cpp b/examples/multimediawidgets/camera/camera.cpp
index f573970d2..f5d507d46 100644
--- a/examples/multimediawidgets/camera/camera.cpp
+++ b/examples/multimediawidgets/camera/camera.cpp
@@ -85,17 +85,17 @@ Camera::Camera() : ui(new Ui::Camera)
setCamera(QMediaDeviceManager::defaultVideoInput());
qDebug() << "Supported Containers:";
- auto containers = QMediaEncoderInfo::supportedFileFormats();
+ auto containers = QMediaFormat().supportedFileFormats(QMediaFormat::Encode);
for (const auto c : containers)
qDebug() << " " << QMediaFormat::fileFormatName(c);
qDebug() << "Supported Audio Codecs:";
- auto audio = QMediaEncoderInfo::supportedAudioCodecs();
+ auto audio = QMediaFormat().supportedAudioCodecs(QMediaFormat::Encode);
for (const auto c : audio)
qDebug() << " " << QMediaFormat::audioCodecName(c);
qDebug() << "Supported Video Codecs:";
- auto video = QMediaEncoderInfo::supportedVideoCodecs();
+ auto video = QMediaFormat().supportedVideoCodecs(QMediaFormat::Encode);
for (const auto c : video)
qDebug() << " " << QMediaFormat::videoCodecName(c);
}
diff --git a/examples/multimediawidgets/camera/videosettings.cpp b/examples/multimediawidgets/camera/videosettings.cpp
index b41462489..127c21388 100644
--- a/examples/multimediawidgets/camera/videosettings.cpp
+++ b/examples/multimediawidgets/camera/videosettings.cpp
@@ -68,8 +68,8 @@ VideoSettings::VideoSettings(QMediaRecorder *mediaRecorder, QWidget *parent)
ui->setupUi(this);
//audio codecs
- ui->audioCodecBox->addItem(tr("Default audio codec"), QVariant(QString()));
- const auto supportedAudioCodecs = QMediaEncoderInfo::supportedAudioCodecs();
+ ui->audioCodecBox->addItem(tr("Default audio codec"), QVariant::fromValue(QMediaFormat::AudioCodec::Unspecified));
+ const auto supportedAudioCodecs = QMediaFormat().supportedAudioCodecs(QMediaFormat::Encode);
for (const auto &codec : supportedAudioCodecs) {
QString description = QMediaFormat::audioCodecDescription(codec);
ui->audioCodecBox->addItem(QMediaFormat::audioCodecName(codec) + ": " + description, QVariant::fromValue(codec));
@@ -80,8 +80,8 @@ VideoSettings::VideoSettings(QMediaRecorder *mediaRecorder, QWidget *parent)
ui->audioSampleRateBox->setRange(sampleRates.minimum, sampleRates.maximum);
//video codecs
- ui->videoCodecBox->addItem(tr("Default video codec"), QVariant(QString()));
- const auto supportedVideoCodecs = QMediaEncoderInfo::supportedVideoCodecs();
+ ui->videoCodecBox->addItem(tr("Default video codec"), QVariant::fromValue(QMediaFormat::VideoCodec::Unspecified));
+ const auto supportedVideoCodecs = QMediaFormat().supportedVideoCodecs(QMediaFormat::Encode);
for (const auto &codec : supportedVideoCodecs) {
QString description = QMediaFormat::videoCodecDescription(codec);
ui->videoCodecBox->addItem(QMediaFormat::videoCodecName(codec) + ": " + description, QVariant::fromValue(codec));
@@ -103,8 +103,8 @@ VideoSettings::VideoSettings(QMediaRecorder *mediaRecorder, QWidget *parent)
// }
//containers
- ui->containerFormatBox->addItem(tr("Default container"), QVariant(QString()));
- const auto formats = QMediaEncoderInfo::supportedFileFormats();
+ ui->containerFormatBox->addItem(tr("Default container"), QVariant::fromValue(QMediaFormat::UnspecifiedFormat));
+ const auto formats = QMediaFormat().supportedFileFormats(QMediaFormat::Encode);
for (auto format : formats) {
ui->containerFormatBox->addItem(QMediaFormat::fileFormatName(format) + ": " + QMediaFormat::fileFormatDescription(format),
QVariant::fromValue(format));
diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt
index 6ed2d10b9..2b3fbbb34 100644
--- a/src/multimedia/CMakeLists.txt
+++ b/src/multimedia/CMakeLists.txt
@@ -200,7 +200,6 @@ qt_internal_extend_target(Multimedia CONDITION QT_FEATURE_gstreamer
platform/gstreamer/audio/qaudiooutput_gstreamer.cpp platform/gstreamer/audio/qaudiooutput_gstreamer_p.h
platform/gstreamer/audio/qgstreameraudiodecodercontrol.cpp platform/gstreamer/audio/qgstreameraudiodecodercontrol_p.h
platform/gstreamer/common/qgstappsrc.cpp platform/gstreamer/common/qgstappsrc_p.h
- platform/gstreamer/common/qgstcodecsinfo.cpp platform/gstreamer/common/qgstcodecsinfo_p.h
platform/gstreamer/common/qgstreamerbufferprobe.cpp platform/gstreamer/common/qgstreamerbufferprobe_p.h
platform/gstreamer/common/qgstreamerbushelper.cpp platform/gstreamer/common/qgstreamerbushelper_p.h
platform/gstreamer/common/qgstreamermessage.cpp platform/gstreamer/common/qgstreamermessage_p.h
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
diff --git a/src/multimedia/qmediaformat.cpp b/src/multimedia/qmediaformat.cpp
index 80fe154b0..6ae2314be 100644
--- a/src/multimedia/qmediaformat.cpp
+++ b/src/multimedia/qmediaformat.cpp
@@ -46,110 +46,6 @@ QT_BEGIN_NAMESPACE
namespace {
-// info from https://en.wikipedia.org/wiki/Comparison_of_video_container_formats
-constexpr bool audioSupportMatrix[QMediaFormat::FileFormat::LastFileFormat + 1][(int)QMediaFormat::AudioCodec::LastAudioCodec + 1] =
-{
- // MP3, AAC, AC3, EAC3, FLAC, DTHD, Opus,Vorbis, Wave, ALAC
- // Container formats (Audio and Video)
- { true, true, true, true, true, false, true, false, false, true }, // ASF
- { true, true, true, false, true, false, true, false, false, true }, // AVI,
- { true, true, true, true, true, true, true, true, false, true }, // Matroska,
- { true, true, true, true, true, true, true, false, false, true }, // MPEG4,
- { false, false, false, false, true, false, true, true, false, false }, // Ogg,
- { true, true, true, true, false, false, false, false, false, true }, // QuickTime,
- { false, false, false, false, true, false, true, true, false, false }, // WebM,
- // Audio Formats
- { false, true, false, false, false, false, false, false, false, false }, // AAC,
- { false, false, false, false, true, false, false, false, false, false }, // FLAC,
- { true, false, false, false, false, false, false, false, false, false }, // Mpeg3,
- { true, true, true, true, true, true, true, false, false, true }, // Mpeg4Audio,
- { false, false, false, false, false, false, false, false, false, true }, // ALAC,
- { false, false, false, false, false, false, false, false, true, false }, // Wave,
-};
-
-inline bool formatSupportsCodec(QMediaFormat::FileFormat format, QMediaFormat::AudioCodec codec)
-{
- return audioSupportMatrix[format][(int)codec];
-}
-
-// info from https://en.wikipedia.org/wiki/Comparison_of_video_container_formats
-constexpr bool videoSupportMatrix[QMediaFormat::FileFormat::LastFileFormat + 1][(int)QMediaFormat::VideoCodec::LastVideoCodec + 1] =
-{
- //MPEG1, MPEG2, MPEG4, H264, H265, VP8, VP9, AV1,Theora, MotionJPEG,
- // Container formats (Audio and Video)
- { true, true, true, true, true, false, false, false, false,false }, // ASF
- { true, true, true, true, true, true, true, false, true, true }, // AVI,
- { true, true, true, true, true, true, true, true, true, false }, // Matroska,
- { true, true, true, true, true, true, true, true, true, true }, // MPEG4,
- { false, true, true, true, true, false, false, false, false, true }, // Ogg,
- { false, false, false, false, false, false, false, false, true, false }, // QuickTime,
- { false, false, false, false, false, true, true, true, false, false }, // WebM,
- // Audio Formats
- { false, false, false, false, false, false, false, false, false, false }, // AAC,
- { false, false, false, false, false, false, false, false, false, false }, // FLAC,
- { false, false, false, false, false, false, false, false, false, false }, // Mpeg3,
- { false, false, false, false, false, false, false, false, false, false }, // Mpeg4Audio,
- { false, false, false, false, false, false, false, false, false, false }, // ALAC,
- { false, false, false, false, false, false, false, false, false, false }, // Wave,
-};
-
-inline bool formatSupportsCodec(QMediaFormat::FileFormat format, QMediaFormat::VideoCodec codec)
-{
- return videoSupportMatrix[format][(int)codec];
-}
-
-
-constexpr QMediaFormat::FileFormat videoFormatPriorityList[] =
-{
- QMediaFormat::MPEG4,
- QMediaFormat::QuickTime,
- QMediaFormat::AVI,
- QMediaFormat::WebM,
- QMediaFormat::ASF,
- QMediaFormat::Matroska,
- QMediaFormat::Ogg,
- QMediaFormat::UnspecifiedFormat
-};
-
-constexpr QMediaFormat::FileFormat audioFormatPriorityList[] =
-{
- QMediaFormat::AAC,
- QMediaFormat::MP3,
- QMediaFormat::Mpeg4Audio,
- QMediaFormat::FLAC,
- QMediaFormat::ALAC,
- QMediaFormat::Wave,
- QMediaFormat::UnspecifiedFormat
-};
-
-constexpr QMediaFormat::AudioCodec audioPriorityList[] =
-{
- QMediaFormat::AudioCodec::AAC,
- QMediaFormat::AudioCodec::MP3,
- QMediaFormat::AudioCodec::AC3,
- QMediaFormat::AudioCodec::Opus,
- QMediaFormat::AudioCodec::EAC3,
- QMediaFormat::AudioCodec::DolbyTrueHD,
- QMediaFormat::AudioCodec::FLAC,
- QMediaFormat::AudioCodec::Vorbis,
- QMediaFormat::AudioCodec::Wave,
- QMediaFormat::AudioCodec::Unspecified
-};
-
-constexpr QMediaFormat::VideoCodec videoPriorityList[] =
-{
- QMediaFormat::VideoCodec::H265,
- QMediaFormat::VideoCodec::VP9,
- QMediaFormat::VideoCodec::H264,
- QMediaFormat::VideoCodec::AV1,
- QMediaFormat::VideoCodec::VP8,
- QMediaFormat::VideoCodec::Theora,
- QMediaFormat::VideoCodec::MPEG4,
- QMediaFormat::VideoCodec::MPEG2,
- QMediaFormat::VideoCodec::MPEG1,
- QMediaFormat::VideoCodec::MotionJPEG,
-};
-
const char *mimeTypeForFormat[QMediaFormat::LastFileFormat + 2] =
{
"",
@@ -169,85 +65,6 @@ const char *mimeTypeForFormat[QMediaFormat::LastFileFormat + 2] =
"audio/wave",
};
-
-}
-
-void QMediaFormatPrivate::resolveForEncoding(QMediaFormat *f, bool audioOnly)
-{
- auto supportedFormats = QMediaEncoderInfo::supportedFileFormats();
- auto supportedAudioCodecs = QMediaEncoderInfo::supportedAudioCodecs();
- auto supportedVideoCodecs = QMediaEncoderInfo::supportedVideoCodecs();
-
- auto bestSupportedFileFormat = [&](QMediaFormat::AudioCodec audio = QMediaFormat::AudioCodec::Unspecified,
- QMediaFormat::VideoCodec video = QMediaFormat::VideoCodec::Unspecified)
- {
- auto *list = audioOnly ? audioFormatPriorityList : videoFormatPriorityList;
- while (*list != QMediaFormat::UnspecifiedFormat) {
- if (supportedFormats.contains(*list)) {
- if ((audio == QMediaFormat::AudioCodec::Unspecified || formatSupportsCodec(f->fmt, audio)) &&
- (video == QMediaFormat::VideoCodec::Unspecified || formatSupportsCodec(f->fmt, video)))
- break;
- }
- ++list;
- }
- return *list;
- };
-
- // reset non supported formats and codecs
- if (!supportedFormats.contains(f->fmt))
- f->fmt = QMediaFormat::UnspecifiedFormat;
- if (!supportedAudioCodecs.contains(f->audio))
- f->audio = QMediaFormat::AudioCodec::Unspecified;
- if (audioOnly || !supportedVideoCodecs.contains(f->video))
- f->video = QMediaFormat::VideoCodec::Unspecified;
-
- // try finding a file format that is supported
- if (f->fmt == QMediaFormat::UnspecifiedFormat)
- f->fmt = bestSupportedFileFormat(f->audio, f->video);
- // try without the audio codec
- if (f->fmt == QMediaFormat::UnspecifiedFormat)
- f->fmt = bestSupportedFileFormat(QMediaFormat::AudioCodec::Unspecified, f->video);
- // try without the video codec
- if (f->fmt == QMediaFormat::UnspecifiedFormat)
- f->fmt = bestSupportedFileFormat(f->audio);
- // give me a format that's supported
- if (f->fmt == QMediaFormat::UnspecifiedFormat)
- f->fmt = bestSupportedFileFormat();
- // still nothing? Give up
- if (f->fmt == QMediaFormat::UnspecifiedFormat)
- return;
-
- // now that we have a format, reset codecs that won't work
- if (f->audio != QMediaFormat::AudioCodec::Unspecified) {
- if (!formatSupportsCodec(f->fmt, f->audio) || !supportedAudioCodecs.contains(f->audio))
- f->audio = QMediaFormat::AudioCodec::Unspecified;
- }
- if (f->video != QMediaFormat::VideoCodec::Unspecified) {
- if (!formatSupportsCodec(f->fmt, f->video) || !supportedVideoCodecs.contains(f->video))
- f->video = QMediaFormat::VideoCodec::Unspecified;
- }
-
- // find a matching audio format
- if (f->audio == QMediaFormat::AudioCodec::Unspecified) {
- auto *list = audioPriorityList;
- while (*list != QMediaFormat::AudioCodec::Unspecified) {
- if (supportedAudioCodecs.contains(*list) && formatSupportsCodec(f->fmt, *list))
- break;
- ++list;
- }
- f->audio = *list;
- }
-
- // find a matching video format
- if (!audioOnly && f->video == QMediaFormat::VideoCodec::Unspecified) {
- auto *list = videoPriorityList;
- while (*list != QMediaFormat::VideoCodec::Unspecified) {
- if (supportedVideoCodecs.contains(*list) && formatSupportsCodec(f->fmt, *list))
- break;
- ++list;
- }
- f->video = *list;
- }
}
/*! \enum QMediaFormat::FileFormat
@@ -274,8 +91,9 @@ void QMediaFormatPrivate::resolveForEncoding(QMediaFormat *f, bool audioOnly)
*/
// these are non inline to make a possible future addition of a d pointer binary compatible
-QMediaFormat::QMediaFormat(FileFormat format)
- : fmt(format)
+QMediaFormat::QMediaFormat(FileFormat format, Mode mode)
+ : fmtMode(mode),
+ fmt(format)
{
Q_UNUSED(d);
}
@@ -305,13 +123,6 @@ QMediaFormat &QMediaFormat::operator=(const QMediaFormat &other) = default;
\sa videoCodec(), QMediaFormat::VideoCodec
*/
-bool QMediaFormat::setVideoCodec(VideoCodec codec)
-{
- if (!videoSupportMatrix[fmt][(int)codec])
- return false;
- video = codec;
- return true;
-}
/*! \fn QMediaFormat::VideoCodec QMediaFormat::videoCodec() const
@@ -326,13 +137,6 @@ bool QMediaFormat::setVideoCodec(VideoCodec codec)
\sa audioCodec(), QMediaFormat::AudioCodec
*/
-bool QMediaFormat::setAudioCodec(QMediaFormat::AudioCodec codec)
-{
- if (!audioSupportMatrix[fmt][(int)codec])
- return false;
- audio = codec;
- return true;
-}
/*! \fn QMediaFormat::AudioCodec QMediaFormat::audioCodec() const
@@ -353,19 +157,7 @@ bool QMediaFormat::setAudioCodec(QMediaFormat::AudioCodec codec)
*/
bool QMediaFormat::canDecode() const
{
- if (!QMediaDecoderInfo::supportedFileFormats().contains(fmt))
- return false;
- if (audio == QMediaFormat::AudioCodec::Unspecified && video == QMediaFormat::VideoCodec::Unspecified)
- return false;
- if (audio != QMediaFormat::AudioCodec::Unspecified) {
- if (!QMediaDecoderInfo::supportedAudioCodecs().contains(audio))
- return false;
- }
- if (video != QMediaFormat::VideoCodec::Unspecified) {
- if (!QMediaDecoderInfo::supportedVideoCodecs().contains(video))
- return false;
- }
- return true;
+ return QMediaPlatformIntegration::instance()->formatInfo()->isSupported(*this, Decode);
}
/*!
@@ -375,43 +167,62 @@ bool QMediaFormat::canDecode() const
*/
bool QMediaFormat::canEncode() const
{
- if (!QMediaEncoderInfo::supportedFileFormats().contains(fmt))
- return false;
- if (audio == QMediaFormat::AudioCodec::Unspecified && video == QMediaFormat::VideoCodec::Unspecified)
- return false;
- if (audio != QMediaFormat::AudioCodec::Unspecified) {
- if (!QMediaEncoderInfo::supportedAudioCodecs().contains(audio))
- return false;
- }
- if (video != QMediaFormat::VideoCodec::Unspecified) {
- if (!QMediaEncoderInfo::supportedVideoCodecs().contains(video))
- return false;
- }
- return true;
+ return QMediaPlatformIntegration::instance()->formatInfo()->isSupported(*this, Encode);
}
/*!
- Returns true if is is an audio-only file format.
+ Returns the mimetype for the file format used in this media format.
+
+ \sa format(), setFormat()
*/
-bool QMediaFormat::isAudioFormat() const
+QMimeType QMediaFormat::mimeType() const
{
- return fmt >= AAC;
+ return QMimeDatabase().mimeTypeForName(QString::fromLatin1(mimeTypeForFormat[fmt + 1]));
}
/*!
- Returns the mimetype for the file format used in this media format.
+ Returns a list of container formats that are supported for \a mode.
- \sa format(), setFormat()
+ The list is constrained by the chosen audio and video codec and will only match file
+ formats that can be created with those codecs.
+
+ To get all supported file formats, run this query on a default constructed QMediaFormat.
*/
-QMimeType QMediaFormat::mimeType() const
+QList<QMediaFormat::FileFormat> QMediaFormat::supportedFileFormats(QMediaFormat::ConversionMode m)
{
- return QMimeDatabase().mimeTypeForName(QString::fromLatin1(mimeTypeForFormat[fmt + 1]));
+ return QMediaPlatformIntegration::instance()->formatInfo()->supportedFileFormats(*this, m);
+}
+
+/*!
+ Returns a list of video codecs that are supported for \a mode.
+
+ The list is constrained by the chosen file format and audio codec and will only return
+ the video codecs that can be used with those settings.
+
+ To get all supported video codecs, run this query on a default constructed QMediaFormat.
+ */
+QList<QMediaFormat::VideoCodec> QMediaFormat::supportedVideoCodecs(QMediaFormat::ConversionMode m)
+{
+ return QMediaPlatformIntegration::instance()->formatInfo()->supportedVideoCodecs(*this, m);
+}
+
+/*!
+ Returns a list of audio codecs that are supported for \a mode.
+
+ The list is constrained by the chosen file format and video codec and will only return
+ the audio codecs that can be used with those settings.
+
+ To get all supported audio codecs, run this query on a default constructed QMediaFormat.
+ */
+QList<QMediaFormat::AudioCodec> QMediaFormat::supportedAudioCodecs(QMediaFormat::ConversionMode m)
+{
+ return QMediaPlatformIntegration::instance()->formatInfo()->supportedAudioCodecs(*this, m);
}
QString QMediaFormat::fileFormatName(QMediaFormat::FileFormat c)
{
constexpr const char *descriptions[QMediaFormat::LastFileFormat + 2] = {
- "Unspecified File Format"
+ "Unspecified",
"ASF",
"AVI",
"Matroska",
@@ -524,81 +335,4 @@ QString QMediaFormat::videoCodecDescription(QMediaFormat::VideoCodec c)
return QString::fromUtf8(descriptions[int(c) + 1]);
}
-/*! \class QMediaDecoderInfo
-
- QMediaDecoderInfo describes the media formats supported for decoding
- on the current platform.
-
- Qt Multimedia might be able to decode formats that are not listed
- in the QMediaFormat::FileFormat, QMediaFormat::AudioCodec and QMediaFormat::VideoCodec enums.
-
- \sa QMediaFormat::canDecode()
-*/
-
-/*!
- Returns a list of container formats that are supported for decoding by
- Qt Multimedia.
-
- This does not imply that Qt can successfully decode the media file or
- stream, as the audio or video codec used within the container might not
- be supported.
- */
-QList<QMediaFormat::FileFormat> QMediaDecoderInfo::supportedFileFormats()
-{
- return QMediaPlatformIntegration::instance()->formatInfo()->decodableMediaContainers();
-}
-
-/*!
- Returns a list of video codecs that are supported for decoding by
- Qt Multimedia.
- */
-QList<QMediaFormat::VideoCodec> QMediaDecoderInfo::supportedVideoCodecs()
-{
- return QMediaPlatformIntegration::instance()->formatInfo()->decodableVideoCodecs();
-}
-
-/*!
- Returns a list of audio codecs that are supported for decoding by
- Qt Multimedia.
- */
-QList<QMediaFormat::AudioCodec> QMediaDecoderInfo::supportedAudioCodecs()
-{
- return QMediaPlatformIntegration::instance()->formatInfo()->decodableAudioCodecs();
-}
-
-/*! \class QMediaEncodecInfo
-
- QMediaEncoderInfo describes the media formats supported for
- encoding on the current platform.
-
- \sa QMediaFormat::canEncode()
-*/
-
-/*!
- Returns a list of container formats that are supported for encoding by
- Qt Multimedia.
- */
-QList<QMediaFormat::FileFormat> QMediaEncoderInfo::supportedFileFormats()
-{
- return QMediaPlatformIntegration::instance()->formatInfo()->encodableMediaContainers();
-}
-
-/*!
- Returns a list of video codecs that are supported for encoding by
- Qt Multimedia.
- */
-QList<QMediaFormat::VideoCodec> QMediaEncoderInfo::supportedVideoCodecs()
-{
- return QMediaPlatformIntegration::instance()->formatInfo()->encodableVideoCodecs();
-}
-
-/*!
- Returns a list of audio codecs that are supported for encoding by
- Qt Multimedia.
- */
-QList<QMediaFormat::AudioCodec> QMediaEncoderInfo::supportedAudioCodecs()
-{
- return QMediaPlatformIntegration::instance()->formatInfo()->encodableAudioCodecs();
-}
-
QT_END_NAMESPACE
diff --git a/src/multimedia/qmediaformat.h b/src/multimedia/qmediaformat.h
index a488fd378..6b3684ab6 100644
--- a/src/multimedia/qmediaformat.h
+++ b/src/multimedia/qmediaformat.h
@@ -49,11 +49,7 @@ QT_BEGIN_NAMESPACE
class QMimeType;
class QMediaFormat;
class QMediaEncoderSettings;
-class QMediaFormatPrivate
-{
- friend class QMediaEncoderSettings;
- static void resolveForEncoding(QMediaFormat *fmt, bool audioOnly);
-};
+class QMediaFormatPrivate;
class Q_MULTIMEDIA_EXPORT QMediaFormat
{
@@ -108,7 +104,17 @@ public:
LastVideoCodec = MotionJPEG
};
- QMediaFormat(FileFormat format = UnspecifiedFormat);
+ enum ConversionMode {
+ Encode,
+ Decode
+ };
+
+ enum Mode {
+ AudioOnly,
+ AudioAndVideo
+ };
+
+ QMediaFormat(FileFormat format = UnspecifiedFormat, Mode = AudioAndVideo);
~QMediaFormat();
QMediaFormat(const QMediaFormat &other);
QMediaFormat &operator=(const QMediaFormat &other);
@@ -116,19 +122,24 @@ public:
FileFormat format() const { return fmt; }
void setFormat(FileFormat f) { fmt = f; }
- bool setVideoCodec(VideoCodec codec);
+ void setVideoCodec(VideoCodec codec) { video = codec; }
VideoCodec videoCodec() const { return video; }
- bool setAudioCodec(AudioCodec codec);
+ void setAudioCodec(AudioCodec codec) { audio = codec; }
AudioCodec audioCodec() const { return audio; }
bool canDecode() const;
bool canEncode() const;
- bool isAudioFormat() const;
+ void setMode(Mode m) { fmtMode = m; }
+ Mode mode() const { return fmtMode; }
QMimeType mimeType() const;
+ QList<QMediaFormat::FileFormat> supportedFileFormats(ConversionMode m);
+ QList<QMediaFormat::VideoCodec> supportedVideoCodecs(ConversionMode m);
+ QList<QMediaFormat::AudioCodec> supportedAudioCodecs(ConversionMode m);
+
static QString fileFormatName(QMediaFormat::FileFormat c);
static QString audioCodecName(QMediaFormat::AudioCodec c);
static QString videoCodecName(QMediaFormat::VideoCodec c);
@@ -139,29 +150,13 @@ public:
protected:
friend class QMediaFormatPrivate;
+ Mode fmtMode;
FileFormat fmt;
AudioCodec audio = AudioCodec::Unspecified;
VideoCodec video = VideoCodec::Unspecified;
QMediaFormatPrivate *d = nullptr;
};
-
-class Q_MULTIMEDIA_EXPORT QMediaDecoderInfo
-{
-public:
- static QList<QMediaFormat::FileFormat> supportedFileFormats();
- static QList<QMediaFormat::VideoCodec> supportedVideoCodecs();
- static QList<QMediaFormat::AudioCodec> supportedAudioCodecs();
-};
-
-class Q_MULTIMEDIA_EXPORT QMediaEncoderInfo
-{
-public:
- static QList<QMediaFormat::FileFormat> supportedFileFormats();
- static QList<QMediaFormat::VideoCodec> supportedVideoCodecs();
- static QList<QMediaFormat::AudioCodec> supportedAudioCodecs();
-};
-
QT_END_NAMESPACE
#endif
diff --git a/src/multimedia/recording/qmediaencodersettings.cpp b/src/multimedia/recording/qmediaencodersettings.cpp
index 1c0414b8d..68df20216 100644
--- a/src/multimedia/recording/qmediaencodersettings.cpp
+++ b/src/multimedia/recording/qmediaencodersettings.cpp
@@ -42,6 +42,61 @@
QT_BEGIN_NAMESPACE
+namespace {
+
+
+constexpr QMediaFormat::FileFormat videoFormatPriorityList[] =
+{
+ QMediaFormat::MPEG4,
+ QMediaFormat::QuickTime,
+ QMediaFormat::AVI,
+ QMediaFormat::WebM,
+ QMediaFormat::ASF,
+ QMediaFormat::Matroska,
+ QMediaFormat::Ogg,
+ QMediaFormat::UnspecifiedFormat
+};
+
+constexpr QMediaFormat::FileFormat audioFormatPriorityList[] =
+{
+ QMediaFormat::AAC,
+ QMediaFormat::MP3,
+ QMediaFormat::Mpeg4Audio,
+ QMediaFormat::FLAC,
+ QMediaFormat::ALAC,
+ QMediaFormat::Wave,
+ QMediaFormat::UnspecifiedFormat
+};
+
+constexpr QMediaFormat::AudioCodec audioPriorityList[] =
+{
+ QMediaFormat::AudioCodec::AAC,
+ QMediaFormat::AudioCodec::MP3,
+ QMediaFormat::AudioCodec::AC3,
+ QMediaFormat::AudioCodec::Opus,
+ QMediaFormat::AudioCodec::EAC3,
+ QMediaFormat::AudioCodec::DolbyTrueHD,
+ QMediaFormat::AudioCodec::FLAC,
+ QMediaFormat::AudioCodec::Vorbis,
+ QMediaFormat::AudioCodec::Wave,
+ QMediaFormat::AudioCodec::Unspecified
+};
+
+constexpr QMediaFormat::VideoCodec videoPriorityList[] =
+{
+ QMediaFormat::VideoCodec::H265,
+ QMediaFormat::VideoCodec::VP9,
+ QMediaFormat::VideoCodec::H264,
+ QMediaFormat::VideoCodec::AV1,
+ QMediaFormat::VideoCodec::VP8,
+ QMediaFormat::VideoCodec::Theora,
+ QMediaFormat::VideoCodec::MPEG4,
+ QMediaFormat::VideoCodec::MPEG2,
+ QMediaFormat::VideoCodec::MPEG1,
+ QMediaFormat::VideoCodec::MotionJPEG,
+};
+
+}
/*!
\class QMediaEncoderSettings
@@ -159,9 +214,92 @@ void QMediaEncoderSettings::setQuality(QMultimedia::EncodingQuality quality)
Settings that are not supported by the encoder will be modified to the closest
match that is supported.
*/
-void QMediaEncoderSettings::resolveFormat(QMediaEncoderSettings::ResolveMode mode)
-{
- QMediaFormatPrivate::resolveForEncoding(this, mode == AudioOnly);
+void QMediaEncoderSettings::resolveFormat()
+{
+ if (canEncode())
+ return;
+
+ QMediaFormat nullFormat;
+ auto supportedFormats = nullFormat.supportedFileFormats(QMediaFormat::Encode);
+ auto supportedAudioCodecs = nullFormat.supportedAudioCodecs(QMediaFormat::Encode);
+ auto supportedVideoCodecs = nullFormat.supportedVideoCodecs(QMediaFormat::Encode);
+
+ auto bestSupportedFileFormat = [&](QMediaFormat::AudioCodec audio = QMediaFormat::AudioCodec::Unspecified,
+ QMediaFormat::VideoCodec video = QMediaFormat::VideoCodec::Unspecified)
+ {
+ QMediaFormat f;
+ f.setAudioCodec(audio);
+ f.setVideoCodec(video);
+ auto supportedFormats = f.supportedFileFormats(QMediaFormat::Encode);
+ auto *list = (fmtMode == AudioOnly) ? audioFormatPriorityList : videoFormatPriorityList;
+ while (*list != QMediaFormat::UnspecifiedFormat) {
+ if (supportedFormats.contains(*list))
+ break;
+ ++list;
+ }
+ return *list;
+ };
+
+ // reset non supported formats and codecs
+ if (!supportedFormats.contains(fmt))
+ fmt = QMediaFormat::UnspecifiedFormat;
+ if (!supportedAudioCodecs.contains(audio))
+ audio = QMediaFormat::AudioCodec::Unspecified;
+ if ((fmtMode == AudioOnly) || !supportedVideoCodecs.contains(video))
+ video = QMediaFormat::VideoCodec::Unspecified;
+
+ if (!(fmtMode == AudioOnly)) {
+ // try finding a file format that is supported
+ if (fmt == QMediaFormat::UnspecifiedFormat)
+ fmt = bestSupportedFileFormat(audio, video);
+ // try without the audio codec
+ if (fmt == QMediaFormat::UnspecifiedFormat)
+ fmt = bestSupportedFileFormat(QMediaFormat::AudioCodec::Unspecified, video);
+ }
+ // try without the video codec
+ if (fmt == QMediaFormat::UnspecifiedFormat)
+ fmt = bestSupportedFileFormat(audio);
+ // give me a format that's supported
+ if (fmt == QMediaFormat::UnspecifiedFormat)
+ fmt = bestSupportedFileFormat();
+ // still nothing? Give up
+ if (fmt == QMediaFormat::UnspecifiedFormat)
+ return;
+
+ // find a working video codec
+ if (!(fmtMode == AudioOnly)) {
+ // reset the audio codec, so that we won't throw away the video codec
+ // if it is supported (choosing the specified video codec has higher
+ // priority than the specified audio codec)
+ auto a = audio;
+ audio = QMediaFormat::AudioCodec::Unspecified;
+ auto videoCodecs = this->supportedVideoCodecs(QMediaFormat::Encode);
+ if (!videoCodecs.contains(video)) {
+ // not supported, try to find a replacement
+ auto *list = videoPriorityList;
+ while (*list != QMediaFormat::VideoCodec::Unspecified) {
+ if (videoCodecs.contains(*list))
+ break;
+ ++list;
+ }
+ video = *list;
+ }
+ audio = a;
+ } else {
+ video = QMediaFormat::VideoCodec::Unspecified;
+ }
+
+ // and a working audio codec
+ auto audioCodecs = this->supportedAudioCodecs(QMediaFormat::Encode);
+ if (!audioCodecs.contains(audio)) {
+ auto *list = audioPriorityList;
+ while (*list != QMediaFormat::AudioCodec::Unspecified) {
+ if (audioCodecs.contains(*list))
+ break;
+ ++list;
+ }
+ audio = *list;
+ }
}
/*!
diff --git a/src/multimedia/recording/qmediaencodersettings.h b/src/multimedia/recording/qmediaencodersettings.h
index 673c6f3a4..b0a68af2d 100644
--- a/src/multimedia/recording/qmediaencodersettings.h
+++ b/src/multimedia/recording/qmediaencodersettings.h
@@ -66,12 +66,7 @@ public:
QMultimedia::EncodingQuality quality() const;
void setQuality(QMultimedia::EncodingQuality quality);
- enum ResolveMode {
- AudioOnly,
- AudioAndVideo
- };
-
- void resolveFormat(ResolveMode mode = AudioAndVideo);
+ void resolveFormat();
QSize videoResolution() const;
void setVideoResolution(const QSize &);