fix(encode): use modern nvenc low-latency preset
This commit is contained in:
@@ -7,6 +7,7 @@ SRS_ROOT="${SRS_ROOT:-$HOME/Code/srs}"
|
|||||||
SRS_BIN="${SRS_BIN:-$SRS_ROOT/trunk/objs/srs}"
|
SRS_BIN="${SRS_BIN:-$SRS_ROOT/trunk/objs/srs}"
|
||||||
SRS_CONF="${SRS_CONF:-$SRS_ROOT/trunk/conf/srs.conf}"
|
SRS_CONF="${SRS_CONF:-$SRS_ROOT/trunk/conf/srs.conf}"
|
||||||
FFPROBE_BIN="${FFPROBE_BIN:-ffprobe}"
|
FFPROBE_BIN="${FFPROBE_BIN:-ffprobe}"
|
||||||
|
ENCODER_DEVICE="${ENCODER_DEVICE:-software}"
|
||||||
|
|
||||||
wait_for_port() {
|
wait_for_port() {
|
||||||
local host="$1"
|
local host="$1"
|
||||||
@@ -48,7 +49,7 @@ wait_for_stream() {
|
|||||||
run_case() {
|
run_case() {
|
||||||
local transport="$1"
|
local transport="$1"
|
||||||
local codec="$2"
|
local codec="$2"
|
||||||
local stream_name="cvmmap_${transport}_${codec}"
|
local stream_name="cvmmap_${transport}_${codec}_${ENCODER_DEVICE}"
|
||||||
local expected_codec="$codec"
|
local expected_codec="$codec"
|
||||||
if [[ "$codec" == "h265" ]]; then
|
if [[ "$codec" == "h265" ]]; then
|
||||||
expected_codec="hevc"
|
expected_codec="hevc"
|
||||||
@@ -57,6 +58,7 @@ run_case() {
|
|||||||
"${BUILD_DIR}/rtmp_output_tester" \
|
"${BUILD_DIR}/rtmp_output_tester" \
|
||||||
--transport "$transport" \
|
--transport "$transport" \
|
||||||
--codec "$codec" \
|
--codec "$codec" \
|
||||||
|
--encoder-device "$ENCODER_DEVICE" \
|
||||||
--rtmp-url "rtmp://127.0.0.1/live/${stream_name}" \
|
--rtmp-url "rtmp://127.0.0.1/live/${stream_name}" \
|
||||||
--frames 36 \
|
--frames 36 \
|
||||||
--frame-interval-ms 33 \
|
--frame-interval-ms 33 \
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ private:
|
|||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Status configure_codec(std::string_view encoder_name, const RuntimeConfig &config) {
|
Status configure_codec(std::string_view encoder_name, const RuntimeConfig &config) {
|
||||||
av_opt_set(context_->priv_data, "preset", encoder_name.find("nvenc") != std::string_view::npos ? "llhq" : "veryfast", 0);
|
av_opt_set(context_->priv_data, "preset", encoder_name.find("nvenc") != std::string_view::npos ? "p1" : "veryfast", 0);
|
||||||
if (encoder_name.find("nvenc") != std::string_view::npos) {
|
if (encoder_name.find("nvenc") != std::string_view::npos) {
|
||||||
av_opt_set(context_->priv_data, "tune", "ull", 0);
|
av_opt_set(context_->priv_data, "tune", "ull", 0);
|
||||||
av_opt_set(context_->priv_data, "zerolatency", "1", 0);
|
av_opt_set(context_->priv_data, "zerolatency", "1", 0);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ struct Config {
|
|||||||
std::string rtmp_url{"rtmp://127.0.0.1/live/cvmmap_streamer_test"};
|
std::string rtmp_url{"rtmp://127.0.0.1/live/cvmmap_streamer_test"};
|
||||||
std::string transport{"libavformat"};
|
std::string transport{"libavformat"};
|
||||||
std::string codec{"h264"};
|
std::string codec{"h264"};
|
||||||
|
std::string encoder_device{"software"};
|
||||||
std::string ffmpeg_path{"ffmpeg"};
|
std::string ffmpeg_path{"ffmpeg"};
|
||||||
std::uint32_t frames{48};
|
std::uint32_t frames{48};
|
||||||
std::uint32_t width{320};
|
std::uint32_t width{320};
|
||||||
@@ -57,6 +58,8 @@ std::expected<Config, int> parse_args(int argc, char **argv) {
|
|||||||
->check(CLI::IsMember({"libavformat", "ffmpeg_process", "legacy_custom"}));
|
->check(CLI::IsMember({"libavformat", "ffmpeg_process", "legacy_custom"}));
|
||||||
app.add_option("--codec", config.codec, "Video codec (h264|h265)")
|
app.add_option("--codec", config.codec, "Video codec (h264|h265)")
|
||||||
->check(CLI::IsMember({"h264", "h265"}));
|
->check(CLI::IsMember({"h264", "h265"}));
|
||||||
|
app.add_option("--encoder-device", config.encoder_device, "Encoder device (auto|nvidia|software)")
|
||||||
|
->check(CLI::IsMember({"auto", "nvidia", "software"}));
|
||||||
app.add_option("--ffmpeg-path", config.ffmpeg_path, "ffmpeg binary path for ffmpeg_process transport");
|
app.add_option("--ffmpeg-path", config.ffmpeg_path, "ffmpeg binary path for ffmpeg_process transport");
|
||||||
app.add_option("--frames", config.frames, "Number of frames to publish")->check(CLI::PositiveNumber);
|
app.add_option("--frames", config.frames, "Number of frames to publish")->check(CLI::PositiveNumber);
|
||||||
app.add_option("--width", config.width, "Frame width")->check(CLI::PositiveNumber);
|
app.add_option("--width", config.width, "Frame width")->check(CLI::PositiveNumber);
|
||||||
@@ -98,6 +101,20 @@ std::expected<cvmmap_streamer::RtmpTransportType, std::string> parse_transport(s
|
|||||||
return std::unexpected("unsupported transport");
|
return std::unexpected("unsupported transport");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
std::expected<cvmmap_streamer::EncoderDeviceType, std::string> parse_encoder_device(std::string_view raw) {
|
||||||
|
if (raw == "auto") {
|
||||||
|
return cvmmap_streamer::EncoderDeviceType::Auto;
|
||||||
|
}
|
||||||
|
if (raw == "nvidia") {
|
||||||
|
return cvmmap_streamer::EncoderDeviceType::Nvidia;
|
||||||
|
}
|
||||||
|
if (raw == "software") {
|
||||||
|
return cvmmap_streamer::EncoderDeviceType::Software;
|
||||||
|
}
|
||||||
|
return std::unexpected("unsupported encoder device");
|
||||||
|
}
|
||||||
|
|
||||||
void fill_pattern(std::vector<std::uint8_t> &buffer, std::uint32_t width, std::uint32_t height, std::uint32_t frame_index) {
|
void fill_pattern(std::vector<std::uint8_t> &buffer, std::uint32_t width, std::uint32_t height, std::uint32_t frame_index) {
|
||||||
for (std::uint32_t y = 0; y < height; ++y) {
|
for (std::uint32_t y = 0; y < height; ++y) {
|
||||||
for (std::uint32_t x = 0; x < width; ++x) {
|
for (std::uint32_t x = 0; x < width; ++x) {
|
||||||
@@ -129,9 +146,15 @@ int main(int argc, char **argv) {
|
|||||||
return exit_code(TesterExitCode::InvalidArgument);
|
return exit_code(TesterExitCode::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto encoder_device = parse_encoder_device(args->encoder_device);
|
||||||
|
if (!encoder_device) {
|
||||||
|
spdlog::error("{}", encoder_device.error());
|
||||||
|
return exit_code(TesterExitCode::InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
cvmmap_streamer::RuntimeConfig config = cvmmap_streamer::RuntimeConfig::defaults();
|
cvmmap_streamer::RuntimeConfig config = cvmmap_streamer::RuntimeConfig::defaults();
|
||||||
config.encoder.backend = cvmmap_streamer::EncoderBackendType::FFmpeg;
|
config.encoder.backend = cvmmap_streamer::EncoderBackendType::FFmpeg;
|
||||||
config.encoder.device = cvmmap_streamer::EncoderDeviceType::Software;
|
config.encoder.device = *encoder_device;
|
||||||
config.encoder.codec = *codec;
|
config.encoder.codec = *codec;
|
||||||
config.encoder.gop = 15;
|
config.encoder.gop = 15;
|
||||||
config.encoder.b_frames = 0;
|
config.encoder.b_frames = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user