diff --git a/config.def.h b/config.def.h index 5980cc6de5..1e158e4171 100644 --- a/config.def.h +++ b/config.def.h @@ -189,6 +189,9 @@ static const bool second_pass_smooth = true; // Record video assuming game runs hi-res. static const bool hires_record = false; +// Enables lossless RGB H.264 recording if possible (if not, FFV1 is used). +static const bool h264_record = true; + // Record post-filtered (CPU filter) video rather than raw SNES output. static const bool post_filter_record = false; diff --git a/general.h b/general.h index 0262376f5d..47cda8c995 100644 --- a/general.h +++ b/general.h @@ -121,6 +121,7 @@ struct settings bool disable_composition; bool hires_record; + bool h264_record; bool post_filter_record; char external_driver[PATH_MAX]; diff --git a/record/ffemu.c b/record/ffemu.c index 5dcff18d65..0c09833a65 100644 --- a/record/ffemu.c +++ b/record/ffemu.c @@ -36,9 +36,10 @@ extern "C" { #include #include #include "../boolean.h" -#include "ffemu.h" #include "../fifo_buffer.h" #include "../thread.h" +#include "../general.h" +#include "ffemu.h" #include #ifdef HAVE_CONFIG_H @@ -107,7 +108,7 @@ struct ffemu volatile bool can_sleep; }; -static bool init_audio(struct ff_audio_info *audio, struct ffemu_params *param) +static bool ffemu_init_audio(struct ff_audio_info *audio, struct ffemu_params *param) { AVCodec *codec = avcodec_find_encoder(CODEC_ID_FLAC); if (!codec) @@ -153,10 +154,10 @@ static bool init_audio(struct ff_audio_info *audio, struct ffemu_params *param) return true; } -static bool init_video(struct ff_video_info *video, const struct ffemu_params *param) +static bool ffemu_init_video(struct ff_video_info *video, const struct ffemu_params *param) { #ifdef HAVE_X264RGB - AVCodec *codec = avcodec_find_encoder(CODEC_ID_H264); + AVCodec *codec = avcodec_find_encoder(g_settings.video.h264_record ? CODEC_ID_H264 : CODEC_ID_FFV1); #else AVCodec *codec = avcodec_find_encoder(CODEC_ID_FFV1); #endif @@ -178,7 +179,7 @@ static bool init_video(struct ff_video_info *video, const struct ffemu_params *p } #ifdef HAVE_X264RGB - video->pix_fmt = PIX_FMT_BGR24; + video->pix_fmt = g_settings.video.h264_record ? PIX_FMT_BGR24 : PIX_FMT_RGB32; #else video->pix_fmt = PIX_FMT_RGB32; #endif @@ -201,8 +202,13 @@ static bool init_video(struct ff_video_info *video, const struct ffemu_params *p #endif #ifdef HAVE_X264RGB - video->codec->thread_count = 3; - av_dict_set(&opts, "qp", "0", 0); + if (g_settings.video.h264_record) + { + video->codec->thread_count = 3; + av_dict_set(&opts, "qp", "0", 0); + } + else + video->codec->thread_count = 2; #else video->codec->thread_count = 2; #endif @@ -233,7 +239,7 @@ static bool init_video(struct ff_video_info *video, const struct ffemu_params *p return true; } -static bool init_muxer(ffemu_t *handle) +static bool ffemu_init_muxer(ffemu_t *handle) { AVFormatContext *ctx = avformat_alloc_context(); av_strlcpy(ctx->filename, handle->params.filename, sizeof(ctx->filename)); @@ -285,7 +291,8 @@ static bool init_muxer(ffemu_t *handle) handle->muxer.astream = stream; #ifdef HAVE_X264RGB // Avoids a warning at end about non-monotonically increasing DTS values. It seems to be harmless to disable this. - ctx->oformat->flags |= AVFMT_TS_NONSTRICT; + if (g_settings.video.h264_record) + ctx->oformat->flags |= AVFMT_TS_NONSTRICT; #endif av_dict_set(&ctx->metadata, "title", "SSNES video dump", 0); @@ -379,13 +386,13 @@ ffemu_t *ffemu_new(const struct ffemu_params *params) handle->params = *params; - if (!init_video(&handle->video, &handle->params)) + if (!ffemu_init_video(&handle->video, &handle->params)) goto error; - if (!init_audio(&handle->audio, &handle->params)) + if (!ffemu_init_audio(&handle->audio, &handle->params)) goto error; - if (!init_muxer(handle)) + if (!ffemu_init_muxer(handle)) goto error; if (!init_thread(handle)) diff --git a/settings.c b/settings.c index 398d287127..c4e76d15fb 100644 --- a/settings.c +++ b/settings.c @@ -186,6 +186,7 @@ void config_set_defaults(void) g_settings.video.refresh_rate = refresh_rate; g_settings.video.hires_record = hires_record; + g_settings.video.h264_record = h264_record; g_settings.video.post_filter_record = post_filter_record; g_settings.audio.enable = audio_enable; @@ -388,6 +389,7 @@ bool config_load_file(const char *path) #endif CONFIG_GET_BOOL(video.hires_record, "video_hires_record"); + CONFIG_GET_BOOL(video.h264_record, "video_h264_record"); CONFIG_GET_BOOL(video.post_filter_record, "video_post_filter_record"); #ifdef HAVE_DYLIB diff --git a/ssnes.cfg b/ssnes.cfg index f018ec4795..1d94b34b03 100644 --- a/ssnes.cfg +++ b/ssnes.cfg @@ -315,6 +315,9 @@ # Records video assuming video is hi-res. # video_hires_record = false +# Enables lossless RGB H.264 recording if possible (if not, FFV1 is used). +# video_h264_record = true + # Records video after CPU video filter. # video_post_filter_record = false