aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJérôme Duval <korli@users.berlios.de>2011-08-25 16:36:48 +0000
committerJérôme Duval <korli@users.berlios.de>2011-08-25 16:36:48 +0000
commit51a01ea03b482556ca9780c879a727fad22201c6 (patch)
tree4ccc72a7430384f51e2e6e26d461c89c4f6278f7
parent61f3c5c1c70ec0f97268c23ee0095cb43912384d (diff)
Patch from Gabriel Hartmann for his GSoC UVC project. Coding style updates by myself. Thanks!hrev42688
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42688 a95241bf-73f2-0310-859d-f6bbb57e9c96
-rw-r--r--src/add-ons/media/media-add-ons/usb_webcam/CamDevice.cpp24
-rw-r--r--src/add-ons/media/media-add-ons/usb_webcam/Jamfile2
-rw-r--r--src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.cpp844
-rw-r--r--src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.h48
-rw-r--r--src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.cpp79
-rw-r--r--src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.h31
-rw-r--r--src/bin/listusb.cpp2
7 files changed, 940 insertions, 90 deletions
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 01ad8b1c1e..81d83fba02 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
@@ -565,8 +565,15 @@ CamDevice::DataPumpThread()
}
#ifdef SUPPORT_ISO
else if (SupportsIsochronous()) {
- int numPacketDescriptors = 20;
+ int numPacketDescriptors = 16;
usb_iso_packet_descriptor packetDescriptors[numPacketDescriptors];
+
+ // Initialize packetDescriptor request lengths
+ for (int i = 0; i<numPacketDescriptors; i++)
+ packetDescriptors[i].request_length = 256;
+
+ int fullPackets = 0;
+ int totalPackets = 0;
while (fTransferEnabled) {
ssize_t len = -1;
BAutolock lock(fLocker);
@@ -575,7 +582,8 @@ CamDevice::DataPumpThread()
if (!fIsoIn)
break;
#ifndef DEBUG_DISCARD_INPUT
- len = fIsoIn->IsochronousTransfer(fBuffer, fBufferLen, packetDescriptors, numPacketDescriptors);
+ len = fIsoIn->IsochronousTransfer(fBuffer, fBufferLen, packetDescriptors,
+ numPacketDescriptors);
#endif
//PRINT((CH ": got %d bytes" CT, len));
@@ -594,8 +602,16 @@ CamDevice::DataPumpThread()
#ifndef DEBUG_DISCARD_DATA
if (fDataInput) {
- fDataInput->Write(fBuffer, len);
- // else drop
+ int fBufferIndex = 0;
+ for (int i = 0; i < numPacketDescriptors; i++) {
+ int actual_length = ((usb_iso_packet_descriptor)
+ packetDescriptors[i]).actual_length;
+ if (actual_length > 0) {
+ fDataInput->Write(&fBuffer[fBufferIndex],
+ actual_length);
+ }
+ fBufferIndex += actual_length;
+ }
}
#endif
//snooze(2000);
diff --git a/src/add-ons/media/media-add-ons/usb_webcam/Jamfile b/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
index 994f6e6a0b..c8f5e3f1a2 100644
--- a/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
+++ b/src/add-ons/media/media-add-ons/usb_webcam/Jamfile
@@ -35,7 +35,7 @@ addonSources =
QuickCamDevice.cpp
SonixCamDevice.cpp
NW80xCamDevice.cpp
-# UVCCamDevice.cpp
+# UVCCamDevice.cpp UVCDeframer.cpp
;
## colorspace transforms sources
diff --git a/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.cpp b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.cpp
index 1fe8479863..21b3b06cb7 100644
--- a/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.cpp
+++ b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.cpp
@@ -1,4 +1,5 @@
/*
+ * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com.
* Copyright 2011, Jérôme Duval, korli@users.berlios.de.
* Copyright 2009, Ithamar Adema, <ithamar.adema@team-embedded.nl>.
* Distributed under the terms of the MIT License.
@@ -6,10 +7,12 @@
#include "UVCCamDevice.h"
+#include "UVCDeframer.h"
#include <stdio.h>
-
-#include "CamStreamingDeframer.h"
+#include <stdlib.h>
+#include <ParameterWeb.h>
+#include <media/Buffer.h>
usb_webcam_support_descriptor kSupportedDevices[] = {
@@ -60,27 +63,14 @@ print_guid(const usbvc_guid guid)
}
-// TODO dumb sof_marks and eof_marks
-static const uint8 sof_mark_1[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00 };
-static const uint8 sof_mark_2[] = { 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01 };
-static const uint8 *sof_marks[] = { sof_mark_1, sof_mark_2 };
-
-static const uint8 eof_mark_1[] = { 0x00, 0x00, 0x00, 0x00 };
-static const uint8 eof_mark_2[] = { 0x40, 0x00, 0x00, 0x00 };
-static const uint8 eof_mark_3[] = { 0x80, 0x00, 0x00, 0x00 };
-static const uint8 eof_mark_4[] = { 0xc0, 0x00, 0x00, 0x00 };
-static const uint8 *eof_marks[] = { eof_mark_1, eof_mark_2, eof_mark_3, eof_mark_4 };
-
-
-
-UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
+UVCCamDevice::UVCCamDevice(CamDeviceAddon& _addon, BUSBDevice* _device)
: CamDevice(_addon, _device),
fHeaderDescriptor(NULL),
- fInterruptIn(NULL)
+ fInterruptIn(NULL),
+ fUncompressedFormatIndex(1),
+ fUncompressedFrameIndex(1)
{
- fDeframer = new CamStreamingDeframer(this);
- fDeframer->RegisterSOFTags(sof_marks, 2, sizeof(sof_mark_1), 12);
- fDeframer->RegisterEOFTags(eof_marks, 4, sizeof(eof_mark_1), sizeof(eof_mark_1));
+ fDeframer = new UVCDeframer(this);
SetDataInput(fDeframer);
const BUSBConfiguration* config;
@@ -88,7 +78,7 @@ UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
usb_descriptor* generic;
uint8 buffer[1024];
- generic = (usb_descriptor *)buffer;
+ generic = (usb_descriptor*)buffer;
for (uint32 i = 0; i < _device->CountConfigurations(); i++) {
config = _device->ConfigurationAt(i);
@@ -111,9 +101,8 @@ UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
_ParseVideoControl((const usbvc_class_descriptor*)generic,
generic->generic.length);
}
-
for (uint32 k = 0; k < interface->CountEndpoints(); k++) {
- const BUSBEndpoint *e = interface->EndpointAt(i);
+ const BUSBEndpoint* e = interface->EndpointAt(i);
if (e && e->IsInterrupt() && e->IsInput()) {
fInterruptIn = e;
break;
@@ -137,7 +126,7 @@ UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
}
for (uint32 k = 0; k < interface->CountEndpoints(); k++) {
- const BUSBEndpoint *e = interface->EndpointAt(i);
+ const BUSBEndpoint* e = interface->EndpointAt(i);
if (e && e->IsIsochronous() && e->IsInput()) {
fIsoIn = e;
break;
@@ -151,6 +140,7 @@ UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
UVCCamDevice::~UVCCamDevice()
{
+ free(fHeaderDescriptor);
}
@@ -158,11 +148,11 @@ void
UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
size_t len)
{
- switch(_descriptor->descriptorSubtype) {
+ switch (_descriptor->descriptorSubtype) {
case VS_INPUT_HEADER:
{
- const usbvc_input_header_descriptor* descriptor =
- (const usbvc_input_header_descriptor*)_descriptor;
+ const usbvc_input_header_descriptor* descriptor
+ = (const usbvc_input_header_descriptor*)_descriptor;
printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", descriptor->numFormats,
descriptor->endpointAddress);
if (descriptor->info & 1)
@@ -173,7 +163,7 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
printf("\ttrigger button fixed to still capture=%s\n",
descriptor->triggerUsage ? "no" : "yes");
}
- const uint8 *controls = descriptor->controls;
+ const uint8* controls = descriptor->controls;
for (uint8 i = 0; i < descriptor->numFormats; i++,
controls += descriptor->controlSize) {
printf("\tfmt%d: %s %s %s %s - %s %s\n", i,
@@ -188,8 +178,9 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
}
case VS_FORMAT_UNCOMPRESSED:
{
- const usbvc_format_descriptor* descriptor =
- (const usbvc_format_descriptor*)_descriptor;
+ const usbvc_format_descriptor* descriptor
+ = (const usbvc_format_descriptor*)_descriptor;
+ fUncompressedFormatIndex = descriptor->formatIndex;
printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=",
descriptor->formatIndex, descriptor->numFrameDescriptors);
print_guid(descriptor->uncompressed.format);
@@ -206,7 +197,7 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
if (descriptor->uncompressed.interlaceFlags & 4)
printf("\tField 1 first\n");
printf("\tField Pattern: ");
- switch((descriptor->uncompressed.interlaceFlags & 0x30) >> 4) {
+ switch ((descriptor->uncompressed.interlaceFlags & 0x30) >> 4) {
case 0: printf("Field 1 only\n"); break;
case 1: printf("Field 2 only\n"); break;
case 2: printf("Regular pattern of fields 1 and 2\n"); break;
@@ -217,13 +208,18 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
break;
}
case VS_FRAME_MJPEG:
- printf("VS_FRAME_MJPEG:"); // fall through
case VS_FRAME_UNCOMPRESSED:
{
- if (_descriptor->descriptorSubtype == VS_FRAME_UNCOMPRESSED)
+ const usbvc_frame_descriptor* descriptor
+ = (const usbvc_frame_descriptor*)_descriptor;
+ if (_descriptor->descriptorSubtype == VS_FRAME_UNCOMPRESSED) {
printf("VS_FRAME_UNCOMPRESSED:");
- const usbvc_frame_descriptor* descriptor =
- (const usbvc_frame_descriptor*)_descriptor;
+ fUncompressedFrames.AddItem(
+ new usbvc_frame_descriptor(*descriptor));
+ } else {
+ printf("VS_FRAME_MJPEG:");
+ fMJPEGFrames.AddItem(new usbvc_frame_descriptor(*descriptor));
+ }
printf("\tbFrameIdx=%d,stillsupported=%s,"
"fixedframerate=%s\n", descriptor->frameIndex,
(descriptor->capabilities & 1) ? "yes" : "no",
@@ -240,17 +236,17 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
descriptor->continuous.maxFrameInterval,
descriptor->continuous.frameIntervalStep);
} else for (uint8 i = 0; i < descriptor->frameIntervalType; i++) {
- printf("discrete frame interval: %lu\n",
+ printf("\tdiscrete frame interval: %lu\n",
descriptor->discreteFrameIntervals[i]);
}
break;
}
case VS_COLORFORMAT:
{
- const usbvc_color_matching_descriptor* descriptor =
- (const usbvc_color_matching_descriptor*)_descriptor;
+ const usbvc_color_matching_descriptor* descriptor
+ = (const usbvc_color_matching_descriptor*)_descriptor;
printf("VS_COLORFORMAT:\n\tbColorPrimaries: ");
- switch(descriptor->colorPrimaries) {
+ switch (descriptor->colorPrimaries) {
case 0: printf("Unspecified\n"); break;
case 1: printf("BT.709,sRGB\n"); break;
case 2: printf("BT.470-2(M)\n"); break;
@@ -260,7 +256,7 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
default: printf("Invalid (%d)\n", descriptor->colorPrimaries);
}
printf("\tbTransferCharacteristics: ");
- switch(descriptor->transferCharacteristics) {
+ switch (descriptor->transferCharacteristics) {
case 0: printf("Unspecified\n"); break;
case 1: printf("BT.709\n"); break;
case 2: printf("BT.470-2(M)\n"); break;
@@ -273,7 +269,7 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
descriptor->transferCharacteristics);
}
printf("\tbMatrixCoefficients: ");
- switch(descriptor->matrixCoefficients) {
+ switch (descriptor->matrixCoefficients) {
case 0: printf("Unspecified\n"); break;
case 1: printf("BT.709\n"); break;
case 2: printf("FCC\n"); break;
@@ -286,12 +282,12 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
}
case VS_OUTPUT_HEADER:
{
- const usbvc_output_header_descriptor* descriptor =
- (const usbvc_output_header_descriptor*)_descriptor;
+ const usbvc_output_header_descriptor* descriptor
+ = (const usbvc_output_header_descriptor*)_descriptor;
printf("VS_OUTPUT_HEADER:\t#fmts=%d,ept=0x%x\n",
descriptor->numFormats, descriptor->endpointAddress);
printf("\toutput terminal id=%d\n", descriptor->terminalLink);
- const uint8 *controls = descriptor->controls;
+ const uint8* controls = descriptor->controls;
for (uint8 i = 0; i < descriptor->numFormats; i++,
controls += descriptor->controlSize) {
printf("\tfmt%d: %s %s %s %s\n", i,
@@ -304,8 +300,8 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
}
case VS_STILL_IMAGE_FRAME:
{
- const usbvc_still_image_frame_descriptor* descriptor =
- (const usbvc_still_image_frame_descriptor*)_descriptor;
+ const usbvc_still_image_frame_descriptor* descriptor
+ = (const usbvc_still_image_frame_descriptor*)_descriptor;
printf("VS_STILL_IMAGE_FRAME:\t#imageSizes=%d,compressions=%d,"
"ept=0x%x\n", descriptor->numImageSizePatterns,
descriptor->NumCompressionPatterns(),
@@ -323,8 +319,9 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
}
case VS_FORMAT_MJPEG:
{
- const usbvc_format_descriptor* descriptor =
- (const usbvc_format_descriptor*)_descriptor;
+ const usbvc_format_descriptor* descriptor
+ = (const usbvc_format_descriptor*)_descriptor;
+ fMJPEGFormatIndex = descriptor->formatIndex;
printf("VS_FORMAT_MJPEG:\tbFormatIdx=%d,#frmdesc=%d\n",
descriptor->formatIndex, descriptor->numFrameDescriptors);
printf("\t#flgs=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n",
@@ -340,7 +337,7 @@ UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
if (descriptor->mjpeg.interlaceFlags & 4)
printf("\tField 1 first\n");
printf("\tField Pattern: ");
- switch((descriptor->mjpeg.interlaceFlags & 0x30) >> 4) {
+ switch ((descriptor->mjpeg.interlaceFlags & 0x30) >> 4) {
case 0: printf("Field 1 only\n"); break;
case 1: printf("Field 2 only\n"); break;
case 2: printf("Regular pattern of fields 1 and 2\n"); break;
@@ -376,10 +373,15 @@ void
UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor,
size_t len)
{
- switch(_descriptor->descriptorSubtype) {
+ switch (_descriptor->descriptorSubtype) {
case VC_HEADER:
{
- fHeaderDescriptor = (usbvc_interface_header_descriptor*)_descriptor;
+ if (fHeaderDescriptor != NULL) {
+ printf("ERROR: multiple VC_HEADER! Skipping...\n");
+ break;
+ }
+ fHeaderDescriptor = (usbvc_interface_header_descriptor*)malloc(len);
+ memcpy(fHeaderDescriptor, _descriptor, len);
printf("VC_HEADER:\tUVC v%x.%02x, clk %.5f MHz\n",
fHeaderDescriptor->version >> 8,
fHeaderDescriptor->version & 0xff,
@@ -392,16 +394,16 @@ UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor,
}
case VC_INPUT_TERMINAL:
{
- const usbvc_input_terminal_descriptor* descriptor =
- (const usbvc_input_terminal_descriptor*)_descriptor;
+ const usbvc_input_terminal_descriptor* descriptor
+ = (const usbvc_input_terminal_descriptor*)_descriptor;
printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal="
"%d\n", descriptor->terminalID, descriptor->terminalType,
descriptor->associatedTerminal);
printf("\tDesc: %s\n",
fDevice->DecodeStringDescriptor(descriptor->terminal));
if (descriptor->terminalType == 0x201) {
- const usbvc_camera_terminal_descriptor* desc =
- (const usbvc_camera_terminal_descriptor*)descriptor;
+ const usbvc_camera_terminal_descriptor* desc
+ = (const usbvc_camera_terminal_descriptor*)descriptor;
printf("\tObjectiveFocalLength Min/Max %d/%d\n",
desc->objectiveFocalLengthMin,
desc->objectiveFocalLengthMax);
@@ -412,8 +414,8 @@ UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor,
}
case VC_OUTPUT_TERMINAL:
{
- const usbvc_output_terminal_descriptor* descriptor =
- (const usbvc_output_terminal_descriptor*)_descriptor;
+ const usbvc_output_terminal_descriptor* descriptor
+ = (const usbvc_output_terminal_descriptor*)_descriptor;
printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal="
"%d, src id=%d\n", descriptor->terminalID,
descriptor->terminalType, descriptor->associatedTerminal,
@@ -424,8 +426,8 @@ UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor,
}
case VC_SELECTOR_UNIT:
{
- const usbvc_selector_unit_descriptor* descriptor =
- (const usbvc_selector_unit_descriptor*)_descriptor;
+ const usbvc_selector_unit_descriptor* descriptor
+ = (const usbvc_selector_unit_descriptor*)_descriptor;
printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n",
descriptor->unitID, descriptor->numInputPins);
printf("\t");
@@ -438,9 +440,10 @@ UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor,
}
case VC_PROCESSING_UNIT:
{
- const usbvc_processing_unit_descriptor* descriptor =
- (const usbvc_processing_unit_descriptor*)_descriptor;
- printf("VC_PROCESSING_UNIT:\tid=%d,src id=%d, digmul=%d\n",
+ const usbvc_processing_unit_descriptor* descriptor
+ = (const usbvc_processing_unit_descriptor*)_descriptor;
+ fControlRequestIndex = fControlIndex + (descriptor->unitID << 8);
+ printf("VC_PROCESSING_UNIT:\t unit id=%d,src id=%d, digmul=%d\n",
descriptor->unitID, descriptor->sourceID,
descriptor->maxMultiplier);
printf("\tbControlSize=%d\n", descriptor->controlSize);
@@ -502,8 +505,8 @@ UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor* _descriptor,
}
case VC_EXTENSION_UNIT:
{
- const usbvc_extension_unit_descriptor* descriptor =
- (const usbvc_extension_unit_descriptor*)_descriptor;
+ const usbvc_extension_unit_descriptor* descriptor
+ = (const usbvc_extension_unit_descriptor*)_descriptor;
printf("VC_EXTENSION_UNIT:\tid=%d, guid=", descriptor->unitID);
print_guid(descriptor->guidExtensionCode);
printf("\n\t#ctrls=%d, #pins=%d\n", descriptor->numControls,
@@ -547,34 +550,81 @@ UVCCamDevice::StopTransfer()
status_t
-UVCCamDevice::SuggestVideoFrame(uint32 &width, uint32 &height)
+UVCCamDevice::SuggestVideoFrame(uint32& width, uint32& height)
{
+ printf("UVCCamDevice::SuggestVideoFrame(%ld, %ld)\n", width, height);
+ // As in AcceptVideoFrame(), the suggestion should probably just be the
+ // first advertised uncompressed format, but current applications prefer
+ // 320x240, so this is tried first here as a suggestion.
width = 320;
height = 240;
+ if (!AcceptVideoFrame(width, height)) {
+ const usbvc_frame_descriptor* descriptor
+ = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem();
+ width = (*descriptor).width;
+ height = (*descriptor).height;
+ }
return B_OK;
}
status_t
-UVCCamDevice::AcceptVideoFrame(uint32 &width, uint32 &height)
+UVCCamDevice::AcceptVideoFrame(uint32& width, uint32& height)
{
- width = 320;
- height = 240;
+ printf("UVCCamDevice::AcceptVideoFrame(%ld, %ld)\n", width, height);
+ if (width <= 0 || height <= 0) {
+ // Uncomment below when applications support dimensions other than 320x240
+ // This code selects the first listed available uncompressed frame format
+ /*
+ const usbvc_frame_descriptor* descriptor
+ = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem();
+ width = (*descriptor).width;
+ height = (*descriptor).height;
+ SetVideoFrame(BRect(0, 0, width - 1, height - 1));
+ return B_OK;
+ */
+
+ width = 320;
+ height = 240;
+ }
- SetVideoFrame(BRect(0, 0, width - 1, height - 1));
- return B_OK;
+ for (int i = 0; i<fUncompressedFrames.CountItems(); i++) {
+ const usbvc_frame_descriptor* descriptor
+ = (const usbvc_frame_descriptor*)fUncompressedFrames.ItemAt(i);
+ if ((*descriptor).width == width && (*descriptor).height == height) {
+ fUncompressedFrameIndex = i;
+ SetVideoFrame(BRect(0, 0, width - 1, height - 1));
+ return B_OK;
+ }
+ }
+
+ fprintf(stderr, "UVCCamDevice::AcceptVideoFrame() Invalid frame dimensions"
+ "\n");
+ return B_ERROR;
}
status_t
UVCCamDevice::_ProbeCommitFormat()
{
+ printf("UVCCamDevice::_ProbeCommitFormat()\n");
+ printf("UVCCamDevice::fStreamingIndex = %ld\n", fStreamingIndex);
+
+ /*
+ char error;
+ printf("BEFORE ERROR CODE CHECK.\n");
+ fDevice->ControlTransfer(
+ USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_CUR,
+ VS_STREAM_ERROR_CODE_CONTROL << 8, fStreamingIndex, 1, &error);
+ printf("Error code = Ox%x\n", error);
+ */
+
usbvc_probecommit request;
memset(&request, 0, sizeof(request));
- request.hint = 1 << 8;
+ request.hint = 1;
request.SetFrameInterval(333333);
- request.formatIndex = 1;
- request.frameIndex = 3;
+ request.formatIndex = fUncompressedFormatIndex;
+ request.frameIndex = fUncompressedFrameIndex;
size_t length = fHeaderDescriptor->version > 0x100 ? 34 : 26;
size_t actualLength = fDevice->ControlTransfer(
USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR,
@@ -584,7 +634,8 @@ UVCCamDevice::_ProbeCommitFormat()
" failed %ld\n", actualLength);
return B_ERROR;
}
-
+
+ /*
usbvc_probecommit response;
actualLength = fDevice->ControlTransfer(
USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_MAX,
@@ -597,7 +648,16 @@ UVCCamDevice::_ProbeCommitFormat()
printf("usbvc_probecommit response.compQuality %d\n", response.compQuality);
request.compQuality = response.compQuality;
-
+ */
+
+
+ usbvc_probecommit response;
+ memset(&response, 0, sizeof(response));
+ actualLength = fDevice->ControlTransfer(
+ USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_CUR,
+ VS_PROBE_CONTROL << 8, fStreamingIndex, length, &response);
+
+ /*
actualLength = fDevice->ControlTransfer(
USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR,
VS_PROBE_CONTROL << 8, fStreamingIndex, length, &request);
@@ -606,6 +666,7 @@ UVCCamDevice::_ProbeCommitFormat()
" failed\n");
return B_ERROR;
}
+ */
actualLength = fDevice->ControlTransfer(
USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR,
@@ -616,12 +677,14 @@ UVCCamDevice::_ProbeCommitFormat()
return B_ERROR;
}
+
fMaxVideoFrameSize = response.maxVideoFrameSize;
fMaxPayloadTransferSize = response.maxPayloadTransferSize;
printf("usbvc_probecommit setup done maxVideoFrameSize:%ld"
" maxPayloadTransferSize:%ld\n", fMaxVideoFrameSize,
fMaxPayloadTransferSize);
+ printf("UVCCamDevice::_ProbeCommitFormat()\n --> SUCCESSFUL\n");
return B_OK;
}
@@ -629,17 +692,18 @@ UVCCamDevice::_ProbeCommitFormat()
status_t
UVCCamDevice::_SelectBestAlternate()
{
- const BUSBConfiguration *config = fDevice->ActiveConfiguration();
- const BUSBInterface *streaming = config->InterfaceAt(fStreamingIndex);
+ printf("UVCCamDevice::_SelectBestAlternate()\n");
+ const BUSBConfiguration* config = fDevice->ActiveConfiguration();
+ const BUSBInterface* streaming = config->InterfaceAt(fStreamingIndex);
uint32 bestBandwidth = 0;
uint32 alternateIndex = 0;
uint32 endpointIndex = 0;
for (uint32 i = 0; i < streaming->CountAlternates(); i++) {
- const BUSBInterface *alternate = streaming->AlternateAt(i);
+ const BUSBInterface* alternate = streaming->AlternateAt(i);
for (uint32 j = 0; j < alternate->CountEndpoints(); j++) {
- const BUSBEndpoint *endpoint = alternate->EndpointAt(j);
+ const BUSBEndpoint* endpoint = alternate->EndpointAt(j);
if (!endpoint->IsIsochronous() || !endpoint->IsInput())
continue;
if (fMaxPayloadTransferSize > endpoint->MaxPacketSize())
@@ -660,7 +724,7 @@ UVCCamDevice::_SelectBestAlternate()
}
printf("UVCCamDevice::_SelectBestAlternate() %ld\n", bestBandwidth);
- if (((BUSBInterface *)streaming)->SetAlternate(alternateIndex) != B_OK) {
+ if (((BUSBInterface*)streaming)->SetAlternate(alternateIndex) != B_OK) {
fprintf(stderr, "UVCCamDevice::_SelectBestAlternate()"
" selecting alternate failed\n");
return B_ERROR;
@@ -675,9 +739,10 @@ UVCCamDevice::_SelectBestAlternate()
status_t
UVCCamDevice::_SelectIdleAlternate()
{
- const BUSBConfiguration *config = fDevice->ActiveConfiguration();
- const BUSBInterface *streaming = config->InterfaceAt(fStreamingIndex);
- if (((BUSBInterface *)streaming)->SetAlternate(0) != B_OK) {
+ printf("UVCCamDevice::_SelectIdleAlternate()\n");
+ const BUSBConfiguration* config = fDevice->ActiveConfiguration();
+ const BUSBInterface* streaming = config->InterfaceAt(fStreamingIndex);
+ if (((BUSBInterface*)streaming)->SetAlternate(0) != B_OK) {
fprintf(stderr, "UVCCamDevice::_SelectIdleAlternate()"
" selecting alternate failed\n");
return B_ERROR;
@@ -692,6 +757,7 @@ UVCCamDevice::_SelectIdleAlternate()
UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam)
: CamDeviceAddon(webcam)
{
+ printf("UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam)\n");
SetSupportedDevices(kSupportedDevices);
}
@@ -704,17 +770,627 @@ UVCCamDeviceAddon::~UVCCamDeviceAddon()
const char *
UVCCamDeviceAddon::BrandName()
{
+ printf("UVCCamDeviceAddon::BrandName()\n");
return "USB Video Class";
}
UVCCamDevice *
-UVCCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from)
+UVCCamDeviceAddon::Instantiate(CamRoster& roster, BUSBDevice* from)
{
+ printf("UVCCamDeviceAddon::Instantiate()\n");
return new UVCCamDevice(*this, from);
}
+float
+UVCCamDevice::_AddParameter(BParameterGroup* group,
+ BParameterGroup** subgroup, int32 index, uint16 wValue, const char* name)
+{
+ float minValue = 0.0;
+ float maxValue = 100.0;
+ float currValue = 0.0;
+
+ BContinuousParameter* p;
+ uint16 data;
+
+ wValue = wValue << 8;
+
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_MAX, wValue, fControlRequestIndex, 2, &data);
+ maxValue = (float)(*((uint16*)data));
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_MIN, wValue, fControlRequestIndex, 2, &data);
+ minValue = (float)(*((uint16*)data));
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_CUR, wValue, fControlRequestIndex, 2, &data);
+ currValue = (float)data;
+
+ *subgroup = group->MakeGroup(name);
+ p = (*subgroup)->MakeContinuousParameter(index,
+ B_MEDIA_RAW_VIDEO, name,
+ B_GAIN, "", minValue, maxValue, 1.0 / (maxValue - minValue));
+
+ return currValue;
+}
+
+
+int UVCCamDevice::_AddAutoParameter(BParameterGroup* subgroup, int32 index,
+ uint16 wValue)
+{
+ uint8 data;
+ wValue <<= 8;
+
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_CUR, wValue, fControlRequestIndex, 1, &data);
+ subgroup->MakeDiscreteParameter(index, B_MEDIA_RAW_VIDEO, "Auto",
+ B_ENABLE);
+
+ return data;
+}
+
+
+void
+UVCCamDevice::AddParameters(BParameterGroup* group, int32& index)
+{
+ printf("UVCCamDevice::AddParameters()\n");
+ fFirstParameterID = index;
+// debug_printf("fIndex = %d\n",fIndex);
+ BParameterGroup* subgroup;
+ BContinuousParameter* p;
+ CamDevice::AddParameters(group, index);
+
+ const BUSBConfiguration* config;
+ const BUSBInterface* interface;
+ usb_descriptor* generic;
+ uint8 buffer[1024];
+
+ void* data = (void*)(new uint16);
+
+ generic = (usb_descriptor*)buffer;
+
+ for (uint32 i = 0; i < fDevice->CountConfigurations(); i++) {
+ config = fDevice->ConfigurationAt(i);
+ fDevice->SetConfiguration(config);
+ for (uint32 j = 0; j < config->CountInterfaces(); j++) {
+ interface = config->InterfaceAt(j);
+ if (interface->Class() == CC_VIDEO && interface->Subclass()
+ == SC_VIDEOCONTROL) {
+ for (uint32 k = 0; interface->OtherDescriptorAt(k, generic,
+ sizeof(buffer)) == B_OK; k++) {
+ if (generic->generic.descriptor_type != (USB_REQTYPE_CLASS
+ | USB_DESCRIPTOR_INTERFACE))
+ continue;
+
+ if (((const usbvc_class_descriptor*)generic)->descriptorSubtype
+ == VC_PROCESSING_UNIT) {
+ const usbvc_processing_unit_descriptor* descriptor
+ = (const usbvc_processing_unit_descriptor*)generic;
+ uint16 wValue = 0; // Control Selector
+ float minValue = 0.0;
+ float maxValue = 100.0;
+ if (descriptor->controlSize >= 1) {
+ if (descriptor->controls[0] & 1) {
+ // debug_printf("\tBRIGHTNESS\n");
+ fBrightness = _AddParameter(group, &subgroup, index,
+ PU_BRIGHTNESS_CONTROL, "Brightness");
+ }
+ if (descriptor->controls[0] & 2) {
+ // debug_printf("\tCONSTRAST\n");
+ fContrast = _AddParameter(group, &subgroup, index + 1,
+ PU_CONTRAST_CONTROL, "Contrast");
+ }
+ if (descriptor->controls[0] & 4) {
+ // debug_printf("\tHUE\n");
+ fHue = _AddParameter(group, &subgroup, index + 2,
+ PU_HUE_CONTROL, "Hue");
+ if (descriptor->controlSize >= 2) {
+ if (descriptor->controls[1] & 8) {
+ fHueAuto = _AddAutoParameter(subgroup, index + 3,
+ PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL);
+ }
+ }
+ }
+ if (descriptor->controls[0] & 8) {
+ // debug_printf("\tSATURATION\n");
+ fSaturation = _AddParameter(group, &subgroup, index + 4,
+ PU_SATURATION_CONTROL, "Saturation");
+ }
+ if (descriptor->controls[0] & 16) {
+ // debug_printf("\tSHARPNESS\n");
+ fSharpness = _AddParameter(group, &subgroup, index + 5,
+ PU_SHARPNESS_CONTROL, "Sharpness");
+ }
+ if (descriptor->controls[0] & 32) {
+ // debug_printf("\tGamma\n");
+ fGamma = _AddParameter(group, &subgroup, index + 6,
+ PU_GAMMA_CONTROL, "Gamma");
+ }
+ if (descriptor->controls[0] & 64) {
+ // debug_printf("\tWHITE BALANCE TEMPERATURE\n");
+ fWBTemp = _AddParameter(group, &subgroup, index + 7,
+ PU_WHITE_BALANCE_TEMPERATURE_CONTROL, "WB Temperature");
+ if (descriptor->controlSize >= 2) {
+ if (descriptor->controls[1] & 16) {
+ fWBTempAuto = _AddAutoParameter(subgroup, index + 8,
+ PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL);
+ }
+ }
+ }
+ if (descriptor->controls[0] & 128) {
+ // debug_printf("\tWhite Balance Component\n");
+ fWBComponent = _AddParameter(group, &subgroup, index + 9,
+ PU_WHITE_BALANCE_COMPONENT_CONTROL, "WB Component");
+ if (descriptor->controlSize >= 2) {
+ if (descriptor->controls[1] & 32) {
+ fWBTempAuto = _AddAutoParameter(subgroup, index + 10,
+ PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL);
+ }
+ }
+ }
+ }
+ if (descriptor->controlSize >= 2) {
+ if (descriptor->controls[1] & 1) {
+ // debug_printf("\tBACKLIGHT COMPENSATION\n");
+ wValue = PU_BACKLIGHT_COMPENSATION_CONTROL;
+ wValue = wValue << 8;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_MAX, wValue, fControlRequestIndex, 2, data);
+ maxValue = (float)(*((uint16*)data));
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_MIN, wValue, fControlRequestIndex, 2, data);
+ minValue = (float)(*((uint16*)data));
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_CUR, wValue, fControlRequestIndex, 2, data);
+ fBacklightCompensation = (float)(*((uint16*)data));
+ subgroup = group->MakeGroup("Backlight Compensation");
+ if (maxValue - minValue == 1) { // Binary Switch
+ fBinaryBacklightCompensation = true;
+ subgroup->MakeDiscreteParameter(index + 11,
+ B_MEDIA_RAW_VIDEO, "Backlight Compensation",
+ B_ENABLE);
+ } else { // Range of values
+ fBinaryBacklightCompensation = false;
+ p = subgroup->MakeContinuousParameter(index + 11,
+ B_MEDIA_RAW_VIDEO, "Backlight Compensation",
+ B_GAIN, "", minValue, maxValue, 1.0/(maxValue - minValue));
+ }
+ }
+ if (descriptor->controls[1] & 2) {
+ // debug_printf("\tGAIN\n");
+ fGain = _AddParameter(group, &subgroup, index + 12, PU_GAIN_CONTROL,
+ "Gain");
+ }
+ if (descriptor->controls[1] & 4) {
+ // debug_printf("\tPOWER LINE FREQUENCY\n");
+ wValue = PU_POWER_LINE_FREQUENCY_CONTROL;
+ wValue = wValue << 8;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_CUR, wValue, fControlRequestIndex, 1, data);
+ fPowerlineFrequency = (uint16)(*((uint8*)data));
+ subgroup = group->MakeGroup("Power Line Frequency");
+ p = subgroup->MakeContinuousParameter(index + 13,
+ B_MEDIA_RAW_VIDEO, "Frequency",
+ B_GAIN, "", 0, 60.0, 1.0 / 60.0);
+ }
+ // TODO Determine whether controls apply to these
+ /*
+ if (descriptor->controls[1] & 64)
+ debug_printf("\tDigital Multiplier\n");
+ if (descriptor->controls[1] & 128)
+ debug_printf("\tDigital Multiplier Limit\n");
+ */
+ }
+ // TODO Determine whether controls apply to these
+ /*
+ if (descriptor->controlSize >= 3) {
+ if (descriptor->controls[2] & 1)
+ debug_printf("\tAnalog Video Standard\n");
+ if (descriptor->controls[2] & 2)
+ debug_printf("\tAnalog Video Lock Status\n");
+ }
+ */
+ }
+ }
+ }
+ }
+ }
+}
+
+
+status_t
+UVCCamDevice::GetParameterValue(int32 id, bigtime_t* last_change, void* value,
+ size_t* size)
+{
+ printf("UVCCAmDevice::GetParameterValue(%ld)\n", id - fFirstParameterID);
+ float* currValue;
+ int* currValueInt;
+ void* data;
+ uint16 wValue = 0;
+ switch (id - fFirstParameterID) {
+ case 0:
+ // debug_printf("\tBrightness:\n");
+ // debug_printf("\tValue = %f\n",fBrightness);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fBrightness;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 1:
+ // debug_printf("\tContrast:\n");
+ // debug_printf("\tValue = %f\n",fContrast);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fContrast;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 2:
+ // debug_printf("\tHue:\n");
+ // debug_printf("\tValue = %f\n",fHue);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fHue;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 4:
+ // debug_printf("\tSaturation:\n");
+ // debug_printf("\tValue = %f\n",fSaturation);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fSaturation;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 5:
+ // debug_printf("\tSharpness:\n");
+ // debug_printf("\tValue = %f\n",fSharpness);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fSharpness;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 7:
+ // debug_printf("\tWB Temperature:\n");
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ wValue = PU_WHITE_BALANCE_TEMPERATURE_CONTROL;
+ wValue = wValue << 8;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN,
+ GET_CUR, wValue, fControlRequestIndex, 2, data);
+ fWBTemp = (float)(*((uint16*)data));
+ // debug_printf("\tValue = %f\n",fWBTemp);
+ *currValue = fWBTemp;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 8:
+ // debug_printf("\tWB Temperature Auto:\n");
+ // debug_printf("\tValue = %d\n",fWBTempAuto);
+ *size = sizeof(int);
+ currValueInt = ((int*)value);
+ *currValueInt = fWBTempAuto;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 11:
+ if (!fBinaryBacklightCompensation) {
+ // debug_printf("\tBacklight Compensation:\n");
+ // debug_printf("\tValue = %f\n",fBacklightCompensation);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fBacklightCompensation;
+ *last_change = fLastParameterChanges;
+ } else {
+ // debug_printf("\tBacklight Compensation:\n");
+ // debug_printf("\tValue = %d\n",fBacklightCompensationBinary);
+ currValueInt = ((int*)value);
+ *currValueInt = fBacklightCompensationBinary;
+ *last_change = fLastParameterChanges;
+ }
+ return B_OK;
+ case 12:
+ // debug_printf("\tGain:\n");
+ // debug_printf("\tValue = %f\n",fGain);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ *currValue = fGain;
+ *last_change = fLastParameterChanges;
+ return B_OK;
+ case 13:
+ // debug_printf("\tPowerline Frequency:\n");
+ // debug_printf("\tValue = %d\n",fPowerlineFrequency);
+ *size = sizeof(float);
+ currValue = ((float*)value);
+ switch (fPowerlineFrequency) {
+ case 0:
+ *currValue = 0.0;
+ break;
+ case 1:
+ *currValue = 50.0;
+ break;
+ case 2:
+ *currValue = 60.0;
+ break;
+ }
+ *last_change = fLastParameterChanges;
+ return B_OK;
+
+ }
+ return B_BAD_VALUE;
+}
+
+
+status_t
+UVCCamDevice::SetParameterValue(int32 id, bigtime_t when, const void* value,
+ size_t size)
+{
+ printf("UVCCamDevice::SetParameterValue(%ld)\n", id - fFirstParameterID);
+ uint16 wValue = 0; //Control Selector
+ uint16 setValue = 0;
+ switch (id - fFirstParameterID) {
+ case 0:
+ // debug_printf("\tBrightness:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_BRIGHTNESS_CONTROL;
+ wValue = wValue << 8;
+ fBrightness = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fBrightness;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ return B_OK;
+ case 1:
+ // debug_printf("\tContrast:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_CONTRAST_CONTROL;
+ wValue = wValue << 8;
+ fContrast = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fContrast;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ return B_OK;
+ case 2:
+ // debug_printf("\tHue:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_HUE_CONTROL;
+ wValue = wValue << 8;
+ fHue = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fHue;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ return B_OK;
+ case 4:
+ // debug_printf("\tSaturation:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_SATURATION_CONTROL;
+ wValue = wValue << 8;
+ fSaturation = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fSaturation;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ return B_OK;
+ case 5:
+ // debug_printf("\tSharpness:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_SHARPNESS_CONTROL;
+ wValue = wValue << 8;
+ fSharpness = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fSharpness;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ return B_OK;
+ case 7:
+ if (!fWBTempAuto) {
+ // debug_printf("\tWB Temperature:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_WHITE_BALANCE_TEMPERATURE_CONTROL;
+ wValue = wValue << 8;
+ fWBTemp = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fWBTemp;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ }
+ return B_OK;
+ case 8:
+ // debug_printf("\tWB Temperature Auto:\n");
+ if (!value || (size != sizeof(int)))
+ return B_BAD_VALUE;
+ // debug_printf("\tValue = %d\n",*((int*)value));
+ wValue = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL;
+ wValue = wValue << 8;
+ fWBTempAuto = *((int*)value);
+ fLastParameterChanges = when;
+ setValue = fWBTempAuto;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 1, &setValue);
+ return B_OK;
+ case 11:
+ if (!fBinaryBacklightCompensation) {
+ // debug_printf("\tBacklight Compensation:\n");
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ wValue = PU_BACKLIGHT_COMPENSATION_CONTROL;
+ wValue = wValue << 8;
+ fBacklightCompensation = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fBacklightCompensation;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ }else{
+ // debug_printf("\tBacklight Compensation:\n");
+ if (!value || (size != sizeof(int)))
+ return B_BAD_VALUE;
+ // debug_printf("\tValue = %d\n",*((int*)value));
+ wValue = PU_BACKLIGHT_COMPENSATION_CONTROL;
+ wValue = wValue << 8;
+ fBacklightCompensationBinary = *((int*)value);
+ fLastParameterChanges = when;
+ setValue = fBacklightCompensationBinary;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ }
+ return B_OK;
+ case 12:
+ // debug_printf("\tGain:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_GAIN_CONTROL;
+ wValue = wValue << 8;
+ fGain = *((float*)value);
+ fLastParameterChanges = when;
+ setValue = (uint16)fGain;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 2, &setValue);
+ return B_OK;
+ case 13:
+ // debug_printf("\tPowerline Frequency:\n");
+ // debug_printf("\tValue = %f\n",*((float*)value));
+ if (!value || (size != sizeof(float)))
+ return B_BAD_VALUE;
+ wValue = PU_POWER_LINE_FREQUENCY_CONTROL;
+ wValue = wValue << 8;
+ float inValue = *((float*)value);
+ fPowerlineFrequency = 0;
+ if (inValue > 45.0 && inValue < 55.0) {
+ fPowerlineFrequency = 1;
+ }
+ if (inValue >= 55.0) {
+ fPowerlineFrequency = 2;
+ }
+ fLastParameterChanges = when;
+ setValue = (uint8)fPowerlineFrequency;
+ fDevice->ControlTransfer(USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CUR, wValue, fControlRequestIndex, 1, &setValue);
+ return B_OK;
+
+ }
+ return B_BAD_VALUE;
+}
+
+
+status_t
+UVCCamDevice::FillFrameBuffer(BBuffer* buffer, bigtime_t* stamp)
+{
+ memset(buffer->Data(), 0, buffer->SizeAvailable());
+ status_t err = fDeframer->WaitFrame(2000000);
+ if (err < B_OK) {
+ fprintf(stderr, "WaitFrame: %lx\n", err);
+ return err;
+ }
+
+ CamFrame* f;
+ err = fDeframer->GetFrame(&f, stamp);
+ if (err < B_OK) {
+ fprintf(stderr, "GetFrame: %lx\n", err);
+ return err;
+ }
+
+ long int w = (long)(VideoFrame().right - VideoFrame().left + 1);
+ long int h = (long)(VideoFrame().bottom - VideoFrame().top + 1);
+
+ if (buffer->SizeAvailable() >= (size_t)w * h * 4) {
+ // TODO: The Video Producer only outputs B_RGB32. This is OK for most
+ // applications. This could be leveraged if applications can
+ // consume B_YUV422.
+ _DecodeColor((unsigned char*)buffer->Data(),
+ (unsigned char*)f->Buffer(), w, h);
+ }
+ delete f;
+ return B_OK;
+}
+
+
+void
+UVCCamDevice::_DecodeColor(unsigned char* dst, unsigned char* src,
+ int32 width, int32 height)
+{
+ long int i;
+ unsigned char* rawpt, * scanpt;
+ long int size;
+
+ rawpt = src;
+ scanpt = dst;
+ size = width*height;
+
+ for ( i = 0; i < size; i++ ) {
+ if ( (i/width) % 2 == 0 ) {
+ if ( (i % 2) == 0 ) {
+ /* B */
+ if ( (i > width) && ((i % width) > 0) ) {
+ *scanpt++ = (*(rawpt-width-1)+*(rawpt-width+1)
+ + *(rawpt+width-1)+*(rawpt+width+1))/4; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1)
+ + *(rawpt+width)+*(rawpt-width))/4; /* G */
+ *scanpt++ = *rawpt; /* B */
+ } else {
+ /* first line or left column */
+ *scanpt++ = *(rawpt+width+1); /* R */
+ *scanpt++ = (*(rawpt+1)+*(rawpt+width))/2; /* G */
+ *scanpt++ = *rawpt; /* B */
+ }
+ } else {
+ /* (B)G */
+ if ( (i > width) && ((i % width) < (width-1)) ) {
+ *scanpt++ = (*(rawpt+width)+*(rawpt-width))/2; /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
+ } else {
+ /* first line or right column */
+ *scanpt++ = *(rawpt+width); /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = *(rawpt-1); /* B */
+ }
+ }
+ } else {
+ if ( (i % 2) == 0 ) {
+ /* G(R) */
+ if ( (i < (width*(height-1))) && ((i % width) > 0) ) {
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = (*(rawpt+width)+*(rawpt-width))/2; /* B */
+ } else {
+ /* bottom line or left column */
+ *scanpt++ = *(rawpt+1); /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = *(rawpt-width); /* B */
+ }
+ } else {
+ /* R */
+ if ( i < (width*(height-1)) && ((i % width) < (width-1)) ) {
+ *scanpt++ = *rawpt; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1)
+ + *(rawpt-width)+*(rawpt+width))/4; /* G */
+ *scanpt++ = (*(rawpt-width-1)+*(rawpt-width+1)
+ + *(rawpt+width-1)+*(rawpt+width+1))/4; /* B */
+ } else {
+ /* bottom line or right column */
+ *scanpt++ = *rawpt; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt-width))/2; /* G */
+ *scanpt++ = *(rawpt-width-1); /* B */
+ }
+ }
+ }
+ rawpt++;
+ }
+}
+
+
extern "C" status_t
B_WEBCAM_MKINTFUNC(uvccam)
(WebCamMediaAddOn* webcam, CamDeviceAddon **addon)
diff --git a/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.h b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.h
index f8960c778d..26ecbf2d26 100644
--- a/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.h
+++ b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCCamDevice.h
@@ -1,4 +1,5 @@
/*
+ * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com.
* Copyright 2011, Jérôme Duval, korli@users.berlios.de.
* Copyright 2009, Ithamar Adema, <ithamar.adema@team-embedded.nl>.
* Distributed under the terms of the MIT License.
@@ -24,6 +25,15 @@ public:
uint32 &height);
virtual status_t AcceptVideoFrame(uint32 &width,
uint32 &height);
+ 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);
+ virtual status_t FillFrameBuffer(BBuffer *buffer,
+ bigtime_t *stamp = NULL);
private:
void _ParseVideoControl(
@@ -35,14 +45,52 @@ private:
status_t _ProbeCommitFormat();
status_t _SelectBestAlternate();
status_t _SelectIdleAlternate();
+ void _DecodeColor(unsigned char *dst,
+ unsigned char *src, int32 width,
+ int32 height);
+ float _AddParameter(BParameterGroup* group,
+ BParameterGroup** subgroup, int32 index,
+ uint16 wValue, const char* name);
+ int _AddAutoParameter(BParameterGroup* subgroup,
+ int32 index, uint16 wValue);
+
usbvc_interface_header_descriptor *fHeaderDescriptor;
const BUSBEndpoint* fInterruptIn;
uint32 fControlIndex;
+ uint16 fControlRequestIndex;
uint32 fStreamingIndex;
+ uint32 fUncompressedFormatIndex;
+ uint32 fUncompressedFrameIndex;
+ uint32 fMJPEGFormatIndex;
+ uint32 fMJPEGFrameIndex;
uint32 fMaxVideoFrameSize;
uint32 fMaxPayloadTransferSize;
+
+ BList fUncompressedFrames;
+ BList fMJPEGFrames;
+
+ float fBrightness;
+ float fContrast;
+ float fHue;
+ float fSaturation;
+ float fSharpness;
+ float fGamma;
+ float fWBTemp;
+ float fWBComponent;
+ float fBacklightCompensation;
+ float fGain;
+
+ bool fBinaryBacklightCompensation;
+
+ int fWBTempAuto;
+ int fWBCompAuto;
+ int fHueAuto;
+ int fBacklightCompensationBinary;
+ int fPowerlineFrequency;
+
+
};
diff --git a/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.cpp b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.cpp
new file mode 100644
index 0000000000..de84f3840c
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "UVCDeframer.h"
+
+#include "CamDebug.h"
+#include "CamDevice.h"
+
+#include <Autolock.h>
+
+
+#define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN
+#define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES
+
+
+UVCDeframer::UVCDeframer(CamDevice* device)
+ : CamDeframer(device),
+ fFrameCount(0),
+ fID(0)
+{
+}
+
+
+UVCDeframer::~UVCDeframer()
+{
+}
+
+
+ssize_t
+UVCDeframer::Write(const void* buffer, size_t size)
+{
+ const uint8* buf = (const uint8*)buffer;
+ int payloadSize = size - buf[0]; // total length - header length
+
+ // This packet is just a header
+ if (size == buf[0])
+ return 0;
+
+ // Allocate frame
+ if (!fCurrentFrame) {
+ BAutolock l(fLocker);
+ if (fFrames.CountItems() < MAXFRAMEBUF)
+ fCurrentFrame = AllocFrame();
+ else {
+ printf("Dropped %ld bytes. Too many queued frames.)\n", size);
+ return size;
+ }
+ }
+
+ // Write payload to buffer
+ fInputBuffer.Write(&buf[buf[0]], payloadSize);
+
+ // If end of frame add frame to list of frames
+ if ((buf[1] & 2) || (buf[1] & 1) != fID) {
+ fID = buf[1] & 1;
+ fFrameCount++;
+ buf = (uint8*)fInputBuffer.Buffer();
+ fCurrentFrame->Write(buf, fInputBuffer.BufferLength());
+ fFrames.AddItem(fCurrentFrame);
+ release_sem(fFrameSem);
+ fCurrentFrame = NULL;
+ }
+
+ return size;
+}
+
+
+void
+UVCDeframer::_PrintBuffer(const void* buffer, size_t size)
+{
+ uint8* b = (uint8*)buffer;
+ for (size_t i = 0; i < size; i++)
+ printf("0x%x\t", b[i]);
+ printf("\n");
+}
+
diff --git a/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.h b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.h
new file mode 100644
index 0000000000..f642bafdc7
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_webcam/addons/uvc/UVCDeframer.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _UVC_DEFRAMER_H
+#define _UVC_DEFRAMER_H
+
+
+#include "CamDeframer.h"
+
+#include <USB3.h>
+
+
+class UVCDeframer : public CamDeframer {
+public:
+ UVCDeframer(CamDevice *device);
+ virtual ~UVCDeframer();
+ // BPositionIO interface
+ // write from usb transfers
+ virtual ssize_t Write(const void *buffer, size_t size);
+
+private:
+ void _PrintBuffer(const void* buffer, size_t size);
+
+ int32 fFrameCount;
+ int32 fID;
+ BMallocIO fInputBuffer;
+};
+
+#endif /* _UVC_DEFRAMER_H */
+
diff --git a/src/bin/listusb.cpp b/src/bin/listusb.cpp
index f884b87690..f1e9782a1e 100644
--- a/src/bin/listusb.cpp
+++ b/src/bin/listusb.cpp
@@ -52,7 +52,7 @@ ClassName(int classNumber) {
case 0xE0:
return "Wireless controller";
case 0xEF:
- return "Miscelaneous";
+ return "Miscellaneous";
case 0xFE:
return "Application specific";
case 0xFF: