(Recording) Bake in HAVE_RECORD implicitly

This commit is contained in:
twinaphex 2014-08-12 05:28:43 +02:00
parent 717def1717
commit fcbbf08109
11 changed files with 39 additions and 64 deletions

View File

@ -356,10 +356,12 @@ ifeq ($(HAVE_ZLIB), 1)
DEFINES += $(ZLIB_CFLAGS) -DHAVE_ZLIB_DEFLATE
endif
OBJ += record/ffemu.o
ifeq ($(HAVE_FFMPEG), 1)
OBJ += record/ffemu.o record/ffmpeg.o
OBJ += record/ffmpeg.o
LIBS += $(AVCODEC_LIBS) $(AVFORMAT_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS)
DEFINES += $(AVCODEC_CFLAGS) $(AVFORMAT_CFLAGS) $(AVUTIL_CFLAGS) $(SWSCALE_CFLAGS) -DHAVE_RECORD
DEFINES += $(AVCODEC_CFLAGS) $(AVFORMAT_CFLAGS) $(AVUTIL_CFLAGS) $(SWSCALE_CFLAGS)
endif
ifeq ($(HAVE_DYNAMIC), 1)

View File

@ -259,10 +259,12 @@ ifeq ($(HAVE_DINPUT), 1)
OBJ += input/dinput.o
endif
OBJ += record/ffemu.o
ifeq ($(HAVE_FFMPEG), 1)
LIBS += -lavformat -lavcodec -lavutil -lswscale -lws2_32 -lz
DEFINES += -DHAVE_FFMPEG -DHAVE_RECORD -Iffmpeg
OBJ += record/ffemu.o record/ffmpeg.o
DEFINES += -DHAVE_FFMPEG -Iffmpeg
OBJ += record/ffmpeg.o
endif
ifneq ($(V), 1)

View File

@ -45,7 +45,7 @@ It is designed to be very portable and features a gamepad-centric UI.
It also has a full-featured command-line interface.
In some areas, RetroArch goes beyond and emphasizes on not-so-common technical features such as multi-pass shader support,
real-time rewind (Braid-style), FFmpeg video recording, etc.
real-time rewind (Braid-style), video recording (using FFmpeg), etc.
RetroArch also emphasizes on being easy to integrate into various launcher frontends.

View File

@ -142,11 +142,11 @@ Codecs used are (FFV1 or H264 RGB lossless (x264))/FLAC, suitable for processing
.TP
\fB--recordconfig PATH\fR
Sets path to a config file for use during FFmpeg recording.
Sets path to a config file for use during recording.
.TP
\fB--size WIDTHxHEIGHT\fR
Allows specifying the exact output width and height of FFmpeg recording. This option will override any configuration settings.
Allows specifying the exact output width and height of recording. This option will override any configuration settings.
The video input is scaled with point filtering before being encoded at the correct size.
.TP

View File

@ -502,16 +502,15 @@ bool driver_update_system_av_info(const struct retro_system_av_info *info)
// Cannot continue recording with different parameters.
// Take the easiest route out and just restart the recording.
#ifdef HAVE_RECORD
if (g_extern.rec)
{
static const char *msg = "Restarting FFmpeg recording due to driver reinit.";
static const char *msg = "Restarting recording due to driver reinit.";
msg_queue_push(g_extern.msg_queue, msg, 2, 180);
RARCH_WARN("%s\n", msg);
rarch_main_command(RARCH_CMD_RECORD_DEINIT);
rarch_main_command(RARCH_CMD_RECORD_INIT);
}
#endif
return true;
}

View File

@ -767,10 +767,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
RARCH_LOG("Environ SET_AUDIO_CALLBACK.\n");
const struct retro_audio_callback *info = (const struct retro_audio_callback*)data;
#ifdef HAVE_RECORD
if (g_extern.rec) // A/V sync is a must.
return false;
#endif
#ifdef HAVE_NETPLAY
if (g_extern.netplay_enable)

View File

@ -638,21 +638,19 @@ struct global
uint16_t netplay_port;
#endif
// FFmpeg record.
#ifdef HAVE_RECORD
// Recording.
const ffemu_backend_t *rec_driver;
void *rec;
char record_path[PATH_MAX];
char record_config[PATH_MAX];
bool recording;
bool recording_enable;
unsigned record_width;
unsigned record_height;
uint8_t *record_gpu_buffer;
size_t record_gpu_width;
size_t record_gpu_height;
#endif
struct
{

View File

@ -1928,9 +1928,9 @@ static inline void gl_set_texture_fmts(gl_t *gl, bool rgb32)
static void gl_init_pbo_readback(gl_t *gl)
{
unsigned i;
// Only bother with this if we're doing FFmpeg GPU recording.
// Check g_extern.recording and not g_extern.rec, because recording is not initialized yet.
gl->pbo_readback_enable = g_settings.video.gpu_record && g_extern.recording;
// Only bother with this if we're doing GPU recording.
// Check g_extern.recording_enable and not g_extern.rec, because recording is not initialized yet.
gl->pbo_readback_enable = g_settings.video.gpu_record && g_extern.recording_enable;
if (!gl->pbo_readback_enable)
return;

View File

@ -58,7 +58,7 @@
gl->ctx_driver->write_egl_image(gl, frame, width, height, pitch, base_size, tex_index,img)
#endif
#if defined(HAVE_RECORD) && (!defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES3))
#if (!defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES3))
#define HAVE_GL_ASYNC_READBACK
#endif

View File

@ -568,6 +568,11 @@ RETROARCH
============================================================ */
#include "../retroarch.c"
/*============================================================
RECORDING
============================================================ */
#include "../record/ffemu.c"
/*============================================================
THREAD
============================================================ */

View File

@ -217,12 +217,11 @@ static void readjust_audio_input_rate(void)
// g_extern.audio_data.src_ratio, g_extern.audio_data.orig_src_ratio);
}
#ifdef HAVE_RECORD
static void init_recording(void)
{
struct ffemu_params params = {0};
if (!g_extern.recording)
if (!g_extern.recording_enable)
return;
if (g_extern.libretro_dummy)
@ -233,7 +232,7 @@ static void init_recording(void)
if (!g_settings.video.gpu_record && g_extern.system.hw_render_callback.context_type)
{
RARCH_WARN("Libretro core is hardware rendered. Must use post-shaded FFmpeg recording as well.\n");
RARCH_WARN("Libretro core is hardware rendered. Must use post-shaded recording as well.\n");
return;
}
@ -313,7 +312,7 @@ static void init_recording(void)
}
}
RARCH_LOG("Recording with FFmpeg to %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n",
RARCH_LOG("Recording to %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n",
g_extern.record_path,
params.out_width, params.out_height,
params.fb_width, params.fb_height,
@ -321,7 +320,7 @@ static void init_recording(void)
if (!ffemu_init_first(&g_extern.rec_driver, &g_extern.rec, &params))
{
RARCH_ERR("Failed to start FFmpeg recording.\n");
RARCH_ERR("Failed to start recording.\n");
free(g_extern.record_gpu_buffer);
g_extern.record_gpu_buffer = NULL;
}
@ -332,7 +331,9 @@ static void deinit_recording(void)
if (!g_extern.rec || !g_extern.rec_driver)
return;
if (g_extern.rec_driver->finalize)
g_extern.rec_driver->finalize(g_extern.rec);
if (g_extern.rec_driver->free)
g_extern.rec_driver->free(g_extern.rec);
g_extern.rec = NULL;
@ -396,9 +397,9 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
if (!g_extern.record_gpu_buffer)
ffemu_data.is_dupe = !data;
if (g_extern.rec_driver && g_extern.rec_driver->push_video)
g_extern.rec_driver->push_video(g_extern.rec, &ffemu_data);
}
#endif
static void video_frame(const void *data, unsigned width, unsigned height, size_t pitch)
{
@ -431,10 +432,8 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_
// Slightly messy code,
// but we really need to do processing before blocking on VSync for best possible scheduling.
#ifdef HAVE_RECORD
if (g_extern.rec && (!g_extern.filter.filter || !g_settings.video.post_filter_record || !data || g_extern.record_gpu_buffer))
recording_dump_frame(data, width, height, pitch);
#endif
msg = msg_queue_pull(g_extern.msg_queue);
driver.current_msg = msg;
@ -455,10 +454,8 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_
data, width, height, pitch);
RARCH_PERFORMANCE_STOP(softfilter_process);
#ifdef HAVE_RECORD
if (g_extern.rec && g_settings.video.post_filter_record)
recording_dump_frame(g_extern.filter.buffer, owidth, oheight, opitch);
#endif
data = g_extern.filter.buffer;
width = owidth;
@ -473,11 +470,10 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_
void rarch_render_cached_frame(void)
{
const void *frame = g_extern.frame_cache.data;
#ifdef HAVE_RECORD
// Cannot allow recording when pushing duped frames.
void *recording = g_extern.rec;
g_extern.rec = NULL;
#endif
if (frame == RETRO_HW_FRAME_BUFFER_VALID)
frame = NULL; // Dupe
@ -490,9 +486,7 @@ void rarch_render_cached_frame(void)
g_extern.frame_cache.height,
g_extern.frame_cache.pitch);
#ifdef HAVE_RECORD
g_extern.rec = recording;
#endif
}
static bool audio_flush(const int16_t *data, size_t samples)
@ -503,16 +497,15 @@ static bool audio_flush(const int16_t *data, size_t samples)
struct resampler_data src_data = {0};
struct rarch_dsp_data dsp_data = {0};
#ifdef HAVE_RECORD
if (g_extern.rec)
{
struct ffemu_audio_data ffemu_data = {0};
ffemu_data.data = data;
ffemu_data.frames = samples / 2;
if (g_extern.rec_driver && g_extern.rec_driver->push_audio)
g_extern.rec_driver->push_audio(g_extern.rec, &ffemu_data);
}
#endif
if (g_extern.is_paused || g_extern.audio_data.mute)
return true;
@ -931,11 +924,9 @@ static void print_help(void)
puts("\t\tAvailable commands are listed if command is invalid.");
#endif
#ifdef HAVE_RECORD
puts("\t-r/--record: Path to record video file.\n\t\tUsing .mkv extension is recommended.");
puts("\t--recordconfig: Path to settings used during recording.");
puts("\t--size: Overrides output video size when recording with FFmpeg (format: WIDTHxHEIGHT).");
#endif
puts("\t--size: Overrides output video size when recording (format: WIDTHxHEIGHT).");
puts("\t-v/--verbose: Verbose logging.");
puts("\t-U/--ups: Specifies path for UPS patch that will be applied to content.");
puts("\t--bps: Specifies path for BPS patch that will be applied to content.");
@ -1059,11 +1050,9 @@ static void parse_input(int argc, char *argv[])
{ "help", 0, NULL, 'h' },
{ "save", 1, NULL, 's' },
{ "fullscreen", 0, NULL, 'f' },
#ifdef HAVE_RECORD
{ "record", 1, NULL, 'r' },
{ "recordconfig", 1, &val, 'R' },
{ "size", 1, &val, 's' },
#endif
{ "verbose", 0, NULL, 'v' },
{ "config", 1, NULL, 'c' },
{ "appendconfig", 1, &val, 'C' },
@ -1095,11 +1084,7 @@ static void parse_input(int argc, char *argv[])
{ NULL, 0, NULL, 0 }
};
#ifdef HAVE_RECORD
#define FFMPEG_RECORD_ARG "r:"
#else
#define FFMPEG_RECORD_ARG
#endif
#ifdef HAVE_DYNAMIC
#define DYNAMIC_ARG "L:"
@ -1201,12 +1186,10 @@ static void parse_input(int argc, char *argv[])
strlcpy(g_extern.config_path, optarg, sizeof(g_extern.config_path));
break;
#ifdef HAVE_RECORD
case 'r':
strlcpy(g_extern.record_path, optarg, sizeof(g_extern.record_path));
g_extern.recording = true;
g_extern.recording_enable = true;
break;
#endif
#ifdef HAVE_DYNAMIC
case 'L':
@ -1333,7 +1316,6 @@ static void parse_input(int argc, char *argv[])
g_extern.block_patch = true;
break;
#ifdef HAVE_RECORD
case 's':
{
if (sscanf(optarg, "%ux%u", &g_extern.record_width, &g_extern.record_height) != 2)
@ -1348,7 +1330,6 @@ static void parse_input(int argc, char *argv[])
case 'R':
strlcpy(g_extern.record_config, optarg, sizeof(g_extern.record_config));
break;
#endif
case 'f':
print_features();
exit(0);
@ -3018,9 +2999,7 @@ int rarch_main_init(int argc, char *argv[])
init_rewind();
init_controllers();
#ifdef HAVE_RECORD
init_recording();
#endif
init_sram();
@ -3070,9 +3049,7 @@ static inline void update_frame_time(void)
time = rarch_get_time_usec();
is_locked_fps = g_extern.is_paused || driver.nonblock_state;
#ifdef HAVE_RECORD
is_locked_fps |= !!g_extern.rec;
#endif
if (!g_extern.system.frame_time_last || is_locked_fps)
delta = g_extern.system.frame_time.reference;
@ -3221,14 +3198,10 @@ void rarch_main_command(unsigned action)
g_extern.audio_data.dsp = NULL;
break;
case RARCH_CMD_RECORD_INIT:
#ifdef HAVE_RECORD
init_recording();
#endif
break;
case RARCH_CMD_RECORD_DEINIT:
#ifdef HAVE_RECORD
deinit_recording();
#endif
break;
case RARCH_CMD_HISTORY_INIT:
if (g_extern.history)
@ -3367,9 +3340,7 @@ void rarch_main_deinit(void)
deinit_autosave();
#endif
#ifdef HAVE_RECORD
deinit_recording();
#endif
save_files();