mirror of https://github.com/PCSX2/pcsx2.git
USB: eyetoy mirroring
This commit is contained in:
parent
7801682377
commit
7e10e4d6eb
|
@ -54,6 +54,7 @@ namespace usb_eyetoy
|
||||||
|
|
||||||
buffer_t mpeg_buffer;
|
buffer_t mpeg_buffer;
|
||||||
std::mutex mpeg_mutex;
|
std::mutex mpeg_mutex;
|
||||||
|
bool mirroring_enabled = true;
|
||||||
|
|
||||||
static int xioctl(int fh, unsigned long int request, void* arg)
|
static int xioctl(int fh, unsigned long int request, void* arg)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +79,7 @@ namespace usb_eyetoy
|
||||||
if (pixelformat == V4L2_PIX_FMT_YUYV)
|
if (pixelformat == V4L2_PIX_FMT_YUYV)
|
||||||
{
|
{
|
||||||
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
|
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
|
||||||
int mpegLen = jo_write_mpeg(mpegData, ptr, 320, 240, JO_YUYV, JO_FLIP_X, JO_NONE);
|
int mpegLen = jo_write_mpeg(mpegData, ptr, 320, 240, JO_YUYV, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_NONE);
|
||||||
store_mpeg_frame(mpegData, mpegLen);
|
store_mpeg_frame(mpegData, mpegLen);
|
||||||
free(mpegData);
|
free(mpegData);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ namespace usb_eyetoy
|
||||||
int width, height, actual_comps;
|
int width, height, actual_comps;
|
||||||
unsigned char* rgbData = jpgd::decompress_jpeg_image_from_memory(ptr, size, &width, &height, &actual_comps, 3);
|
unsigned char* rgbData = jpgd::decompress_jpeg_image_from_memory(ptr, size, &width, &height, &actual_comps, 3);
|
||||||
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
|
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
|
||||||
int mpegLen = jo_write_mpeg(mpegData, rgbData, 320, 240, JO_RGB24, JO_FLIP_X, JO_NONE);
|
int mpegLen = jo_write_mpeg(mpegData, rgbData, 320, 240, JO_RGB24, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_NONE);
|
||||||
free(rgbData);
|
free(rgbData);
|
||||||
store_mpeg_frame(mpegData, mpegLen);
|
store_mpeg_frame(mpegData, mpegLen);
|
||||||
free(mpegData);
|
free(mpegData);
|
||||||
|
@ -484,6 +485,11 @@ namespace usb_eyetoy
|
||||||
return len2;
|
return len2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void V4L2::SetMirroring(bool state)
|
||||||
|
{
|
||||||
|
mirroring_enabled = state;
|
||||||
|
}
|
||||||
|
|
||||||
static void deviceChanged(GtkComboBox* widget, gpointer data)
|
static void deviceChanged(GtkComboBox* widget, gpointer data)
|
||||||
{
|
{
|
||||||
*(int*)data = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
|
*(int*)data = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace usb_eyetoy
|
||||||
int Open();
|
int Open();
|
||||||
int Close();
|
int Close();
|
||||||
int GetImage(uint8_t* buf, int len);
|
int GetImage(uint8_t* buf, int len);
|
||||||
|
void SetMirroring(bool state);
|
||||||
int Reset() { return 0; };
|
int Reset() { return 0; };
|
||||||
|
|
||||||
static const TCHAR* Name()
|
static const TCHAR* Name()
|
||||||
|
|
|
@ -355,6 +355,7 @@ namespace usb_eyetoy
|
||||||
|
|
||||||
buffer_t mpeg_buffer{};
|
buffer_t mpeg_buffer{};
|
||||||
std::mutex mpeg_mutex;
|
std::mutex mpeg_mutex;
|
||||||
|
bool mirroring_enabled = true;
|
||||||
|
|
||||||
void store_mpeg_frame(unsigned char* data, unsigned int len)
|
void store_mpeg_frame(unsigned char* data, unsigned int len)
|
||||||
{
|
{
|
||||||
|
@ -369,7 +370,7 @@ namespace usb_eyetoy
|
||||||
if (bitsperpixel == 24)
|
if (bitsperpixel == 24)
|
||||||
{
|
{
|
||||||
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
|
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
|
||||||
int mpegLen = jo_write_mpeg(mpegData, data, 320, 240, JO_RGB24, JO_FLIP_X, JO_FLIP_Y);
|
int mpegLen = jo_write_mpeg(mpegData, data, 320, 240, JO_BGR24, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_FLIP_Y);
|
||||||
store_mpeg_frame(mpegData, mpegLen);
|
store_mpeg_frame(mpegData, mpegLen);
|
||||||
free(mpegData);
|
free(mpegData);
|
||||||
}
|
}
|
||||||
|
@ -476,6 +477,11 @@ namespace usb_eyetoy
|
||||||
return len2;
|
return len2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DirectShow::SetMirroring(bool state)
|
||||||
|
{
|
||||||
|
mirroring_enabled = state;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL CALLBACK DirectShowDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
BOOL CALLBACK DirectShowDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
int port;
|
int port;
|
||||||
|
|
|
@ -88,6 +88,7 @@ namespace usb_eyetoy
|
||||||
int Open();
|
int Open();
|
||||||
int Close();
|
int Close();
|
||||||
int GetImage(uint8_t* buf, int len);
|
int GetImage(uint8_t* buf, int len);
|
||||||
|
void SetMirroring(bool state);
|
||||||
int Reset() { return 0; };
|
int Reset() { return 0; };
|
||||||
|
|
||||||
static const TCHAR* Name()
|
static const TCHAR* Name()
|
||||||
|
|
|
@ -183,6 +183,7 @@ unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, i
|
||||||
unsigned char *head = mpeg_buf;
|
unsigned char *head = mpeg_buf;
|
||||||
jo_bits_t bits = {mpeg_buf};
|
jo_bits_t bits = {mpeg_buf};
|
||||||
|
|
||||||
|
jo_writeBits(&bits, 0x00, 8);
|
||||||
for (int vblock = 0; vblock < (height+15)/16; vblock++) {
|
for (int vblock = 0; vblock < (height+15)/16; vblock++) {
|
||||||
for (int hblock = 0; hblock < (width+15)/16; hblock++) {
|
for (int hblock = 0; hblock < (width+15)/16; hblock++) {
|
||||||
if (vblock == 0 && hblock == 0) {
|
if (vblock == 0 && hblock == 0) {
|
||||||
|
@ -206,11 +207,7 @@ unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, i
|
||||||
if (flipy) y = height - 1 - y;
|
if (flipy) y = height - 1 - y;
|
||||||
const unsigned char *c = raw + y*width*4+x*4;
|
const unsigned char *c = raw + y*width*4+x*4;
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
if (flipx && flipy) {
|
r = c[0], g = c[1], b = c[2];
|
||||||
r = c[2], g = c[1], b = c[0];
|
|
||||||
} else {
|
|
||||||
r = c[0], g = c[1], b = c[2];
|
|
||||||
}
|
|
||||||
Y[i] = (0.299f*r + 0.587f*g + 0.114f*b) * (219.f/255) + 16;
|
Y[i] = (0.299f*r + 0.587f*g + 0.114f*b) * (219.f/255) + 16;
|
||||||
CBx[i] = (-0.299f*r - 0.587f*g + 0.886f*b) * (224.f/255) + 128;
|
CBx[i] = (-0.299f*r - 0.587f*g + 0.886f*b) * (224.f/255) + 128;
|
||||||
CRx[i] = (0.701f*r - 0.587f*g - 0.114f*b) * (224.f/255) + 128;
|
CRx[i] = (0.701f*r - 0.587f*g - 0.114f*b) * (224.f/255) + 128;
|
||||||
|
@ -222,7 +219,7 @@ unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, i
|
||||||
CR[i] = (CRx[j] + CRx[j+1] + CRx[j+16] + CRx[j+17]) * 0.25f;
|
CR[i] = (CRx[j] + CRx[j+1] + CRx[j+16] + CRx[j+17]) * 0.25f;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (format == JO_RGB24) {
|
if (format == JO_BGR24 || format == JO_RGB24) {
|
||||||
for (int i=0; i<256; ++i) {
|
for (int i=0; i<256; ++i) {
|
||||||
int y = vblock*16+(i/16);
|
int y = vblock*16+(i/16);
|
||||||
int x = hblock*16+(i&15);
|
int x = hblock*16+(i&15);
|
||||||
|
@ -232,7 +229,7 @@ unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, i
|
||||||
if (flipy) y = height - 1 - y;
|
if (flipy) y = height - 1 - y;
|
||||||
const unsigned char *c = raw + y*width*3+x*3;
|
const unsigned char *c = raw + y*width*3+x*3;
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
if (flipx && flipy) {
|
if (format == JO_BGR24) {
|
||||||
r = c[2], g = c[1], b = c[0];
|
r = c[2], g = c[1], b = c[0];
|
||||||
} else {
|
} else {
|
||||||
r = c[0], g = c[1], b = c[2];
|
r = c[0], g = c[1], b = c[2];
|
||||||
|
|
|
@ -5,6 +5,7 @@ extern "C" {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
JO_RGBX,
|
JO_RGBX,
|
||||||
JO_RGB24,
|
JO_RGB24,
|
||||||
|
JO_BGR24,
|
||||||
JO_YUYV,
|
JO_YUYV,
|
||||||
} jo_mpeg_format_t;
|
} jo_mpeg_format_t;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define OV519_R16_DIVIDER 0x16
|
#define OV519_R16_DIVIDER 0x16
|
||||||
#define OV519_R20_DFR 0x20
|
#define OV519_R20_DFR 0x20
|
||||||
#define OV519_R25_FORMAT 0x25
|
#define OV519_R25_FORMAT 0x25
|
||||||
|
#define OV519_RA0_FORMAT 0xA0
|
||||||
|
|
||||||
/* OV519 System Controller register numbers */
|
/* OV519 System Controller register numbers */
|
||||||
#define OV519_R51_RESET1 0x51
|
#define OV519_R51_RESET1 0x51
|
||||||
|
|
|
@ -22,13 +22,6 @@
|
||||||
|
|
||||||
namespace usb_eyetoy
|
namespace usb_eyetoy
|
||||||
{
|
{
|
||||||
|
|
||||||
static const USBDescStrings desc_strings = {
|
|
||||||
"",
|
|
||||||
"Sony corporation",
|
|
||||||
"EyeToy USB camera Namtai",
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct EYETOYState
|
typedef struct EYETOYState
|
||||||
{
|
{
|
||||||
USBDevice dev;
|
USBDevice dev;
|
||||||
|
@ -51,6 +44,12 @@ namespace usb_eyetoy
|
||||||
|
|
||||||
static EYETOYState* static_state;
|
static EYETOYState* static_state;
|
||||||
|
|
||||||
|
static const USBDescStrings desc_strings = {
|
||||||
|
"",
|
||||||
|
"Sony corporation",
|
||||||
|
"EyeToy USB camera Namtai",
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Manufacturer: OmniVision Technologies, Inc.
|
Manufacturer: OmniVision Technologies, Inc.
|
||||||
Product ID: 0x8519
|
Product ID: 0x8519
|
||||||
|
@ -61,7 +60,7 @@ namespace usb_eyetoy
|
||||||
Number of Configurations: 1
|
Number of Configurations: 1
|
||||||
Manufacturer String: 1 "Sony corporation"
|
Manufacturer String: 1 "Sony corporation"
|
||||||
Product String: 2 "EyeToy USB camera Namtai"
|
Product String: 2 "EyeToy USB camera Namtai"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const uint8_t eyetoy_dev_descriptor[] = {
|
static const uint8_t eyetoy_dev_descriptor[] = {
|
||||||
0x12, /* bLength */
|
0x12, /* bLength */
|
||||||
|
@ -80,7 +79,6 @@ namespace usb_eyetoy
|
||||||
0x01, /* bNumConfigurations */
|
0x01, /* bNumConfigurations */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: patch interrupt size */
|
|
||||||
static const uint8_t eyetoy_config_descriptor[] = {
|
static const uint8_t eyetoy_config_descriptor[] = {
|
||||||
0x09, // bLength
|
0x09, // bLength
|
||||||
0x02, // bDescriptorType (Configuration)
|
0x02, // bDescriptorType (Configuration)
|
||||||
|
@ -344,22 +342,21 @@ namespace usb_eyetoy
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VendorDeviceOutRequest | 0x1: //Write register
|
case VendorDeviceOutRequest | 0x1: //Write register
|
||||||
if (!(index >= R51x_I2C_SADDR_3 && index <= R518_I2C_CTL))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case OV519_R51_RESET1:
|
case OV519_RA0_FORMAT:
|
||||||
if (data[0] & 0x8)
|
if (data[0] == 0x42)
|
||||||
{
|
{
|
||||||
// reset video FIFO
|
Console.WriteLn("EyeToy : configured for MPEG format");
|
||||||
//s->videodev->SetSize(s->regs[OV519_R10_H_SIZE] << 4, s->regs[OV519_R11_V_SIZE] << 3);
|
}
|
||||||
|
else if (data[0] == 0x33)
|
||||||
|
{
|
||||||
|
Console.WriteLn("EyeToy : configured for JPEG format; Unimplemented");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLn("EyeToy : configured for unknown format");
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case OV519_R10_H_SIZE:
|
|
||||||
break;
|
|
||||||
case OV519_R11_V_SIZE:
|
|
||||||
break;
|
break;
|
||||||
case R518_I2C_CTL:
|
case R518_I2C_CTL:
|
||||||
if (data[0] == 1) // Commit I2C write
|
if (data[0] == 1) // Commit I2C write
|
||||||
|
@ -376,6 +373,12 @@ namespace usb_eyetoy
|
||||||
{
|
{
|
||||||
s->i2c_regs[reg] = val;
|
s->i2c_regs[reg] = val;
|
||||||
}
|
}
|
||||||
|
if (reg == 0x12)
|
||||||
|
{
|
||||||
|
const bool mirroring_enabled = val & 0x40;
|
||||||
|
s->videodev->SetMirroring(mirroring_enabled);
|
||||||
|
Console.WriteLn("EyeToy : mirroring %s", mirroring_enabled ? "ON" : "OFF");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (s->regs[R518_I2C_CTL] == 0x03 && data[0] == 0x05)
|
else if (s->regs[R518_I2C_CTL] == 0x03 && data[0] == 0x05)
|
||||||
{
|
{
|
||||||
|
@ -416,31 +419,24 @@ namespace usb_eyetoy
|
||||||
case USB_TOKEN_IN:
|
case USB_TOKEN_IN:
|
||||||
if (devep == 1)
|
if (devep == 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
memset(data, 0xff, sizeof(data));
|
memset(data, 0xff, sizeof(data));
|
||||||
|
|
||||||
if (s->frame_step == 0)
|
if (s->frame_step == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
s->mpeg_frame_size = s->videodev->GetImage(s->mpeg_frame_data, 320 * 240 * 2);
|
s->mpeg_frame_size = s->videodev->GetImage(s->mpeg_frame_data, 320 * 240 * 2);
|
||||||
if (s->mpeg_frame_size == 0)
|
if (s->mpeg_frame_size == 0)
|
||||||
{
|
{
|
||||||
goto send_packet;
|
goto send_packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->mpeg_frame_offset = 0;
|
uint8_t header[] = {
|
||||||
uint8_t header1[] = {
|
0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
|
0x69, 0x70, 0x75, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xF0, 0x00, 0x01, 0x00, 0x00, 0x00};
|
||||||
memcpy(data, header1, sizeof(header1));
|
memcpy(data, header, sizeof(header));
|
||||||
uint8_t header2[] = {
|
|
||||||
0x69, 0x70, 0x75, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xF0, 0x00, 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00};
|
|
||||||
memcpy(data + sizeof(header1), header2, sizeof(header2));
|
|
||||||
|
|
||||||
int data_pk = max_ep_size - sizeof(header1) - sizeof(header2);
|
int data_pk = max_ep_size - sizeof(header);
|
||||||
memcpy(data + sizeof(header1) + sizeof(header2), s->mpeg_frame_data + s->mpeg_frame_offset, data_pk);
|
memcpy(data + sizeof(header), s->mpeg_frame_data, data_pk);
|
||||||
s->mpeg_frame_offset = data_pk;
|
s->mpeg_frame_offset = data_pk;
|
||||||
|
|
||||||
s->frame_step++;
|
s->frame_step++;
|
||||||
}
|
}
|
||||||
else if (s->mpeg_frame_offset < s->mpeg_frame_size)
|
else if (s->mpeg_frame_offset < s->mpeg_frame_size)
|
||||||
|
@ -450,7 +446,6 @@ namespace usb_eyetoy
|
||||||
data_pk = max_ep_size;
|
data_pk = max_ep_size;
|
||||||
memcpy(data, s->mpeg_frame_data + s->mpeg_frame_offset, data_pk);
|
memcpy(data, s->mpeg_frame_data + s->mpeg_frame_offset, data_pk);
|
||||||
s->mpeg_frame_offset += data_pk;
|
s->mpeg_frame_offset += data_pk;
|
||||||
|
|
||||||
s->frame_step++;
|
s->frame_step++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -556,8 +551,6 @@ namespace usb_eyetoy
|
||||||
s->frame_step = 0;
|
s->frame_step = 0;
|
||||||
s->mpeg_frame_data = (unsigned char*)calloc(1, 320 * 240 * 4); // TODO: 640x480 ?
|
s->mpeg_frame_data = (unsigned char*)calloc(1, 320 * 240 * 4); // TODO: 640x480 ?
|
||||||
s->mpeg_frame_offset = 0;
|
s->mpeg_frame_offset = 0;
|
||||||
s->regs[OV519_R10_H_SIZE] = 320 >> 4;
|
|
||||||
s->regs[OV519_R11_V_SIZE] = 240 >> 3;
|
|
||||||
|
|
||||||
static_state = s;
|
static_state = s;
|
||||||
return (USBDevice*)s;
|
return (USBDevice*)s;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace usb_eyetoy
|
||||||
virtual int Open() = 0;
|
virtual int Open() = 0;
|
||||||
virtual int Close() = 0;
|
virtual int Close() = 0;
|
||||||
virtual int GetImage(uint8_t* buf, int len) = 0;
|
virtual int GetImage(uint8_t* buf, int len) = 0;
|
||||||
|
virtual void SetMirroring(bool state) = 0;
|
||||||
virtual int Reset() = 0;
|
virtual int Reset() = 0;
|
||||||
|
|
||||||
virtual int Port() { return mPort; }
|
virtual int Port() { return mPort; }
|
||||||
|
|
Loading…
Reference in New Issue