diff --git a/TODO b/TODO index f6bda68..76db810 100644 --- a/TODO +++ b/TODO @@ -387,3 +387,7 @@ Support camera controls, such as white balance. Otherwise tell user to use camer Camera capture doesn't work perfectly. The image gets glitched, need to properly wait for image to be done. Use one pipewire connection (pipewire video) instead of multiple ones when recording with portal multiple times (multiple sources). + +Close pipewire links or maybe there are file descriptor leaks? + +Make multiple capture sources work properly in regards to size. The size of the video should be the region size of each capture source. \ No newline at end of file diff --git a/gpu-screen-recorder.1 b/gpu-screen-recorder.1 index bab12b2..ab946a2 100644 --- a/gpu-screen-recorder.1 +++ b/gpu-screen-recorder.1 @@ -302,9 +302,25 @@ Script to run after saving video. Receives filepath and type ("regular", "replay Portal session token file (default: ~/.config/gpu-screen-recorder/restore_token). .TP .BI \-ffmpeg-opts " options" -Additional arguments to pass to FFmpeg in a list of key-values pairs in the format "key=value;key=value", +Additional arguments to pass to FFmpeg for the file in a list of key-values pairs in the format "key=value;key=value", .br for example: -ffmpeg-opts "hls_list_size=3;hls_time=1;hls_flags=delete_segments". +.br +Note: this overwrites options set by GPU Screen Recorder with the same name. +.TP +.BI \-ffmpeg-video-opts " options" +Additional arguments to pass to FFmpeg for the video in a list of key-values pairs in the format "key=value;key=value", +.br +for example: -ffmpeg-video-opts "codec=cabac;rc_mode=CQP;qp=16". +.br +Note: this overwrites options set by GPU Screen Recorder with the same name. +.TP +.BI \-ffmpeg-audio-opts " options" +Additional arguments to pass to FFmpeg for the audio in a list of key-values pairs in the format "key=value;key=value", +.br +for example: -ffmpeg-audio-opts "aac_coder=fast;aac_pce=true". +.br +Note: this overwrites options set by GPU Screen Recorder with the same name. .TP .BI \-gl\-debug " yes|no" OpenGL debug output (default: no). diff --git a/include/args_parser.h b/include/args_parser.h index 0a03024..8e60b8b 100644 --- a/include/args_parser.h +++ b/include/args_parser.h @@ -8,7 +8,7 @@ typedef struct gsr_egl gsr_egl; -#define NUM_ARGS 33 +#define NUM_ARGS 35 typedef enum { GSR_CAPTURE_SOURCE_TYPE_WINDOW, @@ -86,6 +86,8 @@ typedef struct { const char *portal_session_token_filepath; const char *recording_saved_script; const char *ffmpeg_opts; + const char *ffmpeg_video_opts; + const char *ffmpeg_audio_opts; bool verbose; bool gl_debug; bool fallback_cpu_encoding; diff --git a/src/args_parser.c b/src/args_parser.c index c95c43a..5584e5c 100644 --- a/src/args_parser.c +++ b/src/args_parser.c @@ -441,6 +441,8 @@ static bool args_parser_set_values(args_parser *self) { } self->ffmpeg_opts = args_get_value_by_key(self->args, NUM_ARGS, "-ffmpeg-opts"); + self->ffmpeg_video_opts = args_get_value_by_key(self->args, NUM_ARGS, "-ffmpeg-video-opts"); + self->ffmpeg_audio_opts = args_get_value_by_key(self->args, NUM_ARGS, "-ffmpeg-audio-opts"); return true; } @@ -532,6 +534,8 @@ bool args_parser_parse(args_parser *self, int argc, char **argv, const args_hand self->args[arg_index++] = (Arg){ .key = "-replay-storage", .optional = true, .list = false, .type = ARG_TYPE_ENUM, .enum_values = replay_storage_enums, .num_enum_values = sizeof(replay_storage_enums)/sizeof(ArgEnum) }; self->args[arg_index++] = (Arg){ .key = "-p", .optional = true, .list = true, .type = ARG_TYPE_STRING }; self->args[arg_index++] = (Arg){ .key = "-ffmpeg-opts", .optional = true, .list = false, .type = ARG_TYPE_STRING }; + self->args[arg_index++] = (Arg){ .key = "-ffmpeg-video-opts", .optional = true, .list = false, .type = ARG_TYPE_STRING }; + self->args[arg_index++] = (Arg){ .key = "-ffmpeg-audio-opts", .optional = true, .list = false, .type = ARG_TYPE_STRING }; assert(arg_index == NUM_ARGS); for(int i = 1; i < argc; i += 2) { diff --git a/src/main.cpp b/src/main.cpp index bcfce99..d2c999a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -528,10 +528,13 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt, const A return codec_context; } -static void open_audio(AVCodecContext *audio_codec_context) { +static void open_audio(AVCodecContext *audio_codec_context, const char *ffmpeg_audio_opts) { AVDictionary *options = nullptr; av_dict_set(&options, "strict", "experimental", 0); + if(ffmpeg_audio_opts) + av_dict_parse_string(&options, ffmpeg_audio_opts, "=", ";", 0); + int ret; ret = avcodec_open2(audio_codec_context, audio_codec_context->codec, &options); if(ret < 0) { @@ -678,6 +681,9 @@ static void open_video_software(AVCodecContext *codec_context, const args_parser av_dict_set(&options, "strict", "experimental", 0); + if(arg_parser.ffmpeg_video_opts) + av_dict_parse_string(&options, arg_parser.ffmpeg_video_opts, "=", ";", 0); + int ret = avcodec_open2(codec_context, codec_context->codec, &options); if (ret < 0) { fprintf(stderr, "gsr error: Could not open video codec: %s\n", av_error_to_string(ret)); @@ -926,6 +932,9 @@ static void open_video_hardware(AVCodecContext *codec_context, bool low_power, c av_dict_set(&options, "strict", "experimental", 0); + if(arg_parser.ffmpeg_video_opts) + av_dict_parse_string(&options, arg_parser.ffmpeg_video_opts, "=", ";", 0); + int ret = avcodec_open2(codec_context, codec_context->codec, &options); if (ret < 0) { fprintf(stderr, "gsr error: Could not open video codec: %s\n", av_error_to_string(ret)); @@ -1219,6 +1228,7 @@ static RecordingStartResult start_recording_create_streams(const char *filename, AVDictionary *options = nullptr; av_dict_set(&options, "strict", "experimental", 0); + if(args_parser.ffmpeg_opts) av_dict_parse_string(&options, args_parser.ffmpeg_opts, "=", ";", 0); @@ -2388,6 +2398,7 @@ static std::vector create_video_sources(const args_parser &arg_pars } } + // TODO: Video size should be end pos - start pos, where start pos = pos and end pos = pos + size video_size = {0, 0}; for(const VideoSource &video_source : video_sources) { video_size.x = std::max(video_size.x, video_source.metadata.video_size.x); @@ -3441,6 +3452,7 @@ static bool av_open_file_write_header(AVFormatContext *av_format_context, const AVDictionary *options = nullptr; av_dict_set(&options, "strict", "experimental", 0); + if(ffmpeg_opts) av_dict_parse_string(&options, ffmpeg_opts, "=", ";", 0); @@ -3934,7 +3946,7 @@ int main(int argc, char **argv) { if(audio_stream && !merged_audio_inputs.track_name.empty()) av_dict_set(&audio_stream->metadata, "title", merged_audio_inputs.track_name.c_str(), 0); - open_audio(audio_codec_context); + open_audio(audio_codec_context, arg_parser.ffmpeg_audio_opts); if(audio_stream) avcodec_parameters_from_context(audio_stream->codecpar, audio_codec_context);