USB: Add experimental support for JPEG and multiple resolutions

This commit is contained in:
Florin9doi 2021-05-08 11:38:40 +03:00 committed by jackun
parent de728dbefc
commit 060ca1915f
12 changed files with 307 additions and 88 deletions

View File

@ -395,6 +395,7 @@ set(pcsx2USBSources
USB/usb-mic/usb-mic-logitech.cpp
USB/usb-mic/usb-headset.cpp
USB/usb-eyetoy/jpgd/jpgd.cpp
USB/usb-eyetoy/jpgd/jpge.cpp
USB/usb-eyetoy/jo_mpeg.cpp
USB/usb-eyetoy/usb-eyetoy-webcam.cpp
USB/usb-hid/usb-hid.cpp
@ -449,6 +450,7 @@ set(pcsx2USBHeaders
USB/usb-mic/usb-headset.h
USB/usb-mic/audiodev-noop.h
USB/usb-eyetoy/jpgd/jpgd.h
USB/usb-eyetoy/jpgd/jpge.h
USB/usb-eyetoy/jo_mpeg.h
USB/usb-eyetoy/videodeviceproxy.h
USB/usb-eyetoy/videodev.h

View File

@ -16,6 +16,7 @@
#include "cam-linux.h"
#include "usb-eyetoy-webcam.h"
#include "jpgd/jpgd.h"
#include "jpgd/jpge.h"
#include "jo_mpeg.h"
#include "USB/gtk.h"
#include "Utilities/Console.h"
@ -52,6 +53,9 @@ namespace usb_eyetoy
buffer_t mpeg_buffer;
std::mutex mpeg_mutex;
int frame_width;
int frame_height;
FrameFormat frame_format;
bool mirroring_enabled = true;
static int xioctl(int fh, unsigned long int request, void* arg)
@ -64,7 +68,7 @@ namespace usb_eyetoy
return r;
}
static void store_mpeg_frame(unsigned char* data, unsigned int len)
static void store_mpeg_frame(const unsigned char* data, const unsigned int len)
{
mpeg_mutex.lock();
memcpy(mpeg_buffer.start, data, len);
@ -72,24 +76,77 @@ namespace usb_eyetoy
mpeg_mutex.unlock();
}
static void process_image(const unsigned char* ptr, int size)
static void process_image(const unsigned char* data, int size)
{
const int bytesPerPixel = 3;
int comprBufSize = frame_width * frame_height * bytesPerPixel;
if (pixelformat == V4L2_PIX_FMT_YUYV)
{
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
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);
free(mpegData);
unsigned char* comprBuf = (unsigned char*)calloc(1, comprBufSize);
int comprLen = 0;
if (frame_format == format_mpeg)
{
comprLen = jo_write_mpeg(comprBuf, data, frame_width, frame_height, JO_YUYV, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_NONE);
}
else if (frame_format == format_jpeg)
{
unsigned char* data2 = (unsigned char*)calloc(1, comprBufSize);
for (int y = 0; y < frame_height; y++)
{
for (int x = 0; x < frame_width; x += 2)
{
const unsigned char* src = data + (y * frame_width + x) * 2;
unsigned char* dst = data2 + (y * frame_width + x) * bytesPerPixel;
int y1 = (int) src[0] << 8;
int u = (int) src[1] - 128;
int y2 = (int) src[2] << 8;
int v = (int) src[3] - 128;
int r = (y1 + (259 * v) >> 8);
int g = (y1 - (88 * u) - (183 * v)) >> 8;
int b = (y1 + (454 * u)) >> 8;
dst[0] = (r > 255) ? 255 : ((r < 0) ? 0 : r);
dst[1] = (g > 255) ? 255 : ((g < 0) ? 0 : g);
dst[2] = (b > 255) ? 255 : ((b < 0) ? 0 : b);
r = (y2 + (259 * v) >> 8);
g = (y2 - (88 * u) - (183 * v)) >> 8;
b = (y2 + (454 * u)) >> 8;
dst[3] = (r > 255) ? 255 : ((r < 0) ? 0 : r);
dst[4] = (g > 255) ? 255 : ((g < 0) ? 0 : g);
dst[5] = (b > 255) ? 255 : ((b < 0) ? 0 : b);
}
}
jpge::params params;
params.m_quality = 80;
params.m_subsampling = jpge::H2V1;
comprLen = comprBufSize;
if (!jpge::compress_image_to_jpeg_file_in_memory(comprBuf, comprLen, frame_width, frame_height, 3, data2, params))
{
comprLen = 0;
}
free(data2);
}
store_mpeg_frame(comprBuf, comprLen);
free(comprBuf);
}
else if (pixelformat == V4L2_PIX_FMT_JPEG)
{
int width, height, actual_comps;
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);
int mpegLen = jo_write_mpeg(mpegData, rgbData, 320, 240, JO_RGB24, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
if (frame_format == format_mpeg)
{
int width, height, actual_comps;
unsigned char* rgbData = jpgd::decompress_jpeg_image_from_memory(data, size, &width, &height, &actual_comps, 3);
unsigned char* comprBuf = (unsigned char*)calloc(1, comprBufSize);
int comprLen = jo_write_mpeg(comprBuf, rgbData, frame_width, frame_height, JO_RGB24, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(comprBuf, comprLen);
free(comprBuf);
}
else if (frame_format == format_jpeg)
{
store_mpeg_frame(data, size);
}
}
else
{
@ -272,8 +329,8 @@ namespace usb_eyetoy
struct v4l2_format fmt;
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.width = frame_width;
fmt.fmt.pix.height = frame_height;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
@ -438,32 +495,60 @@ namespace usb_eyetoy
void create_dummy_frame()
{
const int width = 320;
const int height = 240;
const int bytesPerPixel = 3;
unsigned char* rgbData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
for (int y = 0; y < height; y++)
int comprBufSize = frame_width * frame_height * bytesPerPixel;
unsigned char* rgbData = (unsigned char*)calloc(1, comprBufSize);
for (int y = 0; y < frame_height; y++)
{
for (int x = 0; x < width; x++)
for (int x = 0; x < frame_width; x++)
{
unsigned char* ptr = rgbData + (y * width + x) * bytesPerPixel;
ptr[0] = 255 - y;
ptr[1] = y;
ptr[2] = 255 - y;
unsigned char* ptr = rgbData + (y * frame_width + x) * bytesPerPixel;
ptr[0] = 255 * y / frame_height;
ptr[1] = 255 * x / frame_width;
ptr[2] = 255 * y / frame_height;
}
}
unsigned char* comprBuf = (unsigned char*)calloc(1, comprBufSize);
int comprLen = 0;
if (frame_format == format_mpeg)
{
comprLen = jo_write_mpeg(comprBuf, rgbData, frame_width, frame_height, JO_RGB24, JO_NONE, JO_NONE);
}
else if (frame_format == format_jpeg)
{
jpge::params params;
params.m_quality = 80;
params.m_subsampling = jpge::H2V1;
comprLen = comprBufSize;
if (!jpge::compress_image_to_jpeg_file_in_memory(comprBuf, comprLen, frame_width, frame_height, 3, rgbData, params))
{
comprLen = 0;
}
}
unsigned char* mpegData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
int mpegLen = jo_write_mpeg(mpegData, rgbData, width, height, JO_RGB24, JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
store_mpeg_frame(comprBuf, comprLen);
free(comprBuf);
}
int V4L2::Open()
V4L2::V4L2(int port)
{
mpeg_buffer.start = calloc(1, 320 * 240 * 2);
mPort = port;
mpeg_buffer.start = calloc(1, 640 * 480 * 2);
}
V4L2::~V4L2()
{
free(mpeg_buffer.start);
mpeg_buffer.start = nullptr;
}
int V4L2::Open(int width, int height, FrameFormat format, int mirror)
{
frame_width = width;
frame_height = height;
frame_format = format;
mirroring_enabled = mirror;
create_dummy_frame();
if (eyetoy_running)
{
@ -493,11 +578,11 @@ namespace usb_eyetoy
return 0;
};
int V4L2::GetImage(uint8_t* buf, int len)
int V4L2::GetImage(uint8_t* buf, size_t len)
{
mpeg_mutex.lock();
int len2 = mpeg_buffer.length;
if (len < (int)mpeg_buffer.length)
if (len < mpeg_buffer.length)
len2 = len;
memcpy(buf, mpeg_buffer.start, len2);
mpeg_buffer.length = 0;

View File

@ -20,7 +20,7 @@ namespace usb_eyetoy
namespace linux_api
{
typedef struct
typedef struct _buffer_t
{
void* start;
size_t length;
@ -31,12 +31,11 @@ namespace usb_eyetoy
class V4L2 : public VideoDevice
{
public:
V4L2(int port)
: mPort(port){};
~V4L2(){};
int Open();
V4L2(int port);
~V4L2();
int Open(int width, int height, FrameFormat format, int mirror);
int Close();
int GetImage(uint8_t* buf, int len);
int GetImage(uint8_t* buf, size_t len);
void SetMirroring(bool state);
int Reset() { return 0; };

View File

@ -18,6 +18,7 @@
#include "cam-windows.h"
#include "usb-eyetoy-webcam.h"
#include "jo_mpeg.h"
#include "jpgd/jpge.h"
#include "USB/Win32/Config_usb.h"
#include "USB/Win32/resource_usb.h"
@ -26,6 +27,12 @@ namespace usb_eyetoy
{
namespace windows_api
{
buffer_t mpeg_buffer{};
std::mutex mpeg_mutex;
int frame_width;
int frame_height;
FrameFormat frame_format;
bool mirroring_enabled = true;
HRESULT DirectShow::CallbackHandler::SampleCB(double time, IMediaSample* sample)
{
@ -224,8 +231,8 @@ namespace usb_eyetoy
{
VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
pVih->bmiHeader.biWidth = 320;
pVih->bmiHeader.biHeight = 240;
pVih->bmiHeader.biWidth = frame_width;
pVih->bmiHeader.biHeight = frame_height;
pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);
hr = pSourceConfig->SetFormat(pmtConfig);
}
@ -354,11 +361,7 @@ namespace usb_eyetoy
throw hr;
}
buffer_t mpeg_buffer{};
std::mutex mpeg_mutex;
bool mirroring_enabled = true;
void store_mpeg_frame(unsigned char* data, unsigned int len)
void store_mpeg_frame(const unsigned char* data, const unsigned int len)
{
mpeg_mutex.lock();
memcpy(mpeg_buffer.start, data, len);
@ -370,10 +373,42 @@ namespace usb_eyetoy
{
if (bitsperpixel == 24)
{
unsigned char* mpegData = (unsigned char*)calloc(1, 320 * 240 * 2);
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);
free(mpegData);
const int bytesPerPixel = 3;
int comprBufSize = frame_width * frame_height * bytesPerPixel;
unsigned char* comprBuf = (unsigned char*)calloc(1, comprBufSize);
int comprLen = 0;
if (frame_format == format_mpeg)
{
comprLen = jo_write_mpeg(comprBuf, data, frame_width, frame_height, JO_BGR24, mirroring_enabled ? JO_FLIP_X : JO_NONE, JO_FLIP_Y);
}
else if (frame_format == format_jpeg)
{
// flip Y - always required on windows
unsigned char* data2 = (unsigned char*)calloc(1, comprBufSize);
for (int y = 0; y < frame_height; y++)
{
for (int x = 0; x < frame_width; x++)
{
unsigned char* src = data + (y * frame_width + x) * bytesPerPixel;
unsigned char* dst = data2 + ((frame_height - y - 1) * frame_width + x) * bytesPerPixel;
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
}
}
jpge::params params;
params.m_quality = 80;
params.m_subsampling = jpge::H2V1;
comprLen = comprBufSize;
if (!jpge::compress_image_to_jpeg_file_in_memory(comprBuf, comprLen, frame_width, frame_height, 3, data2, params))
{
comprLen = 0;
}
free(data2);
}
store_mpeg_frame(comprBuf, comprLen);
free(comprBuf);
}
else
{
@ -383,27 +418,40 @@ namespace usb_eyetoy
void create_dummy_frame()
{
const int width = 320;
const int height = 240;
const int bytesPerPixel = 3;
unsigned char* rgbData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
for (int y = 0; y < height; y++)
int comprBufSize = frame_width * frame_height * bytesPerPixel;
unsigned char* rgbData = (unsigned char*)calloc(1, comprBufSize);
for (int y = 0; y < frame_height; y++)
{
for (int x = 0; x < width; x++)
for (int x = 0; x < frame_width; x++)
{
unsigned char* ptr = rgbData + (y * width + x) * bytesPerPixel;
ptr[0] = 255 - y;
ptr[1] = y;
ptr[2] = 255 - y;
unsigned char* ptr = rgbData + (y * frame_width + x) * bytesPerPixel;
ptr[0] = 255 * y / frame_height;
ptr[1] = 255 * x / frame_width;
ptr[2] = 255 * y / frame_height;
}
}
unsigned char* comprBuf = (unsigned char*)calloc(1, comprBufSize);
int comprLen = 0;
if (frame_format == format_mpeg)
{
comprLen = jo_write_mpeg(comprBuf, rgbData, frame_width, frame_height, JO_RGB24, JO_NONE, JO_NONE);
}
else if (frame_format == format_jpeg)
{
jpge::params params;
params.m_quality = 80;
params.m_subsampling = jpge::H2V1;
comprLen = comprBufSize;
if (!jpge::compress_image_to_jpeg_file_in_memory(comprBuf, comprLen, frame_width, frame_height, 3, rgbData, params))
{
comprLen = 0;
}
}
unsigned char* mpegData = (unsigned char*)calloc(1, width * height * bytesPerPixel);
int mpegLen = jo_write_mpeg(mpegData, rgbData, width, height, JO_RGB24, JO_NONE, JO_NONE);
free(rgbData);
store_mpeg_frame(mpegData, mpegLen);
free(mpegData);
store_mpeg_frame(comprBuf, comprLen);
free(comprBuf);
}
DirectShow::DirectShow(int port)
@ -419,11 +467,21 @@ namespace usb_eyetoy
samplegrabber = nullptr;
callbackhandler = new CallbackHandler();
CoInitialize(NULL);
mpeg_buffer.start = calloc(1, 640 * 480 * 2);
}
int DirectShow::Open()
DirectShow::~DirectShow()
{
mpeg_buffer.start = calloc(1, 320 * 240 * 2);
free(mpeg_buffer.start);
mpeg_buffer.start = nullptr;
}
int DirectShow::Open(int width, int height, FrameFormat format, int mirror)
{
frame_width = width;
frame_height = height;
frame_format = format;
mirroring_enabled = mirror;
create_dummy_frame();
std::wstring selectedDevice;
@ -461,13 +519,10 @@ namespace usb_eyetoy
safe_release(pGraphBuilder);
safe_release(pGraph);
safe_release(pControl);
free(mpeg_buffer.start);
mpeg_buffer.start = nullptr;
return 0;
};
int DirectShow::GetImage(uint8_t* buf, int len)
int DirectShow::GetImage(uint8_t* buf, size_t len)
{
mpeg_mutex.lock();
int len2 = mpeg_buffer.length;

View File

@ -84,10 +84,10 @@ namespace usb_eyetoy
{
public:
DirectShow(int port);
~DirectShow() {}
int Open();
~DirectShow();
int Open(int width, int height, FrameFormat format, int mirror);
int Close();
int GetImage(uint8_t* buf, int len);
int GetImage(uint8_t* buf, size_t len);
void SetMirroring(bool state);
int Reset() { return 0; };

View File

@ -178,11 +178,35 @@ static int jo_processDU(jo_bits_t *bits, float A[64], const unsigned char htdc[9
return Q[0];
}
void write_ipu_header(jo_bits_t* bits, int width, int height) {
jo_writeBits(bits, 0x69, 8);
jo_writeBits(bits, 0x70, 8);
jo_writeBits(bits, 0x75, 8);
jo_writeBits(bits, 0x6D, 8);
jo_writeBits(bits, 0x00, 8);
jo_writeBits(bits, 0x00, 8);
jo_writeBits(bits, 0x00, 8);
jo_writeBits(bits, 0x00, 8);
jo_writeBits(bits, width & 0xFF, 8);
jo_writeBits(bits, width >> 8, 8);
jo_writeBits(bits, height & 0xFF, 8);
jo_writeBits(bits, height >> 8, 8);
jo_writeBits(bits, 0x01, 8);
jo_writeBits(bits, 0x00, 8);
jo_writeBits(bits, 0x00, 8);
jo_writeBits(bits, 0x00, 8);
}
unsigned long jo_write_mpeg(unsigned char *mpeg_buf, const unsigned char *raw, int width, int height, int format, int flipx, int flipy) {
int lastDCY = 128, lastDCCR = 128, lastDCCB = 128;
unsigned char *head = mpeg_buf;
jo_bits_t bits = {mpeg_buf};
write_ipu_header(&bits, width, height);
jo_writeBits(&bits, 0x00, 8);
for (int vblock = 0; vblock < (height+15)/16; vblock++) {
for (int hblock = 0; hblock < (width+15)/16; hblock++) {

View File

@ -28,6 +28,7 @@
// Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02.
// v1.05, March 25, 2020: Added Apache 2.0 alternate license
#include "PrecompiledHeader.h"
#include "jpge.h"
#include <stdlib.h>

View File

@ -33,6 +33,8 @@
#define OV519_R20_DFR 0x20
#define OV519_R25_FORMAT 0x25
#define OV519_RA0_FORMAT 0xA0
#define OV519_RA0_FORMAT_MPEG 0x42
#define OV519_RA0_FORMAT_JPEG 0x33
/* OV519 System Controller register numbers */
#define OV519_R51_RESET1 0x51
@ -50,6 +52,8 @@
#define OV8610_REG_HUE 0x04 /* 04 reserved */
#define OV7610_REG_CNT 0x05 /* Y contrast */
#define OV7610_REG_BRT 0x06 /* Y brightness */
#define OV7610_REG_COM_A 0x12 /* misc common regs */
#define OV7610_REG_COM_A_MASK_MIRROR 0x40 /* mirror image */
#define OV7610_REG_COM_C 0x14 /* misc common regs */
#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */

View File

@ -33,12 +33,11 @@ namespace usb_eyetoy
uint8_t regs[0xFF]; //OV519
uint8_t i2c_regs[0xFF]; //OV764x
int hw_camera_running;
int frame_step;
unsigned char* mpeg_frame_data;
unsigned int mpeg_frame_size;
unsigned int mpeg_frame_offset;
uint8_t alts[3];
uint8_t filter_log;
// } f;
} EYETOYState;
@ -341,18 +340,31 @@ namespace usb_eyetoy
switch (index)
{
case OV519_RA0_FORMAT:
if (data[0] == 0x42)
if (data[0] == OV519_RA0_FORMAT_MPEG)
{
Console.WriteLn("EyeToy : configured for MPEG format");
}
else if (data[0] == 0x33)
else if (data[0] == OV519_RA0_FORMAT_JPEG)
{
Console.WriteLn("EyeToy : configured for JPEG format; Unimplemented");
Console.WriteLn("EyeToy : configured for JPEG format");
}
else
{
Console.WriteLn("EyeToy : configured for unknown format");
}
if (s->hw_camera_running && s->regs[OV519_RA0_FORMAT] != data[0])
{
Console.WriteLn("EyeToy : reinitialize the camera");
s->dev.klass.close(dev);
s->dev.klass.open(dev);
}
break;
case OV519_R10_H_SIZE:
Console.WriteLn("EyeToy : Image width : %d", data[0] << 4);
break;
case OV519_R11_V_SIZE:
Console.WriteLn("EyeToy : Image height : %d", data[0] << 3);
break;
case OV519_GPIO_DATA_OUT0:
{
@ -379,9 +391,9 @@ namespace usb_eyetoy
{
s->i2c_regs[reg] = val;
}
if (reg == 0x12)
if (reg == OV7610_REG_COM_A)
{
const bool mirroring_enabled = val & 0x40;
const bool mirroring_enabled = val & OV7610_REG_COM_A_MASK_MIRROR;
s->videodev->SetMirroring(mirroring_enabled);
Console.WriteLn("EyeToy : mirroring %s", mirroring_enabled ? "ON" : "OFF");
}
@ -420,6 +432,13 @@ namespace usb_eyetoy
uint8_t data[max_ep_size];
uint8_t devep = p->ep->nr;
if (!s->hw_camera_running)
{
Console.WriteLn("EyeToy : initialization done; start the camera");
s->hw_camera_running = 1;
s->dev.klass.open(dev);
}
switch (p->pid)
{
case USB_TOKEN_IN:
@ -429,7 +448,7 @@ namespace usb_eyetoy
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, 640 * 480 * 3);
if (s->mpeg_frame_size == 0)
{
p->status = USB_RET_NAK;
@ -437,8 +456,8 @@ namespace usb_eyetoy
}
uint8_t header[] = {
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};
0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
header[0x0A] = s->regs[OV519_RA0_FORMAT] == OV519_RA0_FORMAT_JPEG ? 0x03 : 0x01;
memcpy(data, header, sizeof(header));
int data_pk = max_ep_size - sizeof(header);
@ -459,9 +478,11 @@ namespace usb_eyetoy
{
uint8_t footer[] = {
0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
footer[0x0A] = s->regs[OV519_RA0_FORMAT] == OV519_RA0_FORMAT_JPEG ? 0x03 : 0x01;
memcpy(data, footer, sizeof(footer));
s->frame_step = 0;
}
usb_packet_copy(p, data, max_ep_size);
}
else if (devep == 2)
@ -489,14 +510,28 @@ namespace usb_eyetoy
int eyetoy_open(USBDevice* dev)
{
EYETOYState* s = (EYETOYState*)dev;
s->videodev->Open();
if (s->hw_camera_running)
{
const int width = s->regs[OV519_R10_H_SIZE] << 4;
const int height = s->regs[OV519_R11_V_SIZE] << 3;
const FrameFormat format = s->regs[OV519_RA0_FORMAT] == OV519_RA0_FORMAT_JPEG ? format_jpeg : format_mpeg;
const int mirror = !!(s->i2c_regs[OV7610_REG_COM_A] & OV7610_REG_COM_A_MASK_MIRROR);
Console.Error("EyeToy : eyetoy_open(); hw=%d, w=%d, h=%d, fmt=%d, mirr=%d", s->hw_camera_running,
width, height, format, mirror);
s->videodev->Open(width, height, format, mirror);
}
return 1;
}
void eyetoy_close(USBDevice* dev)
{
EYETOYState* s = (EYETOYState*)dev;
s->videodev->Close();
Console.Error("EyeToy : eyetoy_close(); hw=%d", s->hw_camera_running);
if (s->hw_camera_running)
{
s->hw_camera_running = 0;
s->videodev->Close();
}
}
USBDevice* EyeToyWebCamDevice::CreateDevice(int port)
@ -552,8 +587,9 @@ namespace usb_eyetoy
usb_ep_init(&s->dev);
eyetoy_handle_reset((USBDevice*)s);
s->hw_camera_running = 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, 640 * 480 * 3);
s->mpeg_frame_offset = 0;
static_state = s;

View File

@ -20,14 +20,19 @@
namespace usb_eyetoy
{
enum FrameFormat
{
format_mpeg,
format_jpeg
};
class VideoDevice
{
public:
virtual ~VideoDevice() {}
virtual int Open() = 0;
virtual int Open(int width, int height, FrameFormat format, int mirror) = 0;
virtual int Close() = 0;
virtual int GetImage(uint8_t* buf, int len) = 0;
virtual int GetImage(uint8_t* buf, size_t len) = 0;
virtual void SetMirroring(bool state) = 0;
virtual int Reset() = 0;

View File

@ -451,6 +451,7 @@
<ClCompile Include="USB\usb-eyetoy\cam-windows.cpp" />
<ClCompile Include="USB\usb-eyetoy\jo_mpeg.cpp" />
<ClCompile Include="USB\usb-eyetoy\jpgd\jpgd.cpp" />
<ClCompile Include="USB\usb-eyetoy\jpgd\jpge.cpp" />
<ClCompile Include="USB\usb-eyetoy\usb-eyetoy-webcam.cpp" />
<ClCompile Include="USB\usb-hid\api_init_win32_hid.cpp" />
<ClCompile Include="USB\usb-hid\raw\rawinput.cpp" />
@ -936,6 +937,7 @@
<ClInclude Include="USB\usb-eyetoy\cam-windows.h" />
<ClInclude Include="USB\usb-eyetoy\jo_mpeg.h" />
<ClInclude Include="USB\usb-eyetoy\jpgd\jpgd.h" />
<ClInclude Include="USB\usb-eyetoy\jpgd\jpge.h" />
<ClInclude Include="USB\usb-eyetoy\ov519.h" />
<ClInclude Include="USB\usb-eyetoy\usb-eyetoy-webcam.h" />
<ClInclude Include="USB\usb-eyetoy\videodev.h" />

View File

@ -1218,6 +1218,9 @@
<ClCompile Include="USB\usb-eyetoy\jpgd\jpgd.cpp">
<Filter>System\Ps2\USB\usb-eyetoy\jpgd</Filter>
</ClCompile>
<ClCompile Include="USB\usb-eyetoy\jpgd\jpge.cpp">
<Filter>System\Ps2\USB\usb-eyetoy\jpgd</Filter>
</ClCompile>
<ClCompile Include="USB\usb-eyetoy\jo_mpeg.cpp">
<Filter>System\Ps2\USB\usb-eyetoy</Filter>
</ClCompile>
@ -2251,6 +2254,9 @@
<ClInclude Include="USB\usb-eyetoy\jpgd\jpgd.h">
<Filter>System\Ps2\USB\usb-eyetoy\jpgd</Filter>
</ClInclude>
<ClInclude Include="USB\usb-eyetoy\jpgd\jpge.h">
<Filter>System\Ps2\USB\usb-eyetoy\jpgd</Filter>
</ClInclude>
<ClInclude Include="USB\usb-hid\hidproxy.h">
<Filter>System\Ps2\USB\usb-hid</Filter>
</ClInclude>