7#include <QtCore/qloggingcategory.h>
15inline constexpr auto InvalidAvValue = T{};
18inline constexpr auto InvalidAvValue<AVSampleFormat> = AV_SAMPLE_FMT_NONE;
21inline constexpr auto InvalidAvValue<AVPixelFormat> = AV_PIX_FMT_NONE;
24QSpan<
const T> makeSpan(
const T *values)
30 while (values[size] != InvalidAvValue<T>)
33 return QSpan<
const T>{ values, size };
36#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
38Q_STATIC_LOGGING_CATEGORY(qLcFFmpegUtils,
"qt.multimedia.ffmpeg.utils");
40void logGetCodecConfigError(
const AVCodec *codec, AVCodecConfig config,
int error)
42 qCWarning(qLcFFmpegUtils) <<
"Failed to retrieve config" << config <<
"for codec" << codec->name
43 <<
"with error" << error << AVError(error);
47QSpan<
const T> getCodecConfig(
const AVCodec *codec, AVCodecConfig config)
49 const T *result =
nullptr;
51 const auto error = avcodec_get_supported_config(
52 nullptr, codec, config, 0u,
reinterpret_cast<
const void **>(&result), &size);
54 logGetCodecConfigError(codec, config, error);
61 Q_ASSERT(!result || (size > 0 && result[size] == InvalidAvValue<T>));
65 return QSpan<
const T>{ result, size };
69QSpan<
const AVPixelFormat> getCodecPixelFormats(
const AVCodec *codec)
71#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
72 return getCodecConfig<AVPixelFormat>(codec, AV_CODEC_CONFIG_PIX_FORMAT);
74 return makeSpan(codec->pix_fmts);
78QSpan<
const AVSampleFormat> getCodecSampleFormats(
const AVCodec *codec)
80#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
81 return getCodecConfig<AVSampleFormat>(codec, AV_CODEC_CONFIG_SAMPLE_FORMAT);
83 return makeSpan(codec->sample_fmts);
87QSpan<
const int> getCodecSampleRates(
const AVCodec *codec)
89#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
90 return getCodecConfig<
int>(codec, AV_CODEC_CONFIG_SAMPLE_RATE);
92 return makeSpan(codec->supported_samplerates);
100 constexpr uint64_t mask = AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT;
101#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
102 AVChannelLayout channelLayout{};
103 av_channel_layout_from_mask(&channelLayout, mask);
104 return channelLayout;
112QSpan<
const ChannelLayoutT> getCodecChannelLayouts(
const AVCodec *codec)
114 QSpan<
const ChannelLayoutT> layout;
115#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
116 layout = getCodecConfig<AVChannelLayout>(codec, AV_CODEC_CONFIG_CHANNEL_LAYOUT);
117#elif QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
118 layout = makeSpan(codec->ch_layouts);
120 layout = makeSpan(codec->channel_layouts);
126 if (layout.empty() && QLatin1StringView(codec->name) == QLatin1StringView(
"mp3_mf")) {
127 static const ChannelLayoutT defaultLayout[] = { stereoLayout() };
128 layout = defaultLayout;
134QSpan<
const AVRational> getCodecFrameRates(
const AVCodec *codec)
136#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
137 return getCodecConfig<AVRational>(codec, AV_CODEC_CONFIG_FRAME_RATE);
139 return makeSpan(codec->supported_framerates);
166 return QLatin1StringView{ m_codec->name };
173 return m_codec->type;
181 return m_codec->capabilities;
188 return av_codec_is_encoder(m_codec) != 0;
195 return av_codec_is_decoder(m_codec) != 0;
202 return (m_codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) != 0;
209 if (m_codec->type != AVMEDIA_TYPE_VIDEO)
212 return getCodecPixelFormats(m_codec);
219 if (m_codec->type != AVMEDIA_TYPE_AUDIO)
222 return getCodecSampleFormats(m_codec);
229 if (m_codec->type != AVMEDIA_TYPE_AUDIO)
232 return getCodecSampleRates(m_codec);
239 if (m_codec->type != AVMEDIA_TYPE_AUDIO)
242 return getCodecChannelLayouts(m_codec);
249 if (m_codec->type != AVMEDIA_TYPE_VIDEO)
252 return getCodecFrameRates(m_codec);
261 std::vector<
const AVCodecHWConfig *> configs;
263 for (
int index = 0;
auto config = avcodec_get_hw_config(m_codec, index); ++index)
264 configs.push_back(config);
272 iterator.m_codec = av_codec_iterate(&iterator.m_state);
284 m_codec = av_codec_iterate(&m_state);
296 return m_codec != other.m_codec;
301 return makeSpan<AVPixelFormat>(values);
static CodecIterator end()
CodecIterator & operator++() noexcept
bool operator!=(const CodecIterator &other) const noexcept
static CodecIterator begin()
Codec operator*() const noexcept
QSpan< const int > sampleRates() const noexcept
const AVCodec * get() const noexcept
AVCodecID id() const noexcept
QSpan< const ChannelLayoutT > channelLayouts() const noexcept
bool isExperimental() const noexcept
QSpan< const AVPixelFormat > pixelFormats() const noexcept
QLatin1StringView name() const noexcept
std::vector< const AVCodecHWConfig * > hwConfigs() const noexcept
bool isEncoder() const noexcept
Codec(const AVCodec *codec)
int capabilities() const noexcept
QSpan< const AVRational > frameRates() const noexcept
AVMediaType type() const noexcept
bool isDecoder() const noexcept
QSpan< const AVSampleFormat > sampleFormats() const noexcept
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
QSpan< const AVPixelFormat > makeSpan(const AVPixelFormat *values)