Merge pull request #7302 from fr500/master

[record] streaming & recording refinements
This commit is contained in:
Twinaphex 2018-09-27 11:47:57 +02:00 committed by GitHub
commit 1baf58716f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 200 additions and 137 deletions

View File

@ -3041,6 +3041,7 @@ static bool config_load_file(const char *path, bool set_defaults,
}
frontend_driver_set_sustained_performance_mode(settings->bools.sustained_performance_mode);
recording_driver_update_streaming_url();
ret = true;

View File

@ -2656,6 +2656,7 @@ static int menu_displaylist_parse_load_content_settings(
MENU_ENUM_LABEL_ADD_TO_FAVORITES, FILE_TYPE_PLAYLIST_ENTRY, 0, 0);
}
#ifdef HAVE_FFMPEG
if (!recording_is_enabled())
{
menu_entries_append_enum(info->list,
@ -2680,8 +2681,8 @@ static int menu_displaylist_parse_load_content_settings(
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QUICK_MENU_STOP_RECORDING),
msg_hash_to_str(MENU_ENUM_LABEL_QUICK_MENU_STOP_RECORDING),
MENU_ENUM_LABEL_QUICK_MENU_STOP_RECORDING, MENU_SETTING_ACTION, 0, 0);
}
#endif
if (settings->bools.quick_menu_show_options && !settings->bools.kiosk_mode_enable)
{
@ -7050,43 +7051,37 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data)
info->need_push = true;
break;
case DISPLAYLIST_RECORDING_SETTINGS_LIST:
{
settings_t *settings = config_get_ptr();
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_RECORD_ENABLE,
PARSE_ONLY_BOOL, false) == 0)
MENU_ENUM_LABEL_VIDEO_RECORD_QUALITY,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_RECORD_CONFIG,
PARSE_ONLY_PATH, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_STREAM_CONFIG,
PARSE_ONLY_PATH, false) == 0)
MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_RECORD_PATH,
PARSE_ONLY_STRING, false) == 0)
MENU_ENUM_LABEL_STREAM_CONFIG,
PARSE_ONLY_PATH, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_STREAMING_MODE,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_RECORD_USE_OUTPUT_DIRECTORY,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_UDP_STREAM_PORT,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_VIDEO_RECORD_QUALITY,
PARSE_ONLY_UINT, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY,
PARSE_ONLY_UINT, false) == 0)
count++;
if (settings->uints.streaming_mode == STREAMING_MODE_LOCAL)
{
/* To-Do: Refresh on settings->uints.streaming_mode change to show this parameter */
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_UDP_STREAM_PORT,
PARSE_ONLY_UINT, false) == 0)
count++;
}
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_STREAMING_URL,
PARSE_ONLY_STRING, false) == 0)
@ -7108,6 +7103,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data)
0, 0, 0);
info->need_push = true;
}
break;
case DISPLAYLIST_MAIN_MENU:
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);

View File

@ -305,8 +305,11 @@ static void setting_get_string_representation_streaming_mode(
case STREAMING_MODE_YOUTUBE:
strlcpy(s, "YouTube", len);
break;
case STREAMING_MODE_UDP:
strlcpy(s, "UDP", len);
case STREAMING_MODE_LOCAL:
strlcpy(s, "Local", len);
break;
case STREAMING_MODE_CUSTOM:
strlcpy(s, "Custom", len);
break;
}
}
@ -2950,6 +2953,13 @@ static void achievement_hardcore_mode_write_handler(rarch_setting_t *setting)
}
#endif
#ifdef HAVE_FFMPEG
static void update_streaming_url_write_handler(rarch_setting_t *setting)
{
recording_driver_update_streaming_url();
}
#endif
#ifdef HAVE_LAKKA
static void systemd_service_toggle(const char *path, char *unit, bool enable)
{
@ -6485,99 +6495,100 @@ static bool setting_append_list(
parent_group = msg_hash_to_str(MENU_ENUM_LABEL_RECORDING_SETTINGS);
START_SUB_GROUP(list, list_info, "State", &group_info, &subgroup_info, parent_group);
CONFIG_PATH(
list, list_info,
settings->paths.path_record_config,
sizeof(settings->paths.path_record_config),
MENU_ENUM_LABEL_RECORD_CONFIG,
MENU_ENUM_LABEL_VALUE_RECORD_CONFIG,
"",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
menu_settings_list_current_add_values(list, list_info, "cfg");
CONFIG_UINT(
list, list_info,
&settings->uints.video_record_quality,
MENU_ENUM_LABEL_VIDEO_RECORD_QUALITY,
MENU_ENUM_LABEL_VALUE_VIDEO_RECORD_QUALITY,
RECORD_CONFIG_TYPE_RECORDING_MED_QUALITY,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_video_record_quality;
menu_settings_list_current_add_range(list, list_info, RECORD_CONFIG_TYPE_RECORDING_CUSTOM, RECORD_CONFIG_TYPE_RECORDING_LOSSLESS_QUALITY, 1, true, true);
CONFIG_PATH(
list, list_info,
settings->paths.path_stream_config,
sizeof(settings->paths.path_stream_config),
MENU_ENUM_LABEL_STREAM_CONFIG,
MENU_ENUM_LABEL_VALUE_STREAM_CONFIG,
"",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
list, list_info,
settings->paths.path_record_config,
sizeof(settings->paths.path_record_config),
MENU_ENUM_LABEL_RECORD_CONFIG,
MENU_ENUM_LABEL_VALUE_RECORD_CONFIG,
"",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
menu_settings_list_current_add_values(list, list_info, "cfg");
CONFIG_UINT(
list, list_info,
&settings->uints.streaming_mode,
MENU_ENUM_LABEL_STREAMING_MODE,
MENU_ENUM_LABEL_VALUE_STREAMING_MODE,
STREAMING_MODE_TWITCH,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_streaming_mode;
menu_settings_list_current_add_range(list, list_info, 0, 2, 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.streaming_mode,
MENU_ENUM_LABEL_STREAMING_MODE,
MENU_ENUM_LABEL_VALUE_STREAMING_MODE,
STREAMING_MODE_TWITCH,
&group_info,
&subgroup_info,
parent_group,
update_streaming_url_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_streaming_mode;
menu_settings_list_current_add_range(list, list_info, 0, STREAMING_MODE_CUSTOM, 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.video_stream_port,
MENU_ENUM_LABEL_UDP_STREAM_PORT,
MENU_ENUM_LABEL_VALUE_UDP_STREAM_PORT,
1,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].offset_by = 1;
menu_settings_list_current_add_range(list, list_info, 1, 65536, 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.video_stream_port,
MENU_ENUM_LABEL_UDP_STREAM_PORT,
MENU_ENUM_LABEL_VALUE_UDP_STREAM_PORT,
1,
&group_info,
&subgroup_info,
parent_group,
update_streaming_url_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].offset_by = 1;
menu_settings_list_current_add_range(list, list_info, 1, 65536, 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.video_record_quality,
MENU_ENUM_LABEL_VIDEO_RECORD_QUALITY,
MENU_ENUM_LABEL_VALUE_VIDEO_RECORD_QUALITY,
1,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_video_record_quality;
menu_settings_list_current_add_range(list, list_info, 0, 4, 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.video_stream_quality,
MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY,
MENU_ENUM_LABEL_VALUE_VIDEO_STREAM_QUALITY,
1,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_video_stream_quality;
(*list)[list_info->index - 1].offset_by = 5;
menu_settings_list_current_add_range(list, list_info, 5, 8, 1, true, true);
CONFIG_UINT(
list, list_info,
&settings->uints.video_stream_quality,
MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY,
MENU_ENUM_LABEL_VALUE_VIDEO_STREAM_QUALITY,
RECORD_CONFIG_TYPE_STREAMING_MED_QUALITY,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_video_stream_quality;
(*list)[list_info->index - 1].offset_by = 5;
menu_settings_list_current_add_range(list, list_info, RECORD_CONFIG_TYPE_STREAMING_CUSTOM, RECORD_CONFIG_TYPE_STREAMING_HIGH_QUALITY, 1, true, true);
CONFIG_STRING(
CONFIG_PATH(
list, list_info,
settings->paths.path_stream_config,
sizeof(settings->paths.path_stream_config),
MENU_ENUM_LABEL_STREAM_CONFIG,
MENU_ENUM_LABEL_VALUE_STREAM_CONFIG,
"",
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
menu_settings_list_current_add_values(list, list_info, "cfg");
CONFIG_STRING(
list, list_info,
settings->paths.path_stream_url,
sizeof(settings->paths.path_stream_url),
@ -6589,9 +6600,9 @@ static bool setting_append_list(
parent_group,
general_write_handler,
general_read_handler);
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ALLOW_INPUT);
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ALLOW_INPUT);
CONFIG_DIR(
CONFIG_DIR(
list, list_info,
global->record.output_dir,
sizeof(global->record.output_dir),
@ -6604,7 +6615,7 @@ static bool setting_append_list(
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_start = directory_action_start_generic;
(*list)[list_info->index - 1].action_start = directory_action_start_generic;
END_SUB_GROUP(list, list_info, parent_group);
@ -9646,7 +9657,7 @@ static bool setting_append_list(
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
update_streaming_url_write_handler,
general_read_handler);
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ALLOW_INPUT);
@ -9672,7 +9683,7 @@ static bool setting_append_list(
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
update_streaming_url_write_handler,
general_read_handler);
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ALLOW_INPUT);

View File

@ -597,7 +597,7 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
strlcpy(params->vcodec, "libx264", sizeof(params->vcodec));
strlcpy(params->acodec, "libmp3lame", sizeof(params->acodec));
av_dict_set(&params->video_opts, "preset", "medium", 0);
av_dict_set(&params->video_opts, "preset", "superfast", 0);
av_dict_set(&params->video_opts, "tune", "animation", 0);
av_dict_set(&params->video_opts, "crf", "15", 0);
av_dict_set(&params->audio_opts, "audio_global_quality", "100", 0);
@ -652,12 +652,15 @@ static bool ffmpeg_init_config_common(struct ff_config_param *params, unsigned p
settings->uints.video_stream_scale_factor : 1;
else
params->scale_factor = 1;
strlcpy(params->format, "flv", sizeof(params->format));
if (settings->uints.streaming_mode == STREAMING_MODE_YOUTUBE || settings->uints.streaming_mode == STREAMING_MODE_TWITCH)
strlcpy(params->format, "flv", sizeof(params->format));
else
strlcpy(params->format, "mpegts", sizeof(params->format));
}
else
else if (preset == RECORD_CONFIG_TYPE_STREAMING_NETPLAY)
{
params->scale_factor = 1;
strlcpy(params->format, "flv", sizeof(params->format));
strlcpy(params->format, "mpegts", sizeof(params->format));
}
return true;
@ -698,9 +701,10 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
return true;
params->conf = config_file_new(config);
RARCH_LOG("[FFmpeg] Loading FFmpeg config \"%s\".\n", config);
if (!params->conf)
{
RARCH_ERR("Failed to load FFmpeg config \"%s\".\n", config);
RARCH_ERR("[FFmpeg] Failed to load FFmpeg config \"%s\".\n", config);
return false;
}
@ -735,7 +739,7 @@ static bool ffmpeg_init_config(struct ff_config_param *params,
params->out_pix_fmt = av_get_pix_fmt(pix_fmt);
if (params->out_pix_fmt == PIX_FMT_NONE)
{
RARCH_ERR("Cannot find pix_fmt \"%s\".\n", pix_fmt);
RARCH_ERR("[FFmpeg] Cannot find pix_fmt \"%s\".\n", pix_fmt);
return false;
}
}
@ -938,7 +942,7 @@ static void *ffmpeg_new(const struct record_params *params)
handle->params = *params;
if (params->preset == RECORD_CONFIG_TYPE_RECORDING_CUSTOM)
if (params->preset == RECORD_CONFIG_TYPE_RECORDING_CUSTOM || params->preset == RECORD_CONFIG_TYPE_STREAMING_CUSTOM)
{
if (!ffmpeg_init_config(&handle->config, params->config))
goto error;

View File

@ -37,7 +37,6 @@
#include "../list_special.h"
#include "../paths.h"
static const record_driver_t *record_drivers[] = {
#ifdef HAVE_FFMPEG
&record_ffmpeg,
@ -119,12 +118,12 @@ void find_record_driver(void)
{
unsigned d;
RARCH_ERR("Couldn't find any record driver named \"%s\"\n",
RARCH_ERR("[recording] Couldn't find any record driver named \"%s\"\n",
settings->arrays.record_driver);
RARCH_LOG_OUTPUT("Available record drivers are:\n");
for (d = 0; record_driver_find_handle(d); d++)
RARCH_LOG_OUTPUT("\t%s\n", record_driver_find_ident(d));
RARCH_WARN("Going to default to first record driver...\n");
RARCH_WARN("[recording] Going to default to first record driver...\n");
}
recording_driver = (const record_driver_t*)record_driver_find_handle(0);
@ -217,7 +216,7 @@ void recording_dump_frame(const void *data, unsigned width,
if (!vp.width || !vp.height)
{
RARCH_WARN("%s \n",
RARCH_WARN("[recording] %s \n",
msg_hash_to_str(MSG_VIEWPORT_SIZE_CALCULATION_FAILED));
command_event(CMD_EVENT_GPU_RECORD_DEINIT, NULL);
@ -229,7 +228,7 @@ void recording_dump_frame(const void *data, unsigned width,
if ( vp.width != recording_gpu_width ||
vp.height != recording_gpu_height)
{
RARCH_WARN("%s\n", msg_hash_to_str(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE));
RARCH_WARN("[recording] %s\n", msg_hash_to_str(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE));
runloop_msg_queue_push(
msg_hash_to_str(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE),
@ -336,7 +335,7 @@ bool recording_init(void)
if (rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
{
RARCH_WARN("%s\n",
RARCH_WARN("[recording] %s\n",
msg_hash_to_str(MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED));
return false;
}
@ -344,12 +343,12 @@ bool recording_init(void)
if (!settings->bools.video_gpu_record
&& video_driver_is_hw_context())
{
RARCH_WARN("%s.\n",
RARCH_WARN("[recording] %s.\n",
msg_hash_to_str(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING));
return false;
}
RARCH_LOG("%s: FPS: %.4f, Sample rate: %.4f\n",
RARCH_LOG("[recording] %s: FPS: %.4f, Sample rate: %.4f\n",
msg_hash_to_str(MSG_CUSTOM_TIMING_GIVEN),
(float)av_info->timing.fps,
(float)av_info->timing.sample_rate);
@ -362,7 +361,7 @@ bool recording_init(void)
if (!string_is_empty(settings->paths.path_stream_url))
strlcpy(output, settings->paths.path_stream_url, sizeof(output));
else
/* to-do determine the local interface, this won't work for connecting over the internet*/
/* Fallback, stream locally to 127.0.0.1 */
snprintf(output, sizeof(output), "udp://127.0.0.1:%u", settings->uints.video_stream_port);
else
{
@ -418,7 +417,7 @@ bool recording_init(void)
if (!vp.width || !vp.height)
{
RARCH_ERR("Failed to get viewport information from video driver. "
RARCH_ERR("[recording] Failed to get viewport information from video driver. "
"Cannot start recording ...\n");
return false;
}
@ -438,7 +437,7 @@ bool recording_init(void)
recording_gpu_width = vp.width;
recording_gpu_height = vp.height;
RARCH_LOG("%s %u x %u\n", msg_hash_to_str(MSG_DETECTED_VIEWPORT_OF),
RARCH_LOG("[recording] %s %u x %u\n", msg_hash_to_str(MSG_DETECTED_VIEWPORT_OF),
vp.width, vp.height);
gpu_size = vp.width * vp.height * 3;
@ -478,7 +477,7 @@ bool recording_init(void)
}
}
RARCH_LOG("%s %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n",
RARCH_LOG("[recording] %s %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n",
msg_hash_to_str(MSG_RECORDING_TO),
output,
params.out_width, params.out_height,
@ -487,7 +486,7 @@ bool recording_init(void)
if (!record_driver_init_first(&recording_driver, &recording_data, &params))
{
RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_RECORDING));
RARCH_ERR("[recording] %s\n", msg_hash_to_str(MSG_FAILED_TO_START_RECORDING));
command_event(CMD_EVENT_GPU_RECORD_DEINIT, NULL);
return false;
@ -521,6 +520,55 @@ unsigned *recording_driver_get_height(void)
return &recording_height;
}
void recording_driver_update_streaming_url()
{
settings_t *settings = config_get_ptr();
const char* youtube_url = "rtmp://a.rtmp.youtube.com/live2/";
const char* twitch_url = "rtmp://live.twitch.tv/app/";
if (!settings)
return;
switch (settings->uints.streaming_mode)
{
case STREAMING_MODE_TWITCH:
{
if (!string_is_empty(settings->arrays.twitch_stream_key))
snprintf(settings->paths.path_stream_url, sizeof(settings->paths.path_stream_url),
"%s%s", twitch_url, settings->arrays.twitch_stream_key);
else
{
/* To-Do: Show input box for twitch_stream_key*/
RARCH_LOG("[recording] twitch streaming key empty");
}
break;
}
case STREAMING_MODE_YOUTUBE:
{
if (!string_is_empty(settings->arrays.youtube_stream_key))
{
snprintf(settings->paths.path_stream_url, sizeof(settings->paths.path_stream_url),
"%s%s", youtube_url, settings->arrays.youtube_stream_key);
}
else
{
/* To-Do: Show input box for youtube_stream_key*/
RARCH_LOG("[recording] youtube streaming key empty");
}
break;
}
case STREAMING_MODE_LOCAL:
/* To-Do: figure out default interface and bind to that instead */
snprintf(settings->paths.path_stream_url, sizeof(settings->paths.path_stream_url),
"udp://%s:%u", "127.0.0.1", settings->uints.video_stream_port);
break;
case STREAMING_MODE_CUSTOM:
default:
/* Do nothing, let the user input the URL */
break;
}
}
void recording_driver_free_state(void)
{
recording_gpu_width = 0;

View File

@ -35,7 +35,8 @@ enum streaming_mode
{
STREAMING_MODE_TWITCH = 0,
STREAMING_MODE_YOUTUBE,
STREAMING_MODE_UDP
STREAMING_MODE_LOCAL,
STREAMING_MODE_CUSTOM
};
enum record_config_type
@ -207,6 +208,8 @@ bool recording_is_enabled(void);
bool streaming_is_enabled(void);
void recording_driver_update_streaming_url();
extern void *recording_data;
RETRO_END_DECLS