120QFFmpegMediaFormatInfo::QFFmpegMediaFormatInfo()
122 using VideoCodec = QMediaFormat::VideoCodec;
123 using AudioCodec = QMediaFormat::AudioCodec;
125 QList<AudioCodec> audioEncoders;
126 QList<AudioCodec> extraAudioDecoders;
127 QList<VideoCodec> videoEncoders;
128 QList<VideoCodec> extraVideoDecoders;
131 const AVCodecDescriptor *descriptor =
nullptr;
132 while ((descriptor = avcodec_descriptor_next(descriptor))) {
134 const bool canEncode{ QFFmpeg::findAVEncoder(descriptor->id).has_value() };
135 const bool canDecode{ QFFmpeg::findAVDecoder(descriptor->id).has_value() };
137 const VideoCodec videoCodec = videoCodecForAVCodecId(descriptor->id);
138 const AudioCodec audioCodec = audioCodecForAVCodecId(descriptor->id);
140 if (descriptor->type == AVMEDIA_TYPE_VIDEO && videoCodec != VideoCodec::Unspecified) {
142 if (!videoEncoders.contains(videoCodec))
143 videoEncoders.append(videoCodec);
144 }
else if (canDecode) {
145 if (!extraVideoDecoders.contains(videoCodec))
146 extraVideoDecoders.append(videoCodec);
148 }
else if (descriptor->type == AVMEDIA_TYPE_AUDIO && audioCodec != AudioCodec::Unspecified) {
150 if (!audioEncoders.contains(audioCodec))
151 audioEncoders.append(audioCodec);
152 }
else if (canDecode) {
153 if (!extraAudioDecoders.contains(audioCodec))
154 extraAudioDecoders.append(audioCodec);
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)
168 encoder.format = mediaFormat;
170 for (AudioCodec codec : audioEncoders) {
171 const AVCodecID id = codecId(codec);
174 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
175 if (result == 1 || (result < 0 && id == outputFormat->audio_codec)) {
177 encoder.audio.append(codec);
181 for (VideoCodec codec : videoEncoders) {
182 const AVCodecID id = codecId(codec);
185 const int result = avformat_query_codec(outputFormat, id, FF_COMPLIANCE_NORMAL);
186 if (result == 1 || (result < 0 && id == outputFormat->video_codec)) {
188 encoder.video.append(codec);
193 if (encoder.audio.isEmpty() && encoder.video.isEmpty())
197 switch (encoder.format) {
198 case QMediaFormat::WMV:
200 encoders.append({ QMediaFormat::WMA, encoder.audio, {} });
202 case QMediaFormat::MPEG4:
204 encoders.append({ QMediaFormat::QuickTime, encoder.audio, encoder.video });
205 encoders.append({ QMediaFormat::Mpeg4Audio, encoder.audio, {} });
207 case QMediaFormat::Wave:
209 if (!encoder.audio.contains(AudioCodec::Wave))
211 encoder.audio = { AudioCodec::Wave };
217 encoders.append(encoder);
227 for (
auto &encoder : encoders) {
228 auto h265index = encoder.video.indexOf(VideoCodec::H265);
230 encoder.video.removeAt(h265index);
235 for (
auto &encoder : encoders) {
236 if (encoder.format == QMediaFormat::Matroska) {
237 encoder.video.removeAll(VideoCodec::H264);
241 encoder.video.removeAll(VideoCodec::H265);
247 if (extraAudioDecoders.contains(AudioCodec::WMA)) {
248 decoders[QMediaFormat::WMA].audio.append(AudioCodec::WMA);
249 decoders[QMediaFormat::WMV].audio.append(AudioCodec::WMA);
252 if (extraVideoDecoders.contains(VideoCodec::WMV)) {
253 decoders[QMediaFormat::WMV].video.append(VideoCodec::WMV);
259 const QList<QByteArray> imgFormats = QImageWriter::supportedImageFormats();
260 for (
const auto &f : imgFormats) {
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);
294QFFmpegMediaFormatInfo::fileFormatForAVInputFormat(
const AVInputFormat &format)
302 QMediaFormat::FileFormat fileFormat;
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" },
313 { QMediaFormat::AAC,
"aac"},
315 { QMediaFormat::FLAC,
"flac" },
316 { QMediaFormat::MP3,
"mp3" },
317 { QMediaFormat::Wave,
"wav" },
318 { QMediaFormat::UnspecifiedFormat,
nullptr }
322 return QMediaFormat::UnspecifiedFormat;
325 while (m->fileFormat != QMediaFormat::UnspecifiedFormat) {
326 if (!strncmp(m->name, format.name, strlen(m->name)))
327 return m->fileFormat;
331 return QMediaFormat::UnspecifiedFormat;
393int64_t QFFmpegMediaFormatInfo::avChannelLayout(QAudioFormat::ChannelConfig channelConfig)
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;
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;
447 return avChannelLayout;
450QAudioFormat::ChannelConfig QFFmpegMediaFormatInfo::channelConfigForAVLayout(int64_t avChannelLayout)
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);
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);
504 return QAudioFormat::ChannelConfig(channelConfig);
508QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(
const AVCodecParameters &codecpar)
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;
518 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.ch_layout.nb_channels));
520 uint64_t channelLayout = codecpar.channel_layout;
522 channelLayout = avChannelLayout(QAudioFormat::defaultChannelConfigForChannelCount(codecpar.channels));
524 format.setChannelConfig(channelConfigForAVLayout(channelLayout));