ffmpeg: Avoid listing child classes for AVFormatContext and AVCodecContext

As they actually have every encoder/format as their child classes, this will result in a lot of extra options being added.
This commit is contained in:
zhupengfei 2020-02-28 16:40:13 +08:00
parent a28eac08ae
commit f3e9780d10
No known key found for this signature in database
GPG key ID: DD129E108BD09378

View file

@ -728,41 +728,33 @@ void GetOptionListSingle(std::vector<OptionInfo>& out, const AVClass* av_class)
} }
} }
void GetOptionList(std::vector<OptionInfo>& out, const AVClass* av_class) { void GetOptionList(std::vector<OptionInfo>& out, const AVClass* av_class, bool search_children) {
if (av_class == nullptr) { if (av_class == nullptr) {
return; return;
} }
GetOptionListSingle(out, av_class); GetOptionListSingle(out, av_class);
if (!search_children) {
return;
}
const AVClass* child_class = nullptr; const AVClass* child_class = nullptr;
while ((child_class = av_opt_child_class_next(av_class, child_class))) { while ((child_class = av_opt_child_class_next(av_class, child_class))) {
GetOptionListSingle(out, child_class); GetOptionListSingle(out, child_class);
} }
} }
std::vector<OptionInfo> GetOptionList(const AVClass* av_class) { std::vector<OptionInfo> GetOptionList(const AVClass* av_class, bool search_children) {
std::vector<OptionInfo> out; std::vector<OptionInfo> out;
GetOptionList(out, av_class); GetOptionList(out, av_class, search_children);
return out;
// Filter out identical options (why do they exist in the first place?)
std::unordered_set<std::string> option_name_set;
std::vector<OptionInfo> final_out;
for (auto& option : out) {
if (option_name_set.count(option.name)) {
continue;
}
option_name_set.emplace(option.name);
final_out.emplace_back(std::move(option));
}
return final_out;
} }
std::vector<EncoderInfo> ListEncoders(AVMediaType type) { std::vector<EncoderInfo> ListEncoders(AVMediaType type) {
InitializeFFmpegLibraries(); InitializeFFmpegLibraries();
const auto general_options = GetOptionList(avcodec_get_class()); const auto general_options = GetOptionList(avcodec_get_class(), false);
std::vector<EncoderInfo> out; std::vector<EncoderInfo> out;
@ -776,7 +768,7 @@ std::vector<EncoderInfo> ListEncoders(AVMediaType type) {
if (!av_codec_is_encoder(current) || current->type != type) { if (!av_codec_is_encoder(current) || current->type != type) {
continue; continue;
} }
auto options = GetOptionList(current->priv_class); auto options = GetOptionList(current->priv_class, true);
options.insert(options.end(), general_options.begin(), general_options.end()); options.insert(options.end(), general_options.begin(), general_options.end());
out.push_back( out.push_back(
{current->name, ToStdString(current->long_name), current->id, std::move(options)}); {current->name, ToStdString(current->long_name), current->id, std::move(options)});
@ -787,7 +779,7 @@ std::vector<EncoderInfo> ListEncoders(AVMediaType type) {
std::vector<FormatInfo> ListFormats() { std::vector<FormatInfo> ListFormats() {
InitializeFFmpegLibraries(); InitializeFFmpegLibraries();
const auto general_options = GetOptionList(avformat_get_class()); const auto general_options = GetOptionList(avformat_get_class(), false);
std::vector<FormatInfo> out; std::vector<FormatInfo> out;
@ -798,7 +790,7 @@ std::vector<FormatInfo> ListFormats() {
void* data = nullptr; // For libavformat to save the iteration state void* data = nullptr; // For libavformat to save the iteration state
while ((current = av_muxer_iterate(&data))) { while ((current = av_muxer_iterate(&data))) {
#endif #endif
auto options = GetOptionList(current->priv_class); auto options = GetOptionList(current->priv_class, true);
options.insert(options.end(), general_options.begin(), general_options.end()); options.insert(options.end(), general_options.begin(), general_options.end());
std::vector<std::string> extensions; std::vector<std::string> extensions;