mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-20 22:40:18 +00:00
capabilities: report video compression codecs, encoders, options
This commit is contained in:
45
src/host.cpp
45
src/host.cpp
@@ -314,6 +314,51 @@ void print_capabilities(struct module *root, bool use_vidcap)
|
||||
it.dec_prop.latency << ";" << it.dec_prop.cpu_cores << ";" << it.dec_prop.gpu_gflops <<
|
||||
")\n";
|
||||
}
|
||||
|
||||
if(vci->get_module_info){
|
||||
auto module_info = vci->get_module_info();
|
||||
cout << "[capability][video_compress][v3] {"
|
||||
"\"name\":\"" << it.first << "\", "
|
||||
"\"options\": [";
|
||||
|
||||
int i = 0;
|
||||
for(const auto& opt : module_info.opts){
|
||||
if(i++ > 0)
|
||||
cout << ", ";
|
||||
|
||||
cout << "{"
|
||||
"\"display_name\":\"" << opt.display_name << "\", "
|
||||
"\"display_desc\":\"" << opt.display_desc << "\", "
|
||||
"\"key\":\"" << opt.key << "\", "
|
||||
"\"opt_str\":\"" << opt.opt_str << "\", "
|
||||
"\"is_boolean\":\"" << (opt.is_boolean ? "t" : "f") << "\"}";
|
||||
}
|
||||
|
||||
cout << "], "
|
||||
"\"codecs\": [";
|
||||
|
||||
int j = 0;
|
||||
for(const auto& c : module_info.codecs){
|
||||
if(j++ > 0)
|
||||
cout << ", ";
|
||||
|
||||
cout << "{\"name\":\"" << c.name << "\", "
|
||||
"\"encoders\":[";
|
||||
|
||||
int z = 0;
|
||||
for(const auto& e : c.encoders){
|
||||
if(z++ > 0)
|
||||
cout << ", ";
|
||||
|
||||
cout << "{\"name\":\"" << e.name << "\", "
|
||||
"\"opt_str\":\"" << e.opt_str << "\"}";
|
||||
}
|
||||
cout << "]}";
|
||||
}
|
||||
|
||||
cout << "]}" << std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// capture filters
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define VIDEO_COMPRESS_ABI_VERSION 7
|
||||
#define VIDEO_COMPRESS_ABI_VERSION 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -101,6 +101,7 @@ const char *get_compress_name(struct compress_state *);
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Compresses video frame
|
||||
@@ -174,6 +175,36 @@ struct compress_preset {
|
||||
compress_prop dec_prop;
|
||||
};
|
||||
|
||||
struct module_option{
|
||||
std::string display_name; //Name displayed to user
|
||||
std::string display_desc; //Description displayed to user
|
||||
|
||||
/* internal name of option, options that are used in the same way should
|
||||
* have the same key (e.g. both bitrate for libavcodec and quality for jpeg
|
||||
* should have the same key). This allows using different labels displayed
|
||||
* to user */
|
||||
std::string key;
|
||||
std::string opt_str; //Option string to pass to ug (e.g. ":bitrate=")
|
||||
|
||||
bool is_boolean; //If true, GUI shows a checkbox instead of text edit
|
||||
};
|
||||
|
||||
struct encoder{
|
||||
std::string name;
|
||||
std::string opt_str;
|
||||
};
|
||||
|
||||
struct codec{
|
||||
std::string name;
|
||||
std::vector<encoder> encoders;
|
||||
};
|
||||
|
||||
struct compress_module_info{
|
||||
std::string name;
|
||||
std::vector<module_option> opts;
|
||||
std::vector<codec> codecs;
|
||||
};
|
||||
|
||||
/**
|
||||
* There are 4 possible APIs for video compress modules. Each module may choose
|
||||
* which one to implement, however, only one should be implemented (there is no
|
||||
@@ -203,6 +234,8 @@ struct video_compress_info {
|
||||
* Optional - currently not used
|
||||
*/
|
||||
std::list<compress_preset> (*get_presets)();
|
||||
|
||||
compress_module_info (*get_module_info)();
|
||||
};
|
||||
|
||||
std::shared_ptr<video_frame> compress_pop(struct compress_state *);
|
||||
|
||||
@@ -451,7 +451,8 @@ static struct video_compress_info j2k_compress_info = {
|
||||
NULL,
|
||||
j2k_compress_push,
|
||||
j2k_compress_pop,
|
||||
[] { return list<compress_preset>{}; }
|
||||
[] { return list<compress_preset>{}; },
|
||||
NULL
|
||||
};
|
||||
|
||||
REGISTER_MODULE(cmpto_j2k, &j2k_compress_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION);
|
||||
|
||||
@@ -299,7 +299,8 @@ const struct video_compress_info cuda_dxt_info = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
[] { return list<compress_preset>{}; }
|
||||
[] { return list<compress_preset>{}; },
|
||||
NULL
|
||||
};
|
||||
|
||||
REGISTER_MODULE(cuda_dxt, &cuda_dxt_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION);
|
||||
|
||||
@@ -344,7 +344,8 @@ const struct video_compress_info rtdxt_info = {
|
||||
{ "DXT5", 50, [](const struct video_desc *d){return (long)(d->width * d->height * d->fps * 8.0);},
|
||||
{75, 0.3, 35}, {15, 0.1, 20} },
|
||||
} : list<compress_preset>{};
|
||||
}
|
||||
},
|
||||
NULL
|
||||
};
|
||||
|
||||
REGISTER_MODULE(rtdxt, &rtdxt_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION);
|
||||
|
||||
@@ -244,76 +244,76 @@ struct state_video_compress_libav {
|
||||
#endif
|
||||
};
|
||||
|
||||
static void print_codec_info(AVCodecID id, char *buf, size_t buflen)
|
||||
{
|
||||
struct codec_encoders_decoders{
|
||||
std::vector<std::string> encoders;
|
||||
std::vector<std::string> decoders;
|
||||
};
|
||||
|
||||
static codec_encoders_decoders get_codec_encoders_decoders(AVCodecID id){
|
||||
codec_encoders_decoders res;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 9, 100)
|
||||
assert(buflen > 0);
|
||||
buf[0] = '\0';
|
||||
const AVCodec *codec = nullptr;
|
||||
void *i = 0;
|
||||
char *enc = (char *) alloca(buflen);
|
||||
char *dec = (char *) alloca(buflen);
|
||||
dec[0] = enc[0] = '\0';
|
||||
while ((codec = av_codec_iterate(&i))) {
|
||||
if (av_codec_is_encoder(codec) && codec->id == id) {
|
||||
strncat(enc, " ", buflen - strlen(enc) - 1);
|
||||
strncat(enc, codec->name, buflen - strlen(enc) - 1);
|
||||
res.encoders.emplace_back(codec->name);
|
||||
}
|
||||
if (av_codec_is_decoder(codec) && codec->id == id) {
|
||||
strncat(dec, " ", buflen - strlen(dec) - 1);
|
||||
strncat(dec, codec->name, buflen - strlen(dec) - 1);
|
||||
res.decoders.emplace_back(codec->name);
|
||||
}
|
||||
}
|
||||
if (strlen(enc) || strlen(dec)) {
|
||||
strncat(buf, " (", buflen - strlen(buf) - 1);
|
||||
if (strlen(enc)) {
|
||||
strncat(buf, "encoders:", buflen - strlen(buf) - 1);
|
||||
strncat(buf, enc, buflen - strlen(buf) - 1);
|
||||
}
|
||||
if (strlen(dec)) {
|
||||
if (strlen(enc)) {
|
||||
strncat(buf, ", ", buflen - strlen(buf) - 1);
|
||||
}
|
||||
strncat(buf, "decoders:", buflen - strlen(buf) - 1);
|
||||
strncat(buf, dec, buflen - strlen(buf) - 1);
|
||||
}
|
||||
strncat(buf, ")", buflen - strlen(buf) - 1);
|
||||
}
|
||||
#elif LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
const AVCodec *codec;
|
||||
const AVCodec *codec = nullptr;
|
||||
if ((codec = avcodec_find_encoder(id))) {
|
||||
strncpy(buf, " (encoders:", buflen - 1);
|
||||
buf[buflen - 1] = '\0';
|
||||
do {
|
||||
if (av_codec_is_encoder(codec) && codec->id == id) {
|
||||
strncat(buf, " ", buflen - strlen(buf) - 1);
|
||||
strncat(buf, codec->name, buflen - strlen(buf) - 1);
|
||||
res.encoders.emplace_back(codec->name);
|
||||
}
|
||||
} while ((codec = av_codec_next(codec)));
|
||||
}
|
||||
|
||||
if ((codec = avcodec_find_decoder(id))) {
|
||||
if (avcodec_find_encoder(id)) {
|
||||
strncat(buf, ", ", buflen - strlen(buf) - 1);
|
||||
} else {
|
||||
strncat(buf, " (", buflen - strlen(buf) - 1);
|
||||
}
|
||||
strncat(buf, "decoders:", buflen - strlen(buf) - 1);
|
||||
do {
|
||||
if (av_codec_is_decoder(codec) && codec->id == id) {
|
||||
strncat(buf, " ", buflen - strlen(buf) - 1);
|
||||
strncat(buf, codec->name, buflen - strlen(buf) - 1);
|
||||
res.decoders.emplace_back(codec->name);
|
||||
}
|
||||
} while ((codec = av_codec_next(codec)));
|
||||
}
|
||||
if (avcodec_find_encoder(id) || avcodec_find_decoder(id)) {
|
||||
strncat(buf, ")", buflen - strlen(buf) - 1);
|
||||
}
|
||||
#else
|
||||
UNUSED(id);
|
||||
UNUSED(buf);
|
||||
UNUSED(buflen);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void print_codec_info(AVCodecID id, char *buf, size_t buflen)
|
||||
{
|
||||
auto info = get_codec_encoders_decoders(id);
|
||||
assert(buflen > 0);
|
||||
buf[0] = '\0';
|
||||
if(info.encoders.empty() && info.decoders.empty())
|
||||
return;
|
||||
|
||||
strncat(buf, " (", buflen - strlen(buf) - 1);
|
||||
if (!info.encoders.empty()) {
|
||||
strncat(buf, "encoders:", buflen - strlen(buf) - 1);
|
||||
for(const auto& enc : info.encoders){
|
||||
strncat(buf, " ", buflen - strlen(buf) - 1);
|
||||
strncat(buf, enc.c_str(), buflen - strlen(buf) - 1);
|
||||
}
|
||||
}
|
||||
if (!info.decoders.empty()) {
|
||||
if (!info.encoders.empty()) {
|
||||
strncat(buf, ", ", buflen - strlen(buf) - 1);
|
||||
}
|
||||
strncat(buf, "decoders:", buflen - strlen(buf) - 1);
|
||||
|
||||
for(const auto& dec : info.decoders){
|
||||
strncat(buf, " ", buflen - strlen(buf) - 1);
|
||||
strncat(buf, dec.c_str(), buflen - strlen(buf) - 1);
|
||||
}
|
||||
}
|
||||
strncat(buf, ")", buflen - strlen(buf) - 1);
|
||||
}
|
||||
|
||||
static void usage() {
|
||||
@@ -500,6 +500,39 @@ static list<compress_preset> get_libavcodec_presets() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static compress_module_info get_libavcodec_module_info(){
|
||||
compress_module_info module_info;
|
||||
module_info.name = "libavcodec";
|
||||
module_info.opts.emplace_back(module_option{"Bitrate", "Bitrate", "quality", "bitrate=", false});
|
||||
module_info.opts.emplace_back(module_option{"Crf", "Crf", "crf", "crf=", false});
|
||||
|
||||
for (const auto& param : codec_params) {
|
||||
enum AVCodecID avID = get_ug_to_av_codec(param.first);
|
||||
if (avID == AV_CODEC_ID_NONE) { // old FFMPEG -> codec id is flushed to 0 in compat
|
||||
continue;
|
||||
}
|
||||
const AVCodec *i;
|
||||
if (!(i = avcodec_find_encoder(avID))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
codec codec_info;
|
||||
codec_info.name = get_codec_name(param.first);
|
||||
codec_info.encoders.emplace_back(
|
||||
encoder{"default", ":codec=" + codec_info.name});
|
||||
|
||||
auto coders = get_codec_encoders_decoders(avID);
|
||||
for(const auto& enc : coders.encoders){
|
||||
codec_info.encoders.emplace_back(
|
||||
encoder{enc, ":encoder=" + enc});
|
||||
}
|
||||
|
||||
module_info.codecs.emplace_back(std::move(codec_info));
|
||||
}
|
||||
|
||||
return module_info;
|
||||
}
|
||||
|
||||
struct module * libavcodec_compress_init(struct module *parent, const char *opts)
|
||||
{
|
||||
struct state_video_compress_libav *s;
|
||||
@@ -1880,6 +1913,7 @@ const struct video_compress_info libavcodec_info = {
|
||||
NULL,
|
||||
NULL,
|
||||
get_libavcodec_presets,
|
||||
get_libavcodec_module_info,
|
||||
};
|
||||
|
||||
REGISTER_MODULE(libavcodec, &libavcodec_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION);
|
||||
|
||||
@@ -110,7 +110,8 @@ const struct video_compress_info none_info = {
|
||||
{ "", 100, [](const struct video_desc *d){return (long)(d->width * d->height * d->fps * get_bpp(d->color_spec) * 8.0);},
|
||||
{0, 1, 0}, {0, 1, 0} },
|
||||
};
|
||||
}
|
||||
},
|
||||
NULL
|
||||
};
|
||||
|
||||
REGISTER_MODULE(none, &none_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION);
|
||||
|
||||
@@ -308,7 +308,8 @@ const struct video_compress_info uyvy_info = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
[] {return list<compress_preset>{}; }
|
||||
[] {return list<compress_preset>{}; },
|
||||
NULL
|
||||
};
|
||||
|
||||
REGISTER_MODULE(uyvy, &uyvy_info, LIBRARY_CLASS_VIDEO_COMPRESS, VIDEO_COMPRESS_ABI_VERSION);
|
||||
|
||||
Reference in New Issue
Block a user