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
qffmpegmediaformatinfo.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
6#include "qaudioformat.h"
7#include "qimagewriter.h"
8
10
11static constexpr struct {
14} s_videoCodecMap [] = {
15 { AV_CODEC_ID_MPEG1VIDEO, QMediaFormat::VideoCodec::MPEG1 },
16 { AV_CODEC_ID_MPEG2VIDEO, QMediaFormat::VideoCodec::MPEG2 },
17 { AV_CODEC_ID_MPEG4, QMediaFormat::VideoCodec::MPEG4 },
18 { AV_CODEC_ID_H264, QMediaFormat::VideoCodec::H264 },
19 { AV_CODEC_ID_HEVC, QMediaFormat::VideoCodec::H265 },
20 { AV_CODEC_ID_VP8, QMediaFormat::VideoCodec::VP8 },
21 { AV_CODEC_ID_VP9, QMediaFormat::VideoCodec::VP9 },
22 { AV_CODEC_ID_AV1, QMediaFormat::VideoCodec::AV1 },
23 { AV_CODEC_ID_THEORA, QMediaFormat::VideoCodec::Theora },
24 { AV_CODEC_ID_WMV3, QMediaFormat::VideoCodec::WMV },
25 { AV_CODEC_ID_MJPEG, QMediaFormat::VideoCodec::MotionJPEG }
26};
27
28static AVCodecID codecId(QMediaFormat::VideoCodec codec)
29{
30 for (const auto &c : s_videoCodecMap) {
31 if (c.codec == codec)
32 return c.id;
33 }
34 return AV_CODEC_ID_NONE;
35}
36
37static constexpr struct {
38 AVCodecID id;
39 QMediaFormat::AudioCodec codec;
40} s_audioCodecMap [] = {
41 { AV_CODEC_ID_MP3, QMediaFormat::AudioCodec::MP3 },
42 { AV_CODEC_ID_AAC, QMediaFormat::AudioCodec::AAC },
43 { AV_CODEC_ID_AC3, QMediaFormat::AudioCodec::AC3 },
44 { AV_CODEC_ID_EAC3, QMediaFormat::AudioCodec::EAC3 },
45 { AV_CODEC_ID_FLAC, QMediaFormat::AudioCodec::FLAC },
46 { AV_CODEC_ID_TRUEHD, QMediaFormat::AudioCodec::DolbyTrueHD },
47 { AV_CODEC_ID_OPUS, QMediaFormat::AudioCodec::Opus },
48 { AV_CODEC_ID_VORBIS, QMediaFormat::AudioCodec::Vorbis },
49 { AV_CODEC_ID_PCM_S16LE, QMediaFormat::AudioCodec::Wave },
50 { AV_CODEC_ID_WMAPRO, QMediaFormat::AudioCodec::WMA },
51 { AV_CODEC_ID_ALAC, QMediaFormat::AudioCodec::ALAC }
52};
53
54static AVCodecID codecId(QMediaFormat::AudioCodec codec)
55{
56 for (const auto &c : s_audioCodecMap) {
57 if (c.codec == codec)
58 return c.id;
59 }
60 return AV_CODEC_ID_NONE;
61}
62
63// mimetypes are mostly copied from qmediaformat.cpp. Unfortunately, FFmpeg uses
64// in some cases slightly different mimetypes
65static constexpr struct
66{
68 const char *mimeType;
69 const char *name; // disambiguate if we have several muxers/demuxers
70} s_mimeMap[] = {
71 { QMediaFormat::WMV, "video/x-ms-asf", "asf" },
72 { QMediaFormat::AVI, "video/x-msvideo", nullptr },
73 { QMediaFormat::Matroska, "video/x-matroska", nullptr },
74 { QMediaFormat::MPEG4, "video/mp4", "mp4" },
75 { QMediaFormat::Ogg, "video/ogg", nullptr },
76 // QuickTime is the same as MP4
77 { QMediaFormat::WebM, "video/webm", "webm" },
78 // Audio Formats
79 // Mpeg4Audio is the same as MP4 without the video codecs
80 { QMediaFormat::AAC, "audio/aac", nullptr },
81 // WMA is the same as WMV
82 { QMediaFormat::FLAC, "audio/x-flac", nullptr },
83 { QMediaFormat::MP3, "audio/mpeg", "mp3" },
84 { QMediaFormat::Wave, "audio/x-wav", nullptr },
85 { QMediaFormat::Ogg, "audio/ogg", nullptr }
86};
87
88template <typename AVFormat>
89static QMediaFormat::FileFormat formatForAVFormat(AVFormat *format)
90{
91 if (!format->mime_type || !*format->mime_type)
92 return QMediaFormat::UnspecifiedFormat;
93
94 for (const auto &m : s_mimeMap) {
95 if (m.mimeType && !strcmp(m.mimeType, format->mime_type)) {
96 // check if the name matches. This is used to disambiguate where FFmpeg provides
97 // multiple muxers or demuxers
98 if (!m.name || !strcmp(m.name, format->name))
99 return m.fileFormat;
100 }
101 }
102 return QMediaFormat::UnspecifiedFormat;
103}
104
105static const AVOutputFormat *avFormatForFormat(QMediaFormat::FileFormat format)
106{
107 if (format == QMediaFormat::QuickTime || format == QMediaFormat::Mpeg4Audio)
108 format = QMediaFormat::MPEG4;
109 if (format == QMediaFormat::WMA)
110 format = QMediaFormat::WMV;
111
112 for (const auto &m : s_mimeMap) {
113 if (m.fileFormat == format)
114 return av_guess_format(m.name, nullptr, m.mimeType);
115 }
116
117 return nullptr;
118}
119
120QFFmpegMediaFormatInfo::QFFmpegMediaFormatInfo()
121{
122 using VideoCodec = QMediaFormat::VideoCodec;
123 using AudioCodec = QMediaFormat::AudioCodec;
124
125 QList<AudioCodec> audioEncoders; // All audio encoders that Qt support
126 QList<AudioCodec> extraAudioDecoders; // All audio decoders that do not support encoding
127 QList<VideoCodec> videoEncoders; // All video encoders that Qt support
128 QList<VideoCodec> extraVideoDecoders; // All video decoders that do not support encoding
129
130 // Sort all FFmpeg's codecs into the buckets
131 const AVCodecDescriptor *descriptor = nullptr;
132 while ((descriptor = avcodec_descriptor_next(descriptor))) {
133
134 const bool canEncode{ QFFmpeg::findAVEncoder(descriptor->id).has_value() };
135 const bool canDecode{ QFFmpeg::findAVDecoder(descriptor->id).has_value() };
136
137 const VideoCodec videoCodec = videoCodecForAVCodecId(descriptor->id);
138 const AudioCodec audioCodec = audioCodecForAVCodecId(descriptor->id);
139
140 if (descriptor->type == AVMEDIA_TYPE_VIDEO && videoCodec != VideoCodec::Unspecified) {
141 if (canEncode) {
142 if (!videoEncoders.contains(videoCodec))
143 videoEncoders.append(videoCodec);
144 } else if (canDecode) {
145 if (!extraVideoDecoders.contains(videoCodec))
146 extraVideoDecoders.append(videoCodec);
147 }
148 } else if (descriptor->type == AVMEDIA_TYPE_AUDIO && audioCodec != AudioCodec::Unspecified) {
149 if (canEncode) {
150 if (!audioEncoders.contains(audioCodec))
151 audioEncoders.append(audioCodec);
152 } else if (canDecode) {
153 if (!extraAudioDecoders.contains(audioCodec))
154 extraAudioDecoders.append(audioCodec);
155 }
156 }
157 }
158
159 // Update 'encoders' list with muxer/encoder combinations that Qt supports
160 void *opaque = nullptr;
161 const AVOutputFormat *outputFormat = nullptr;
162 while ((outputFormat = av_muxer_iterate(&opaque))) {
163 QMediaFormat::FileFormat mediaFormat = formatForAVFormat(outputFormat);
164 if (mediaFormat == QMediaFormat::UnspecifiedFormat)
165 continue;
166
167 CodecMap encoder;
168 encoder.format = mediaFormat;
169
170 for (AudioCodec codec : audioEncoders) {
171 const AVCodecID id = codecId(codec);
172 // Only add the codec if it can be used with this container. A negative
173 // result means that the codec may work, but information is unavailable
174 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
175 if (result == 1 || (result < 0 && id == outputFormat->audio_codec)) {
176 // add codec for container
177 encoder.audio.append(codec);
178 }
179 }
180
181 for (VideoCodec codec : videoEncoders) {
182 const AVCodecID id = codecId(codec);
183 // Only add the codec if it can be used with this container. A negative
184 // result means that the codec may work, but information is unavailable
185 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
186 if (result == 1 || (result < 0 && id == outputFormat->video_codec)) {
187 // add codec for container
188 encoder.video.append(codec);
189 }
190 }
191
192 // If no encoders support either audio or video, we skip this format.
193 if (encoder.audio.isEmpty() && encoder.video.isEmpty())
194 continue;
195
196 // Handle special cases
197 switch (encoder.format) {
198 case QMediaFormat::WMV:
199 // add WMA
200 encoders.append({ QMediaFormat::WMA, encoder.audio, {} });
201 break;
202 case QMediaFormat::MPEG4:
203 // add Mpeg4Audio and QuickTime
204 encoders.append({ QMediaFormat::QuickTime, encoder.audio, encoder.video });
205 encoders.append({ QMediaFormat::Mpeg4Audio, encoder.audio, {} });
206 break;
207 case QMediaFormat::Wave:
208 // FFmpeg allows other encoded formats in WAV containers, but we do not want that
209 if (!encoder.audio.contains(AudioCodec::Wave))
210 continue;
211 encoder.audio = { AudioCodec::Wave };
212 break;
213 default:
214 break;
215 }
216
217 encoders.append(encoder);
218 }
219
220 // FFmpeg doesn't allow querying supported codecs for demuxers.
221 // We take a simple approximation stating that we can decode what we
222 // can encode. That's a safe subset.
223 decoders = encoders;
224
225#ifdef Q_OS_WINDOWS
226 // MediaFoundation HVEC encoder fails when processing frames
227 for (auto &encoder : encoders) {
228 auto h265index = encoder.video.indexOf(VideoCodec::H265);
229 if (h265index >= 0)
230 encoder.video.removeAt(h265index);
231 }
232#endif
233
234 // FFmpeg's Matroska muxer does not work with H264 video codec
235 for (auto &encoder : encoders) {
236 if (encoder.format == QMediaFormat::Matroska) {
237 encoder.video.removeAll(VideoCodec::H264);
238
239 // And on macOS, also not with H265
240#ifdef Q_OS_MACOS
241 encoder.video.removeAll(VideoCodec::H265);
242#endif
243 }
244 }
245
246 // FFmpeg can currently only decode WMA and WMV, not encode
247 if (extraAudioDecoders.contains(AudioCodec::WMA)) {
248 decoders[QMediaFormat::WMA].audio.append(AudioCodec::WMA);
249 decoders[QMediaFormat::WMV].audio.append(AudioCodec::WMA);
250 }
251
252 if (extraVideoDecoders.contains(VideoCodec::WMV)) {
253 decoders[QMediaFormat::WMV].video.append(VideoCodec::WMV);
254 }
255
256 // Add image formats we support. We currently simply use Qt's built-in image write
257 // to save images. That doesn't give us HDR support or support for larger bit depths,
258 // but most cameras can currently not generate those anyway.
259 const QList<QByteArray> imgFormats = QImageWriter::supportedImageFormats();
260 for (const auto &f : imgFormats) {
261 if (f == "png")
262 imageFormats.append(QImageCapture::PNG);
263 else if (f == "jpeg")
264 imageFormats.append(QImageCapture::JPEG);
265 else if (f == "tiff")
266 imageFormats.append(QImageCapture::Tiff);
267 else if (f == "webp")
268 imageFormats.append(QImageCapture::WebP);
269 }
270
271}
272
273QFFmpegMediaFormatInfo::~QFFmpegMediaFormatInfo() = default;
274
275QMediaFormat::AudioCodec QFFmpegMediaFormatInfo::audioCodecForAVCodecId(AVCodecID id)
276{
277 for (const auto &c : s_audioCodecMap) {
278 if (c.id == id)
279 return c.codec;
280 }
281 return QMediaFormat::AudioCodec::Unspecified;
282}
283
284QMediaFormat::VideoCodec QFFmpegMediaFormatInfo::videoCodecForAVCodecId(AVCodecID id)
285{
286 for (const auto &c : s_videoCodecMap) {
287 if (c.id == id)
288 return c.codec;
289 }
290 return QMediaFormat::VideoCodec::Unspecified;
291}
292
293QMediaFormat::FileFormat
294QFFmpegMediaFormatInfo::fileFormatForAVInputFormat(const AVInputFormat &format)
295{
296 // Seems like FFmpeg uses different names for muxers and demuxers of the same format.
297 // that makes it somewhat cumbersome to detect things correctly.
298 // The input formats have a comma separated list of short names. We check the first one of those
299 // as the docs specify that you only append to the list
300 static const struct
301 {
302 QMediaFormat::FileFormat fileFormat;
303 const char *name;
304 } map[QMediaFormat::LastFileFormat + 1] = {
305 { QMediaFormat::WMV, "asf" },
306 { QMediaFormat::AVI, "avi" },
307 { QMediaFormat::Matroska, "matroska" },
308 { QMediaFormat::MPEG4, "mov" },
309 { QMediaFormat::Ogg, "ogg" },
310 { QMediaFormat::WebM, "webm" },
311 // Audio Formats
312 // Mpeg4Audio is the same as MP4 without the video codecs
313 { QMediaFormat::AAC, "aac"},
314 // WMA is the same as WMV
315 { QMediaFormat::FLAC, "flac" },
316 { QMediaFormat::MP3, "mp3" },
317 { QMediaFormat::Wave, "wav" },
318 { QMediaFormat::UnspecifiedFormat, nullptr }
319 };
320
321 if (!format.name)
322 return QMediaFormat::UnspecifiedFormat;
323
324 auto *m = map;
325 while (m->fileFormat != QMediaFormat::UnspecifiedFormat) {
326 if (!strncmp(m->name, format.name, strlen(m->name)))
327 return m->fileFormat;
328 ++m;
329 }
330
331 return QMediaFormat::UnspecifiedFormat;
332}
333
334const AVOutputFormat *
335QFFmpegMediaFormatInfo::outputFormatForFileFormat(QMediaFormat::FileFormat format)
336{
337 return avFormatForFormat(format);
338}
339
340AVCodecID QFFmpegMediaFormatInfo::codecIdForVideoCodec(QMediaFormat::VideoCodec codec)
341{
342 return codecId(codec);
343}
344
345AVCodecID QFFmpegMediaFormatInfo::codecIdForAudioCodec(QMediaFormat::AudioCodec codec)
346{
347 return codecId(codec);
348}
349
350QAudioFormat::SampleFormat QFFmpegMediaFormatInfo::sampleFormat(AVSampleFormat format)
351{
352 switch (format) {
353 case AV_SAMPLE_FMT_NONE:
354 default:
355 return QAudioFormat::Unknown;
356 case AV_SAMPLE_FMT_U8: ///< unsigned 8 bits
357 case AV_SAMPLE_FMT_U8P: ///< unsigned 8 bits: planar
358 return QAudioFormat::UInt8;
359 case AV_SAMPLE_FMT_S16: ///< signed 16 bits
360 case AV_SAMPLE_FMT_S16P: ///< signed 16 bits: planar
361 return QAudioFormat::Int16;
362 case AV_SAMPLE_FMT_S32: ///< signed 32 bits
363 case AV_SAMPLE_FMT_S32P: ///< signed 32 bits: planar
364 return QAudioFormat::Int32;
365 case AV_SAMPLE_FMT_FLT: ///< float
366 case AV_SAMPLE_FMT_FLTP: ///< float: planar
367 return QAudioFormat::Float;
368 case AV_SAMPLE_FMT_DBL: ///< double
369 case AV_SAMPLE_FMT_DBLP: ///< double: planar
370 case AV_SAMPLE_FMT_S64: ///< signed 64 bits
371 case AV_SAMPLE_FMT_S64P: ///< signed 64 bits, planar
372 // let's use float
373 return QAudioFormat::Float;
374 }
375}
376
377AVSampleFormat QFFmpegMediaFormatInfo::avSampleFormat(QAudioFormat::SampleFormat format)
378{
379 switch (format) {
380 case QAudioFormat::UInt8:
381 return AV_SAMPLE_FMT_U8;
382 case QAudioFormat::Int16:
383 return AV_SAMPLE_FMT_S16;
384 case QAudioFormat::Int32:
385 return AV_SAMPLE_FMT_S32;
386 case QAudioFormat::Float:
387 return AV_SAMPLE_FMT_FLT;
388 default:
389 return AV_SAMPLE_FMT_NONE;
390 }
391}
392
393int64_t QFFmpegMediaFormatInfo::avChannelLayout(QAudioFormat::ChannelConfig channelConfig)
394{
395 int64_t avChannelLayout = 0;
396 if (channelConfig & (1 << QAudioFormat::FrontLeft))
397 avChannelLayout |= AV_CH_FRONT_LEFT;
398 if (channelConfig & (1 << QAudioFormat::FrontRight))
399 avChannelLayout |= AV_CH_FRONT_RIGHT;
400 if (channelConfig & (1 << QAudioFormat::FrontCenter))
401 avChannelLayout |= AV_CH_FRONT_CENTER;
402 if (channelConfig & (1 << QAudioFormat::LFE))
403 avChannelLayout |= AV_CH_LOW_FREQUENCY;
404 if (channelConfig & (1 << QAudioFormat::BackLeft))
405 avChannelLayout |= AV_CH_BACK_LEFT;
406 if (channelConfig & (1 << QAudioFormat::BackRight))
407 avChannelLayout |= AV_CH_BACK_RIGHT;
408 if (channelConfig & (1 << QAudioFormat::FrontLeftOfCenter))
409 avChannelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
410 if (channelConfig & (1 << QAudioFormat::FrontRightOfCenter))
411 avChannelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
412 if (channelConfig & (1 << QAudioFormat::BackCenter))
413 avChannelLayout |= AV_CH_BACK_CENTER;
414 if (channelConfig & (1 << QAudioFormat::LFE2))
415 avChannelLayout |= AV_CH_LOW_FREQUENCY_2;
416 if (channelConfig & (1 << QAudioFormat::SideLeft))
417 avChannelLayout |= AV_CH_SIDE_LEFT;
418 if (channelConfig & (1 << QAudioFormat::SideRight))
419 avChannelLayout |= AV_CH_SIDE_RIGHT;
420 if (channelConfig & (1 << QAudioFormat::TopFrontLeft))
421 avChannelLayout |= AV_CH_TOP_FRONT_LEFT;
422 if (channelConfig & (1 << QAudioFormat::TopFrontRight))
423 avChannelLayout |= AV_CH_TOP_FRONT_RIGHT;
424 if (channelConfig & (1 << QAudioFormat::TopFrontCenter))
425 avChannelLayout |= AV_CH_TOP_FRONT_CENTER;
426 if (channelConfig & (1 << QAudioFormat::TopCenter))
427 avChannelLayout |= AV_CH_TOP_CENTER;
428 if (channelConfig & (1 << QAudioFormat::TopBackLeft))
429 avChannelLayout |= AV_CH_TOP_BACK_LEFT;
430 if (channelConfig & (1 << QAudioFormat::TopBackRight))
431 avChannelLayout |= AV_CH_TOP_BACK_RIGHT;
432 if (channelConfig & (1 << QAudioFormat::TopBackCenter))
433 avChannelLayout |= AV_CH_TOP_BACK_CENTER;
434 // The defines used below got added together for FFmpeg 4.4
435#ifdef AV_CH_TOP_SIDE_LEFT
436 if (channelConfig & (1 << QAudioFormat::TopSideLeft))
437 avChannelLayout |= AV_CH_TOP_SIDE_LEFT;
438 if (channelConfig & (1 << QAudioFormat::TopSideRight))
439 avChannelLayout |= AV_CH_TOP_SIDE_RIGHT;
440 if (channelConfig & (1 << QAudioFormat::BottomFrontCenter))
441 avChannelLayout |= AV_CH_BOTTOM_FRONT_CENTER;
442 if (channelConfig & (1 << QAudioFormat::BottomFrontLeft))
443 avChannelLayout |= AV_CH_BOTTOM_FRONT_LEFT;
444 if (channelConfig & (1 << QAudioFormat::BottomFrontRight))
445 avChannelLayout |= AV_CH_BOTTOM_FRONT_RIGHT;
446#endif
447 return avChannelLayout;
448}
449
450QAudioFormat::ChannelConfig QFFmpegMediaFormatInfo::channelConfigForAVLayout(int64_t avChannelLayout)
451{
452 quint32 channelConfig = 0;
453 if (avChannelLayout & AV_CH_FRONT_LEFT)
454 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeft);
455 if (avChannelLayout & AV_CH_FRONT_RIGHT)
456 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRight);
457 if (avChannelLayout & AV_CH_FRONT_CENTER)
458 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontCenter);
459 if (avChannelLayout & AV_CH_LOW_FREQUENCY)
460 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE);
461 if (avChannelLayout & AV_CH_BACK_LEFT)
462 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackLeft);
463 if (avChannelLayout & AV_CH_BACK_RIGHT)
464 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackRight);
465 if (avChannelLayout & AV_CH_FRONT_LEFT_OF_CENTER)
466 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeftOfCenter);
467 if (avChannelLayout & AV_CH_FRONT_RIGHT_OF_CENTER)
468 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRightOfCenter);
469 if (avChannelLayout & AV_CH_BACK_CENTER)
470 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackCenter);
471 if (avChannelLayout & AV_CH_LOW_FREQUENCY_2)
472 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE2);
473 if (avChannelLayout & AV_CH_SIDE_LEFT)
474 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideLeft);
475 if (avChannelLayout & AV_CH_SIDE_RIGHT)
476 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideRight);
477 if (avChannelLayout & AV_CH_TOP_FRONT_LEFT)
478 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontLeft);
479 if (avChannelLayout & AV_CH_TOP_FRONT_RIGHT)
480 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontRight);
481 if (avChannelLayout & AV_CH_TOP_FRONT_CENTER)
482 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontCenter);
483 if (avChannelLayout & AV_CH_TOP_CENTER)
484 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopCenter);
485 if (avChannelLayout & AV_CH_TOP_BACK_LEFT)
486 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackLeft);
487 if (avChannelLayout & AV_CH_TOP_BACK_RIGHT)
488 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackRight);
489 if (avChannelLayout & AV_CH_TOP_BACK_CENTER)
490 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackCenter);
491 // The defines used below got added together for FFmpeg 4.4
492#ifdef AV_CH_TOP_SIDE_LEFT
493 if (avChannelLayout & AV_CH_TOP_SIDE_LEFT)
494 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideLeft);
495 if (avChannelLayout & AV_CH_TOP_SIDE_RIGHT)
496 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideRight);
497 if (avChannelLayout & AV_CH_BOTTOM_FRONT_CENTER)
498 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontCenter);
499 if (avChannelLayout & AV_CH_BOTTOM_FRONT_LEFT)
500 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontLeft);
501 if (avChannelLayout & AV_CH_BOTTOM_FRONT_RIGHT)
502 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontRight);
503#endif
504 return QAudioFormat::ChannelConfig(channelConfig);
505}
506
507QAudioFormat
508QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(const AVCodecParameters &codecpar)
509{
510 QAudioFormat format;
511 format.setSampleFormat(sampleFormat(AVSampleFormat(codecpar.format)));
512 format.setSampleRate(codecpar.sample_rate);
513#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
514 uint64_t channelLayout = 0;
515 if (codecpar.ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
516 channelLayout = codecpar.ch_layout.u.mask;
517 else
518 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.ch_layout.nb_channels));
519#else
520 uint64_t channelLayout = codecpar.channel_layout;
521 if (!channelLayout)
522 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.channels));
523#endif
524 format.setChannelConfig(channelConfigForAVLayout(channelLayout));
525 return format;
526}
527
528QT_END_NAMESPACE
Combined button and popup list for selecting options.
static QMediaFormat::FileFormat formatForAVFormat(AVFormat *format)
AVCodecID id
QMediaFormat::VideoCodec codec
const char * mimeType
static AVCodecID codecId(QMediaFormat::VideoCodec codec)
const char * name
static const AVOutputFormat * avFormatForFormat(QMediaFormat::FileFormat format)
QMediaFormat::FileFormat fileFormat