diff --git a/tools/replay/decode_threads.h b/tools/replay/decode_threads.h new file mode 100644 index 0000000000..47ed7baa29 --- /dev/null +++ b/tools/replay/decode_threads.h @@ -0,0 +1,8 @@ +#pragma once + +// Zero means unspecified: preserve FFmpeg's existing default behavior. +inline int replay_decode_threads(const char *value) { + if (value == nullptr) return 0; + if (value[0] >= '1' && value[0] <= '4' && value[1] == '\0') return value[0] - '0'; + return -1; +} diff --git a/tools/replay/framereader.cc b/tools/replay/framereader.cc index a5f0f748c7..2030a9b56a 100644 --- a/tools/replay/framereader.cc +++ b/tools/replay/framereader.cc @@ -1,6 +1,8 @@ #include "tools/replay/framereader.h" #include +#include +#include "tools/replay/decode_threads.h" #include #include #include @@ -152,10 +154,33 @@ bool FFmpegVideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { rWarning("No device with hardware decoder found. fallback to CPU decoding."); } + const int slice_threads = replay_decode_threads(std::getenv("ROADSCORE_REPLAY_DECODE_THREADS")); + if (slice_threads < 0) { + rError("ROADSCORE_REPLAY_DECODE_THREADS must be an integer from 1 to 4"); + return false; + } + const bool configure_slices = slice_threads > 0 && hw_device_ctx == nullptr; + if (configure_slices) { + if (!(decoder->capabilities & AV_CODEC_CAP_SLICE_THREADS)) { + rError("Requested software decoder does not support slice threading"); + return false; + } + decoder_ctx->thread_count = slice_threads; + decoder_ctx->thread_type = FF_THREAD_SLICE; + } + if (avcodec_open2(decoder_ctx, decoder, nullptr) < 0) { rError("Failed to open codec"); return false; } + if (configure_slices) { + rInfo("REPLAY_SOFTWARE_DECODER requested_threads=%d threads=%d active_thread_type=%d", slice_threads, + decoder_ctx->thread_count, decoder_ctx->active_thread_type); + if (decoder_ctx->active_thread_type & FF_THREAD_FRAME) { + rError("Frame threading is incompatible with replay's immediate-frame decoder"); + return false; + } + } return true; } diff --git a/tools/replay/tests/test_decode_threads.cc b/tools/replay/tests/test_decode_threads.cc new file mode 100644 index 0000000000..aee9f281d1 --- /dev/null +++ b/tools/replay/tests/test_decode_threads.cc @@ -0,0 +1,12 @@ +#include +#include +#include "tools/replay/decode_threads.h" +int main() { + assert(replay_decode_threads(nullptr) == 0); + assert(replay_decode_threads("1") == 1); + assert(replay_decode_threads("2") == 2); + assert(replay_decode_threads("4") == 4); + for (const char *value : {"", "0", "5", "-1", "2x", " 2", "2 ", "9999999999999999999"}) { + assert(replay_decode_threads(value) == -1); + } +}