diff --git a/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp b/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp index 05a870b83e..39138ed6cc 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp +++ b/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp @@ -30,6 +30,7 @@ struct { const char *name; SensorInstFunc instfunc; } kSensorTable[] = { CamDevice::CamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) : fInitStatus(B_NO_INIT), fSensor(NULL), + fLastParameterChanges(0), fCamDeviceAddon(_addon), fDevice(_device), fSupportedDeviceIndex(-1), @@ -203,6 +204,26 @@ CamDevice::SetVideoParams(float brightness, float contrast, float hue, float red return B_OK; } +// ----------------------------------------------------------------------------- +void +CamDevice::AddParameters(BParameterGroup *group, int32 &index) +{ + fFirstParameterID = index; +} + +status_t +CamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size) +{ + return B_BAD_VALUE; +} + +status_t +CamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size) +{ + return B_BAD_VALUE; +} + + // ----------------------------------------------------------------------------- size_t CamDevice::MinRawFrameSize() diff --git a/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.h b/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.h index 1bab2b8861..43c1300caf 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.h +++ b/src/add-ons/media/media-add-ons/usb_webcam/CamDevice.h @@ -19,6 +19,7 @@ class BBitmap; class BBuffer; class BDataIO; +class BParameterGroup; class CamRoster; class CamDeviceAddon; class CamSensor; @@ -58,6 +59,11 @@ class CamDevice { virtual status_t SetScale(float scale); virtual status_t SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue); + virtual void AddParameters(BParameterGroup *group, int32 &index); + virtual status_t GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size); + virtual status_t SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size); + + // for use by deframer virtual size_t MinRawFrameSize(); virtual size_t MaxRawFrameSize(); @@ -108,8 +114,10 @@ class CamDevice { CamDeframer* fDeframer; BDataIO* fDataInput; // where data from usb goes, likely fDeframer const BUSBEndpoint* fBulkIn; + int32 fFirstParameterID; + bigtime_t fLastParameterChanges; - private: + protected: friend class CamDeviceAddon; CamDeviceAddon& fCamDeviceAddon; BUSBDevice* fDevice; diff --git a/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.cpp b/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.cpp index 23c8174c23..0ad1d5819d 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.cpp +++ b/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.cpp @@ -6,6 +6,7 @@ CamSensor::CamSensor(CamDevice *_camera) : fInitStatus(B_NO_INIT), fTransferEnabled(false), fVideoFrame(), + fLastParameterChanges(0), fCamDevice(_camera) { @@ -68,6 +69,25 @@ CamSensor::SetVideoParams(float brightness, float contrast, float hue, float red return ENOSYS; } +// ----------------------------------------------------------------------------- +void +CamSensor::AddParameters(BParameterGroup *group, int32 &index) +{ + fFirstParameterID = index; +} + +status_t +CamSensor::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size) +{ + return B_BAD_VALUE; +} + +status_t +CamSensor::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size) +{ + return B_BAD_VALUE; +} + // ----------------------------------------------------------------------------- CamDevice * CamSensor::Device() diff --git a/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.h b/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.h index 9babe0fa51..c605d6ebe9 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.h +++ b/src/add-ons/media/media-add-ons/usb_webcam/CamSensor.h @@ -32,6 +32,10 @@ class CamSensor virtual status_t SetVideoFrame(BRect rect); virtual BRect VideoFrame() const { return fVideoFrame; }; virtual status_t SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue); + + virtual void AddParameters(BParameterGroup *group, int32 &index); + virtual status_t GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size); + virtual status_t SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size); CamDevice *Device(); @@ -50,6 +54,8 @@ class CamSensor status_t fInitStatus; bool fTransferEnabled; BRect fVideoFrame; + int32 fFirstParameterID; + bigtime_t fLastParameterChanges; private: CamDevice *fCamDevice; }; diff --git a/src/add-ons/media/media-add-ons/usb_webcam/CamStreamingDeframer.cpp b/src/add-ons/media/media-add-ons/usb_webcam/CamStreamingDeframer.cpp index af578877cb..51dbd98726 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/CamStreamingDeframer.cpp +++ b/src/add-ons/media/media-add-ons/usb_webcam/CamStreamingDeframer.cpp @@ -34,7 +34,7 @@ CamStreamingDeframer::Write(const void *buffer, size_t size) int bufsize = size; bool detach = false; bool discard = false; - PRINT((CH "(%p, %d); state=%s framesz=%u queued=%u" CT, buffer, size, (fState==ST_SYNC)?"sync":"frame", (size_t)(fCurrentFrame?(fCurrentFrame->Position()):-1), (size_t)fInputBuff.Position())); + //PRINT((CH "(%p, %d); state=%s framesz=%u queued=%u" CT, buffer, size, (fState==ST_SYNC)?"sync":"frame", (size_t)(fCurrentFrame?(fCurrentFrame->Position()):-1), (size_t)fInputBuff.Position())); if (!fCurrentFrame) { BAutolock l(fLocker); if (fFrames.CountItems() < MAXFRAMEBUF) diff --git a/src/add-ons/media/media-add-ons/usb_webcam/Producer.cpp b/src/add-ons/media/media-add-ons/usb_webcam/Producer.cpp index 36850e6034..6f00e10d96 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/Producer.cpp +++ b/src/add-ons/media/media-add-ons/usb_webcam/Producer.cpp @@ -18,6 +18,7 @@ #include #include "CamDevice.h" +#include "CamSensor.h" #define TOUCH(x) ((void)(x)) @@ -138,11 +139,24 @@ VideoProducer::NodeRegistered() return; } + int32 id = P_COLOR; /* Set up the parameter web */ + + //TODO: remove and put sensible stuff there BParameterWeb *web = new BParameterWeb(); BParameterGroup *main = web->MakeGroup(Name()); BDiscreteParameter *state = main->MakeDiscreteParameter( P_COLOR, B_MEDIA_RAW_VIDEO, "Color", "Color"); + + id++; + if (fCamDevice) { + BParameterGroup *dev = web->MakeGroup("Device"); + fCamDevice->AddParameters(dev, id); + if (fCamDevice->Sensor()) { + BParameterGroup *sensor = web->MakeGroup("Sensor"); + fCamDevice->Sensor()->AddParameters(sensor, id); + } + } state->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red"); state->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green"); state->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue"); @@ -385,12 +399,20 @@ VideoProducer::PrepareToConnect(const media_source &source, } //XXX:FIXME +#if 1 // if (format->u.raw_video.display.line_width == 0) format->u.raw_video.display.line_width = 352;//320; format->u.raw_video.display.line_width = 320; // if (format->u.raw_video.display.line_count == 0) format->u.raw_video.display.line_count = 288;//240; format->u.raw_video.display.line_count = 240; +#endif + + if (fCamDevice) { + format->u.raw_video.display.line_width = fCamDevice->VideoFrame().IntegerWidth() + 1; + format->u.raw_video.display.line_count = fCamDevice->VideoFrame().IntegerHeight() + 1; + } + if (format->u.raw_video.field_rate == 0) format->u.raw_video.field_rate = 29.97f; @@ -494,7 +516,7 @@ VideoProducer::Disconnect(const media_source &source, return; } -#if 0 +#if 1 /* Some dumb apps don't stop nodes before disconnecting... */ if (fRunning) HandleStop(); @@ -560,31 +582,58 @@ status_t VideoProducer::GetParameterValue( int32 id, bigtime_t *last_change, void *value, size_t *size) { - if (id != P_COLOR) - return B_BAD_VALUE; + status_t err; - *last_change = fLastColorChange; - *size = sizeof(uint32); - *((uint32 *)value) = fColor; + if (id == P_COLOR) { + //return B_BAD_VALUE; - return B_OK; + *last_change = fLastColorChange; + *size = sizeof(uint32); + *((uint32 *)value) = fColor; + return B_OK; + } + + if (fCamDevice) { + BAutolock lock(fCamDevice->Locker()); + err = fCamDevice->GetParameterValue(id, last_change, value, size); + if (err >= B_OK) + return err; + if (fCamDevice->Sensor()) { + err = fCamDevice->Sensor()->GetParameterValue(id, last_change, value, size); + if (err >= B_OK) + return err; + } + } + + return B_BAD_VALUE; } void VideoProducer::SetParameterValue( int32 id, bigtime_t when, const void *value, size_t size) { - if ((id != P_COLOR) || !value || (size != sizeof(uint32))) - return; + status_t err = B_OK; - if (*(uint32 *)value == fColor) - return; + if (id == P_COLOR) { + if (!value || (size != sizeof(uint32))) + return; - fColor = *(uint32 *)value; - fLastColorChange = when; + if (*(uint32 *)value == fColor) + return; - BroadcastNewParameterValue( - fLastColorChange, P_COLOR, &fColor, sizeof(fColor)); + fColor = *(uint32 *)value; + fLastColorChange = when; + + } else if (fCamDevice) { + BAutolock lock(fCamDevice->Locker()); + err = fCamDevice->SetParameterValue(id, when, value, size); + if ((err < B_OK) && (fCamDevice->Sensor())) { + err = fCamDevice->Sensor()->SetParameterValue(id, when, value, size); + } + } + + if (err >= B_OK) + BroadcastNewParameterValue(when, id, (void *)value, size); } status_t diff --git a/src/add-ons/media/media-add-ons/usb_webcam/Producer.h b/src/add-ons/media/media-add-ons/usb_webcam/Producer.h index 974334d6d0..4e6b89b70c 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/Producer.h +++ b/src/add-ons/media/media-add-ons/usb_webcam/Producer.h @@ -23,6 +23,7 @@ virtual ~VideoProducer(); virtual status_t InitCheck() const { return fInitStatus; } + /* BMediaNode */ public: virtual port_id ControlPort() const; diff --git a/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.cpp b/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.cpp index 1497e73ae9..928e20ea06 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.cpp +++ b/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.cpp @@ -4,6 +4,7 @@ #include "CamBufferingDeframer.h" #include "CamStreamingDeframer.h" +#include #include #include @@ -36,6 +37,8 @@ SonixCamDevice::SonixCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) status_t err; fFrameTagState = 0; + fRGain = fGGain = fBGain = 0; + memset(fCachedRegs, 0, SN9C102_REG_COUNT); fChipVersion = 2; if ((GetDevice()->ProductID() & ~0x3F) == 0x6080) { @@ -88,6 +91,7 @@ SonixCamDevice::SonixCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device) if (Sensor()) { PRINT((CH ": CamSensor: %s" CT, Sensor()->Name())); fInitStatus = Sensor()->Setup(); + fVideoFrame = BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1); // SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); // SetVideoFrame(BRect(0, 0, 320-1, 240-1)); } @@ -127,7 +131,7 @@ SonixCamDevice::StartTransfer() if (Sensor()) SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1)); - SetVideoFrame(BRect(0, 0, 320-1, 240-1)); + //SetVideoFrame(BRect(0, 0, 320-1, 240-1)); DumpRegs(); err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true); @@ -364,6 +368,76 @@ SonixCamDevice::SetVideoParams(float brightness, float contrast, float hue, floa return B_OK; } +void +SonixCamDevice::AddParameters(BParameterGroup *group, int32 &index) +{ + BContinuousParameter *p; + CamDevice::AddParameters(group, index); + + p = group->MakeContinuousParameter(index++, + B_MEDIA_RAW_VIDEO, "RGB gain", + B_GAIN, "", 1.0, 1.0+(float)(SN9C102_RGB_GAIN_MAX)/8, (float)1.0/8); + + p->SetChannelCount(3); + + +} + +status_t +SonixCamDevice::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size) +{ + float *gains; + switch (id - fFirstParameterID) { + case 0: + *size = 3 * sizeof(float); + gains = ((float *)value); + gains[0] = 1.0 + (float)fRGain / 8; + gains[1] = 1.0 + (float)fGGain / 8; + gains[2] = 1.0 + (float)fBGain / 8; + *last_change = fLastParameterChanges; + return B_OK; + } + return B_BAD_VALUE; +} + +status_t +SonixCamDevice::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size) +{ + float *gains; + switch (id - fFirstParameterID) { + case 0: + if (!value || (size != 3 * sizeof(float))) + return B_BAD_VALUE; + gains = ((float *)value); + if ((gains[0] == 1.0 + (float)fRGain / 8) + && (gains[1] == 1.0 + (float)fGGain / 8) + && (gains[2] == 1.0 + (float)fBGain / 8)) + return B_OK; + + fRGain = (int)(8 * (gains[0] - 1.0)) & SN9C102_RGB_GAIN_MAX; + fGGain = (int)(8 * (gains[1] - 1.0)) & SN9C102_RGB_GAIN_MAX; + fBGain = (int)(8 * (gains[2] - 1.0)) & SN9C102_RGB_GAIN_MAX; + fLastParameterChanges = when; + PRINT((CH ": gain: %d,%d,%d" CT, fRGain, fGGain, fBGain)); + //WriteReg8(SN9C102_R_B_GAIN, (fBGain << 4) | fRGain); /* red, blue gain = 1+0/8 = 1 */ + /* Datasheet says: + * reg 0x10 [0:3] is rgain, [4:7] is bgain and 0x11 [0:3] is ggain + * according to sn9c102-1.15 linux driver it's wrong for reg 0x10, + * but it doesn't seem to work any better for a rev 2 chip. + * XXX + */ + WriteReg8(SN9C102_R_GAIN, fRGain); + WriteReg8(SN9C102_B_GAIN, fBGain); + if (fChipVersion >= 3) + WriteReg8(SN9C103_G_GAIN, fGGain); + else + WriteReg8(SN9C102_G_GAIN, (fGGain / 16)); + return B_OK; + } + return B_BAD_VALUE; +} + + // ----------------------------------------------------------------------------- size_t SonixCamDevice::MinRawFrameSize() diff --git a/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.h b/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.h index e4360da86e..b80c380fdf 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.h +++ b/src/add-ons/media/media-add-ons/usb_webcam/addons/sonix/SonixCamDevice.h @@ -8,6 +8,9 @@ #define SN9C102_ASIC_ID 0x00 #define SN9C102_CHIP_CTRL 0x01 #define SN9C102_GPIO 0x02 +#define SN9C103_G_GAIN 0x04 /* chip version dependant! */ +#define SN9C102_R_GAIN 0x05 +#define SN9C102_B_GAIN 0x06 #define SN9C102_I2C_SETUP 0x08 #define SN9C102_I2C_SLAVE_ID 0x09 #define SN9C102_I2C_DATA0 0x0a @@ -16,7 +19,7 @@ #define SN9C102_I2C_DATA3 0x0d #define SN9C102_I2C_DATA4 0x0e #define SN9C102_CONTROL_STAT 0x0f /*I2C ??*/ -#define SN9C102_R_B_GAIN 0x10 +#define SN9C102_R_B_GAIN 0x10 /* datasheet says so but it's WRONG */ #define SN9C102_G_GAIN 0x11 /* Green channel gain control. -> Gain = (1+G_GAIN/8) Note: It is sync with VSYNC */ #define SN9C102_H_START 0x12 /* Start active pixel number after H­sync of sensor @@ -37,6 +40,8 @@ #define SN9C102_AE_ENDX 0x1e #define SN9C102_AE_ENDY 0x1f +#define SN9C102_RGB_GAIN_MAX 0x7f + // This class represents each webcam class SonixCamDevice : public CamDevice { @@ -62,6 +67,11 @@ class SonixCamDevice : public CamDevice virtual status_t SetScale(float scale); virtual status_t SetVideoParams(float brightness, float contrast, float hue, float red, float green, float blue); + virtual void AddParameters(BParameterGroup *group, int32 &index); + virtual status_t GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size); + virtual status_t SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size); + + // for use by deframer virtual size_t MinRawFrameSize(); virtual size_t MaxRawFrameSize(); @@ -81,6 +91,10 @@ class SonixCamDevice : public CamDevice int fChipVersion; int fFrameTagState; + + uint8 fRGain; + uint8 fGGain; + uint8 fBGain; }; // the addon itself, that instanciate diff --git a/src/add-ons/media/media-add-ons/usb_webcam/sensors/tas5110c1b.cpp b/src/add-ons/media/media-add-ons/usb_webcam/sensors/tas5110c1b.cpp index ed34272d9c..5de809832b 100644 --- a/src/add-ons/media/media-add-ons/usb_webcam/sensors/tas5110c1b.cpp +++ b/src/add-ons/media/media-add-ons/usb_webcam/sensors/tas5110c1b.cpp @@ -1,10 +1,14 @@ /* */ +#include + #include "CamSensor.h" #include "CamDebug.h" #include "addons/sonix/SonixCamDevice.h" +#define ENABLE_GAIN 1 + class TAS5110C1BSensor : public CamSensor { public: TAS5110C1BSensor(CamDevice *_camera); @@ -18,8 +22,13 @@ public: virtual int MaxWidth() const { return 352; }; virtual int MaxHeight() const { return 288; }; virtual status_t SetVideoFrame(BRect rect); + virtual void AddParameters(BParameterGroup *group, int32 &firstID); + virtual status_t GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size); + virtual status_t SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size); + private: bool fIsSonix; + float fGain; }; // ----------------------------------------------------------------------------- @@ -33,6 +42,7 @@ TAS5110C1BSensor::TAS5110C1BSensor(CamDevice *_camera) PRINT((CH ": unknown camera device!" CT)); fInitStatus = ENODEV; } + fGain = (float)0x40; // default } // ----------------------------------------------------------------------------- @@ -109,6 +119,53 @@ TAS5110C1BSensor::SetVideoFrame(BRect rect) return B_OK; } +void +TAS5110C1BSensor::AddParameters(BParameterGroup *group, int32 &index) +{ + BContinuousParameter *p; + CamSensor::AddParameters(group, index); + +#ifdef ENABLE_GAIN + p = group->MakeContinuousParameter(index++, + B_MEDIA_RAW_VIDEO, "global gain", + B_GAIN, "", (float)0x00, (float)0xf6, (float)1); +#endif +} + + +status_t +TAS5110C1BSensor::GetParameterValue(int32 id, bigtime_t *last_change, void *value, size_t *size) +{ +#ifdef ENABLE_GAIN + if (id == fFirstParameterID) { + *size = sizeof(float); + *((float *)value) = fGain; + *last_change = fLastParameterChanges; + } +#endif + return B_BAD_VALUE; +} + +status_t +TAS5110C1BSensor::SetParameterValue(int32 id, bigtime_t when, const void *value, size_t size) +{ +#ifdef ENABLE_GAIN + if (id == fFirstParameterID) { + if (!value || (size != sizeof(float))) + return B_BAD_VALUE; + if (*(float *)value == fGain) + return B_OK; + fGain = *(float *)value; + fLastParameterChanges = when; + PRINT((CH ": gain: %f (%d)" CT, fGain, (unsigned)(0xf6-fGain))); + Device()->WriteIIC8(0x20, (uint8)0xf6 - (uint8)fGain); + return B_OK; + } +#endif + return B_BAD_VALUE; +} + + // ----------------------------------------------------------------------------- B_WEBCAM_DECLARE_SENSOR(TAS5110C1BSensor, tas5110c1b)