119QFFmpegMediaFormatInfo::QFFmpegMediaFormatInfo()
121 using VideoCodec = QMediaFormat::VideoCodec;
122 using AudioCodec = QMediaFormat::AudioCodec;
124 QList<AudioCodec> audioEncoders;
125 QList<AudioCodec> extraAudioDecoders;
126 QList<VideoCodec> videoEncoders;
127 QList<VideoCodec> extraVideoDecoders;
130 const AVCodecDescriptor *descriptor =
nullptr;
131 while ((descriptor = avcodec_descriptor_next(descriptor))) {
133 const bool canEncode{ QFFmpeg::findAVEncoder(descriptor->id).has_value() };
134 const bool canDecode{ QFFmpeg::findAVDecoder(descriptor->id).has_value() };
136 const VideoCodec videoCodec = videoCodecForAVCodecId(descriptor->id);
137 const AudioCodec audioCodec = audioCodecForAVCodecId(descriptor->id);
139 if (descriptor->type == AVMEDIA_TYPE_VIDEO && videoCodec != VideoCodec::Unspecified) {
141 if (!videoEncoders.contains(videoCodec))
142 videoEncoders.append(videoCodec);
143 }
else if (canDecode) {
144 if (!extraVideoDecoders.contains(videoCodec))
145 extraVideoDecoders.append(videoCodec);
147 }
else if (descriptor->type == AVMEDIA_TYPE_AUDIO && audioCodec != AudioCodec::Unspecified) {
149 if (!audioEncoders.contains(audioCodec))
150 audioEncoders.append(audioCodec);
151 }
else if (canDecode) {
152 if (!extraAudioDecoders.contains(audioCodec))
153 extraAudioDecoders.append(audioCodec);
159 void *opaque =
nullptr;
160 const AVOutputFormat *outputFormat =
nullptr;
161 while ((outputFormat = av_muxer_iterate(&opaque))) {
162 QMediaFormat::FileFormat mediaFormat = formatForAVFormat(outputFormat);
163 if (mediaFormat == QMediaFormat::UnspecifiedFormat)
167 encoder.format = mediaFormat;
169 for (AudioCodec codec : audioEncoders) {
170 const AVCodecID id = codecId(codec);
173 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
174 if (result == 1 || (result < 0 && id == outputFormat->audio_codec)) {
176 encoder.audio.append(codec);
180 for (VideoCodec codec : videoEncoders) {
181 const AVCodecID id = codecId(codec);
184 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
185 if (result == 1 || (result < 0 && id == outputFormat->video_codec)) {
187 encoder.video.append(codec);
192 if (encoder.audio.isEmpty() && encoder.video.isEmpty())
196 switch (encoder.format) {
197 case QMediaFormat::WMV:
199 encoders.append({ QMediaFormat::WMA, encoder.audio, {} });
201 case QMediaFormat::MPEG4:
203 encoders.append({ QMediaFormat::QuickTime, encoder.audio, encoder.video });
204 encoders.append({ QMediaFormat::Mpeg4Audio, encoder.audio, {} });
206 case QMediaFormat::Wave:
208 if (!encoder.audio.contains(AudioCodec::Wave))
210 encoder.audio = { AudioCodec::Wave };
216 encoders.append(encoder);
226 for (
auto &encoder : encoders) {
227 auto h265index = encoder.video.indexOf(VideoCodec::H265);
229 encoder.video.removeAt(h265index);
234 for (
auto &encoder : encoders) {
235 if (encoder.format == QMediaFormat::Matroska) {
236 encoder.video.removeAll(VideoCodec::H264);
240 encoder.video.removeAll(VideoCodec::H265);
246 if (extraAudioDecoders.contains(AudioCodec::WMA)) {
247 decoders[QMediaFormat::WMA].audio.append(AudioCodec::WMA);
248 decoders[QMediaFormat::WMV].audio.append(AudioCodec::WMA);
251 if (extraVideoDecoders.contains(VideoCodec::WMV)) {
252 decoders[QMediaFormat::WMV].video.append(VideoCodec::WMV);
258 const QList<QByteArray> imgFormats = QImageWriter::supportedImageFormats();
259 for (
const auto &f : imgFormats) {
261 imageFormats.append(QImageCapture::PNG);
262 else if (f ==
"jpeg")
263 imageFormats.append(QImageCapture::JPEG);
264 else if (f ==
"tiff")
265 imageFormats.append(QImageCapture::Tiff);
266 else if (f ==
"webp")
267 imageFormats.append(QImageCapture::WebP);
293QFFmpegMediaFormatInfo::fileFormatForAVInputFormat(
const AVInputFormat &format)
301 QMediaFormat::FileFormat fileFormat;
303 } map[QMediaFormat::LastFileFormat + 1] = {
304 { QMediaFormat::WMV,
"asf" },
305 { QMediaFormat::AVI,
"avi" },
306 { QMediaFormat::Matroska,
"matroska" },
307 { QMediaFormat::MPEG4,
"mov" },
308 { QMediaFormat::Ogg,
"ogg" },
309 { QMediaFormat::WebM,
"webm" },
312 { QMediaFormat::AAC,
"aac"},
314 { QMediaFormat::FLAC,
"flac" },
315 { QMediaFormat::MP3,
"mp3" },
316 { QMediaFormat::Wave,
"wav" },
317 { QMediaFormat::UnspecifiedFormat,
nullptr }
321 return QMediaFormat::UnspecifiedFormat;
324 while (m->fileFormat != QMediaFormat::UnspecifiedFormat) {
325 if (!strncmp(m->name, format.name, strlen(m->name)))
326 return m->fileFormat;
330 return QMediaFormat::UnspecifiedFormat;
392int64_t QFFmpegMediaFormatInfo::avChannelLayout(QAudioFormat::ChannelConfig channelConfig)
394 int64_t avChannelLayout = 0;
395 if (channelConfig & (1 << QAudioFormat::FrontLeft))
396 avChannelLayout |= AV_CH_FRONT_LEFT;
397 if (channelConfig & (1 << QAudioFormat::FrontRight))
398 avChannelLayout |= AV_CH_FRONT_RIGHT;
399 if (channelConfig & (1 << QAudioFormat::FrontCenter))
400 avChannelLayout |= AV_CH_FRONT_CENTER;
401 if (channelConfig & (1 << QAudioFormat::LFE))
402 avChannelLayout |= AV_CH_LOW_FREQUENCY;
403 if (channelConfig & (1 << QAudioFormat::BackLeft))
404 avChannelLayout |= AV_CH_BACK_LEFT;
405 if (channelConfig & (1 << QAudioFormat::BackRight))
406 avChannelLayout |= AV_CH_BACK_RIGHT;
407 if (channelConfig & (1 << QAudioFormat::FrontLeftOfCenter))
408 avChannelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
409 if (channelConfig & (1 << QAudioFormat::FrontRightOfCenter))
410 avChannelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
411 if (channelConfig & (1 << QAudioFormat::BackCenter))
412 avChannelLayout |= AV_CH_BACK_CENTER;
413 if (channelConfig & (1 << QAudioFormat::LFE2))
414 avChannelLayout |= AV_CH_LOW_FREQUENCY_2;
415 if (channelConfig & (1 << QAudioFormat::SideLeft))
416 avChannelLayout |= AV_CH_SIDE_LEFT;
417 if (channelConfig & (1 << QAudioFormat::SideRight))
418 avChannelLayout |= AV_CH_SIDE_RIGHT;
419 if (channelConfig & (1 << QAudioFormat::TopFrontLeft))
420 avChannelLayout |= AV_CH_TOP_FRONT_LEFT;
421 if (channelConfig & (1 << QAudioFormat::TopFrontRight))
422 avChannelLayout |= AV_CH_TOP_FRONT_RIGHT;
423 if (channelConfig & (1 << QAudioFormat::TopFrontCenter))
424 avChannelLayout |= AV_CH_TOP_FRONT_CENTER;
425 if (channelConfig & (1 << QAudioFormat::TopCenter))
426 avChannelLayout |= AV_CH_TOP_CENTER;
427 if (channelConfig & (1 << QAudioFormat::TopBackLeft))
428 avChannelLayout |= AV_CH_TOP_BACK_LEFT;
429 if (channelConfig & (1 << QAudioFormat::TopBackRight))
430 avChannelLayout |= AV_CH_TOP_BACK_RIGHT;
431 if (channelConfig & (1 << QAudioFormat::TopBackCenter))
432 avChannelLayout |= AV_CH_TOP_BACK_CENTER;
434#ifdef AV_CH_TOP_SIDE_LEFT
435 if (channelConfig & (1 << QAudioFormat::TopSideLeft))
436 avChannelLayout |= AV_CH_TOP_SIDE_LEFT;
437 if (channelConfig & (1 << QAudioFormat::TopSideRight))
438 avChannelLayout |= AV_CH_TOP_SIDE_RIGHT;
439 if (channelConfig & (1 << QAudioFormat::BottomFrontCenter))
440 avChannelLayout |= AV_CH_BOTTOM_FRONT_CENTER;
441 if (channelConfig & (1 << QAudioFormat::BottomFrontLeft))
442 avChannelLayout |= AV_CH_BOTTOM_FRONT_LEFT;
443 if (channelConfig & (1 << QAudioFormat::BottomFrontRight))
444 avChannelLayout |= AV_CH_BOTTOM_FRONT_RIGHT;
446 return avChannelLayout;
449QAudioFormat::ChannelConfig QFFmpegMediaFormatInfo::channelConfigForAVLayout(int64_t avChannelLayout)
451 quint32 channelConfig = 0;
452 if (avChannelLayout & AV_CH_FRONT_LEFT)
453 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeft);
454 if (avChannelLayout & AV_CH_FRONT_RIGHT)
455 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRight);
456 if (avChannelLayout & AV_CH_FRONT_CENTER)
457 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontCenter);
458 if (avChannelLayout & AV_CH_LOW_FREQUENCY)
459 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE);
460 if (avChannelLayout & AV_CH_BACK_LEFT)
461 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackLeft);
462 if (avChannelLayout & AV_CH_BACK_RIGHT)
463 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackRight);
464 if (avChannelLayout & AV_CH_FRONT_LEFT_OF_CENTER)
465 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontLeftOfCenter);
466 if (avChannelLayout & AV_CH_FRONT_RIGHT_OF_CENTER)
467 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::FrontRightOfCenter);
468 if (avChannelLayout & AV_CH_BACK_CENTER)
469 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BackCenter);
470 if (avChannelLayout & AV_CH_LOW_FREQUENCY_2)
471 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::LFE2);
472 if (avChannelLayout & AV_CH_SIDE_LEFT)
473 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideLeft);
474 if (avChannelLayout & AV_CH_SIDE_RIGHT)
475 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::SideRight);
476 if (avChannelLayout & AV_CH_TOP_FRONT_LEFT)
477 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontLeft);
478 if (avChannelLayout & AV_CH_TOP_FRONT_RIGHT)
479 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontRight);
480 if (avChannelLayout & AV_CH_TOP_FRONT_CENTER)
481 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopFrontCenter);
482 if (avChannelLayout & AV_CH_TOP_CENTER)
483 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopCenter);
484 if (avChannelLayout & AV_CH_TOP_BACK_LEFT)
485 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackLeft);
486 if (avChannelLayout & AV_CH_TOP_BACK_RIGHT)
487 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackRight);
488 if (avChannelLayout & AV_CH_TOP_BACK_CENTER)
489 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopBackCenter);
491#ifdef AV_CH_TOP_SIDE_LEFT
492 if (avChannelLayout & AV_CH_TOP_SIDE_LEFT)
493 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideLeft);
494 if (avChannelLayout & AV_CH_TOP_SIDE_RIGHT)
495 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::TopSideRight);
496 if (avChannelLayout & AV_CH_BOTTOM_FRONT_CENTER)
497 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontCenter);
498 if (avChannelLayout & AV_CH_BOTTOM_FRONT_LEFT)
499 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontLeft);
500 if (avChannelLayout & AV_CH_BOTTOM_FRONT_RIGHT)
501 channelConfig |= QAudioFormat::channelConfig(QAudioFormat::BottomFrontRight);
503 return QAudioFormat::ChannelConfig(channelConfig);
507QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(
const AVCodecParameters &codecpar)
510 format.setSampleFormat(sampleFormat(AVSampleFormat(codecpar.format)));
511 format.setSampleRate(codecpar.sample_rate);
512#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
513 uint64_t channelLayout = 0;
514 if (codecpar.ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
515 channelLayout = codecpar.ch_layout.u.mask;
517 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.ch_layout.nb_channels));
519 uint64_t channelLayout = codecpar.channel_layout;
521 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.channels));
523 format.setChannelConfig(channelConfigForAVLayout(channelLayout));