mirror of https://github.com/PCSX2/pcsx2.git
USB: Add experimental support for JPEG and multiple resolutions
This commit is contained in:
parent
de728dbefc
commit
060ca1915f
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; };
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; };
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue