mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-22 09:40:30 +00:00
Decoder: use vector for native codecs
This fixes a problem with incorrect handling native codec list - using parameter "decoder-use-codec" only set native_count but there were places where was expected a NULL-terminated list. (Example wrong behavior may be observed with "-d dummy --param decoder-use-codes=" when the codec is not reflected).
This commit is contained in:
@@ -347,8 +347,7 @@ struct state_video_decoder
|
||||
|
||||
struct display *display = NULL; ///< assigned display device
|
||||
/// @{
|
||||
codec_t native_codecs[VIDEO_CODEC_COUNT] = {}; ///< list of native codecs, must be NULL-terminated
|
||||
size_t native_count = 0; ///< count of @ref native_codecs
|
||||
vector<codec_t> native_codecs; ///< list of display native codecs
|
||||
enum interlacing_t *disp_supported_il = NULL; ///< display supported interlacing mode
|
||||
size_t disp_supported_il_cnt = 0; ///< count of @ref disp_supported_il
|
||||
/// @}
|
||||
@@ -569,17 +568,12 @@ static bool blacklist_current_out_codec(struct state_video_decoder *decoder){
|
||||
if(decoder->out_codec == VIDEO_CODEC_NONE)
|
||||
return false;
|
||||
|
||||
for(size_t i = 0; i < decoder->native_count; i++){
|
||||
if(decoder->native_codecs[i] == decoder->out_codec){
|
||||
log_msg(LOG_LEVEL_DEBUG, "Blacklisting codec %s\n", get_codec_name(decoder->out_codec));
|
||||
memmove(decoder->native_codecs + i, decoder->native_codecs + i + 1,
|
||||
(decoder->native_count - i - 1) * sizeof(codec_t));
|
||||
decoder->native_count -= 1;
|
||||
decoder->native_codecs[decoder->native_count] = VIDEO_CODEC_NONE;
|
||||
decoder->out_codec = VIDEO_CODEC_NONE;
|
||||
break;
|
||||
}
|
||||
auto to_erase = find(decoder->native_codecs.begin(), decoder->native_codecs.end(), decoder->out_codec);
|
||||
if (to_erase == decoder->native_codecs.end()) {
|
||||
return true; // should it really return true?
|
||||
}
|
||||
log_msg(LOG_LEVEL_DEBUG, "Blacklisting codec %s\n", get_codec_name(decoder->out_codec));
|
||||
decoder->native_codecs.erase(to_erase);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -824,14 +818,15 @@ static void video_decoder_stop_threads(struct state_video_decoder *decoder)
|
||||
decoder->decompress_thread_id.join();
|
||||
}
|
||||
|
||||
static auto codec_list_to_str(const codec_t *codecs) {
|
||||
if (codecs == nullptr || codecs[0] == VIDEO_CODEC_NONE) {
|
||||
static auto codec_list_to_str(vector<codec_t> const &codecs) {
|
||||
if (codecs.empty()) {
|
||||
return "(none)"s;
|
||||
}
|
||||
ostringstream oss;
|
||||
oss << *codecs;
|
||||
while (*++codecs != VIDEO_CODEC_NONE) {
|
||||
oss << (codecs[1] == VIDEO_CODEC_NONE ? " and " : ", ") << get_codec_name(*codecs);
|
||||
auto it = codecs.begin();
|
||||
oss << *it++;
|
||||
for ( ; it != codecs.end(); ++it) {
|
||||
oss << (it + 1 == codecs.end() ? " and " : ", ") << get_codec_name(*it);
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
@@ -861,37 +856,35 @@ bool video_decoder_register_display(struct state_video_decoder *decoder, struct
|
||||
|
||||
decoder->display = display;
|
||||
|
||||
size_t len = sizeof decoder->native_codecs;
|
||||
ret = display_get_property(decoder->display, DISPLAY_PROPERTY_CODECS, decoder->native_codecs, &len);
|
||||
decoder->native_count = len / sizeof(codec_t);
|
||||
codec_t native_codecs[VIDEO_CODEC_COUNT];
|
||||
size_t len = sizeof native_codecs;
|
||||
ret = display_get_property(decoder->display, DISPLAY_PROPERTY_CODECS, native_codecs, &len);
|
||||
decoder->native_codecs.clear();
|
||||
if (!ret) {
|
||||
log_msg(LOG_LEVEL_ERROR, "Failed to query codecs from video display.\n");
|
||||
decoder->native_count = 0;
|
||||
} else {
|
||||
for (size_t i = 0; i < len / sizeof(codec_t); ++i) {
|
||||
decoder->native_codecs.push_back(native_codecs[i]);
|
||||
}
|
||||
}
|
||||
if (get_commandline_param("decoder-use-codec")) {
|
||||
const char *codec_str = get_commandline_param("decoder-use-codec");
|
||||
codec_t req_codec = get_codec_from_name(codec_str);
|
||||
if ("help"s == codec_str) {
|
||||
LOG(LOG_LEVEL_NOTICE) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(static_cast<codec_t *>(decoder->native_codecs)) << "\n";
|
||||
LOG(LOG_LEVEL_NOTICE) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(decoder->native_codecs) << "\n";
|
||||
return false;
|
||||
}
|
||||
if (req_codec == VIDEO_CODEC_NONE) {
|
||||
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong decoder codec spec: %s.\n", codec_str);
|
||||
LOG(LOG_LEVEL_INFO) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(static_cast<codec_t *>(decoder->native_codecs)) << "\n";
|
||||
LOG(LOG_LEVEL_INFO) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(decoder->native_codecs) << "\n";
|
||||
return false;
|
||||
}
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < decoder->native_count; ++i) {
|
||||
if (decoder->native_codecs[i] == req_codec) {
|
||||
decoder->native_codecs[0] = req_codec;
|
||||
decoder->native_count = 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (find(decoder->native_codecs.begin(), decoder->native_codecs.end(), req_codec) != end(decoder->native_codecs)) {
|
||||
decoder->native_codecs.clear();
|
||||
decoder->native_codecs.push_back(req_codec);
|
||||
} else {
|
||||
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Display doesn't support requested codec: %s.\n", codec_str);
|
||||
LOG(LOG_LEVEL_INFO) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(static_cast<codec_t *>(decoder->native_codecs)) << "\n";
|
||||
LOG(LOG_LEVEL_INFO) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(decoder->native_codecs) << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -992,40 +985,40 @@ void video_decoder_destroy(struct state_video_decoder *decoder)
|
||||
* comp_int_fmt, generic should be catch-all allowing decompression of
|
||||
* arbitrary compressed stream of received codec).
|
||||
*/
|
||||
static vector<pair<codec_t, codec_t>> video_decoder_order_output_codecs(codec_t comp_int_fmt, codec_t *display_codecs, int display_codecs_count)
|
||||
static vector<pair<codec_t, codec_t>> video_decoder_order_output_codecs(codec_t comp_int_fmt, vector<codec_t> const &display_codecs)
|
||||
{
|
||||
vector<pair<codec_t, codec_t>> ret;
|
||||
set<codec_t> used;
|
||||
// first add hw-accelerated codecs
|
||||
for (int i = 0; i < display_codecs_count; ++i) {
|
||||
if (codec_is_hw_accelerated(display_codecs[i])) {
|
||||
ret.push_back({comp_int_fmt, display_codecs[i]});
|
||||
for (auto codec : display_codecs) {
|
||||
if (codec_is_hw_accelerated(codec)) {
|
||||
ret.push_back({comp_int_fmt, codec});
|
||||
if (comp_int_fmt != VIDEO_CODEC_NONE) {
|
||||
ret.push_back({VIDEO_CODEC_NONE, display_codecs[i]});
|
||||
ret.push_back({VIDEO_CODEC_NONE, codec});
|
||||
}
|
||||
used.insert(display_codecs[i]);
|
||||
used.insert(codec);
|
||||
}
|
||||
}
|
||||
// then codecs matching exactly internal codec
|
||||
for (int i = 0; i < display_codecs_count; ++i) {
|
||||
if (used.find(display_codecs[i]) != used.end()) {
|
||||
for (auto codec : display_codecs) {
|
||||
if (used.find(codec) != used.end()) {
|
||||
continue;
|
||||
};
|
||||
if (display_codecs[i] == comp_int_fmt) {
|
||||
ret.push_back({comp_int_fmt, display_codecs[i]});
|
||||
if (codec == comp_int_fmt) {
|
||||
ret.push_back({comp_int_fmt, codec});
|
||||
if (comp_int_fmt != VIDEO_CODEC_NONE) {
|
||||
ret.push_back({VIDEO_CODEC_NONE, display_codecs[i]});
|
||||
ret.push_back({VIDEO_CODEC_NONE, codec});
|
||||
}
|
||||
used.insert(display_codecs[i]);
|
||||
used.insert(codec);
|
||||
}
|
||||
}
|
||||
// then add also all other codecs
|
||||
vector<codec_t> remaining;
|
||||
for (int i = 0; i < display_codecs_count; ++i) {
|
||||
if (used.find(display_codecs[i]) != used.end()) {
|
||||
for (auto codec : display_codecs) {
|
||||
if (used.find(codec) != used.end()) {
|
||||
continue;
|
||||
};
|
||||
remaining.push_back(display_codecs[i]);
|
||||
remaining.push_back(codec);
|
||||
}
|
||||
if (comp_int_fmt != VIDEO_CODEC_NONE) {
|
||||
// sort - first codec of the same color space as internal (YUV
|
||||
@@ -1077,8 +1070,7 @@ static codec_t choose_codec_and_decoder(struct state_video_decoder *decoder, str
|
||||
codec_t out_codec = VIDEO_CODEC_NONE;
|
||||
|
||||
/* first check if the codec is natively supported */
|
||||
for (size_t native = 0u; native < decoder->native_count; ++native) {
|
||||
out_codec = decoder->native_codecs[native];
|
||||
for (auto &out_codec : decoder->native_codecs) {
|
||||
if(desc.color_spec == out_codec) {
|
||||
if((out_codec == DXT1 || out_codec == DXT1_YUV ||
|
||||
out_codec == DXT5)
|
||||
@@ -1098,10 +1090,14 @@ static codec_t choose_codec_and_decoder(struct state_video_decoder *decoder, str
|
||||
}
|
||||
}
|
||||
/* otherwise if we have line decoder (incl. slow codecs) */
|
||||
*decode_line = get_best_decoder_from(desc.color_spec, decoder->native_codecs, &out_codec, true);
|
||||
if (*decode_line) {
|
||||
decoder->decoder_type = LINE_DECODER;
|
||||
goto after_linedecoder_lookup;
|
||||
{
|
||||
vector<codec_t> native_codecs_copy = decoder->native_codecs;
|
||||
native_codecs_copy.push_back(VIDEO_CODEC_NONE); // this needs to be NULL-terminated
|
||||
*decode_line = get_best_decoder_from(desc.color_spec, native_codecs_copy.data(), &out_codec, true);
|
||||
if (*decode_line) {
|
||||
decoder->decoder_type = LINE_DECODER;
|
||||
goto after_linedecoder_lookup;
|
||||
}
|
||||
}
|
||||
|
||||
after_linedecoder_lookup:
|
||||
@@ -1123,8 +1119,7 @@ after_linedecoder_lookup:
|
||||
}
|
||||
|
||||
vector<pair<codec_t, codec_t>> formats_to_try; // (comp_int_fmt || VIDEO_CODEC_NONE), display_fmt
|
||||
formats_to_try = video_decoder_order_output_codecs(comp_int_fmt, decoder->native_codecs,
|
||||
decoder->native_count);
|
||||
formats_to_try = video_decoder_order_output_codecs(comp_int_fmt, decoder->native_codecs);
|
||||
|
||||
for (auto it = formats_to_try.begin(); it != formats_to_try.end(); ++it) {
|
||||
out_codec = (*it).second;
|
||||
@@ -1221,8 +1216,6 @@ static bool reconfigure_decoder(struct state_video_decoder *decoder,
|
||||
decoder->frame = NULL;
|
||||
video_decoder_start_threads(decoder);
|
||||
|
||||
assert(decoder->native_codecs != NULL);
|
||||
|
||||
cleanup(decoder);
|
||||
|
||||
desc.tile_count = get_video_mode_tiles_x(decoder->video_mode)
|
||||
|
||||
Reference in New Issue
Block a user