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 for (
auto &encoder : encoders) {
339 if (encoder.format == QMediaFormat::Matroska) {
340 encoder.video.removeAll(VideoCodec::H264);
343 if constexpr (QOperatingSystemVersion::currentType()
344 == QOperatingSystemVersion::MacOS) {
345 encoder.video.removeAll(VideoCodec::H265);
351 auto findDecoder = [&](QMediaFormat::FileFormat fmt) -> CodecMap * {
352 auto it = ranges::find_if(decoders, [&](
const CodecMap &m) {
353 return m.format == fmt;
355 return it != decoders.end() ? &*it :
nullptr;
358 if (extraAudioDecoders.contains(AudioCodec::WMA)) {
359 if (
auto *wma = findDecoder(QMediaFormat::WMA))
360 wma->audio.append(AudioCodec::WMA);
361 if (
auto *wmv = findDecoder(QMediaFormat::WMV))
362 wmv->audio.append(AudioCodec::WMA);
365 if (extraVideoDecoders.contains(VideoCodec::WMV)) {
366 if (
auto *wmv = findDecoder(QMediaFormat::WMV))
367 wmv->video.append(VideoCodec::WMV);
373 const QList<QByteArray> imgFormats = QImageWriter::supportedImageFormats();
374 for (
const auto &f : imgFormats) {
376 imageFormats.append(QImageCapture::PNG);
377 else if (f ==
"jpeg")
378 imageFormats.append(QImageCapture::JPEG);
379 else if (f ==
"tiff")
380 imageFormats.append(QImageCapture::Tiff);
381 else if (f ==
"webp")
382 imageFormats.append(QImageCapture::WebP);
465int64_t QFFmpegMediaFormatInfo::avChannelLayout(QAudioFormat::ChannelConfig channelConfig)
467 int64_t avChannelLayout = 0;
468 if (channelConfig & (1 << QAudioFormat::FrontLeft))
469 avChannelLayout |= AV_CH_FRONT_LEFT;
470 if (channelConfig & (1 << QAudioFormat::FrontRight))
471 avChannelLayout |= AV_CH_FRONT_RIGHT;
472 if (channelConfig & (1 << QAudioFormat::FrontCenter))
473 avChannelLayout |= AV_CH_FRONT_CENTER;
474 if (channelConfig & (1 << QAudioFormat::LFE))
475 avChannelLayout |= AV_CH_LOW_FREQUENCY;
476 if (channelConfig & (1 << QAudioFormat::BackLeft))
477 avChannelLayout |= AV_CH_BACK_LEFT;
478 if (channelConfig & (1 << QAudioFormat::BackRight))
479 avChannelLayout |= AV_CH_BACK_RIGHT;
480 if (channelConfig & (1 << QAudioFormat::FrontLeftOfCenter))
481 avChannelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
482 if (channelConfig & (1 << QAudioFormat::FrontRightOfCenter))
483 avChannelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
484 if (channelConfig & (1 << QAudioFormat::BackCenter))
485 avChannelLayout |= AV_CH_BACK_CENTER;
486 if (channelConfig & (1 << QAudioFormat::LFE2))
487 avChannelLayout |= AV_CH_LOW_FREQUENCY_2;
488 if (channelConfig & (1 << QAudioFormat::SideLeft))
489 avChannelLayout |= AV_CH_SIDE_LEFT;
490 if (channelConfig & (1 << QAudioFormat::SideRight))
491 avChannelLayout |= AV_CH_SIDE_RIGHT;
492 if (channelConfig & (1 << QAudioFormat::TopFrontLeft))
493 avChannelLayout |= AV_CH_TOP_FRONT_LEFT;
494 if (channelConfig & (1 << QAudioFormat::TopFrontRight))
495 avChannelLayout |= AV_CH_TOP_FRONT_RIGHT;
496 if (channelConfig & (1 << QAudioFormat::TopFrontCenter))
497 avChannelLayout |= AV_CH_TOP_FRONT_CENTER;
498 if (channelConfig & (1 << QAudioFormat::TopCenter))
499 avChannelLayout |= AV_CH_TOP_CENTER;
500 if (channelConfig & (1 << QAudioFormat::TopBackLeft))
501 avChannelLayout |= AV_CH_TOP_BACK_LEFT;
502 if (channelConfig & (1 << QAudioFormat::TopBackRight))
503 avChannelLayout |= AV_CH_TOP_BACK_RIGHT;
504 if (channelConfig & (1 << QAudioFormat::TopBackCenter))
505 avChannelLayout |= AV_CH_TOP_BACK_CENTER;
506 if (channelConfig & (1 << QAudioFormat::TopSideLeft))
507 avChannelLayout |= AV_CH_TOP_SIDE_LEFT;
508 if (channelConfig & (1 << QAudioFormat::TopSideRight))
509 avChannelLayout |= AV_CH_TOP_SIDE_RIGHT;
510 if (channelConfig & (1 << QAudioFormat::BottomFrontCenter))
511 avChannelLayout |= AV_CH_BOTTOM_FRONT_CENTER;
512 if (channelConfig & (1 << QAudioFormat::BottomFrontLeft))
513 avChannelLayout |= AV_CH_BOTTOM_FRONT_LEFT;
514 if (channelConfig & (1 << QAudioFormat::BottomFrontRight))
515 avChannelLayout |= AV_CH_BOTTOM_FRONT_RIGHT;
516 return avChannelLayout;
519QAudioFormat::ChannelConfig QFFmpegMediaFormatInfo::channelConfigForAVLayout(int64_t avChannelLayout)
521 quint32 channelConfig = 0;
522 if (avChannelLayout & AV_CH_FRONT_LEFT)
523 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeft);
524 if (avChannelLayout & AV_CH_FRONT_RIGHT)
525 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRight);
526 if (avChannelLayout & AV_CH_FRONT_CENTER)
527 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontCenter);
528 if (avChannelLayout & AV_CH_LOW_FREQUENCY)
529 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE);
530 if (avChannelLayout & AV_CH_BACK_LEFT)
531 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackLeft);
532 if (avChannelLayout & AV_CH_BACK_RIGHT)
533 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackRight);
534 if (avChannelLayout & AV_CH_FRONT_LEFT_OF_CENTER)
535 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeftOfCenter);
536 if (avChannelLayout & AV_CH_FRONT_RIGHT_OF_CENTER)
537 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRightOfCenter);
538 if (avChannelLayout & AV_CH_BACK_CENTER)
539 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackCenter);
540 if (avChannelLayout & AV_CH_LOW_FREQUENCY_2)
541 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE2);
542 if (avChannelLayout & AV_CH_SIDE_LEFT)
543 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideLeft);
544 if (avChannelLayout & AV_CH_SIDE_RIGHT)
545 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideRight);
546 if (avChannelLayout & AV_CH_TOP_FRONT_LEFT)
547 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontLeft);
548 if (avChannelLayout & AV_CH_TOP_FRONT_RIGHT)
549 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontRight);
550 if (avChannelLayout & AV_CH_TOP_FRONT_CENTER)
551 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontCenter);
552 if (avChannelLayout & AV_CH_TOP_CENTER)
553 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopCenter);
554 if (avChannelLayout & AV_CH_TOP_BACK_LEFT)
555 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackLeft);
556 if (avChannelLayout & AV_CH_TOP_BACK_RIGHT)
557 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackRight);
558 if (avChannelLayout & AV_CH_TOP_BACK_CENTER)
559 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackCenter);
560 if (avChannelLayout & AV_CH_TOP_SIDE_LEFT)
561 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideLeft);
562 if (avChannelLayout & AV_CH_TOP_SIDE_RIGHT)
563 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideRight);
564 if (avChannelLayout & AV_CH_BOTTOM_FRONT_CENTER)
565 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontCenter);
566 if (avChannelLayout & AV_CH_BOTTOM_FRONT_LEFT)
567 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontLeft);
568 if (avChannelLayout & AV_CH_BOTTOM_FRONT_RIGHT)
569 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontRight);
570 return QAudioFormat::ChannelConfig(channelConfig);