Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindowsformatinfo.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <mfapi.h>
7#include <mftransform.h>
8#include <QtCore/private/qcomptr_p.h>
9#include <private/qwindowsmultimediautils_p.h>
10#include <private/qcomtaskresource_p.h>
11
12#include <QtCore/qlist.h>
13#include <QtCore/qset.h>
14#include <QtCore/qhash.h>
15#include <QtGui/qimagewriter.h>
16
18
19namespace {
20
21template<typename T>
22using CheckedCodecs = QHash<std::pair<T, QMediaFormat::ConversionMode>, bool>;
23
24bool isSupportedMFT(const GUID &category, const MFT_REGISTER_TYPE_INFO &type, QMediaFormat::ConversionMode mode)
25{
26 UINT32 count = 0;
27 QComTaskResource<IMFActivate *> activate;
28 HRESULT hr = E_FAIL;
29
30 // MFTEnumEx may crash inside third-party drivers (e.g. D3D12Core.dll,
31 // RTWorkQ.dll) when enumerating hardware codecs. Wrap the call with SEH
32 // to prevent the crash from taking down the whole application.
33#ifdef Q_CC_MSVC
34 __try {
35#endif
36 hr = MFTEnumEx(
37 category,
38 MFT_ENUM_FLAG_ALL,
39 (mode == QMediaFormat::Encode) ? nullptr : &type, // Input type
40 (mode == QMediaFormat::Encode) ? &type : nullptr, // Output type
41 activate.address(),
42 &count
43 );
44#ifdef Q_CC_MSVC
45 } __except (EXCEPTION_EXECUTE_HANDLER) {
46 qWarning("MFTEnumEx crashed while enumerating codecs (SEH exception caught)");
47 return false;
48 }
49#endif
50
51 return SUCCEEDED(hr) && count > 0;
52}
53
54bool isSupportedCodec(QMediaFormat::AudioCodec codec, QMediaFormat::ConversionMode mode)
55{
56 return isSupportedMFT((mode == QMediaFormat::Encode) ? MFT_CATEGORY_AUDIO_ENCODER : MFT_CATEGORY_AUDIO_DECODER,
57 { MFMediaType_Audio, QWindowsMultimediaUtils::audioFormatForCodec(codec) },
58 mode);
59}
60
61bool isSupportedCodec(QMediaFormat::VideoCodec codec, QMediaFormat::ConversionMode mode)
62{
63 return isSupportedMFT((mode == QMediaFormat::Encode) ? MFT_CATEGORY_VIDEO_ENCODER : MFT_CATEGORY_VIDEO_DECODER,
64 { MFMediaType_Video, QWindowsMultimediaUtils::videoFormatForCodec(codec) },
65 mode);
66}
67
68template <typename T>
69bool isSupportedCodec(T codec, QMediaFormat::ConversionMode m, CheckedCodecs<T> &checkedCodecs)
70{
71 if (auto it = checkedCodecs.constFind(std::pair{codec, m}); it != checkedCodecs.constEnd())
72 return it.value();
73
74 const bool supported = isSupportedCodec(codec, m);
75
76 checkedCodecs.insert(std::pair{codec, m}, supported);
77 return supported;
78}
79
80}
81
83{
84 QList<QImageCapture::FileFormat> list;
85 const auto formats = QImageWriter::supportedImageFormats();
86
87 for (const auto &f : formats) {
88 auto format = QString::fromUtf8(f);
89 if (format.compare(QLatin1String("jpg"), Qt::CaseInsensitive) == 0)
90 list.append(QImageCapture::FileFormat::JPEG);
91 else if (format.compare(QLatin1String("png"), Qt::CaseInsensitive) == 0)
92 list.append(QImageCapture::FileFormat::PNG);
93 else if (format.compare(QLatin1String("webp"), Qt::CaseInsensitive) == 0)
94 list.append(QImageCapture::FileFormat::WebP);
95 else if (format.compare(QLatin1String("tiff"), Qt::CaseInsensitive) == 0)
96 list.append(QImageCapture::FileFormat::Tiff);
97 }
98
99 return list;
100}
101
102QWindowsFormatInfo::QWindowsFormatInfo()
103{
104 const QList<CodecMap> containerTable = {
105 { QMediaFormat::MPEG4,
106 { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3 },
107 { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::MotionJPEG } },
108 { QMediaFormat::Matroska,
109 { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3, QMediaFormat::AudioCodec::FLAC, QMediaFormat::AudioCodec::Vorbis, QMediaFormat::AudioCodec::Opus },
110 { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::VP8, QMediaFormat::VideoCodec::VP9, QMediaFormat::VideoCodec::MotionJPEG } },
111 { QMediaFormat::WebM,
112 { QMediaFormat::AudioCodec::Vorbis, QMediaFormat::AudioCodec::Opus },
113 { QMediaFormat::VideoCodec::VP8, QMediaFormat::VideoCodec::VP9 } },
114 { QMediaFormat::QuickTime,
115 { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3 },
116 { QMediaFormat::VideoCodec::H264, QMediaFormat::VideoCodec::H265, QMediaFormat::VideoCodec::MotionJPEG } },
117 { QMediaFormat::AAC,
118 { QMediaFormat::AudioCodec::AAC },
119 {} },
120 { QMediaFormat::MP3,
121 { QMediaFormat::AudioCodec::MP3 },
122 {} },
123 { QMediaFormat::FLAC,
124 { QMediaFormat::AudioCodec::FLAC },
125 {} },
126 { QMediaFormat::Mpeg4Audio,
127 { QMediaFormat::AudioCodec::AAC, QMediaFormat::AudioCodec::MP3, QMediaFormat::AudioCodec::ALAC, QMediaFormat::AudioCodec::AC3, QMediaFormat::AudioCodec::EAC3 },
128 {} },
129 { QMediaFormat::WMA,
130 { QMediaFormat::AudioCodec::WMA },
131 {} },
132 { QMediaFormat::WMV,
133 { QMediaFormat::AudioCodec::WMA },
134 { QMediaFormat::VideoCodec::WMV } }
135 };
136
137 const QSet<QMediaFormat::FileFormat> decoderFormats = {
138 QMediaFormat::MPEG4,
139 QMediaFormat::Matroska,
140 QMediaFormat::WebM,
141 QMediaFormat::QuickTime,
142 QMediaFormat::AAC,
143 QMediaFormat::MP3,
144 QMediaFormat::FLAC,
145 QMediaFormat::Mpeg4Audio,
146 QMediaFormat::WMA,
147 QMediaFormat::WMV,
148 };
149
150 const QSet<QMediaFormat::FileFormat> encoderFormats = {
151 QMediaFormat::MPEG4,
152 QMediaFormat::AAC,
153 QMediaFormat::MP3,
154 QMediaFormat::FLAC,
155 QMediaFormat::Mpeg4Audio,
156 QMediaFormat::WMA,
157 QMediaFormat::WMV,
158 };
159
160 CheckedCodecs<QMediaFormat::AudioCodec> checkedAudioCodecs;
161 CheckedCodecs<QMediaFormat::VideoCodec> checkedVideoCodecs;
162
163 auto ensureCodecs = [&] (CodecMap &codecs, QMediaFormat::ConversionMode mode) {
164 codecs.audio.removeIf([&] (auto codec) { return !isSupportedCodec(codec, mode, checkedAudioCodecs); });
165 codecs.video.removeIf([&] (auto codec) { return !isSupportedCodec(codec, mode, checkedVideoCodecs); });
166 return !codecs.video.empty() || !codecs.audio.empty();
167 };
168
169 for (const auto &codecMap : containerTable) {
170 if (decoderFormats.contains(codecMap.format)) {
171 auto m = codecMap;
172 if (ensureCodecs(m, QMediaFormat::Decode))
173 decoders.append(m);
174 }
175
176 if (encoderFormats.contains(codecMap.format)) {
177 auto m = codecMap;
178 if (ensureCodecs(m, QMediaFormat::Encode))
179 encoders.append(m);
180 }
181 }
182
183 imageFormats = getImageFormatList();
184}
185
186QWindowsFormatInfo::~QWindowsFormatInfo()
187{
188}
189
190QT_END_NAMESPACE
Combined button and popup list for selecting options.
bool isSupportedCodec(T codec, QMediaFormat::ConversionMode m, CheckedCodecs< T > &checkedCodecs)
bool isSupportedMFT(const GUID &category, const MFT_REGISTER_TYPE_INFO &type, QMediaFormat::ConversionMode mode)
bool isSupportedCodec(QMediaFormat::AudioCodec codec, QMediaFormat::ConversionMode mode)
static QList< QImageCapture::FileFormat > getImageFormatList()