70 std::initializer_list<std::pair<
const QMediaFormat::AudioCodec, AVCodecID>>{
71 { QMediaFormat::AudioCodec::MP3, AV_CODEC_ID_MP3 },
72 { QMediaFormat::AudioCodec::AAC, AV_CODEC_ID_AAC },
73 { QMediaFormat::AudioCodec::AC3, AV_CODEC_ID_AC3 },
74 { QMediaFormat::AudioCodec::EAC3, AV_CODEC_ID_EAC3 },
75 { QMediaFormat::AudioCodec::FLAC, AV_CODEC_ID_FLAC },
76 { QMediaFormat::AudioCodec::DolbyTrueHD, AV_CODEC_ID_TRUEHD },
77 { QMediaFormat::AudioCodec::Opus, AV_CODEC_ID_OPUS },
78 { QMediaFormat::AudioCodec::Vorbis, AV_CODEC_ID_VORBIS },
79 { QMediaFormat::AudioCodec::Wave, AV_CODEC_ID_PCM_S16LE },
80 { QMediaFormat::AudioCodec::WMA, AV_CODEC_ID_WMAPRO },
81 { QMediaFormat::AudioCodec::ALAC, AV_CODEC_ID_ALAC },
228QFFmpegMediaFormatInfo::QFFmpegMediaFormatInfo()
230 namespace ranges = QtMultimediaPrivate::ranges;
231 namespace views = QtMultimediaPrivate::views;
233 using VideoCodec = QMediaFormat::VideoCodec;
234 using AudioCodec = QMediaFormat::AudioCodec;
236 QList<AudioCodec> audioEncoders;
237 QList<AudioCodec> extraAudioDecoders;
238 QList<VideoCodec> videoEncoders;
239 QList<VideoCodec> extraVideoDecoders;
241 QFFmpeg::FFmpegValueIteratorRange<
const AVCodecDescriptor *, avcodec_descriptor_next>;
244 for (
const AVCodecDescriptor *descriptor : Descriptors{}) {
246 const bool canEncode{ QFFmpeg::findAVEncoder(descriptor->id).has_value() };
247 const bool canDecode{ QFFmpeg::findAVDecoder(descriptor->id).has_value() };
248 const bool isAVCodec = canEncode || canDecode;
253 const VideoCodec videoCodec = videoCodecForAVCodecId(descriptor->id);
254 const AudioCodec audioCodec = audioCodecForAVCodecId(descriptor->id);
256 if (descriptor->type == AVMEDIA_TYPE_VIDEO && videoCodec != VideoCodec::Unspecified) {
258 if (!videoEncoders.contains(videoCodec))
259 videoEncoders.append(videoCodec);
260 }
else if (canDecode) {
261 if (!extraVideoDecoders.contains(videoCodec))
262 extraVideoDecoders.append(videoCodec);
264 }
else if (descriptor->type == AVMEDIA_TYPE_AUDIO && audioCodec != AudioCodec::Unspecified) {
266 if (!audioEncoders.contains(audioCodec))
267 audioEncoders.append(audioCodec);
268 }
else if (canDecode) {
269 if (!extraAudioDecoders.contains(audioCodec))
270 extraAudioDecoders.append(audioCodec);
276 using MuxerRange = QFFmpeg::FFmpegOpaqueIteratorRange<
const AVOutputFormat *, av_muxer_iterate>;
277 for (
const AVOutputFormat *outputFormat : MuxerRange()) {
278 QMediaFormat::FileFormat mediaFormat = formatForAVFormat(outputFormat);
279 if (mediaFormat == QMediaFormat::UnspecifiedFormat)
283 encoder.format = mediaFormat;
285 auto supportedAudioCodecs = audioEncoders | views::filter([&](AudioCodec codec) {
286 return codecSupportsFormat<CodecType::Audio>(outputFormat, codecId(codec));
288 encoder.audio = supportedAudioCodecs | ranges::to<QList<AudioCodec>>();
290 auto supportedVideoCodecs = videoEncoders | views::filter([&](VideoCodec codec) {
291 return codecSupportsFormat<CodecType::Video>(outputFormat, codecId(codec));
293 encoder.video = supportedVideoCodecs | ranges::to<QList<VideoCodec>>();
296 if (encoder.audio.isEmpty() && encoder.video.isEmpty())
300 switch (encoder.format) {
301 case QMediaFormat::WMV:
303 encoders.append({ QMediaFormat::WMA, encoder.audio, {} });
305 case QMediaFormat::MPEG4:
307 encoders.append({ QMediaFormat::QuickTime, encoder.audio, encoder.video });
308 encoders.append({ QMediaFormat::Mpeg4Audio, encoder.audio, {} });
310 case QMediaFormat::Wave:
312 if (!encoder.audio.contains(AudioCodec::Wave))
314 encoder.audio = { AudioCodec::Wave };
320 encoders.append(encoder);
328 if constexpr (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows) {
330 for (
auto &encoder : encoders) {
331 auto h265index = encoder.video.indexOf(VideoCodec::H265);
333 encoder.video.removeAt(h265index);
338 auto findDecoder = [&](QMediaFormat::FileFormat fmt) -> CodecMap * {
339 auto it = ranges::find_if(decoders, [&](
const CodecMap &m) {
340 return m.format == fmt;
342 return it != decoders.end() ? &*it :
nullptr;
345 if (extraAudioDecoders.contains(AudioCodec::WMA)) {
346 if (
auto *wma = findDecoder(QMediaFormat::WMA))
347 wma->audio.append(AudioCodec::WMA);
348 if (
auto *wmv = findDecoder(QMediaFormat::WMV))
349 wmv->audio.append(AudioCodec::WMA);
352 if (extraVideoDecoders.contains(VideoCodec::WMV)) {
353 if (
auto *wmv = findDecoder(QMediaFormat::WMV))
354 wmv->video.append(VideoCodec::WMV);
360 const QList<QByteArray> imgFormats = QImageWriter::supportedImageFormats();
361 for (
const auto &f : imgFormats) {
363 imageFormats.append(QImageCapture::PNG);
364 else if (f ==
"jpeg")
365 imageFormats.append(QImageCapture::JPEG);
366 else if (f ==
"tiff")
367 imageFormats.append(QImageCapture::Tiff);
368 else if (f ==
"webp")
369 imageFormats.append(QImageCapture::WebP);
452int64_t QFFmpegMediaFormatInfo::avChannelLayout(QAudioFormat::ChannelConfig channelConfig)
454 int64_t avChannelLayout = 0;
455 if (channelConfig & (1 << QAudioFormat::FrontLeft))
456 avChannelLayout |= AV_CH_FRONT_LEFT;
457 if (channelConfig & (1 << QAudioFormat::FrontRight))
458 avChannelLayout |= AV_CH_FRONT_RIGHT;
459 if (channelConfig & (1 << QAudioFormat::FrontCenter))
460 avChannelLayout |= AV_CH_FRONT_CENTER;
461 if (channelConfig & (1 << QAudioFormat::LFE))
462 avChannelLayout |= AV_CH_LOW_FREQUENCY;
463 if (channelConfig & (1 << QAudioFormat::BackLeft))
464 avChannelLayout |= AV_CH_BACK_LEFT;
465 if (channelConfig & (1 << QAudioFormat::BackRight))
466 avChannelLayout |= AV_CH_BACK_RIGHT;
467 if (channelConfig & (1 << QAudioFormat::FrontLeftOfCenter))
468 avChannelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
469 if (channelConfig & (1 << QAudioFormat::FrontRightOfCenter))
470 avChannelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
471 if (channelConfig & (1 << QAudioFormat::BackCenter))
472 avChannelLayout |= AV_CH_BACK_CENTER;
473 if (channelConfig & (1 << QAudioFormat::LFE2))
474 avChannelLayout |= AV_CH_LOW_FREQUENCY_2;
475 if (channelConfig & (1 << QAudioFormat::SideLeft))
476 avChannelLayout |= AV_CH_SIDE_LEFT;
477 if (channelConfig & (1 << QAudioFormat::SideRight))
478 avChannelLayout |= AV_CH_SIDE_RIGHT;
479 if (channelConfig & (1 << QAudioFormat::TopFrontLeft))
480 avChannelLayout |= AV_CH_TOP_FRONT_LEFT;
481 if (channelConfig & (1 << QAudioFormat::TopFrontRight))
482 avChannelLayout |= AV_CH_TOP_FRONT_RIGHT;
483 if (channelConfig & (1 << QAudioFormat::TopFrontCenter))
484 avChannelLayout |= AV_CH_TOP_FRONT_CENTER;
485 if (channelConfig & (1 << QAudioFormat::TopCenter))
486 avChannelLayout |= AV_CH_TOP_CENTER;
487 if (channelConfig & (1 << QAudioFormat::TopBackLeft))
488 avChannelLayout |= AV_CH_TOP_BACK_LEFT;
489 if (channelConfig & (1 << QAudioFormat::TopBackRight))
490 avChannelLayout |= AV_CH_TOP_BACK_RIGHT;
491 if (channelConfig & (1 << QAudioFormat::TopBackCenter))
492 avChannelLayout |= AV_CH_TOP_BACK_CENTER;
493 if (channelConfig & (1 << QAudioFormat::TopSideLeft))
494 avChannelLayout |= AV_CH_TOP_SIDE_LEFT;
495 if (channelConfig & (1 << QAudioFormat::TopSideRight))
496 avChannelLayout |= AV_CH_TOP_SIDE_RIGHT;
497 if (channelConfig & (1 << QAudioFormat::BottomFrontCenter))
498 avChannelLayout |= AV_CH_BOTTOM_FRONT_CENTER;
499 if (channelConfig & (1 << QAudioFormat::BottomFrontLeft))
500 avChannelLayout |= AV_CH_BOTTOM_FRONT_LEFT;
501 if (channelConfig & (1 << QAudioFormat::BottomFrontRight))
502 avChannelLayout |= AV_CH_BOTTOM_FRONT_RIGHT;
503 return avChannelLayout;
506QAudioFormat::ChannelConfig QFFmpegMediaFormatInfo::channelConfigForAVLayout(int64_t avChannelLayout)
508 quint32 channelConfig = 0;
509 if (avChannelLayout & AV_CH_FRONT_LEFT)
510 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeft);
511 if (avChannelLayout & AV_CH_FRONT_RIGHT)
512 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRight);
513 if (avChannelLayout & AV_CH_FRONT_CENTER)
514 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontCenter);
515 if (avChannelLayout & AV_CH_LOW_FREQUENCY)
516 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE);
517 if (avChannelLayout & AV_CH_BACK_LEFT)
518 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackLeft);
519 if (avChannelLayout & AV_CH_BACK_RIGHT)
520 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackRight);
521 if (avChannelLayout & AV_CH_FRONT_LEFT_OF_CENTER)
522 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeftOfCenter);
523 if (avChannelLayout & AV_CH_FRONT_RIGHT_OF_CENTER)
524 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRightOfCenter);
525 if (avChannelLayout & AV_CH_BACK_CENTER)
526 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackCenter);
527 if (avChannelLayout & AV_CH_LOW_FREQUENCY_2)
528 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE2);
529 if (avChannelLayout & AV_CH_SIDE_LEFT)
530 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideLeft);
531 if (avChannelLayout & AV_CH_SIDE_RIGHT)
532 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideRight);
533 if (avChannelLayout & AV_CH_TOP_FRONT_LEFT)
534 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontLeft);
535 if (avChannelLayout & AV_CH_TOP_FRONT_RIGHT)
536 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontRight);
537 if (avChannelLayout & AV_CH_TOP_FRONT_CENTER)
538 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontCenter);
539 if (avChannelLayout & AV_CH_TOP_CENTER)
540 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopCenter);
541 if (avChannelLayout & AV_CH_TOP_BACK_LEFT)
542 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackLeft);
543 if (avChannelLayout & AV_CH_TOP_BACK_RIGHT)
544 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackRight);
545 if (avChannelLayout & AV_CH_TOP_BACK_CENTER)
546 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackCenter);
547 if (avChannelLayout & AV_CH_TOP_SIDE_LEFT)
548 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideLeft);
549 if (avChannelLayout & AV_CH_TOP_SIDE_RIGHT)
550 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideRight);
551 if (avChannelLayout & AV_CH_BOTTOM_FRONT_CENTER)
552 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontCenter);
553 if (avChannelLayout & AV_CH_BOTTOM_FRONT_LEFT)
554 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontLeft);
555 if (avChannelLayout & AV_CH_BOTTOM_FRONT_RIGHT)
556 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontRight);
557 return QAudioFormat::ChannelConfig(channelConfig);
561QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(
const AVCodecParameters &codecpar)
564 format.setSampleFormat(sampleFormat(AVSampleFormat(codecpar.format)));
565 format.setSampleRate(codecpar.sample_rate);
566#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
567 uint64_t channelLayout = 0;
568 if (codecpar.ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
569 channelLayout = codecpar.ch_layout.u.mask;
571 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.ch_layout.nb_channels));
573 uint64_t channelLayout = codecpar.channel_layout;
575 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.channels));
577 format.setChannelConfig(channelConfigForAVLayout(channelLayout));