UI: Refactor FFmpeg utilities codec/format enumeration

This commit is contained in:
derrod 2023-08-01 10:45:59 +02:00 committed by Lain
parent c1cd268532
commit c20bf0271c
3 changed files with 57 additions and 70 deletions

View file

@ -26,71 +26,25 @@ extern "C" {
using namespace std;
static void GetCodecsForId(const FFmpegFormat &format,
vector<FFmpegCodec> &codecs, enum AVCodecID id,
bool ignore_compaibility)
{
const AVCodec *codec = nullptr;
void *i = 0;
while ((codec = av_codec_iterate(&i)) != nullptr) {
if (codec->id != id)
continue;
// Not an encoding codec
if (!av_codec_is_encoder(codec))
continue;
// Skip if not supported and compatibility check not disabled
if (!ignore_compaibility &&
!av_codec_get_tag(format.codec_tags, codec->id)) {
continue;
}
FFmpegCodec d{codec->name, codec->long_name, codec->id};
const AVCodec *base_codec = avcodec_find_encoder(codec->id);
if (strcmp(base_codec->name, codec->name) != 0) {
d.alias = true;
d.base_name = base_codec->name;
}
switch (codec->type) {
case AVMEDIA_TYPE_AUDIO:
d.type = FFmpegCodecType::AUDIO;
break;
case AVMEDIA_TYPE_VIDEO:
d.type = FFmpegCodecType::VIDEO;
break;
default:
d.type = FFmpegCodecType::UNKNOWN;
}
codecs.push_back(d);
}
}
static std::vector<const AVCodecDescriptor *> GetCodecDescriptors()
{
std::vector<const AVCodecDescriptor *> codecs;
const AVCodecDescriptor *desc = nullptr;
while ((desc = avcodec_descriptor_next(desc)) != nullptr)
codecs.push_back(desc);
return codecs;
}
vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format,
bool ignore_compatibility)
{
vector<FFmpegCodec> codecs;
auto codecDescriptors = GetCodecDescriptors();
const AVCodec *codec;
void *i = 0;
if (codecDescriptors.empty())
return codecs;
while ((codec = av_codec_iterate(&i)) != nullptr) {
// Not an encoding codec
if (!av_codec_is_encoder(codec))
continue;
// Skip if not supported and compatibility check not disabled
if (!ignore_compatibility &&
!av_codec_get_tag(format.codec_tags, codec->id)) {
continue;
}
for (const AVCodecDescriptor *codec : codecDescriptors)
GetCodecsForId(format, codecs, codec->id, ignore_compatibility);
codecs.emplace_back(codec);
}
return codecs;
}
@ -120,15 +74,7 @@ vector<FFmpegFormat> GetSupportedFormats()
if (is_output_device(output_format->priv_class))
continue;
formats.push_back({
output_format->name,
output_format->long_name,
output_format->mime_type,
output_format->extensions,
output_format->audio_codec,
output_format->video_codec,
output_format->codec_tag,
});
formats.emplace_back(output_format);
}
return formats;

View file

@ -58,6 +58,23 @@ struct FFmpegFormat {
FFmpegFormat() = default;
FFmpegFormat(const char *name, const char *mime_type)
: name(name),
mime_type(mime_type)
{
}
FFmpegFormat(const AVOutputFormat *av_format)
: name(av_format->name),
long_name(av_format->long_name),
mime_type(av_format->mime_type),
extensions(av_format->extensions),
audio_codec(av_format->audio_codec),
video_codec(av_format->video_codec),
codec_tags(av_format->codec_tag)
{
}
const char *GetDefaultName(FFmpegCodecType codec_type) const;
bool HasAudio() const { return audio_codec != AV_CODEC_ID_NONE; }
@ -85,6 +102,30 @@ struct FFmpegCodec {
FFmpegCodec() = default;
FFmpegCodec(const char *name, int id, FFmpegCodecType type = UNKNOWN)
: name(name),
id(id),
type(type)
{
}
FFmpegCodec(const AVCodec *codec)
: name(codec->name),
long_name(codec->long_name),
id(codec->id)
{
switch (codec->type) {
case AVMEDIA_TYPE_AUDIO:
type = AUDIO;
break;
case AVMEDIA_TYPE_VIDEO:
type = VIDEO;
break;
default:
type = UNKNOWN;
}
}
bool operator==(const FFmpegCodec &codec) const
{
if (id != codec.id)

View file

@ -186,7 +186,7 @@ static inline QString GetComboData(QComboBox *combo)
static int FindEncoder(QComboBox *combo, const char *name, int id)
{
FFmpegCodec codec{name, nullptr, id};
FFmpegCodec codec{name, id};
for (int i = 0; i < combo->count(); i++) {
QVariant v = combo->itemData(i);
@ -2238,7 +2238,7 @@ void OBSBasicSettings::LoadAdvOutputRecordingEncoderProperties()
static void SelectFormat(QComboBox *combo, const char *name,
const char *mimeType)
{
FFmpegFormat format{name, nullptr, mimeType};
FFmpegFormat format{name, mimeType};
for (int i = 0; i < combo->count(); i++) {
QVariant v = combo->itemData(i);