diff options
| author | Jérôme Duval <korli@users.berlios.de> | 2011-08-25 16:36:48 +0000 |
|---|---|---|
| committer | Jérôme Duval <korli@users.berlios.de> | 2011-08-25 16:36:48 +0000 |
| commit | 51a01ea03b482556ca9780c879a727fad22201c6 (patch) | |
| tree | 4ccc72a7430384f51e2e6e26d461c89c4f6278f7 | |
| parent | 61f3c5c1c70ec0f97268c23ee0095cb43912384d (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
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: |
