6#include <common/qglist_helper_p.h>
8#include <QtCore/qset.h>
14QMediaFormat::AudioCodec QGstreamerFormatInfo::audioCodecForCaps(QGstStructureView structure)
16 using namespace std::string_view_literals;
17 const char *name = structure.name().data();
19 if (!name || (strncmp(name,
"audio/", 6) != 0))
20 return QMediaFormat::AudioCodec::Unspecified;
22 if (name ==
"mpeg"sv) {
23 auto version = structure[
"mpegversion"].toInt();
25 auto layer = structure[
"layer"];
27 return QMediaFormat::AudioCodec::MP3;
30 return QMediaFormat::AudioCodec::AAC;
31 return QMediaFormat::AudioCodec::Unspecified;
33 if (name ==
"x-ac3"sv)
34 return QMediaFormat::AudioCodec::AC3;
36 if (name ==
"x-eac3"sv)
37 return QMediaFormat::AudioCodec::EAC3;
39 if (name ==
"x-flac"sv)
40 return QMediaFormat::AudioCodec::FLAC;
42 if (name ==
"x-alac"sv)
43 return QMediaFormat::AudioCodec::ALAC;
45 if (name ==
"x-true-hd"sv)
46 return QMediaFormat::AudioCodec::DolbyTrueHD;
48 if (name ==
"x-vorbis"sv)
49 return QMediaFormat::AudioCodec::Vorbis;
51 if (name ==
"x-opus"sv)
52 return QMediaFormat::AudioCodec::Opus;
54 if (name ==
"x-wav"sv)
55 return QMediaFormat::AudioCodec::Wave;
57 if (name ==
"x-wma"sv)
58 return QMediaFormat::AudioCodec::WMA;
60 return QMediaFormat::AudioCodec::Unspecified;
65 using namespace std::string_view_literals;
66 const char *name = structure.name().data();
68 if (!name || (strncmp(name,
"video/", 6) != 0))
69 return QMediaFormat::VideoCodec::Unspecified;
72 if (name ==
"mpeg"sv) {
73 auto version = structure
["mpegversion"].toInt();
75 return QMediaFormat::VideoCodec::MPEG1;
77 return QMediaFormat::VideoCodec::MPEG2;
79 return QMediaFormat::VideoCodec::MPEG4;
80 return QMediaFormat::VideoCodec::Unspecified;
82 if (name ==
"x-h264"sv)
83 return QMediaFormat::VideoCodec::H264;
85 if (name ==
"x-h265"sv)
86 return QMediaFormat::VideoCodec::H265;
88 if (name ==
"x-vp8"sv)
89 return QMediaFormat::VideoCodec::VP8;
91 if (name ==
"x-vp9"sv)
92 return QMediaFormat::VideoCodec::VP9;
94 if (name ==
"x-av1"sv)
95 return QMediaFormat::VideoCodec::AV1;
97 if (name ==
"x-theora"sv)
98 return QMediaFormat::VideoCodec::Theora;
100 if (name ==
"x-jpeg"sv)
101 return QMediaFormat::VideoCodec::MotionJPEG;
103 if (name ==
"x-wmv"sv)
104 return QMediaFormat::VideoCodec::WMV;
106 return QMediaFormat::VideoCodec::Unspecified;
111 using namespace std::string_view_literals;
112 const char *name = structure.name().data();
114 if (name ==
"video/x-ms-asf"sv)
115 return QMediaFormat::FileFormat::WMV;
117 if (name ==
"video/x-msvideo"sv)
118 return QMediaFormat::FileFormat::AVI;
120 if (name ==
"video/x-matroska"sv)
121 return QMediaFormat::FileFormat::Matroska;
123 if (name ==
"video/quicktime"sv) {
126 return QMediaFormat::FileFormat::QuickTime;
127 if (variant ==
"iso"sv)
128 return QMediaFormat::FileFormat::MPEG4;
130 if (name ==
"video/ogg"sv)
131 return QMediaFormat::FileFormat::Ogg;
133 if (name ==
"video/webm"sv)
134 return QMediaFormat::FileFormat::WebM;
136 if (name ==
"audio/x-m4a"sv)
137 return QMediaFormat::FileFormat::Mpeg4Audio;
139 if (name ==
"audio/x-wav"sv)
140 return QMediaFormat::FileFormat::Wave;
142 if (name ==
"audio/mpeg"sv) {
143 auto mpegversion = structure
["mpegversion"].toInt();
144 if (mpegversion == 1) {
145 auto layer = structure
["layer"];
147 return QMediaFormat::FileFormat::MP3;
151 if (name ==
"audio/aac"sv)
152 return QMediaFormat::FileFormat::AAC;
154 if (name ==
"audio/x-ms-wma"sv)
155 return QMediaFormat::FileFormat::WMA;
157 if (name ==
"audio/x-flac"sv)
158 return QMediaFormat::FileFormat::FLAC;
160 return QMediaFormat::UnspecifiedFormat;
166 using namespace std::string_view_literals;
167 const char *name = structure.name().data();
169 if (name ==
"image/jpeg"sv)
170 return QImageCapture::JPEG;
172 if (name ==
"image/png"sv)
173 return QImageCapture::PNG;
175 if (name ==
"image/webp"sv)
176 return QImageCapture::WebP;
178 if (name ==
"image/tiff"sv)
179 return QImageCapture::Tiff;
181 return QImageCapture::UnspecifiedFormat;
184static std::pair<QList<QMediaFormat::AudioCodec>, QList<QMediaFormat::VideoCodec>>
185getCodecsList(
bool decode)
187 QList<QMediaFormat::AudioCodec> audio;
188 QList<QMediaFormat::VideoCodec> video;
190 GstPadDirection padDirection = decode ? GST_PAD_SINK : GST_PAD_SRC;
192 GList *elementList = gst_element_factory_list_get_elements(decode ? GST_ELEMENT_FACTORY_TYPE_DECODER : GST_ELEMENT_FACTORY_TYPE_ENCODER,
195 for (GstElementFactory *factory :
196 QGstUtils::GListRangeAdaptor<GstElementFactory *>(elementList)) {
197 for (GstStaticPadTemplate *padTemplate :
198 QGstUtils::GListConstRangeAdaptor<GstStaticPadTemplate *>(
199 gst_element_factory_get_static_pad_templates(factory))) {
200 if (padTemplate->direction == padDirection) {
201 auto caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
203 for (
int i = 0; i < caps.size(); i++) {
204 QGstStructureView structure = caps.at(i);
205 auto a = QGstreamerFormatInfo::audioCodecForCaps(structure);
206 if (a != QMediaFormat::AudioCodec::Unspecified && !audio.contains(a))
208 auto v = QGstreamerFormatInfo::videoCodecForCaps(structure);
209 if (v != QMediaFormat::VideoCodec::Unspecified && !video.contains(v))
215 gst_plugin_feature_list_free(elementList);
216 return {audio, video};
219QList<QGstreamerFormatInfo::CodecMap>
221 QList<QMediaFormat::AudioCodec> supportedAudioCodecs,
222 QList<QMediaFormat::VideoCodec> supportedVideoCodecs)
224 QList<QGstreamerFormatInfo::CodecMap> maps;
226 GstPadDirection dataPadDirection =
227 (conversionMode == QMediaFormat::Decode) ? GST_PAD_SINK : GST_PAD_SRC;
229 auto encodableFactoryTypes =
230 (GST_ELEMENT_FACTORY_TYPE_MUXER | GST_ELEMENT_FACTORY_TYPE_PAYLOADER
231 | GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR | GST_ELEMENT_FACTORY_TYPE_ENCODER);
232 GList *elementList = gst_element_factory_list_get_elements(
233 (conversionMode == QMediaFormat::Decode) ? GST_ELEMENT_FACTORY_TYPE_DECODABLE
234 : encodableFactoryTypes,
237 for (GstElementFactory *factory :
238 QGstUtils::GListRangeAdaptor<GstElementFactory *>(elementList)) {
239 QList<QMediaFormat::FileFormat> fileFormats;
241 for (GstStaticPadTemplate *padTemplate :
242 QGstUtils::GListConstRangeAdaptor<GstStaticPadTemplate *>(
243 gst_element_factory_get_static_pad_templates(factory))) {
246 if (padTemplate->direction == dataPadDirection
247 || (gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_PARSER)
248 && padTemplate->direction == GST_PAD_SRC)) {
249 auto caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
251 for (
int i = 0; i < caps.size(); i++) {
252 QGstStructureView structure = caps.at(i);
253 auto fmt = fileFormatForCaps(structure);
254 if (fmt != QMediaFormat::UnspecifiedFormat)
255 fileFormats.append(fmt);
260 if (fileFormats.isEmpty())
263 QList<QMediaFormat::AudioCodec> audioCodecs;
264 QList<QMediaFormat::VideoCodec> videoCodecs;
266 for (GstStaticPadTemplate *padTemplate :
267 QGstUtils::GListConstRangeAdaptor<GstStaticPadTemplate *>(
268 gst_element_factory_get_static_pad_templates(factory))) {
271 if (padTemplate->direction != dataPadDirection) {
272 auto caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
274 bool acceptsRawAudio =
false;
275 for (
int i = 0; i < caps.size(); i++) {
276 QGstStructureView structure = caps.at(i);
277 if (structure.name() ==
"audio/x-raw")
278 acceptsRawAudio =
true;
279 auto audio = audioCodecForCaps(structure);
280 if (audio != QMediaFormat::AudioCodec::Unspecified && supportedAudioCodecs.contains(audio))
281 audioCodecs.append(audio);
282 auto video = videoCodecForCaps(structure);
283 if (video != QMediaFormat::VideoCodec::Unspecified && supportedVideoCodecs.contains(video))
284 videoCodecs.append(video);
286 if (acceptsRawAudio && fileFormats.size() == 1) {
287 switch (fileFormats.at(0)) {
288 case QMediaFormat::Mpeg4Audio:
291 case QMediaFormat::MP3:
292 audioCodecs.append(QMediaFormat::AudioCodec::MP3);
294 case QMediaFormat::FLAC:
295 audioCodecs.append(QMediaFormat::AudioCodec::FLAC);
297 case QMediaFormat::Wave:
298 audioCodecs.append(QMediaFormat::AudioCodec::Wave);
304 if (!audioCodecs.isEmpty() || !videoCodecs.isEmpty()) {
305 for (
auto f : std::as_const(fileFormats)) {
306 maps.append({f, audioCodecs, videoCodecs});
307 if (f == QMediaFormat::MPEG4 && !fileFormats.contains(QMediaFormat::Mpeg4Audio)) {
308 maps.append({QMediaFormat::Mpeg4Audio, audioCodecs, {}});
309 if (audioCodecs.contains(QMediaFormat::AudioCodec::AAC))
310 maps.append({QMediaFormat::AAC, { QMediaFormat::AudioCodec::AAC }, {}});
311 }
else if (f == QMediaFormat::WMV && !fileFormats.contains(QMediaFormat::WMA)) {
312 maps.append({QMediaFormat::WMA, audioCodecs, {}});
317 gst_plugin_feature_list_free(elementList);
323 QSet<QImageCapture::FileFormat> formats;
325 GList *elementList = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ENCODER,
328 for (GstElementFactory *factory :
329 QGstUtils::GListRangeAdaptor<GstElementFactory *>(elementList)) {
331 for (GstStaticPadTemplate *padTemplate :
332 QGstUtils::GListConstRangeAdaptor<GstStaticPadTemplate *>(
333 gst_element_factory_get_static_pad_templates(factory))) {
334 if (padTemplate->direction == GST_PAD_SRC) {
335 QGstCaps caps = QGstCaps(gst_static_caps_get(&padTemplate->static_caps), QGstCaps::HasRef);
337 for (
int i = 0; i < caps.size(); i++) {
338 QGstStructureView structure = caps.at(i);
339 auto f = QGstreamerFormatInfo::imageFormatForCaps(structure);
340 if (f != QImageCapture::UnspecifiedFormat) {
348 gst_plugin_feature_list_free(elementList);
349 return formats.values();
353static void dumpAudioCodecs(
const QList<QMediaFormat::AudioCodec> &codecList)
355 qDebug() <<
"Audio codecs:";
356 for (
const auto &c : codecList)
357 qDebug() <<
" " << QMediaFormat::audioCodecName(c);
360static void dumpVideoCodecs(
const QList<QMediaFormat::VideoCodec> &codecList)
362 qDebug() <<
"Video codecs:";
363 for (
const auto &c : codecList)
364 qDebug() <<
" " << QMediaFormat::videoCodecName(c);
367static void dumpMuxers(
const QList<QPlatformMediaFormatInfo::CodecMap> &muxerList)
369 for (
const auto &m : muxerList) {
370 qDebug() <<
" " << QMediaFormat::fileFormatName(m.format);
371 qDebug() <<
" Audio";
372 for (
const auto &a : m.audio)
373 qDebug() <<
" " << QMediaFormat::audioCodecName(a);
374 qDebug() <<
" Video";
375 for (
const auto &v : m.video)
376 qDebug() <<
" " << QMediaFormat::videoCodecName(v);
384 auto codecs = getCodecsList(
true);
385 decoders = getCodecMaps(QMediaFormat::Decode, codecs.first, codecs.second);
387 codecs = getCodecsList(
false);
388 encoders = getCodecMaps(QMediaFormat::Encode, codecs.first, codecs.second);
393 imageFormats = getImageFormatList();
400 auto format = f.fileFormat();
401 Q_ASSERT(format != QMediaFormat::UnspecifiedFormat);
403 const char *capsForFormat[QMediaFormat::LastFileFormat + 1] = {
407 "video/quicktime, variant=(string)iso",
411 "video/quicktime, variant=(string)iso",
412 "video/quicktime, variant=(string)iso",
414 "audio/mpeg, mpegversion=(int)1, layer=(int)3",
418 return QGstCaps(gst_caps_from_string(capsForFormat[format]), QGstCaps::HasRef);
423 auto codec = f.audioCodec();
424 if (codec == QMediaFormat::AudioCodec::Unspecified)
427 const char *capsForCodec[(
int)QMediaFormat::AudioCodec::LastAudioCodec + 1] = {
428 "audio/mpeg, mpegversion=(int)1, layer=(int)3",
429 "audio/mpeg, mpegversion=(int)4",
440 return QGstCaps(gst_caps_from_string(capsForCodec[(
int)codec]), QGstCaps::HasRef);
445 auto codec = f.videoCodec();
446 if (codec == QMediaFormat::VideoCodec::Unspecified)
449 const char *capsForCodec[(
int)QMediaFormat::VideoCodec::LastVideoCodec + 1] = {
450 "video/mpeg, mpegversion=(int)1",
451 "video/mpeg, mpegversion=(int)2",
452 "video/mpeg, mpegversion=(int)4",
462 return QGstCaps(gst_caps_from_string(capsForCodec[(
int)codec]), QGstCaps::HasRef);
const char * toString() const
QGValue operator[](const char *fieldname) const