Start integrating video processor code

This commit is contained in:
twinaphex 2016-07-28 19:10:18 +02:00
parent 31143e5f5e
commit afee38109d
6 changed files with 270 additions and 140 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
#include "../internal_cores.h"

View File

@ -43,6 +43,13 @@
#include <linux/videodev2.h>
#include <libv4l2.h>
#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 <alsa/asoundlib.h>
#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;
}

View File

@ -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;
}