From dce2ea595d5e5203aae2bdb5c113120ff4a3257a Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 9 Jul 2020 12:01:15 +0200 Subject: [PATCH] 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). --- src/rtp/video_decoders.cpp | 111 +++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/src/rtp/video_decoders.cpp b/src/rtp/video_decoders.cpp index e01513cc6..37e7da300 100644 --- a/src/rtp/video_decoders.cpp +++ b/src/rtp/video_decoders.cpp @@ -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 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 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(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(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(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> video_decoder_order_output_codecs(codec_t comp_int_fmt, codec_t *display_codecs, int display_codecs_count) +static vector> video_decoder_order_output_codecs(codec_t comp_int_fmt, vector const &display_codecs) { vector> ret; set 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 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 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> 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)