From afee38109db0cc301acf302c55a54c805ffe74b3 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 28 Jul 2016 19:10:18 +0200 Subject: [PATCH] Start integrating video processor code --- Makefile.common | 6 +- core_type.h | 3 +- cores/internal_cores.h | 56 ++++ .../libretro-video-processor/internal_cores.h | 1 + .../video_processor_v4l2.c | 303 ++++++++++-------- dynamic.c | 41 +++ 6 files changed, 270 insertions(+), 140 deletions(-) create mode 100644 cores/libretro-video-processor/internal_cores.h diff --git a/Makefile.common b/Makefile.common index cc5357e75e..1aa2604cae 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1027,11 +1027,13 @@ ifeq ($(HAVE_ZLIB_DEFLATE),1) DEFINES += -DHAVE_ZLIB_DEFLATE endif -# Camera +# Video4Linux 2 ifeq ($(HAVE_V4L2),1) - OBJ += camera/drivers/video4linux2.o + OBJ += camera/drivers/video4linux2.o \ + cores/libretro-video-processor/video_processor_v4l2.o DEFINES += -DHAVE_V4L2 + LIBS += $(V4L2_LIBS) endif # Things that depend on network availability diff --git a/core_type.h b/core_type.h index 08e9ea8d40..93901f20e1 100644 --- a/core_type.h +++ b/core_type.h @@ -22,7 +22,8 @@ enum rarch_core_type CORE_TYPE_DUMMY, CORE_TYPE_FFMPEG, CORE_TYPE_IMAGEVIEWER, - CORE_TYPE_NETRETROPAD + CORE_TYPE_NETRETROPAD, + CORE_TYPE_VIDEOPROCESSOR }; #endif diff --git a/cores/internal_cores.h b/cores/internal_cores.h index d30b8d17b2..221f358d06 100644 --- a/cores/internal_cores.h +++ b/cores/internal_cores.h @@ -240,4 +240,60 @@ size_t libretro_netretropad_retro_get_memory_size(unsigned id); #endif +#if defined(HAVE_V4L2) +/* Internal video processor core. */ + +void libretro_videoprocessor_retro_init(void); + +void libretro_videoprocessor_retro_deinit(void); + +unsigned libretro_videoprocessor_retro_api_version(void); + +void libretro_videoprocessor_retro_get_system_info(struct retro_system_info *info); + +void libretro_videoprocessor_retro_get_system_av_info(struct retro_system_av_info *info); + +void libretro_videoprocessor_retro_set_environment(retro_environment_t cb); + +void libretro_videoprocessor_retro_set_video_refresh(retro_video_refresh_t cb); + +void libretro_videoprocessor_retro_set_audio_sample(retro_audio_sample_t cb); + +void libretro_videoprocessor_retro_set_audio_sample_batch(retro_audio_sample_batch_t cb); + +void libretro_videoprocessor_retro_set_input_poll(retro_input_poll_t cb); + +void libretro_videoprocessor_retro_set_input_state(retro_input_state_t cb); + +void libretro_videoprocessor_retro_set_controller_port_device(unsigned port, unsigned device); + +void libretro_videoprocessor_retro_reset(void); + +void libretro_videoprocessor_retro_run(void); + +size_t libretro_videoprocessor_retro_serialize_size(void); + +bool libretro_videoprocessor_retro_serialize(void *data, size_t size); + +bool libretro_videoprocessor_retro_unserialize(const void *data, size_t size); + +void libretro_videoprocessor_retro_cheat_reset(void); + +void libretro_videoprocessor_retro_cheat_set(unsigned index, bool enabled, const char *code); + +bool libretro_videoprocessor_retro_load_game(const struct retro_game_info *game); + +bool libretro_videoprocessor_retro_load_game_special(unsigned game_type, + const struct retro_game_info *info, size_t num_info); + +void libretro_videoprocessor_retro_unload_game(void); + +unsigned libretro_videoprocessor_retro_get_region(void); + +void *libretro_videoprocessor_retro_get_memory_data(unsigned id); + +size_t libretro_videoprocessor_retro_get_memory_size(unsigned id); + +#endif + #endif diff --git a/cores/libretro-video-processor/internal_cores.h b/cores/libretro-video-processor/internal_cores.h new file mode 100644 index 0000000000..7e1a2aab98 --- /dev/null +++ b/cores/libretro-video-processor/internal_cores.h @@ -0,0 +1 @@ +#include "../internal_cores.h" diff --git a/cores/libretro-video-processor/video_processor_v4l2.c b/cores/libretro-video-processor/video_processor_v4l2.c index 658052e10e..194c6222da 100644 --- a/cores/libretro-video-processor/video_processor_v4l2.c +++ b/cores/libretro-video-processor/video_processor_v4l2.c @@ -43,6 +43,13 @@ #include #include +#ifdef RARCH_INTERNAL +#include "internal_cores.h" +#define VIDEOPROC_CORE_PREFIX(s) libretro_videoprocessor_##s +#else +#define VIDEOPROC_CORE_PREFIX(s) s +#endif + #ifdef HAVE_ALSA #include #endif @@ -76,22 +83,24 @@ static snd_pcm_t *audio_handle; /* * Libretro API callbacks */ -static retro_environment_t environment_cb; -static retro_video_refresh_t video_refresh_cb; -static retro_audio_sample_t audio_sample_cb; -static retro_audio_sample_batch_t audio_sample_batch_cb; -static retro_input_poll_t input_poll_cb; -static retro_input_state_t input_state_cb; +static retro_environment_t VIDEOPROC_CORE_PREFIX(environment_cb); +static retro_video_refresh_t VIDEOPROC_CORE_PREFIX(video_refresh_cb); +static retro_audio_sample_t VIDEOPROC_CORE_PREFIX(audio_sample_cb); +static retro_audio_sample_batch_t VIDEOPROC_CORE_PREFIX(audio_sample_batch_cb); +static retro_input_poll_t VIDEOPROC_CORE_PREFIX(input_poll_cb); +static retro_input_state_t VIDEOPROC_CORE_PREFIX(input_state_cb); #ifdef HAVE_ALSA -static void -audio_callback(void) +static void audio_callback(void) { int16_t audio_data[128]; int i, frame; - if (audio_handle) { - const int frames = snd_pcm_readi(audio_handle, audio_data, sizeof(audio_data) / 4); + if (audio_handle) + { + const int frames = snd_pcm_readi(audio_handle, + audio_data, sizeof(audio_data) / 4); + for (frame = 0, i = 0; frame < frames; frame++, i += 2) audio_sample_cb(audio_data[i+0], audio_data[i+1]); } @@ -106,9 +115,7 @@ audio_set_state(bool enable) static void appendstr(char *dst, const char *src, size_t dstsize) { - size_t resid; - - resid = dstsize - (strlen(dst) + 1); + size_t resid = dstsize - (strlen(dst) + 1); if (resid == 0) return; strncat(dst, src, resid); @@ -123,21 +130,22 @@ enumerate_video_devices(char *buf, size_t buflen) #ifdef HAVE_UDEV /* Get a list of devices matching the "video4linux" subsystem from udev */ - struct udev *udev; + int ndevs; struct udev_device *dev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; const char *path, *name; - int ndevs; + struct udev *udev = udev_new(); - udev = udev_new(); - if (!udev) { + if (!udev) + { printf("Cannot create udev context\n"); return; } enumerate = udev_enumerate_new(udev); - if (!enumerate) { + if (!enumerate) + { printf("Cannot create enumerate context\n"); udev_unref(udev); return; @@ -147,7 +155,8 @@ enumerate_video_devices(char *buf, size_t buflen) udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); - if (!devices) { + if (!devices) + { printf("Cannot get video device list\n"); udev_enumerate_unref(enumerate); udev_unref(udev); @@ -155,12 +164,14 @@ enumerate_video_devices(char *buf, size_t buflen) } ndevs = 0; - udev_list_entry_foreach(dev_list_entry, devices) { + udev_list_entry_foreach(dev_list_entry, devices) + { path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); name = udev_device_get_devnode(dev); - if (strncmp(name, "/dev/video", strlen("/dev/video")) == 0) { + if (strncmp(name, "/dev/video", strlen("/dev/video")) == 0) + { if (ndevs > 0) appendstr(buf, "|", buflen); appendstr(buf, name, buflen); @@ -194,11 +205,14 @@ enumerate_audio_devices(char *buf, size_t buflen) return; ndevs = 0; - for (n = hints; *n; n++) { + for (n = hints; *n; n++) + { name = snd_device_name_get_hint(*n, "NAME"); ioid = snd_device_name_get_hint(*n, "IOID"); - if ((ioid == NULL || strcmp(ioid, "Input") == 0) && - (strncmp(name, "hw:", strlen("hw:")) == 0 || strncmp(name, "default:", strlen("default:")) == 0)) { + if ((ioid == NULL || !strcmp(ioid, "Input")) && + (!strncmp(name, "hw:", strlen("hw:")) || + !strncmp(name, "default:", strlen("default:")))) + { if (ndevs > 0) appendstr(buf, "|", buflen); appendstr(buf, name, buflen); @@ -212,19 +226,18 @@ enumerate_audio_devices(char *buf, size_t buflen) #endif } -RETRO_API void -retro_set_environment(retro_environment_t cb) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_environment)(retro_environment_t cb) { char video_devices[ENVVAR_BUFLEN]; char audio_devices[ENVVAR_BUFLEN]; - environment_cb = cb; + VIDEOPROC_CORE_PREFIX(environment_cb) = cb; #ifdef HAVE_ALSA struct retro_audio_callback audio_cb; audio_cb.callback = audio_callback; audio_cb.set_state = audio_set_state; - environment_cb(RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK, &audio_cb); + VIDEOPROC_CORE_PREFIX(environment_cb)(RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK, &audio_cb); #endif enumerate_video_devices(video_devices, sizeof(video_devices)); @@ -236,46 +249,39 @@ retro_set_environment(retro_environment_t cb) { NULL, NULL } }; - environment_cb(RETRO_ENVIRONMENT_SET_VARIABLES, envvars); + VIDEOPROC_CORE_PREFIX(environment_cb)(RETRO_ENVIRONMENT_SET_VARIABLES, envvars); } -RETRO_API void -retro_set_video_refresh(retro_video_refresh_t cb) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_video_refresh)(retro_video_refresh_t cb) { - video_refresh_cb = cb; + VIDEOPROC_CORE_PREFIX(video_refresh_cb) = cb; } -RETRO_API void -retro_set_audio_sample(retro_audio_sample_t cb) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_audio_sample)(retro_audio_sample_t cb) { - audio_sample_cb = cb; + VIDEOPROC_CORE_PREFIX(audio_sample_cb) = cb; } -RETRO_API void -retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_audio_sample_batch)(retro_audio_sample_batch_t cb) { - audio_sample_batch_cb = cb; + VIDEOPROC_CORE_PREFIX(audio_sample_batch_cb) = cb; } -RETRO_API void -retro_set_input_poll(retro_input_poll_t cb) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_input_poll)(retro_input_poll_t cb) { - input_poll_cb = cb; + VIDEOPROC_CORE_PREFIX(input_poll_cb) = cb; } -RETRO_API void -retro_set_input_state(retro_input_state_t cb) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_input_state)(retro_input_state_t cb) { - input_state_cb = cb; + VIDEOPROC_CORE_PREFIX(input_state_cb) = cb; } -RETRO_API void -retro_init(void) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_init)(void) { } -static bool -open_devices(void) +static bool open_devices(void) { struct retro_variable videodev = { "v4l2_videodev", NULL }; struct retro_variable audiodev = { "v4l2_audiodev", NULL }; @@ -283,25 +289,28 @@ open_devices(void) int error; /* Get the video and audio capture device names from the environment */ - environment_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &videodev); - environment_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &audiodev); + VIDEOPROC_CORE_PREFIX(environment_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &videodev); + VIDEOPROC_CORE_PREFIX(environment_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &audiodev); /* Video device is required */ - if (videodev.value == NULL) { + if (videodev.value == NULL) + { printf("v4l2_videodev not defined\n"); return false; } /* Open the V4L2 device */ video_fd = v4l2_open(videodev.value, O_RDWR, 0); - if (video_fd == -1) { + if (video_fd == -1) + { printf("Couldn't open %s: %s\n", videodev.value, strerror(errno)); return false; } /* Query V4L2 device capabilities */ error = v4l2_ioctl(video_fd, VIDIOC_QUERYCAP, &caps); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_QUERYCAP failed: %s\n", strerror(errno)); v4l2_close(video_fd); return false; @@ -311,10 +320,12 @@ open_devices(void) printf(" Driver: %s\n", caps.driver); printf(" Card: %s\n", caps.card); printf(" Bus Info: %s\n", caps.bus_info); - printf(" Version: %u.%u.%u\n", (caps.version >> 16) & 0xff, (caps.version >> 8) & 0xff, caps.version & 0xff); + printf(" Version: %u.%u.%u\n", (caps.version >> 16) & 0xff, + (caps.version >> 8) & 0xff, caps.version & 0xff); #ifdef HAVE_ALSA - if (audiodev.value) { + if (audiodev.value) + { snd_pcm_hw_params_t *hw_params; unsigned int rate; @@ -322,55 +333,65 @@ open_devices(void) * Open the audio capture device and configure it for 48kHz, 16-bit stereo */ error = snd_pcm_open(&audio_handle, audiodev.value, SND_PCM_STREAM_CAPTURE, 0); - if (error < 0) { + if (error < 0) + { printf("Couldn't open %s: %s\n", audiodev.value, snd_strerror(error)); return false; } error = snd_pcm_hw_params_malloc(&hw_params); - if (error) { + if (error) + { printf("Couldn't allocate hw param structure: %s\n", snd_strerror(error)); return false; } error = snd_pcm_hw_params_any(audio_handle, hw_params); - if (error) { + if (error) + { printf("Couldn't initialize hw param structure: %s\n", snd_strerror(error)); return false; } error = snd_pcm_hw_params_set_access(audio_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (error) { + if (error) + { printf("Couldn't set hw param access type: %s\n", snd_strerror(error)); return false; } error = snd_pcm_hw_params_set_format(audio_handle, hw_params, SND_PCM_FORMAT_S16_LE); - if (error) { + if (error) + { printf("Couldn't set hw param format to SND_PCM_FORMAT_S16_LE: %s\n", snd_strerror(error)); return false; } rate = AUDIO_SAMPLE_RATE; error = snd_pcm_hw_params_set_rate_near(audio_handle, hw_params, &rate, 0); - if (error) { + if (error) + { printf("Couldn't set hw param sample rate to %u: %s\n", rate, snd_strerror(error)); return false; } - if (rate != AUDIO_SAMPLE_RATE) { + if (rate != AUDIO_SAMPLE_RATE) + { printf("Hardware doesn't support sample rate %u (returned %u)\n", AUDIO_SAMPLE_RATE, rate); return false; } error = snd_pcm_hw_params_set_channels(audio_handle, hw_params, 2); - if (error) { + if (error) + { printf("Couldn't set hw param channels to 2: %s\n", snd_strerror(error)); return false; } error = snd_pcm_hw_params(audio_handle, hw_params); - if (error) { + if (error) + { printf("Couldn't set hw params: %s\n", snd_strerror(error)); return false; } snd_pcm_hw_params_free(hw_params); error = snd_pcm_prepare(audio_handle); - if (error) { + if (error) + { printf("Couldn't prepare audio interface for use: %s\n", snd_strerror(error)); return false; } @@ -382,36 +403,34 @@ open_devices(void) return true; } -static void -close_devices(void) +static void close_devices(void) { #ifdef HAVE_ALSA - if (audio_handle) { + if (audio_handle) + { snd_pcm_close(audio_handle); audio_handle = NULL; } #endif - if (video_fd != -1) { + if (video_fd != -1) + { v4l2_close(video_fd); video_fd = -1; } } -RETRO_API void -retro_deinit(void) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_deinit)(void) { close_devices(); } -RETRO_API unsigned -retro_api_version(void) +RETRO_API unsigned VIDEOPROC_CORE_PREFIX(retro_api_version)(void) { return RETRO_API_VERSION; } -RETRO_API void -retro_get_system_info(struct retro_system_info *info) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_get_system_info)(struct retro_system_info *info) { info->library_name = LIBRARY_NAME; info->library_version = LIBRARY_VERSION; @@ -420,8 +439,7 @@ retro_get_system_info(struct retro_system_info *info) info->block_extract = true; } -RETRO_API void -retro_get_system_av_info(struct retro_system_av_info *info) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_get_system_av_info)(struct retro_system_av_info *info) { struct v4l2_cropcap cc; int error; @@ -432,39 +450,38 @@ retro_get_system_av_info(struct retro_system_av_info *info) memset(&cc, 0, sizeof(cc)); cc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; error = v4l2_ioctl(video_fd, VIDIOC_CROPCAP, &cc); - if (error == 0) { - info->geometry.aspect_ratio = (double)cc.pixelaspect.denominator / (double)cc.pixelaspect.numerator; - } + if (error == 0) + info->geometry.aspect_ratio = (double)cc.pixelaspect.denominator + / (double)cc.pixelaspect.numerator; - info->geometry.base_width = info->geometry.max_width = video_format.fmt.pix.width; + info->geometry.base_width = info->geometry.max_width = video_format.fmt.pix.width; info->geometry.base_height = info->geometry.max_height = video_format.fmt.pix.height; - info->timing.fps = (double)video_standard.frameperiod.denominator / (double)video_standard.frameperiod.numerator; - info->timing.sample_rate = AUDIO_SAMPLE_RATE; + info->timing.fps = (double)video_standard.frameperiod.denominator / + (double)video_standard.frameperiod.numerator; + info->timing.sample_rate = AUDIO_SAMPLE_RATE; - printf("Resolution %ux%u %f fps\n", info->geometry.base_width, info->geometry.base_height, info->timing.fps); + printf("Resolution %ux%u %f fps\n", info->geometry.base_width, + info->geometry.base_height, info->timing.fps); } -RETRO_API void -retro_set_controller_port_device(unsigned port, unsigned device) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_set_controller_port_device)(unsigned port, unsigned device) { } -RETRO_API void -retro_reset(void) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_reset)(void) { close_devices(); open_devices(); } -RETRO_API void -retro_run(void) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_run)(void) { struct v4l2_buffer buf; uint8_t *src; uint16_t *dst; int i, error; - input_poll_cb(); + VIDEOPROC_CORE_PREFIX(input_poll_cb)(); if (video_fd == -1) return; @@ -474,9 +491,10 @@ retro_run(void) buf.memory = V4L2_MEMORY_MMAP; error = v4l2_ioctl(video_fd, VIDIOC_DQBUF, &buf); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_DQBUF failed: %s\n", strerror(errno)); - video_refresh_cb(NULL, 0, 0, 0); + VIDEOPROC_CORE_PREFIX(video_refresh_cb)(NULL, 0, 0, 0); return; } @@ -484,47 +502,41 @@ retro_run(void) dst = conv_data; /* RGB24 to RGB565 */ - for (i = 0; i < video_format.fmt.pix.width * video_format.fmt.pix.height; i++, src += 3, dst += 1) { + for (i = 0; i < video_format.fmt.pix.width * video_format.fmt.pix.height; i++, src += 3, dst += 1) *dst = ((src[0] >> 3) << 11) | ((src[1] >> 2) << 5) | ((src[2] >> 3) << 0); - } error = v4l2_ioctl(video_fd, VIDIOC_QBUF, &buf); if (error != 0) printf("VIDIOC_QBUF failed: %s\n", strerror(errno)); - video_refresh_cb(conv_data, video_format.fmt.pix.width, video_format.fmt.pix.height, video_format.fmt.pix.width * 2); + VIDEOPROC_CORE_PREFIX(video_refresh_cb)(conv_data, video_format.fmt.pix.width, + video_format.fmt.pix.height, video_format.fmt.pix.width * 2); } -RETRO_API size_t -retro_serialize_size(void) +RETRO_API size_t VIDEOPROC_CORE_PREFIX(retro_serialize_size)(void) { return 0; } -RETRO_API bool -retro_serialize(void *data, size_t size) +RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_serialize)(void *data, size_t size) { return false; } -RETRO_API bool -retro_unserialize(const void *data, size_t size) +RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_unserialize)(const void *data, size_t size) { return false; } -RETRO_API void -retro_cheat_reset(void) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_cheat_reset)(void) { } -RETRO_API void -retro_cheat_set(unsigned index, bool enabled, const char *code) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_cheat_set)(unsigned index, bool enabled, const char *code) { } -RETRO_API bool -retro_load_game(const struct retro_game_info *game) +RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_load_game)(const struct retro_game_info *game) { enum retro_pixel_format pixel_format; struct v4l2_standard std; @@ -537,7 +549,8 @@ retro_load_game(const struct retro_game_info *game) bool std_found; int error; - if (open_devices() == false) { + if (open_devices() == false) + { printf("Couldn't open capture device\n"); close_devices(); return false; @@ -547,35 +560,43 @@ retro_load_game(const struct retro_game_info *game) fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; error = v4l2_ioctl(video_fd, VIDIOC_G_FMT, &fmt); - if (error != 0) { + + if (error != 0) + { printf("VIDIOC_G_FMT failed: %s\n", strerror(errno)); return false; } + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; error = v4l2_ioctl(video_fd, VIDIOC_S_FMT, &fmt); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_S_FMT failed: %s\n", strerror(errno)); return false; } error = v4l2_ioctl(video_fd, VIDIOC_G_STD, &std_id); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_G_STD failed: %s\n", strerror(errno)); return false; } - for (index = 0, std_found = false; ; index++) { + for (index = 0, std_found = false; ; index++) + { memset(&std, 0, sizeof(std)); std.index = index; error = v4l2_ioctl(video_fd, VIDIOC_ENUMSTD, &std); if (error) break; - if (std.id == std_id) { + if (std.id == std_id) + { video_standard = std; std_found = true; } printf("VIDIOC_ENUMSTD[%u]: %s%s\n", index, std.name, std.id == std_id ? " [*]" : ""); } - if (!std_found) { + if (!std_found) + { printf("VIDIOC_ENUMSTD did not contain std ID %08x\n", (unsigned)std_id); return false; } @@ -588,61 +609,72 @@ retro_load_game(const struct retro_game_info *game) reqbufs.memory = V4L2_MEMORY_MMAP; error = v4l2_ioctl(video_fd, VIDIOC_REQBUFS, &reqbufs); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_REQBUFS failed: %s\n", strerror(errno)); return false; } video_nbuffers = reqbufs.count; - for (index = 0; index < video_nbuffers; index++) { + for (index = 0; index < video_nbuffers; index++) + { memset(&buf, 0, sizeof(buf)); buf.index = index; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; error = v4l2_ioctl(video_fd, VIDIOC_QUERYBUF, &buf); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_QUERYBUF failed for %u: %s\n", index, strerror(errno)); return false; } video_buffer[index].len = buf.length; - video_buffer[index].start = v4l2_mmap(NULL, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, video_fd, buf.m.offset); - if (video_buffer[index].start == MAP_FAILED) { + video_buffer[index].start = v4l2_mmap(NULL, buf.length, + PROT_READ|PROT_WRITE, MAP_SHARED, video_fd, buf.m.offset); + if (video_buffer[index].start == MAP_FAILED) + { printf("v4l2_mmap failed: %s\n", strerror(errno)); return false; } } - for (index = 0; index < video_nbuffers; index++) { + for (index = 0; index < video_nbuffers; index++) + { memset(&buf, 0, sizeof(buf)); buf.index = index; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; error = v4l2_ioctl(video_fd, VIDIOC_QBUF, &buf); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_QBUF failed for %u: %s\n", index, strerror(errno)); return false; } } conv_data = calloc(1, video_format.fmt.pix.width * video_format.fmt.pix.height * 2); - if (conv_data == NULL) { + if (conv_data == NULL) + { printf("Cannot allocate conversion buffer\n"); return false; } - printf("Allocated %u byte conversion buffer\n", video_format.fmt.pix.width * video_format.fmt.pix.height * 2); + printf("Allocated %u byte conversion buffer\n", + video_format.fmt.pix.width * video_format.fmt.pix.height * 2); pixel_format = RETRO_PIXEL_FORMAT_RGB565; - if (!environment_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &pixel_format)) { + if (!VIDEOPROC_CORE_PREFIX(environment_cb)(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &pixel_format)) + { printf("Cannot set pixel format\n"); return false; } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; error = v4l2_ioctl(video_fd, VIDIOC_STREAMON, &type); - if (error != 0) { + if (error != 0) + { printf("VIDIOC_STREAMON failed: %s\n", strerror(errno)); return false; } @@ -650,14 +682,14 @@ retro_load_game(const struct retro_game_info *game) return true; } -RETRO_API void -retro_unload_game(void) +RETRO_API void VIDEOPROC_CORE_PREFIX(retro_unload_game)(void) { enum v4l2_buf_type type; uint32_t index; int error; - if (video_fd != -1) { + if (video_fd != -1) + { type = V4L2_BUF_TYPE_VIDEO_CAPTURE; error = v4l2_ioctl(video_fd, VIDIOC_STREAMOFF, &type); if (error != 0) @@ -673,26 +705,23 @@ retro_unload_game(void) close_devices(); } -RETRO_API bool -retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) +RETRO_API bool VIDEOPROC_CORE_PREFIX(retro_load_game_special)(unsigned game_type, + const struct retro_game_info *info, size_t num_info) { return false; } -RETRO_API unsigned -retro_get_region(void) +RETRO_API unsigned VIDEOPROC_CORE_PREFIX(retro_get_region)(void) { return (video_standard.id & V4L2_STD_NTSC) != 0 ? RETRO_REGION_NTSC : RETRO_REGION_PAL; } -RETRO_API void * -retro_get_memory_data(unsigned id) +RETRO_API void *VIDEOPROC_CORE_PREFIX(retro_get_memory_data)(unsigned id) { return NULL; } -RETRO_API size_t -retro_get_memory_size(unsigned id) +RETRO_API size_t VIDEOPROC_CORE_PREFIX(retro_get_memory_size)(unsigned id) { return 0; } diff --git a/dynamic.c b/dynamic.c index 4a049ea55b..434d67d0a2 100644 --- a/dynamic.c +++ b/dynamic.c @@ -81,6 +81,10 @@ static dylib_t lib_handle; #define SYMBOL_NETRETROPAD(x) current_core->x = libretro_netretropad_##x #endif +#if defined(HAVE_V4L2) +#define SYMBOL_VIDEOPROCESSOR(x) current_core->x = libretro_videoprocessor_##x +#endif + static bool ignore_environment_cb; const struct retro_subsystem_info *libretro_find_subsystem_info( @@ -543,6 +547,43 @@ static void load_symbols(enum rarch_core_type type, struct retro_core_t *current SYMBOL_NETRETROPAD(retro_get_region); SYMBOL_NETRETROPAD(retro_get_memory_data); SYMBOL_NETRETROPAD(retro_get_memory_size); +#endif + break; + case CORE_TYPE_VIDEOPROCESSOR: +#if defined(HAVE_NETWORKGAMEPAD) && defined(HAVE_NETPLAY) + SYMBOL_VIDEOPROCESSOR(retro_init); + SYMBOL_VIDEOPROCESSOR(retro_deinit); + + SYMBOL_VIDEOPROCESSOR(retro_api_version); + SYMBOL_VIDEOPROCESSOR(retro_get_system_info); + SYMBOL_VIDEOPROCESSOR(retro_get_system_av_info); + + SYMBOL_VIDEOPROCESSOR(retro_set_environment); + SYMBOL_VIDEOPROCESSOR(retro_set_video_refresh); + SYMBOL_VIDEOPROCESSOR(retro_set_audio_sample); + SYMBOL_VIDEOPROCESSOR(retro_set_audio_sample_batch); + SYMBOL_VIDEOPROCESSOR(retro_set_input_poll); + SYMBOL_VIDEOPROCESSOR(retro_set_input_state); + + SYMBOL_VIDEOPROCESSOR(retro_set_controller_port_device); + + SYMBOL_VIDEOPROCESSOR(retro_reset); + SYMBOL_VIDEOPROCESSOR(retro_run); + + SYMBOL_VIDEOPROCESSOR(retro_serialize_size); + SYMBOL_VIDEOPROCESSOR(retro_serialize); + SYMBOL_VIDEOPROCESSOR(retro_unserialize); + + SYMBOL_VIDEOPROCESSOR(retro_cheat_reset); + SYMBOL_VIDEOPROCESSOR(retro_cheat_set); + + SYMBOL_VIDEOPROCESSOR(retro_load_game); + SYMBOL_VIDEOPROCESSOR(retro_load_game_special); + + SYMBOL_VIDEOPROCESSOR(retro_unload_game); + SYMBOL_VIDEOPROCESSOR(retro_get_region); + SYMBOL_VIDEOPROCESSOR(retro_get_memory_data); + SYMBOL_VIDEOPROCESSOR(retro_get_memory_size); #endif break; }