122QFFmpegMediaFormatInfo::QFFmpegMediaFormatInfo()
124 namespace ranges = QtMultimediaPrivate::ranges;
125 using VideoCodec = QMediaFormat::VideoCodec;
126 using AudioCodec = QMediaFormat::AudioCodec;
127 namespace ranges = QtMultimediaPrivate::ranges;
129 QList<AudioCodec> audioEncoders;
130 QList<AudioCodec> extraAudioDecoders;
131 QList<VideoCodec> videoEncoders;
132 QList<VideoCodec> extraVideoDecoders;
135 const AVCodecDescriptor *descriptor =
nullptr;
136 while ((descriptor = avcodec_descriptor_next(descriptor))) {
138 const bool canEncode{ QFFmpeg::findAVEncoder(descriptor->id).has_value() };
139 const bool canDecode{ QFFmpeg::findAVDecoder(descriptor->id).has_value() };
140 const bool isAVCodec = canEncode || canDecode;
145 const VideoCodec videoCodec = videoCodecForAVCodecId(descriptor->id);
146 const AudioCodec audioCodec = audioCodecForAVCodecId(descriptor->id);
148 if (descriptor->type == AVMEDIA_TYPE_VIDEO && videoCodec != VideoCodec::Unspecified) {
150 if (!videoEncoders.contains(videoCodec))
151 videoEncoders.append(videoCodec);
152 }
else if (canDecode) {
153 if (!extraVideoDecoders.contains(videoCodec))
154 extraVideoDecoders.append(videoCodec);
156 }
else if (descriptor->type == AVMEDIA_TYPE_AUDIO && audioCodec != AudioCodec::Unspecified) {
158 if (!audioEncoders.contains(audioCodec))
159 audioEncoders.append(audioCodec);
160 }
else if (canDecode) {
161 if (!extraAudioDecoders.contains(audioCodec))
162 extraAudioDecoders.append(audioCodec);
168 void *opaque =
nullptr;
169 const AVOutputFormat *outputFormat =
nullptr;
170 while ((outputFormat = av_muxer_iterate(&opaque))) {
171 QMediaFormat::FileFormat mediaFormat = formatForAVFormat(outputFormat);
172 if (mediaFormat == QMediaFormat::UnspecifiedFormat)
176 encoder.format = mediaFormat;
178 for (AudioCodec codec : audioEncoders) {
179 const AVCodecID id = codecId(codec);
182 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
183 if (result == 1 || (result < 0 && id == outputFormat->audio_codec)) {
185 encoder.audio.append(codec);
189 for (VideoCodec codec : videoEncoders) {
190 const AVCodecID id = codecId(codec);
193 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
194 if (result == 1 || (result < 0 && id == outputFormat->video_codec)) {
196 encoder.video.append(codec);
201 if (encoder.audio.isEmpty() && encoder.video.isEmpty())
205 switch (encoder.format) {
206 case QMediaFormat::WMV:
208 encoders.append({ QMediaFormat::WMA, encoder.audio, {} });
210 case QMediaFormat::MPEG4:
212 encoders.append({ QMediaFormat::QuickTime, encoder.audio, encoder.video });
213 encoders.append({ QMediaFormat::Mpeg4Audio, encoder.audio, {} });
215 case QMediaFormat::Wave:
217 if (!encoder.audio.contains(AudioCodec::Wave))
219 encoder.audio = { AudioCodec::Wave };
225 encoders.append(encoder);
235 for (
auto &encoder : encoders) {
236 auto h265index = encoder.video.indexOf(VideoCodec::H265);
238 encoder.video.removeAt(h265index);
243 for (
auto &encoder : encoders) {
244 if (encoder.format == QMediaFormat::Matroska) {
245 encoder.video.removeAll(VideoCodec::H264);
249 encoder.video.removeAll(VideoCodec::H265);
255 auto findDecoder = [&](QMediaFormat::FileFormat fmt) -> CodecMap * {
256 auto it = ranges::find_if(decoders, [&](
const CodecMap &m) {
257 return m.format == fmt;
259 return it != decoders.end() ? &*it :
nullptr;
262 if (extraAudioDecoders.contains(AudioCodec::WMA)) {
263 if (
auto *wma = findDecoder(QMediaFormat::WMA))
264 wma->audio.append(AudioCodec::WMA);
265 if (
auto *wmv = findDecoder(QMediaFormat::WMV))
266 wmv->audio.append(AudioCodec::WMA);
269 if (extraVideoDecoders.contains(VideoCodec::WMV)) {
270 if (
auto *wmv = findDecoder(QMediaFormat::WMV))
271 wmv->video.append(VideoCodec::WMV);
277 const QList<QByteArray> imgFormats = QImageWriter::supportedImageFormats();
278 for (
const auto &f : imgFormats) {
280 imageFormats.append(QImageCapture::PNG);
281 else if (f ==
"jpeg")
282 imageFormats.append(QImageCapture::JPEG);
283 else if (f ==
"tiff")
284 imageFormats.append(QImageCapture::Tiff);
285 else if (f ==
"webp")
286 imageFormats.append(QImageCapture::WebP);
412int64_t QFFmpegMediaFormatInfo::avChannelLayout(QAudioFormat::ChannelConfig channelConfig)
414 int64_t avChannelLayout = 0;
415 if (channelConfig & (1 << QAudioFormat::FrontLeft))
416 avChannelLayout |= AV_CH_FRONT_LEFT;
417 if (channelConfig & (1 << QAudioFormat::FrontRight))
418 avChannelLayout |= AV_CH_FRONT_RIGHT;
419 if (channelConfig & (1 << QAudioFormat::FrontCenter))
420 avChannelLayout |= AV_CH_FRONT_CENTER;
421 if (channelConfig & (1 << QAudioFormat::LFE))
422 avChannelLayout |= AV_CH_LOW_FREQUENCY;
423 if (channelConfig & (1 << QAudioFormat::BackLeft))
424 avChannelLayout |= AV_CH_BACK_LEFT;
425 if (channelConfig & (1 << QAudioFormat::BackRight))
426 avChannelLayout |= AV_CH_BACK_RIGHT;
427 if (channelConfig & (1 << QAudioFormat::FrontLeftOfCenter))
428 avChannelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
429 if (channelConfig & (1 << QAudioFormat::FrontRightOfCenter))
430 avChannelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
431 if (channelConfig & (1 << QAudioFormat::BackCenter))
432 avChannelLayout |= AV_CH_BACK_CENTER;
433 if (channelConfig & (1 << QAudioFormat::LFE2))
434 avChannelLayout |= AV_CH_LOW_FREQUENCY_2;
435 if (channelConfig & (1 << QAudioFormat::SideLeft))
436 avChannelLayout |= AV_CH_SIDE_LEFT;
437 if (channelConfig & (1 << QAudioFormat::SideRight))
438 avChannelLayout |= AV_CH_SIDE_RIGHT;
439 if (channelConfig & (1 << QAudioFormat::TopFrontLeft))
440 avChannelLayout |= AV_CH_TOP_FRONT_LEFT;
441 if (channelConfig & (1 << QAudioFormat::TopFrontRight))
442 avChannelLayout |= AV_CH_TOP_FRONT_RIGHT;
443 if (channelConfig & (1 << QAudioFormat::TopFrontCenter))
444 avChannelLayout |= AV_CH_TOP_FRONT_CENTER;
445 if (channelConfig & (1 << QAudioFormat::TopCenter))
446 avChannelLayout |= AV_CH_TOP_CENTER;
447 if (channelConfig & (1 << QAudioFormat::TopBackLeft))
448 avChannelLayout |= AV_CH_TOP_BACK_LEFT;
449 if (channelConfig & (1 << QAudioFormat::TopBackRight))
450 avChannelLayout |= AV_CH_TOP_BACK_RIGHT;
451 if (channelConfig & (1 << QAudioFormat::TopBackCenter))
452 avChannelLayout |= AV_CH_TOP_BACK_CENTER;
453 if (channelConfig & (1 << QAudioFormat::TopSideLeft))
454 avChannelLayout |= AV_CH_TOP_SIDE_LEFT;
455 if (channelConfig & (1 << QAudioFormat::TopSideRight))
456 avChannelLayout |= AV_CH_TOP_SIDE_RIGHT;
457 if (channelConfig & (1 << QAudioFormat::BottomFrontCenter))
458 avChannelLayout |= AV_CH_BOTTOM_FRONT_CENTER;
459 if (channelConfig & (1 << QAudioFormat::BottomFrontLeft))
460 avChannelLayout |= AV_CH_BOTTOM_FRONT_LEFT;
461 if (channelConfig & (1 << QAudioFormat::BottomFrontRight))
462 avChannelLayout |= AV_CH_BOTTOM_FRONT_RIGHT;
463 return avChannelLayout;
466QAudioFormat::ChannelConfig QFFmpegMediaFormatInfo::channelConfigForAVLayout(int64_t avChannelLayout)
468 quint32 channelConfig = 0;
469 if (avChannelLayout & AV_CH_FRONT_LEFT)
470 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeft);
471 if (avChannelLayout & AV_CH_FRONT_RIGHT)
472 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRight);
473 if (avChannelLayout & AV_CH_FRONT_CENTER)
474 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontCenter);
475 if (avChannelLayout & AV_CH_LOW_FREQUENCY)
476 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE);
477 if (avChannelLayout & AV_CH_BACK_LEFT)
478 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackLeft);
479 if (avChannelLayout & AV_CH_BACK_RIGHT)
480 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackRight);
481 if (avChannelLayout & AV_CH_FRONT_LEFT_OF_CENTER)
482 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeftOfCenter);
483 if (avChannelLayout & AV_CH_FRONT_RIGHT_OF_CENTER)
484 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRightOfCenter);
485 if (avChannelLayout & AV_CH_BACK_CENTER)
486 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackCenter);
487 if (avChannelLayout & AV_CH_LOW_FREQUENCY_2)
488 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE2);
489 if (avChannelLayout & AV_CH_SIDE_LEFT)
490 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideLeft);
491 if (avChannelLayout & AV_CH_SIDE_RIGHT)
492 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideRight);
493 if (avChannelLayout & AV_CH_TOP_FRONT_LEFT)
494 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontLeft);
495 if (avChannelLayout & AV_CH_TOP_FRONT_RIGHT)
496 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontRight);
497 if (avChannelLayout & AV_CH_TOP_FRONT_CENTER)
498 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontCenter);
499 if (avChannelLayout & AV_CH_TOP_CENTER)
500 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopCenter);
501 if (avChannelLayout & AV_CH_TOP_BACK_LEFT)
502 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackLeft);
503 if (avChannelLayout & AV_CH_TOP_BACK_RIGHT)
504 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackRight);
505 if (avChannelLayout & AV_CH_TOP_BACK_CENTER)
506 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackCenter);
507 if (avChannelLayout & AV_CH_TOP_SIDE_LEFT)
508 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideLeft);
509 if (avChannelLayout & AV_CH_TOP_SIDE_RIGHT)
510 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideRight);
511 if (avChannelLayout & AV_CH_BOTTOM_FRONT_CENTER)
512 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontCenter);
513 if (avChannelLayout & AV_CH_BOTTOM_FRONT_LEFT)
514 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontLeft);
515 if (avChannelLayout & AV_CH_BOTTOM_FRONT_RIGHT)
516 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontRight);
517 return QAudioFormat::ChannelConfig(channelConfig);
521QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(
const AVCodecParameters &codecpar)
524 format.setSampleFormat(sampleFormat(AVSampleFormat(codecpar.format)));
525 format.setSampleRate(codecpar.sample_rate);
526#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
527 uint64_t channelLayout = 0;
528 if (codecpar.ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
529 channelLayout = codecpar.ch_layout.u.mask;
531 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.ch_layout.nb_channels));
533 uint64_t channelLayout = codecpar.channel_layout;
535 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.channels));
537 format.setChannelConfig(channelConfigForAVLayout(channelLayout));