Can start recording at will with -r/--record.

This commit is contained in:
Themaister 2011-01-05 20:07:55 +01:00
parent 6f9796a3fb
commit ab30663b37
2 changed files with 92 additions and 43 deletions

View File

@ -24,6 +24,7 @@
#include "driver.h" #include "driver.h"
#include <stdio.h> #include <stdio.h>
#include "record/ffemu.h" #include "record/ffemu.h"
#include "config.h"
#define MAX_PLAYERS 2 #define MAX_PLAYERS 2
@ -84,7 +85,11 @@ struct global
char config_path[256]; char config_path[256];
char basename[256]; char basename[256];
#ifdef HAVE_FFMPEG
ffemu_t *rec; ffemu_t *rec;
char record_path[256];
bool recording;
#endif
}; };
void parse_config(void); void parse_config(void);

130
ssnes.c
View File

@ -85,15 +85,18 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height)
if ( !g_extern.video_active ) if ( !g_extern.video_active )
return; return;
///////////// #ifdef HAVE_FFMPEG
struct ffemu_video_data ffemu_data = { if (g_extern.recording)
.data = data, {
.pitch = height == 448 || height == 478 ? 1024 : 2048, struct ffemu_video_data ffemu_data = {
.width = width, .data = data,
.height = height .pitch = height == 448 || height == 478 ? 1024 : 2048,
}; .width = width,
ffemu_push_video(g_extern.rec, &ffemu_data); .height = height
///////////// };
ffemu_push_video(g_extern.rec, &ffemu_data);
}
#endif
#ifdef HAVE_FILTER #ifdef HAVE_FILTER
uint16_t output_filter[width * height * 4 * 4]; uint16_t output_filter[width * height * 4 * 4];
@ -142,16 +145,19 @@ static void audio_sample(uint16_t left, uint16_t right)
if ( !g_extern.audio_active ) if ( !g_extern.audio_active )
return; return;
///////// #ifdef HAVE_FFMPEG
static int16_t static_data[2]; if (g_extern.recording)
static_data[0] = left; {
static_data[1] = right; static int16_t static_data[2];
struct ffemu_audio_data ffemu_data = { static_data[0] = left;
.data = static_data, static_data[1] = right;
.frames = 1 struct ffemu_audio_data ffemu_data = {
}; .data = static_data,
ffemu_push_audio(g_extern.rec, &ffemu_data); .frames = 1
////////// };
ffemu_push_audio(g_extern.rec, &ffemu_data);
}
#endif
static float data[AUDIO_CHUNK_SIZE_NONBLOCKING]; static float data[AUDIO_CHUNK_SIZE_NONBLOCKING];
static int data_ptr = 0; static int data_ptr = 0;
@ -210,15 +216,24 @@ static void fill_pathname(char *out_path, char *in_path, const char *replace)
strcat(out_path, replace); strcat(out_path, replace);
} }
#ifdef HAVE_FFMPEG
#define FFMPEG_HELP_QUARK " | -r/--record "
#else
#define FFMPEG_HELP_QUARK
#endif
static void print_help(void) static void print_help(void)
{ {
puts("================================================="); puts("=================================================");
puts("ssnes: Simple Super Nintendo Emulator (libsnes)"); puts("ssnes: Simple Super Nintendo Emulator (libsnes)");
puts("================================================="); puts("=================================================");
puts("Usage: ssnes [rom file] [-h/--help | -s/--save]"); puts("Usage: ssnes [rom file] [-h/--help | -s/--save" FFMPEG_HELP_QUARK "]");
puts("\t-h/--help: Show this help message"); puts("\t-h/--help: Show this help message");
puts("\t-s/--save: Path for save file (*.srm). Required when rom is input from stdin"); puts("\t-s/--save: Path for save file (*.srm). Required when rom is input from stdin");
puts("\t-c/--config: Path for config file. Defaults to $XDG_CONFIG_HOME/ssnes/ssnes.cfg"); puts("\t-c/--config: Path for config file. Defaults to $XDG_CONFIG_HOME/ssnes/ssnes.cfg");
#ifdef HAVE_FFMPEG
puts("\t-r/--record: Path to record video file. Settings for video/audio codecs are found in config file.");
#endif
puts("\t-v/--verbose: Verbose logging"); puts("\t-v/--verbose: Verbose logging");
} }
@ -233,13 +248,23 @@ static void parse_input(int argc, char *argv[])
struct option opts[] = { struct option opts[] = {
{ "help", 0, NULL, 'h' }, { "help", 0, NULL, 'h' },
{ "save", 1, NULL, 's' }, { "save", 1, NULL, 's' },
#ifdef HAVE_FFMPEG
{ "record", 1, NULL, 'r' },
#endif
{ "verbose", 0, NULL, 'v' }, { "verbose", 0, NULL, 'v' },
{ "config", 0, NULL, 'c' }, { "config", 0, NULL, 'c' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
int option_index = 0; int option_index = 0;
char optstring[] = "hs:vc:";
#ifdef HAVE_FFMPEG
#define FFMPEG_RECORD_ARG "r:"
#else
#define FFMPEG_RECORD_ARG
#endif
char optstring[] = "hs:vc:" FFMPEG_RECORD_ARG;
for(;;) for(;;)
{ {
int c = getopt_long(argc, argv, optstring, opts, &option_index); int c = getopt_long(argc, argv, optstring, opts, &option_index);
@ -266,6 +291,13 @@ static void parse_input(int argc, char *argv[])
strncpy(g_extern.config_path, optarg, sizeof(g_extern.config_path) - 1); strncpy(g_extern.config_path, optarg, sizeof(g_extern.config_path) - 1);
break; break;
#ifdef HAVE_FFMPEG
case 'r':
strncpy(g_extern.record_path, optarg, sizeof(g_extern.record_path) - 1);
g_extern.recording = true;
break;
#endif
case '?': case '?':
print_help(); print_help();
exit(1); exit(1);
@ -358,24 +390,33 @@ int main(int argc, char *argv[])
load_save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM); load_save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
load_save_file(savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC); load_save_file(savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
struct ffemu_rational ntsc_fps = {60000, 1001}; #ifdef HAVE_FFMPEG
struct ffemu_rational pal_fps = {50000, 1001}; // Hardcode these options at the moment. Should be specificed in the config file later on.
//////// if (g_extern.recording)
struct ffemu_params params = { {
.vcodec = FFEMU_VIDEO_H264, struct ffemu_rational ntsc_fps = {60000, 1001};
.acodec = FFEMU_AUDIO_VORBIS, struct ffemu_rational pal_fps = {50000, 1001};
.rescaler = FFEMU_RESCALER_POINT, struct ffemu_params params = {
.out_width = 512, .vcodec = FFEMU_VIDEO_H264,
.out_height = 448, .acodec = FFEMU_AUDIO_VORBIS,
.channels = 2, .rescaler = FFEMU_RESCALER_POINT,
.samplerate = 32040, .out_width = 512,
.filename = "/tmp/ssnes.mkv", .out_height = 448,
.fps = snes_get_region() == SNES_REGION_NTSC ? ntsc_fps : pal_fps, .channels = 2,
.aspect_ratio = 4.0/3 .samplerate = 32040,
}; .filename = g_extern.record_path,
g_extern.rec = ffemu_new(&params); .fps = snes_get_region() == SNES_REGION_NTSC ? ntsc_fps : pal_fps,
assert(g_extern.rec); .aspect_ratio = 4.0/3
///////// };
SSNES_LOG("Recording with FFmpeg to %s.\n", g_extern.record_path);
g_extern.rec = ffemu_new(&params);
if (!g_extern.rec)
{
SSNES_ERR("Failed to start FFmpeg recording.\n");
g_extern.recording = false;
}
}
#endif
///// TODO: Modular friendly!!! ///// TODO: Modular friendly!!!
for(;;) for(;;)
@ -403,10 +444,13 @@ int main(int argc, char *argv[])
psnes_run(); psnes_run();
} }
/////////// #ifdef HAVE_FFMPEG
ffemu_finalize(g_extern.rec); if (g_extern.recording)
ffemu_free(g_extern.rec); {
/////////// ffemu_finalize(g_extern.rec);
ffemu_free(g_extern.rec);
}
#endif
save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM); save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
save_file(savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC); save_file(savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);