Fix incorrect bitrate calculation for constant bitrate

This commit is contained in:
dec05eba
2024-11-05 01:08:56 +01:00
parent 258f690a89
commit aac9b9cde7
7 changed files with 53 additions and 47 deletions

6
TODO
View File

@@ -178,6 +178,10 @@ Default to hevc if capture size is larger than 4096 in width or height.
Set low latency mode on vulkan encoding. Set low latency mode on vulkan encoding.
Support pipewire audio capture which also allows capturing audio from a single application. Support pipewire audio capture which also allows capturing audio from a single application. This can also be done with pulseaudio by creating a virtual sink:
pactl load-module module-combine-sink sink_name=gsr2 slaves=$(pactl get-default-sink) sink_properties=device.description="gsr"
pactl move-sink-input 2944 gsr2 # 2944 comes from 'pactl list sink-inputs'
and then record gsr2.monitor.
Or use pa_stream_set_monitor_stream, which also takes the sink-input as input. However need to track when the sink disconnects to mute and then reconnect again.
Support recording/replay/livestreaming at the same time by allowing commands to be run on an existing gpu screen recorder instance. Support recording/replay/livestreaming at the same time by allowing commands to be run on an existing gpu screen recorder instance.

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
window=$(xdotool selectwindow) window=$(xdotool selectwindow)
window_name=$(xdotool getwindowclassname "$window" || xdotool getwindowname "$window" || echo "Game") window_name=$(xdotool getwindowname "$window" || xdotool getwindowclassname "$window" || echo "Game")
window_name="$(echo "$window_name" | tr '/\\' '_')" window_name="$(echo "$window_name" | tr '/\\' '_')"
gpu-screen-recorder -w "$window" -f 60 -a default_output -o "$HOME/Videos/recording/$window_name/$(date +"Video_%Y-%m-%d_%H-%M-%S.mp4")" gpu-screen-recorder -w "$window" -f 60 -a default_output -o "$HOME/Videos/recording/$window_name/$(date +"Video_%Y-%m-%d_%H-%M-%S.mp4")"

View File

@@ -4,7 +4,7 @@
# gpu-screen-recorder -w screen -f 60 -a default_output -r 60 -sc scripts/record-save-application-name.sh -c mp4 -o "$HOME/Videos" # gpu-screen-recorder -w screen -f 60 -a default_output -r 60 -sc scripts/record-save-application-name.sh -c mp4 -o "$HOME/Videos"
window=$(xdotool getwindowfocus) window=$(xdotool getwindowfocus)
window_name=$(xdotool getwindowclassname "$window" || xdotool getwindowname "$window" || echo "Game") window_name=$(xdotool getwindowname "$window" || xdotool getwindowclassname "$window" || echo "Game")
window_name="$(echo "$window_name" | tr '/\\' '_')" window_name="$(echo "$window_name" | tr '/\\' '_')"
video_dir="$HOME/Videos/Replays/$window_name" video_dir="$HOME/Videos/Replays/$window_name"

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
window=$(xdotool selectwindow) window=$(xdotool selectwindow)
window_name=$(xdotool getwindowclassname "$window" || xdotool getwindowname "$window" || echo "Game") window_name=$(xdotool getwindowname "$window" || xdotool getwindowclassname "$window" || echo "Game")
window_name="$(echo "$window_name" | tr '/\\' '_')" window_name="$(echo "$window_name" | tr '/\\' '_')"
gpu-screen-recorder -w "$window" -f 60 -c mkv -a default_output -r 60 -o "$HOME/Videos/Replays/$window_name" gpu-screen-recorder -w "$window" -f 60 -c mkv -a default_output -r 60 -o "$HOME/Videos/Replays/$window_name"

View File

@@ -223,7 +223,7 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) {
if(wayland) { if(wayland) {
self->wayland.dpy = wl_display_connect(NULL); self->wayland.dpy = wl_display_connect(NULL);
if(!self->wayland.dpy) { if(!self->wayland.dpy) {
fprintf(stderr, "gsr error: gsr_egl_create_window failed: wl_display_connect failed\n"); fprintf(stderr, "gsr error: gsr_egl_create_window failed: failed to connect to the Wayland server\n");
goto fail; goto fail;
} }

View File

@@ -585,7 +585,7 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt,
codec_context->global_quality = 120 * quality_multiply; codec_context->global_quality = 120 * quality_multiply;
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
codec_context->global_quality = 100 * quality_multiply; codec_context->global_quality = 115 * quality_multiply;
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
codec_context->global_quality = 90 * quality_multiply; codec_context->global_quality = 90 * quality_multiply;
@@ -600,7 +600,7 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt,
codec_context->global_quality = 30 * quality_multiply; codec_context->global_quality = 30 * quality_multiply;
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
codec_context->global_quality = 20 * quality_multiply; codec_context->global_quality = 25 * quality_multiply;
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
codec_context->global_quality = 10 * quality_multiply; codec_context->global_quality = 10 * quality_multiply;
@@ -615,7 +615,7 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt,
codec_context->global_quality = 30 * quality_multiply; codec_context->global_quality = 30 * quality_multiply;
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
codec_context->global_quality = 20 * quality_multiply; codec_context->global_quality = 25 * quality_multiply;
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
codec_context->global_quality = 10 * quality_multiply; codec_context->global_quality = 10 * quality_multiply;
@@ -779,10 +779,10 @@ static void video_software_set_qp(AVCodecContext *codec_context, VideoQuality vi
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 23 * qp_multiply, 0); av_dict_set_int(options, "qp", 25 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 20 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
break; break;
} }
} else { } else {
@@ -873,7 +873,7 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 25 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 22 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
@@ -882,16 +882,16 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
} else if(codec_context->codec_id == AV_CODEC_ID_H264) { } else if(codec_context->codec_id == AV_CODEC_ID_H264) {
switch(video_quality) { switch(video_quality) {
case VideoQuality::MEDIUM: case VideoQuality::MEDIUM:
av_dict_set_int(options, "qp", 34 * qp_multiply, 0); av_dict_set_int(options, "qp", 35 * qp_multiply, 0);
break; break;
case VideoQuality::HIGH: case VideoQuality::HIGH:
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 23 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 20 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
break; break;
} }
} else if(codec_context->codec_id == AV_CODEC_ID_HEVC) { } else if(codec_context->codec_id == AV_CODEC_ID_HEVC) {
@@ -903,7 +903,7 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 25 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 22 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
@@ -918,7 +918,7 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 25 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 22 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
@@ -931,16 +931,16 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
} else if(codec_context->codec_id == AV_CODEC_ID_H264) { } else if(codec_context->codec_id == AV_CODEC_ID_H264) {
switch(video_quality) { switch(video_quality) {
case VideoQuality::MEDIUM: case VideoQuality::MEDIUM:
av_dict_set_int(options, "qp", 34 * qp_multiply, 0); av_dict_set_int(options, "qp", 35 * qp_multiply, 0);
break; break;
case VideoQuality::HIGH: case VideoQuality::HIGH:
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 23 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 20 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
break; break;
} }
} else if(codec_context->codec_id == AV_CODEC_ID_HEVC) { } else if(codec_context->codec_id == AV_CODEC_ID_HEVC) {
@@ -952,7 +952,7 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 25 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 22 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
@@ -967,7 +967,7 @@ static void video_hardware_set_qp(AVCodecContext *codec_context, VideoQuality vi
av_dict_set_int(options, "qp", 30 * qp_multiply, 0); av_dict_set_int(options, "qp", 30 * qp_multiply, 0);
break; break;
case VideoQuality::VERY_HIGH: case VideoQuality::VERY_HIGH:
av_dict_set_int(options, "qp", 25 * qp_multiply, 0); av_dict_set_int(options, "qp", 27 * qp_multiply, 0);
break; break;
case VideoQuality::ULTRA: case VideoQuality::ULTRA:
av_dict_set_int(options, "qp", 22 * qp_multiply, 0); av_dict_set_int(options, "qp", 22 * qp_multiply, 0);
@@ -3108,7 +3108,7 @@ int main(int argc, char **argv) {
usage(); usage();
} }
video_bitrate *= 1000LL; video_bitrate *= 1024LL * 8LL;
} else { } else {
if(!quality_str) if(!quality_str)
quality_str = "very_high"; quality_str = "very_high";

View File

@@ -340,16 +340,18 @@ static void pa_server_info_cb(pa_context*, const pa_server_info *server_info, vo
} }
static void get_pulseaudio_default_inputs(AudioDevices &audio_devices) { static void get_pulseaudio_default_inputs(AudioDevices &audio_devices) {
pa_mainloop *main_loop = pa_mainloop_new();
pa_context *ctx = pa_context_new(pa_mainloop_get_api(main_loop), "gpu-screen-recorder-gtk");
pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL);
int state = 0; int state = 0;
int pa_ready = 0; int pa_ready = 0;
pa_context_set_state_callback(ctx, pa_state_cb, &pa_ready);
pa_operation *pa_op = NULL; pa_operation *pa_op = NULL;
pa_mainloop *main_loop = pa_mainloop_new();
pa_context *ctx = pa_context_new(pa_mainloop_get_api(main_loop), "gpu-screen-recorder");
if(pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0)
goto done;
pa_context_set_state_callback(ctx, pa_state_cb, &pa_ready);
for(;;) { for(;;) {
// Not ready // Not ready
if(pa_ready == 0) { if(pa_ready == 0) {
@@ -366,23 +368,25 @@ static void get_pulseaudio_default_inputs(AudioDevices &audio_devices) {
} }
// Couldn't get connection to the server // Couldn't get connection to the server
if(pa_ready == 2 || (state == 1 && pa_op && pa_operation_get_state(pa_op) == PA_OPERATION_DONE)) { if(pa_ready == 2 || (state == 1 && pa_op && pa_operation_get_state(pa_op) == PA_OPERATION_DONE))
if(pa_op) break;
pa_operation_unref(pa_op);
pa_context_disconnect(ctx);
pa_context_unref(ctx);
pa_mainloop_free(main_loop);
return;
}
pa_mainloop_iterate(main_loop, 1, NULL); pa_mainloop_iterate(main_loop, 1, NULL);
} }
done:
if(pa_op)
pa_operation_unref(pa_op);
pa_context_disconnect(ctx);
pa_context_unref(ctx);
pa_mainloop_free(main_loop); pa_mainloop_free(main_loop);
} }
AudioDevices get_pulseaudio_inputs() { AudioDevices get_pulseaudio_inputs() {
AudioDevices audio_devices; AudioDevices audio_devices;
int state = 0;
int pa_ready = 0;
pa_operation *pa_op = NULL;
// TODO: Do this in the same connection below instead of two separate connections // TODO: Do this in the same connection below instead of two separate connections
get_pulseaudio_default_inputs(audio_devices); get_pulseaudio_default_inputs(audio_devices);
@@ -390,12 +394,10 @@ AudioDevices get_pulseaudio_inputs() {
pa_mainloop *main_loop = pa_mainloop_new(); pa_mainloop *main_loop = pa_mainloop_new();
pa_context *ctx = pa_context_new(pa_mainloop_get_api(main_loop), "gpu-screen-recorder"); pa_context *ctx = pa_context_new(pa_mainloop_get_api(main_loop), "gpu-screen-recorder");
pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL); if(pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0)
int state = 0; goto done;
int pa_ready = 0;
pa_context_set_state_callback(ctx, pa_state_cb, &pa_ready);
pa_operation *pa_op = NULL; pa_context_set_state_callback(ctx, pa_state_cb, &pa_ready);
for(;;) { for(;;) {
// Not ready // Not ready
@@ -413,17 +415,17 @@ AudioDevices get_pulseaudio_inputs() {
} }
// Couldn't get connection to the server // Couldn't get connection to the server
if(pa_ready == 2 || (state == 1 && pa_op && pa_operation_get_state(pa_op) == PA_OPERATION_DONE)) { if(pa_ready == 2 || (state == 1 && pa_op && pa_operation_get_state(pa_op) == PA_OPERATION_DONE))
if(pa_op)
pa_operation_unref(pa_op);
pa_context_disconnect(ctx);
pa_context_unref(ctx);
break; break;
}
pa_mainloop_iterate(main_loop, 1, NULL); pa_mainloop_iterate(main_loop, 1, NULL);
} }
done:
if(pa_op)
pa_operation_unref(pa_op);
pa_context_disconnect(ctx);
pa_context_unref(ctx);
pa_mainloop_free(main_loop); pa_mainloop_free(main_loop);
return audio_devices; return audio_devices;
} }