2 * Copyright 2011, Gabriel Hartmann, gabriel.hartmann@gmail.com.
3 * Copyright 2011, Jérôme Duval, korli@users.berlios.de.
4 * Copyright 2009, Ithamar Adema, <ithamar.adema@team-embedded.nl>.
5 * Distributed under the terms of the MIT License.
9 #include "UVCCamDevice.h"
10 #include "UVCDeframer.h"
14 #include <ParameterWeb.h>
15 #include <media/Buffer.h>
18 usb_webcam_support_descriptor kSupportedDevices
[] = {
19 // ofcourse we support a generic UVC device...
20 {{ CC_VIDEO
, SC_VIDEOCONTROL
, 0, 0, 0 }, "Generic UVC", "Video Class", "??" },
21 // ...whilst the following IDs were 'stolen' from a recent Linux driver:
22 {{ 0, 0, 0, 0x045e, 0x00f8, }, "Microsoft", "Lifecam NX-6000", "??" },
23 {{ 0, 0, 0, 0x045e, 0x0723, }, "Microsoft", "Lifecam VX-7000", "??" },
24 {{ 0, 0, 0, 0x046d, 0x08c1, }, "Logitech", "QuickCam Fusion", "??" },
25 {{ 0, 0, 0, 0x046d, 0x08c2, }, "Logitech", "QuickCam Orbit MP", "??" },
26 {{ 0, 0, 0, 0x046d, 0x08c3, }, "Logitech", "QuickCam Pro for Notebook", "??" },
27 {{ 0, 0, 0, 0x046d, 0x08c5, }, "Logitech", "QuickCam Pro 5000", "??" },
28 {{ 0, 0, 0, 0x046d, 0x08c6, }, "Logitech", "QuickCam OEM Dell Notebook", "??" },
29 {{ 0, 0, 0, 0x046d, 0x08c7, }, "Logitech", "QuickCam OEM Cisco VT Camera II", "??" },
30 {{ 0, 0, 0, 0x046d, 0x0821, }, "Logitech", "HD Pro Webcam C910", "??" },
31 {{ 0, 0, 0, 0x05ac, 0x8501, }, "Apple", "Built-In iSight", "??" },
32 {{ 0, 0, 0, 0x05e3, 0x0505, }, "Genesys Logic", "USB 2.0 PC Camera", "??" },
33 {{ 0, 0, 0, 0x0e8d, 0x0004, }, "N/A", "MT6227", "??" },
34 {{ 0, 0, 0, 0x174f, 0x5212, }, "Syntek", "(HP Spartan)", "??" },
35 {{ 0, 0, 0, 0x174f, 0x5931, }, "Syntek", "(Samsung Q310)", "??" },
36 {{ 0, 0, 0, 0x174f, 0x8a31, }, "Syntek", "Asus F9SG", "??" },
37 {{ 0, 0, 0, 0x174f, 0x8a33, }, "Syntek", "Asus U3S", "??" },
38 {{ 0, 0, 0, 0x17ef, 0x480b, }, "N/A", "Lenovo Thinkpad SL500", "??" },
39 {{ 0, 0, 0, 0x18cd, 0xcafe, }, "Ecamm", "Pico iMage", "??" },
40 {{ 0, 0, 0, 0x19ab, 0x1000, }, "Bodelin", "ProScopeHR", "??" },
41 {{ 0, 0, 0, 0x1c4f, 0x3000, }, "SiGma Micro", "USB Web Camera", "??" },
42 {{ 0, 0, 0, 0, 0}, NULL
, NULL
, NULL
}
45 /* Table 2-1 Compression Formats of USB Video Payload Uncompressed */
46 usbvc_guid kYUY2Guid
= {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80,
47 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
48 usbvc_guid kNV12Guid
= {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80,
49 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
52 print_guid(const usbvc_guid guid
)
54 if (!memcmp(guid
, kYUY2Guid
, sizeof(usbvc_guid
)))
56 else if (!memcmp(guid
, kNV12Guid
, sizeof(usbvc_guid
)))
59 printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
60 "%02x:%02x:%02x:%02x", guid
[0], guid
[1], guid
[2], guid
[3], guid
[4],
61 guid
[5], guid
[6], guid
[7], guid
[8], guid
[9], guid
[10], guid
[11],
62 guid
[12], guid
[13], guid
[14], guid
[15]);
67 UVCCamDevice::UVCCamDevice(CamDeviceAddon
& _addon
, BUSBDevice
* _device
)
68 : CamDevice(_addon
, _device
),
69 fHeaderDescriptor(NULL
),
71 fUncompressedFormatIndex(1),
72 fUncompressedFrameIndex(1)
74 fDeframer
= new UVCDeframer(this);
75 SetDataInput(fDeframer
);
77 const BUSBConfiguration
* config
;
78 const BUSBInterface
* interface
;
79 usb_descriptor
* generic
;
82 generic
= (usb_descriptor
*)buffer
;
84 for (uint32 i
= 0; i
< _device
->CountConfigurations(); i
++) {
85 config
= _device
->ConfigurationAt(i
);
88 _device
->SetConfiguration(config
);
89 for (uint32 j
= 0; j
< config
->CountInterfaces(); j
++) {
90 interface
= config
->InterfaceAt(j
);
91 if (interface
== NULL
)
94 if (interface
->Class() == CC_VIDEO
&& interface
->Subclass()
96 printf("UVCCamDevice: (%lu,%lu): Found Video Control "
97 "interface.\n", i
, j
);
99 // look for class specific interface descriptors and parse them
100 for (uint32 k
= 0; interface
->OtherDescriptorAt(k
, generic
,
101 sizeof(buffer
)) == B_OK
; k
++) {
102 if (generic
->generic
.descriptor_type
!= (USB_REQTYPE_CLASS
103 | USB_DESCRIPTOR_INTERFACE
))
105 fControlIndex
= interface
->Index();
106 _ParseVideoControl((const usbvc_class_descriptor
*)generic
,
107 generic
->generic
.length
);
109 for (uint32 k
= 0; k
< interface
->CountEndpoints(); k
++) {
110 const BUSBEndpoint
* e
= interface
->EndpointAt(i
);
111 if (e
&& e
->IsInterrupt() && e
->IsInput()) {
117 } else if (interface
->Class() == CC_VIDEO
&& interface
->Subclass()
118 == SC_VIDEOSTREAMING
) {
119 printf("UVCCamDevice: (%lu,%lu): Found Video Streaming "
120 "interface.\n", i
, j
);
122 // look for class specific interface descriptors and parse them
123 for (uint32 k
= 0; interface
->OtherDescriptorAt(k
, generic
,
124 sizeof(buffer
)) == B_OK
; k
++) {
125 if (generic
->generic
.descriptor_type
!= (USB_REQTYPE_CLASS
126 | USB_DESCRIPTOR_INTERFACE
))
128 fStreamingIndex
= interface
->Index();
129 _ParseVideoStreaming((const usbvc_class_descriptor
*)generic
,
130 generic
->generic
.length
);
133 for (uint32 k
= 0; k
< interface
->CountEndpoints(); k
++) {
134 const BUSBEndpoint
* e
= interface
->EndpointAt(i
);
135 if (e
&& e
->IsIsochronous() && e
->IsInput()) {
146 UVCCamDevice::~UVCCamDevice()
148 free(fHeaderDescriptor
);
153 UVCCamDevice::_ParseVideoStreaming(const usbvc_class_descriptor
* _descriptor
,
156 switch (_descriptor
->descriptorSubtype
) {
157 case VS_INPUT_HEADER
:
159 const usbvc_input_header_descriptor
* descriptor
160 = (const usbvc_input_header_descriptor
*)_descriptor
;
161 printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", descriptor
->numFormats
,
162 descriptor
->endpointAddress
);
163 if (descriptor
->info
& 1)
164 printf("\tDynamic Format Change supported\n");
165 printf("\toutput terminal id=%d\n", descriptor
->terminalLink
);
166 printf("\tstill capture method=%d\n", descriptor
->stillCaptureMethod
);
167 if (descriptor
->triggerSupport
) {
168 printf("\ttrigger button fixed to still capture=%s\n",
169 descriptor
->triggerUsage
? "no" : "yes");
171 const uint8
* controls
= descriptor
->controls
;
172 for (uint8 i
= 0; i
< descriptor
->numFormats
; i
++,
173 controls
+= descriptor
->controlSize
) {
174 printf("\tfmt%d: %s %s %s %s - %s %s\n", i
,
175 (*controls
& 1) ? "wKeyFrameRate" : "",
176 (*controls
& 2) ? "wPFrameRate" : "",
177 (*controls
& 4) ? "wCompQuality" : "",
178 (*controls
& 8) ? "wCompWindowSize" : "",
179 (*controls
& 16) ? "<Generate Key Frame>" : "",
180 (*controls
& 32) ? "<Update Frame Segment>" : "");
184 case VS_FORMAT_UNCOMPRESSED
:
186 const usbvc_format_descriptor
* descriptor
187 = (const usbvc_format_descriptor
*)_descriptor
;
188 fUncompressedFormatIndex
= descriptor
->formatIndex
;
189 printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=",
190 descriptor
->formatIndex
, descriptor
->numFrameDescriptors
);
191 print_guid(descriptor
->uncompressed
.format
);
192 printf("\n\t#bpp=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n",
193 descriptor
->uncompressed
.bytesPerPixel
,
194 descriptor
->uncompressed
.defaultFrameIndex
,
195 descriptor
->uncompressed
.aspectRatioX
,
196 descriptor
->uncompressed
.aspectRatioY
);
197 printf("\tbmInterlaceFlags:\n");
198 if (descriptor
->uncompressed
.interlaceFlags
& 1)
199 printf("\tInterlaced stream or variable\n");
200 printf("\t%d fields per frame\n",
201 (descriptor
->uncompressed
.interlaceFlags
& 2) ? 1 : 2);
202 if (descriptor
->uncompressed
.interlaceFlags
& 4)
203 printf("\tField 1 first\n");
204 printf("\tField Pattern: ");
205 switch ((descriptor
->uncompressed
.interlaceFlags
& 0x30) >> 4) {
206 case 0: printf("Field 1 only\n"); break;
207 case 1: printf("Field 2 only\n"); break;
208 case 2: printf("Regular pattern of fields 1 and 2\n"); break;
209 case 3: printf("Random pattern of fields 1 and 2\n"); break;
211 if (descriptor
->uncompressed
.copyProtect
)
212 printf("\tRestrict duplication\n");
216 case VS_FRAME_UNCOMPRESSED
:
218 const usbvc_frame_descriptor
* descriptor
219 = (const usbvc_frame_descriptor
*)_descriptor
;
220 if (_descriptor
->descriptorSubtype
== VS_FRAME_UNCOMPRESSED
) {
221 printf("VS_FRAME_UNCOMPRESSED:");
222 fUncompressedFrames
.AddItem(
223 new usbvc_frame_descriptor(*descriptor
));
225 printf("VS_FRAME_MJPEG:");
226 fMJPEGFrames
.AddItem(new usbvc_frame_descriptor(*descriptor
));
228 printf("\tbFrameIdx=%d,stillsupported=%s,"
229 "fixedframerate=%s\n", descriptor
->frameIndex
,
230 (descriptor
->capabilities
& 1) ? "yes" : "no",
231 (descriptor
->capabilities
& 2) ? "yes" : "no");
232 printf("\twidth=%u,height=%u,min/max bitrate=%lu/%lu, maxbuf=%lu\n",
233 descriptor
->width
, descriptor
->height
,
234 descriptor
->minBitRate
, descriptor
->maxBitRate
,
235 descriptor
->maxVideoFrameBufferSize
);
236 printf("\tdefault frame interval: %lu, #intervals(0=cont): %d\n",
237 descriptor
->defaultFrameInterval
, descriptor
->frameIntervalType
);
238 if (descriptor
->frameIntervalType
== 0) {
239 printf("min/max frame interval=%lu/%lu, step=%lu\n",
240 descriptor
->continuous
.minFrameInterval
,
241 descriptor
->continuous
.maxFrameInterval
,
242 descriptor
->continuous
.frameIntervalStep
);
243 } else for (uint8 i
= 0; i
< descriptor
->frameIntervalType
; i
++) {
244 printf("\tdiscrete frame interval: %lu\n",
245 descriptor
->discreteFrameIntervals
[i
]);
251 const usbvc_color_matching_descriptor
* descriptor
252 = (const usbvc_color_matching_descriptor
*)_descriptor
;
253 printf("VS_COLORFORMAT:\n\tbColorPrimaries: ");
254 switch (descriptor
->colorPrimaries
) {
255 case 0: printf("Unspecified\n"); break;
256 case 1: printf("BT.709,sRGB\n"); break;
257 case 2: printf("BT.470-2(M)\n"); break;
258 case 3: printf("BT.470-2(B,G)\n"); break;
259 case 4: printf("SMPTE 170M\n"); break;
260 case 5: printf("SMPTE 240M\n"); break;
261 default: printf("Invalid (%d)\n", descriptor
->colorPrimaries
);
263 printf("\tbTransferCharacteristics: ");
264 switch (descriptor
->transferCharacteristics
) {
265 case 0: printf("Unspecified\n"); break;
266 case 1: printf("BT.709\n"); break;
267 case 2: printf("BT.470-2(M)\n"); break;
268 case 3: printf("BT.470-2(B,G)\n"); break;
269 case 4: printf("SMPTE 170M\n"); break;
270 case 5: printf("SMPTE 240M\n"); break;
271 case 6: printf("Linear (V=Lc)\n"); break;
272 case 7: printf("sRGB\n"); break;
273 default: printf("Invalid (%d)\n",
274 descriptor
->transferCharacteristics
);
276 printf("\tbMatrixCoefficients: ");
277 switch (descriptor
->matrixCoefficients
) {
278 case 0: printf("Unspecified\n"); break;
279 case 1: printf("BT.709\n"); break;
280 case 2: printf("FCC\n"); break;
281 case 3: printf("BT.470-2(B,G)\n"); break;
282 case 4: printf("SMPTE 170M (BT.601)\n"); break;
283 case 5: printf("SMPTE 240M\n"); break;
284 default: printf("Invalid (%d)\n", descriptor
->matrixCoefficients
);
288 case VS_OUTPUT_HEADER
:
290 const usbvc_output_header_descriptor
* descriptor
291 = (const usbvc_output_header_descriptor
*)_descriptor
;
292 printf("VS_OUTPUT_HEADER:\t#fmts=%d,ept=0x%x\n",
293 descriptor
->numFormats
, descriptor
->endpointAddress
);
294 printf("\toutput terminal id=%d\n", descriptor
->terminalLink
);
295 const uint8
* controls
= descriptor
->controls
;
296 for (uint8 i
= 0; i
< descriptor
->numFormats
; i
++,
297 controls
+= descriptor
->controlSize
) {
298 printf("\tfmt%d: %s %s %s %s\n", i
,
299 (*controls
& 1) ? "wKeyFrameRate" : "",
300 (*controls
& 2) ? "wPFrameRate" : "",
301 (*controls
& 4) ? "wCompQuality" : "",
302 (*controls
& 8) ? "wCompWindowSize" : "");
306 case VS_STILL_IMAGE_FRAME
:
308 const usbvc_still_image_frame_descriptor
* descriptor
309 = (const usbvc_still_image_frame_descriptor
*)_descriptor
;
310 printf("VS_STILL_IMAGE_FRAME:\t#imageSizes=%d,compressions=%d,"
311 "ept=0x%x\n", descriptor
->numImageSizePatterns
,
312 descriptor
->NumCompressionPatterns(),
313 descriptor
->endpointAddress
);
314 for (uint8 i
= 0; i
< descriptor
->numImageSizePatterns
; i
++) {
315 printf("imageSize%d: %dx%d\n", i
,
316 descriptor
->imageSizePatterns
[i
].width
,
317 descriptor
->imageSizePatterns
[i
].height
);
319 for (uint8 i
= 0; i
< descriptor
->NumCompressionPatterns(); i
++) {
320 printf("compression%d: %d\n", i
,
321 descriptor
->CompressionPatterns()[i
]);
325 case VS_FORMAT_MJPEG
:
327 const usbvc_format_descriptor
* descriptor
328 = (const usbvc_format_descriptor
*)_descriptor
;
329 fMJPEGFormatIndex
= descriptor
->formatIndex
;
330 printf("VS_FORMAT_MJPEG:\tbFormatIdx=%d,#frmdesc=%d\n",
331 descriptor
->formatIndex
, descriptor
->numFrameDescriptors
);
332 printf("\t#flgs=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n",
333 descriptor
->mjpeg
.flags
,
334 descriptor
->mjpeg
.defaultFrameIndex
,
335 descriptor
->mjpeg
.aspectRatioX
,
336 descriptor
->mjpeg
.aspectRatioY
);
337 printf("\tbmInterlaceFlags:\n");
338 if (descriptor
->mjpeg
.interlaceFlags
& 1)
339 printf("\tInterlaced stream or variable\n");
340 printf("\t%d fields per frame\n",
341 (descriptor
->mjpeg
.interlaceFlags
& 2) ? 1 : 2);
342 if (descriptor
->mjpeg
.interlaceFlags
& 4)
343 printf("\tField 1 first\n");
344 printf("\tField Pattern: ");
345 switch ((descriptor
->mjpeg
.interlaceFlags
& 0x30) >> 4) {
346 case 0: printf("Field 1 only\n"); break;
347 case 1: printf("Field 2 only\n"); break;
348 case 2: printf("Regular pattern of fields 1 and 2\n"); break;
349 case 3: printf("Random pattern of fields 1 and 2\n"); break;
351 if (descriptor
->mjpeg
.copyProtect
)
352 printf("\tRestrict duplication\n");
355 case VS_FORMAT_MPEG2TS
:
356 printf("VS_FORMAT_MPEG2TS:\t\n");
359 printf("VS_FORMAT_DV:\t\n");
361 case VS_FORMAT_FRAME_BASED
:
362 printf("VS_FORMAT_FRAME_BASED:\t\n");
364 case VS_FRAME_FRAME_BASED
:
365 printf("VS_FRAME_FRAME_BASED:\t\n");
367 case VS_FORMAT_STREAM_BASED
:
368 printf("VS_FORMAT_STREAM_BASED:\t\n");
371 printf("INVALID STREAM UNIT TYPE=%d!\n",
372 _descriptor
->descriptorSubtype
);
378 UVCCamDevice::_ParseVideoControl(const usbvc_class_descriptor
* _descriptor
,
381 switch (_descriptor
->descriptorSubtype
) {
384 if (fHeaderDescriptor
!= NULL
) {
385 printf("ERROR: multiple VC_HEADER! Skipping...\n");
388 fHeaderDescriptor
= (usbvc_interface_header_descriptor
*)malloc(len
);
389 memcpy(fHeaderDescriptor
, _descriptor
, len
);
390 printf("VC_HEADER:\tUVC v%x.%02x, clk %.5f MHz\n",
391 fHeaderDescriptor
->version
>> 8,
392 fHeaderDescriptor
->version
& 0xff,
393 fHeaderDescriptor
->clockFrequency
/ 1000000.0);
394 for (uint8 i
= 0; i
< fHeaderDescriptor
->numInterfacesNumbers
; i
++) {
395 printf("\tStreaming Interface %d\n",
396 fHeaderDescriptor
->interfaceNumbers
[i
]);
400 case VC_INPUT_TERMINAL
:
402 const usbvc_input_terminal_descriptor
* descriptor
403 = (const usbvc_input_terminal_descriptor
*)_descriptor
;
404 printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal="
405 "%d\n", descriptor
->terminalID
, descriptor
->terminalType
,
406 descriptor
->associatedTerminal
);
407 printf("\tDesc: %s\n",
408 fDevice
->DecodeStringDescriptor(descriptor
->terminal
));
409 if (descriptor
->terminalType
== 0x201) {
410 const usbvc_camera_terminal_descriptor
* desc
411 = (const usbvc_camera_terminal_descriptor
*)descriptor
;
412 printf("\tObjectiveFocalLength Min/Max %d/%d\n",
413 desc
->objectiveFocalLengthMin
,
414 desc
->objectiveFocalLengthMax
);
415 printf("\tOcularFocalLength %d\n", desc
->ocularFocalLength
);
416 printf("\tControlSize %d\n", desc
->controlSize
);
420 case VC_OUTPUT_TERMINAL
:
422 const usbvc_output_terminal_descriptor
* descriptor
423 = (const usbvc_output_terminal_descriptor
*)_descriptor
;
424 printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal="
425 "%d, src id=%d\n", descriptor
->terminalID
,
426 descriptor
->terminalType
, descriptor
->associatedTerminal
,
427 descriptor
->sourceID
);
428 printf("\tDesc: %s\n",
429 fDevice
->DecodeStringDescriptor(descriptor
->terminal
));
432 case VC_SELECTOR_UNIT
:
434 const usbvc_selector_unit_descriptor
* descriptor
435 = (const usbvc_selector_unit_descriptor
*)_descriptor
;
436 printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n",
437 descriptor
->unitID
, descriptor
->numInputPins
);
439 for (uint8 i
= 0; i
< descriptor
->numInputPins
; i
++)
440 printf("%d ", descriptor
->sourceID
[i
]);
442 printf("\tDesc: %s\n",
443 fDevice
->DecodeStringDescriptor(descriptor
->Selector()));
446 case VC_PROCESSING_UNIT
:
448 const usbvc_processing_unit_descriptor
* descriptor
449 = (const usbvc_processing_unit_descriptor
*)_descriptor
;
450 fControlRequestIndex
= fControlIndex
+ (descriptor
->unitID
<< 8);
451 printf("VC_PROCESSING_UNIT:\t unit id=%d,src id=%d, digmul=%d\n",
452 descriptor
->unitID
, descriptor
->sourceID
,
453 descriptor
->maxMultiplier
);
454 printf("\tbControlSize=%d\n", descriptor
->controlSize
);
455 if (descriptor
->controlSize
>= 1) {
456 if (descriptor
->controls
[0] & 1)
457 printf("\tBrightness\n");
458 if (descriptor
->controls
[0] & 2)
459 printf("\tContrast\n");
460 if (descriptor
->controls
[0] & 4)
462 if (descriptor
->controls
[0] & 8)
463 printf("\tSaturation\n");
464 if (descriptor
->controls
[0] & 16)
465 printf("\tSharpness\n");
466 if (descriptor
->controls
[0] & 32)
468 if (descriptor
->controls
[0] & 64)
469 printf("\tWhite Balance Temperature\n");
470 if (descriptor
->controls
[0] & 128)
471 printf("\tWhite Balance Component\n");
473 if (descriptor
->controlSize
>= 2) {
474 if (descriptor
->controls
[1] & 1)
475 printf("\tBacklight Compensation\n");
476 if (descriptor
->controls
[1] & 2)
478 if (descriptor
->controls
[1] & 4)
479 printf("\tPower Line Frequency\n");
480 if (descriptor
->controls
[1] & 8)
481 printf("\t[AUTO] Hue\n");
482 if (descriptor
->controls
[1] & 16)
483 printf("\t[AUTO] White Balance Temperature\n");
484 if (descriptor
->controls
[1] & 32)
485 printf("\t[AUTO] White Balance Component\n");
486 if (descriptor
->controls
[1] & 64)
487 printf("\tDigital Multiplier\n");
488 if (descriptor
->controls
[1] & 128)
489 printf("\tDigital Multiplier Limit\n");
491 if (descriptor
->controlSize
>= 3) {
492 if (descriptor
->controls
[2] & 1)
493 printf("\tAnalog Video Standard\n");
494 if (descriptor
->controls
[2] & 2)
495 printf("\tAnalog Video Lock Status\n");
497 printf("\tDesc: %s\n",
498 fDevice
->DecodeStringDescriptor(descriptor
->Processing()));
499 if (descriptor
->VideoStandards() & 2)
500 printf("\tNTSC 525/60\n");
501 if (descriptor
->VideoStandards() & 4)
502 printf("\tPAL 625/50\n");
503 if (descriptor
->VideoStandards() & 8)
504 printf("\tSECAM 625/50\n");
505 if (descriptor
->VideoStandards() & 16)
506 printf("\tNTSC 625/50\n");
507 if (descriptor
->VideoStandards() & 32)
508 printf("\tPAL 525/60\n");
511 case VC_EXTENSION_UNIT
:
513 const usbvc_extension_unit_descriptor
* descriptor
514 = (const usbvc_extension_unit_descriptor
*)_descriptor
;
515 printf("VC_EXTENSION_UNIT:\tid=%d, guid=", descriptor
->unitID
);
516 print_guid(descriptor
->guidExtensionCode
);
517 printf("\n\t#ctrls=%d, #pins=%d\n", descriptor
->numControls
,
518 descriptor
->numInputPins
);
520 for (uint8 i
= 0; i
< descriptor
->numInputPins
; i
++)
521 printf("%d ", descriptor
->sourceID
[i
]);
523 printf("\tDesc: %s\n",
524 fDevice
->DecodeStringDescriptor(descriptor
->Extension()));
528 printf("Unknown control %d\n", _descriptor
->descriptorSubtype
);
534 UVCCamDevice::SupportsIsochronous()
541 UVCCamDevice::StartTransfer()
543 if (_ProbeCommitFormat() != B_OK
|| _SelectBestAlternate() != B_OK
)
545 return CamDevice::StartTransfer();
550 UVCCamDevice::StopTransfer()
552 _SelectIdleAlternate();
553 return CamDevice::StopTransfer();
558 UVCCamDevice::SuggestVideoFrame(uint32
& width
, uint32
& height
)
560 printf("UVCCamDevice::SuggestVideoFrame(%ld, %ld)\n", width
, height
);
561 // As in AcceptVideoFrame(), the suggestion should probably just be the
562 // first advertised uncompressed format, but current applications prefer
563 // 320x240, so this is tried first here as a suggestion.
566 if (!AcceptVideoFrame(width
, height
)) {
567 const usbvc_frame_descriptor
* descriptor
568 = (const usbvc_frame_descriptor
*)fUncompressedFrames
.FirstItem();
569 width
= (*descriptor
).width
;
570 height
= (*descriptor
).height
;
577 UVCCamDevice::AcceptVideoFrame(uint32
& width
, uint32
& height
)
579 printf("UVCCamDevice::AcceptVideoFrame(%ld, %ld)\n", width
, height
);
580 if (width
<= 0 || height
<= 0) {
581 // Uncomment below when applications support dimensions other than 320x240
582 // This code selects the first listed available uncompressed frame format
584 const usbvc_frame_descriptor* descriptor
585 = (const usbvc_frame_descriptor*)fUncompressedFrames.FirstItem();
586 width = (*descriptor).width;
587 height = (*descriptor).height;
588 SetVideoFrame(BRect(0, 0, width - 1, height - 1));
596 for (int i
= 0; i
<fUncompressedFrames
.CountItems(); i
++) {
597 const usbvc_frame_descriptor
* descriptor
598 = (const usbvc_frame_descriptor
*)fUncompressedFrames
.ItemAt(i
);
599 if ((*descriptor
).width
== width
&& (*descriptor
).height
== height
) {
600 fUncompressedFrameIndex
= i
;
601 SetVideoFrame(BRect(0, 0, width
- 1, height
- 1));
606 fprintf(stderr
, "UVCCamDevice::AcceptVideoFrame() Invalid frame dimensions"
613 UVCCamDevice::_ProbeCommitFormat()
615 printf("UVCCamDevice::_ProbeCommitFormat()\n");
616 printf("UVCCamDevice::fStreamingIndex = %ld\n", fStreamingIndex
);
620 printf("BEFORE ERROR CODE CHECK.\n");
621 fDevice->ControlTransfer(
622 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_CUR,
623 VS_STREAM_ERROR_CODE_CONTROL << 8, fStreamingIndex, 1, &error);
624 printf("Error code = Ox%x\n", error);
627 usbvc_probecommit request
;
628 memset(&request
, 0, sizeof(request
));
630 request
.SetFrameInterval(333333);
631 request
.formatIndex
= fUncompressedFormatIndex
;
632 request
.frameIndex
= fUncompressedFrameIndex
;
633 size_t length
= fHeaderDescriptor
->version
> 0x100 ? 34 : 26;
634 size_t actualLength
= fDevice
->ControlTransfer(
635 USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_OUT
, SET_CUR
,
636 VS_PROBE_CONTROL
<< 8, fStreamingIndex
, length
, &request
);
637 if (actualLength
!= length
) {
638 fprintf(stderr
, "UVCCamDevice::_ProbeFormat() SET_CUR ProbeControl1"
639 " failed %ld\n", actualLength
);
644 usbvc_probecommit response;
645 actualLength = fDevice->ControlTransfer(
646 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_IN, GET_MAX,
647 VS_PROBE_CONTROL << 8, fStreamingIndex, sizeof(response), &response);
648 if (actualLength != sizeof(response)) {
649 fprintf(stderr, "UVCCamDevice::_ProbeFormat() GetMax ProbeControl"
654 printf("usbvc_probecommit response.compQuality %d\n", response.compQuality);
655 request.compQuality = response.compQuality;
659 usbvc_probecommit response
;
660 memset(&response
, 0, sizeof(response
));
661 actualLength
= fDevice
->ControlTransfer(
662 USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
, GET_CUR
,
663 VS_PROBE_CONTROL
<< 8, fStreamingIndex
, length
, &response
);
666 actualLength = fDevice->ControlTransfer(
667 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, SET_CUR,
668 VS_PROBE_CONTROL << 8, fStreamingIndex, length, &request);
669 if (actualLength != length) {
670 fprintf(stderr, "UVCCamDevice::_ProbeFormat() SetCur ProbeControl2"
676 actualLength
= fDevice
->ControlTransfer(
677 USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_OUT
, SET_CUR
,
678 VS_COMMIT_CONTROL
<< 8, fStreamingIndex
, length
, &request
);
679 if (actualLength
!= length
) {
680 fprintf(stderr
, "UVCCamDevice::_ProbeFormat() SetCur CommitControl"
686 fMaxVideoFrameSize
= response
.maxVideoFrameSize
;
687 fMaxPayloadTransferSize
= response
.maxPayloadTransferSize
;
688 printf("usbvc_probecommit setup done maxVideoFrameSize:%ld"
689 " maxPayloadTransferSize:%ld\n", fMaxVideoFrameSize
,
690 fMaxPayloadTransferSize
);
692 printf("UVCCamDevice::_ProbeCommitFormat()\n --> SUCCESSFUL\n");
698 UVCCamDevice::_SelectBestAlternate()
700 printf("UVCCamDevice::_SelectBestAlternate()\n");
701 const BUSBConfiguration
* config
= fDevice
->ActiveConfiguration();
702 const BUSBInterface
* streaming
= config
->InterfaceAt(fStreamingIndex
);
703 if (streaming
== NULL
)
706 uint32 bestBandwidth
= 0;
707 uint32 alternateIndex
= 0;
708 uint32 endpointIndex
= 0;
710 for (uint32 i
= 0; i
< streaming
->CountAlternates(); i
++) {
711 const BUSBInterface
* alternate
= streaming
->AlternateAt(i
);
712 for (uint32 j
= 0; j
< alternate
->CountEndpoints(); j
++) {
713 const BUSBEndpoint
* endpoint
= alternate
->EndpointAt(j
);
714 if (!endpoint
->IsIsochronous() || !endpoint
->IsInput())
716 if (fMaxPayloadTransferSize
> endpoint
->MaxPacketSize())
718 if (bestBandwidth
!= 0
719 && bestBandwidth
< endpoint
->MaxPacketSize())
721 bestBandwidth
= endpoint
->MaxPacketSize();
727 if (bestBandwidth
== 0) {
728 fprintf(stderr
, "UVCCamDevice::_SelectBestAlternate()"
729 " couldn't find a valid alternate\n");
733 printf("UVCCamDevice::_SelectBestAlternate() %ld\n", bestBandwidth
);
734 if (((BUSBInterface
*)streaming
)->SetAlternate(alternateIndex
) != B_OK
) {
735 fprintf(stderr
, "UVCCamDevice::_SelectBestAlternate()"
736 " selecting alternate failed\n");
740 fIsoIn
= streaming
->EndpointAt(endpointIndex
);
747 UVCCamDevice::_SelectIdleAlternate()
749 printf("UVCCamDevice::_SelectIdleAlternate()\n");
750 const BUSBConfiguration
* config
= fDevice
->ActiveConfiguration();
751 const BUSBInterface
* streaming
= config
->InterfaceAt(fStreamingIndex
);
752 if (streaming
== NULL
)
754 if (((BUSBInterface
*)streaming
)->SetAlternate(0) != B_OK
) {
755 fprintf(stderr
, "UVCCamDevice::_SelectIdleAlternate()"
756 " selecting alternate failed\n");
767 UVCCamDevice::_AddProcessingParameter(BParameterGroup
* group
,
768 int32 index
, const usbvc_processing_unit_descriptor
* descriptor
)
770 BParameterGroup
* subgroup
;
771 BContinuousParameter
* p
;
772 uint16 wValue
= 0; // Control Selector
773 float minValue
= 0.0;
774 float maxValue
= 100.0;
775 if (descriptor
->controlSize
>= 1) {
776 if (descriptor
->controls
[0] & 1) {
777 // debug_printf("\tBRIGHTNESS\n");
778 fBrightness
= _AddParameter(group
, &subgroup
, index
,
779 PU_BRIGHTNESS_CONTROL
, "Brightness");
781 if (descriptor
->controls
[0] & 2) {
782 // debug_printf("\tCONSTRAST\n");
783 fContrast
= _AddParameter(group
, &subgroup
, index
+ 1,
784 PU_CONTRAST_CONTROL
, "Contrast");
786 if (descriptor
->controls
[0] & 4) {
787 // debug_printf("\tHUE\n");
788 fHue
= _AddParameter(group
, &subgroup
, index
+ 2,
789 PU_HUE_CONTROL
, "Hue");
790 if (descriptor
->controlSize
>= 2) {
791 if (descriptor
->controls
[1] & 8) {
792 fHueAuto
= _AddAutoParameter(subgroup
, index
+ 3,
793 PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL
);
797 if (descriptor
->controls
[0] & 8) {
798 // debug_printf("\tSATURATION\n");
799 fSaturation
= _AddParameter(group
, &subgroup
, index
+ 4,
800 PU_SATURATION_CONTROL
, "Saturation");
802 if (descriptor
->controls
[0] & 16) {
803 // debug_printf("\tSHARPNESS\n");
804 fSharpness
= _AddParameter(group
, &subgroup
, index
+ 5,
805 PU_SHARPNESS_CONTROL
, "Sharpness");
807 if (descriptor
->controls
[0] & 32) {
808 // debug_printf("\tGamma\n");
809 fGamma
= _AddParameter(group
, &subgroup
, index
+ 6,
810 PU_GAMMA_CONTROL
, "Gamma");
812 if (descriptor
->controls
[0] & 64) {
813 // debug_printf("\tWHITE BALANCE TEMPERATURE\n");
814 fWBTemp
= _AddParameter(group
, &subgroup
, index
+ 7,
815 PU_WHITE_BALANCE_TEMPERATURE_CONTROL
, "WB Temperature");
816 if (descriptor
->controlSize
>= 2) {
817 if (descriptor
->controls
[1] & 16) {
818 fWBTempAuto
= _AddAutoParameter(subgroup
, index
+ 8,
819 PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL
);
823 if (descriptor
->controls
[0] & 128) {
824 // debug_printf("\tWhite Balance Component\n");
825 fWBComponent
= _AddParameter(group
, &subgroup
, index
+ 9,
826 PU_WHITE_BALANCE_COMPONENT_CONTROL
, "WB Component");
827 if (descriptor
->controlSize
>= 2) {
828 if (descriptor
->controls
[1] & 32) {
829 fWBTempAuto
= _AddAutoParameter(subgroup
, index
+ 10,
830 PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL
);
835 if (descriptor
->controlSize
>= 2) {
836 if (descriptor
->controls
[1] & 1) {
837 // debug_printf("\tBACKLIGHT COMPENSATION\n");
839 wValue
= PU_BACKLIGHT_COMPENSATION_CONTROL
<< 8;
840 fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
841 GET_MAX
, wValue
, fControlRequestIndex
, sizeof(data
), &data
);
842 maxValue
= (float)data
;
843 fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
844 GET_MIN
, wValue
, fControlRequestIndex
, sizeof(data
), &data
);
845 minValue
= (float)data
;
846 fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
847 GET_CUR
, wValue
, fControlRequestIndex
, sizeof(data
), &data
);
848 fBacklightCompensation
= (float)data
;
849 subgroup
= group
->MakeGroup("Backlight Compensation");
850 if (maxValue
- minValue
== 1) { // Binary Switch
851 fBinaryBacklightCompensation
= true;
852 subgroup
->MakeDiscreteParameter(index
+ 11,
853 B_MEDIA_RAW_VIDEO
, "Backlight Compensation",
855 } else { // Range of values
856 fBinaryBacklightCompensation
= false;
857 p
= subgroup
->MakeContinuousParameter(index
+ 11,
858 B_MEDIA_RAW_VIDEO
, "Backlight Compensation",
859 B_GAIN
, "", minValue
, maxValue
, 1.0 / (maxValue
- minValue
));
862 if (descriptor
->controls
[1] & 2) {
863 // debug_printf("\tGAIN\n");
864 fGain
= _AddParameter(group
, &subgroup
, index
+ 12, PU_GAIN_CONTROL
,
867 if (descriptor
->controls
[1] & 4) {
868 // debug_printf("\tPOWER LINE FREQUENCY\n");
869 wValue
= PU_POWER_LINE_FREQUENCY_CONTROL
<< 8;
871 if (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
872 GET_CUR
, wValue
, fControlRequestIndex
, sizeof(data
), &data
) == sizeof(data
)) {
873 fPowerlineFrequency
= data
;
875 subgroup
= group
->MakeGroup("Power Line Frequency");
876 p
= subgroup
->MakeContinuousParameter(index
+ 13,
877 B_MEDIA_RAW_VIDEO
, "Frequency", B_GAIN
, "", 0, 60.0, 1.0 / 60.0);
879 // TODO Determine whether controls apply to these
881 if (descriptor->controls[1] & 64)
882 debug_printf("\tDigital Multiplier\n");
883 if (descriptor->controls[1] & 128)
884 debug_printf("\tDigital Multiplier Limit\n");
887 // TODO Determine whether controls apply to these
889 if (descriptor->controlSize >= 3) {
890 if (descriptor->controls[2] & 1)
891 debug_printf("\tAnalog Video Standard\n");
892 if (descriptor->controls[2] & 2)
893 debug_printf("\tAnalog Video Lock Status\n");
902 UVCCamDevice::_AddParameter(BParameterGroup
* group
,
903 BParameterGroup
** subgroup
, int32 index
, uint16 wValue
, const char* name
)
905 float minValue
= 0.0;
906 float maxValue
= 100.0;
907 float currValue
= 0.0;
912 if (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
913 GET_MAX
, wValue
, fControlRequestIndex
, sizeof(data
), &data
)
915 maxValue
= (float)data
;
917 if (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
918 GET_MIN
, wValue
, fControlRequestIndex
, sizeof(data
), &data
)
920 minValue
= (float)data
;
922 if (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
923 GET_CUR
, wValue
, fControlRequestIndex
, sizeof(data
), &data
)
925 currValue
= (float)data
;
928 *subgroup
= group
->MakeGroup(name
);
929 BContinuousParameter
* p
= (*subgroup
)->MakeContinuousParameter(index
,
930 B_MEDIA_RAW_VIDEO
, name
, B_GAIN
, "", minValue
, maxValue
,
931 1.0 / (maxValue
- minValue
));
937 UVCCamDevice::_AddAutoParameter(BParameterGroup
* subgroup
, int32 index
,
943 fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
944 GET_CUR
, wValue
, fControlRequestIndex
, 1, &data
);
945 subgroup
->MakeDiscreteParameter(index
, B_MEDIA_RAW_VIDEO
, "Auto",
953 UVCCamDevice::AddParameters(BParameterGroup
* group
, int32
& index
)
955 printf("UVCCamDevice::AddParameters()\n");
956 fFirstParameterID
= index
;
957 // debug_printf("fIndex = %d\n",fIndex);
958 CamDevice::AddParameters(group
, index
);
960 const BUSBConfiguration
* config
;
961 const BUSBInterface
* interface
;
964 usb_descriptor
* generic
= (usb_descriptor
*)buffer
;
966 for (uint32 i
= 0; i
< fDevice
->CountConfigurations(); i
++) {
967 config
= fDevice
->ConfigurationAt(i
);
970 fDevice
->SetConfiguration(config
);
971 for (uint32 j
= 0; j
< config
->CountInterfaces(); j
++) {
972 interface
= config
->InterfaceAt(j
);
973 if (interface
== NULL
)
975 if (interface
->Class() != CC_VIDEO
|| interface
->Subclass()
978 for (uint32 k
= 0; interface
->OtherDescriptorAt(k
, generic
,
979 sizeof(buffer
)) == B_OK
; k
++) {
980 if (generic
->generic
.descriptor_type
!= (USB_REQTYPE_CLASS
981 | USB_DESCRIPTOR_INTERFACE
))
984 if (((const usbvc_class_descriptor
*)generic
)->descriptorSubtype
985 == VC_PROCESSING_UNIT
) {
986 _AddProcessingParameter(group
, index
,
987 (const usbvc_processing_unit_descriptor
*)generic
);
996 UVCCamDevice::GetParameterValue(int32 id
, bigtime_t
* last_change
, void* value
,
999 printf("UVCCAmDevice::GetParameterValue(%ld)\n", id
- fFirstParameterID
);
1004 switch (id
- fFirstParameterID
) {
1006 // debug_printf("\tBrightness:\n");
1007 // debug_printf("\tValue = %f\n",fBrightness);
1008 *size
= sizeof(float);
1009 currValue
= (float*)value
;
1010 *currValue
= fBrightness
;
1011 *last_change
= fLastParameterChanges
;
1014 // debug_printf("\tContrast:\n");
1015 // debug_printf("\tValue = %f\n",fContrast);
1016 *size
= sizeof(float);
1017 currValue
= (float*)value
;
1018 *currValue
= fContrast
;
1019 *last_change
= fLastParameterChanges
;
1022 // debug_printf("\tHue:\n");
1023 // debug_printf("\tValue = %f\n",fHue);
1024 *size
= sizeof(float);
1025 currValue
= (float*)value
;
1027 *last_change
= fLastParameterChanges
;
1030 // debug_printf("\tSaturation:\n");
1031 // debug_printf("\tValue = %f\n",fSaturation);
1032 *size
= sizeof(float);
1033 currValue
= (float*)value
;
1034 *currValue
= fSaturation
;
1035 *last_change
= fLastParameterChanges
;
1038 // debug_printf("\tSharpness:\n");
1039 // debug_printf("\tValue = %f\n",fSharpness);
1040 *size
= sizeof(float);
1041 currValue
= (float*)value
;
1042 *currValue
= fSharpness
;
1043 *last_change
= fLastParameterChanges
;
1046 // debug_printf("\tWB Temperature:\n");
1047 *size
= sizeof(float);
1048 currValue
= (float*)value
;
1049 wValue
= PU_WHITE_BALANCE_TEMPERATURE_CONTROL
<< 8;
1050 if (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_INTERFACE_IN
,
1051 GET_CUR
, wValue
, fControlRequestIndex
, sizeof(data
), &data
)
1053 fWBTemp
= (float)data
;
1055 // debug_printf("\tValue = %f\n",fWBTemp);
1056 *currValue
= fWBTemp
;
1057 *last_change
= fLastParameterChanges
;
1060 // debug_printf("\tWB Temperature Auto:\n");
1061 // debug_printf("\tValue = %d\n",fWBTempAuto);
1062 *size
= sizeof(int);
1063 currValueInt
= ((int*)value
);
1064 *currValueInt
= fWBTempAuto
;
1065 *last_change
= fLastParameterChanges
;
1068 if (!fBinaryBacklightCompensation
) {
1069 // debug_printf("\tBacklight Compensation:\n");
1070 // debug_printf("\tValue = %f\n",fBacklightCompensation);
1071 *size
= sizeof(float);
1072 currValue
= (float*)value
;
1073 *currValue
= fBacklightCompensation
;
1074 *last_change
= fLastParameterChanges
;
1076 // debug_printf("\tBacklight Compensation:\n");
1077 // debug_printf("\tValue = %d\n",fBacklightCompensationBinary);
1078 currValueInt
= (int*)value
;
1079 *currValueInt
= fBacklightCompensationBinary
;
1080 *last_change
= fLastParameterChanges
;
1084 // debug_printf("\tGain:\n");
1085 // debug_printf("\tValue = %f\n",fGain);
1086 *size
= sizeof(float);
1087 currValue
= (float*)value
;
1089 *last_change
= fLastParameterChanges
;
1092 // debug_printf("\tPowerline Frequency:\n");
1093 // debug_printf("\tValue = %d\n",fPowerlineFrequency);
1094 *size
= sizeof(float);
1095 currValue
= (float*)value
;
1096 switch (fPowerlineFrequency
) {
1107 *last_change
= fLastParameterChanges
;
1116 UVCCamDevice::SetParameterValue(int32 id
, bigtime_t when
, const void* value
,
1119 printf("UVCCamDevice::SetParameterValue(%ld)\n", id
- fFirstParameterID
);
1120 switch (id
- fFirstParameterID
) {
1122 // debug_printf("\tBrightness:\n");
1123 if (!value
|| (size
!= sizeof(float)))
1125 fBrightness
= *((float*)value
);
1126 fLastParameterChanges
= when
;
1127 return _SetParameterValue(PU_BRIGHTNESS_CONTROL
, (int16
)fBrightness
);
1129 // debug_printf("\tContrast:\n");
1130 if (!value
|| (size
!= sizeof(float)))
1132 fContrast
= *((float*)value
);
1133 fLastParameterChanges
= when
;
1134 return _SetParameterValue(PU_CONTRAST_CONTROL
, (int16
)fContrast
);
1136 // debug_printf("\tHue:\n");
1137 if (!value
|| (size
!= sizeof(float)))
1139 fHue
= *((float*)value
);
1140 fLastParameterChanges
= when
;
1141 return _SetParameterValue(PU_HUE_CONTROL
, (int16
)fHue
);
1143 // debug_printf("\tSaturation:\n");
1144 if (!value
|| (size
!= sizeof(float)))
1146 fSaturation
= *((float*)value
);
1147 fLastParameterChanges
= when
;
1148 return _SetParameterValue(PU_SATURATION_CONTROL
, (int16
)fSaturation
);
1150 // debug_printf("\tSharpness:\n");
1151 if (!value
|| (size
!= sizeof(float)))
1153 fSharpness
= *((float*)value
);
1154 fLastParameterChanges
= when
;
1155 return _SetParameterValue(PU_SHARPNESS_CONTROL
, (int16
)fSharpness
);
1159 // debug_printf("\tWB Temperature:\n");
1160 if (!value
|| (size
!= sizeof(float)))
1162 fWBTemp
= *((float*)value
);
1163 fLastParameterChanges
= when
;
1164 return _SetParameterValue(PU_WHITE_BALANCE_TEMPERATURE_CONTROL
,
1167 // debug_printf("\tWB Temperature Auto:\n");
1168 if (!value
|| (size
!= sizeof(int)))
1170 fWBTempAuto
= *((int*)value
);
1171 fLastParameterChanges
= when
;
1172 return _SetParameterValue(
1173 PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL
, (int8
)fWBTempAuto
);
1175 if (!fBinaryBacklightCompensation
) {
1176 // debug_printf("\tBacklight Compensation:\n");
1177 if (!value
|| (size
!= sizeof(float)))
1179 fBacklightCompensation
= *((float*)value
);
1181 // debug_printf("\tBacklight Compensation:\n");
1182 if (!value
|| (size
!= sizeof(int)))
1184 fBacklightCompensationBinary
= *((int*)value
);
1186 fLastParameterChanges
= when
;
1187 return _SetParameterValue(PU_BACKLIGHT_COMPENSATION_CONTROL
,
1188 (int16
)fBacklightCompensationBinary
);
1190 // debug_printf("\tGain:\n");
1191 if (!value
|| (size
!= sizeof(float)))
1193 fGain
= *((float*)value
);
1194 fLastParameterChanges
= when
;
1195 return _SetParameterValue(PU_GAIN_CONTROL
, (int16
)fGain
);
1197 // debug_printf("\tPowerline Frequency:\n");
1198 // debug_printf("\tValue = %f\n",*((float*)value));
1199 if (!value
|| (size
!= sizeof(float)))
1201 float inValue
= *((float*)value
);
1202 fPowerlineFrequency
= 0;
1203 if (inValue
> 45.0 && inValue
< 55.0) {
1204 fPowerlineFrequency
= 1;
1206 if (inValue
>= 55.0) {
1207 fPowerlineFrequency
= 2;
1209 fLastParameterChanges
= when
;
1210 return _SetParameterValue(PU_POWER_LINE_FREQUENCY_CONTROL
,
1211 (int8
)fPowerlineFrequency
);
1219 UVCCamDevice::_SetParameterValue(uint16 wValue
, int16 setValue
)
1221 return (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
1222 | USB_REQTYPE_INTERFACE_OUT
, SET_CUR
, wValue
<< 8, fControlRequestIndex
,
1223 sizeof(setValue
), &setValue
)) == sizeof(setValue
);
1228 UVCCamDevice::_SetParameterValue(uint16 wValue
, int8 setValue
)
1230 return (fDevice
->ControlTransfer(USB_REQTYPE_CLASS
1231 | USB_REQTYPE_INTERFACE_OUT
, SET_CUR
, wValue
<< 8, fControlRequestIndex
,
1232 sizeof(setValue
), &setValue
)) == sizeof(setValue
);
1237 UVCCamDevice::FillFrameBuffer(BBuffer
* buffer
, bigtime_t
* stamp
)
1239 memset(buffer
->Data(), 0, buffer
->SizeAvailable());
1240 status_t err
= fDeframer
->WaitFrame(2000000);
1242 fprintf(stderr
, "WaitFrame: %lx\n", err
);
1247 err
= fDeframer
->GetFrame(&f
, stamp
);
1249 fprintf(stderr
, "GetFrame: %lx\n", err
);
1253 long int w
= (long)(VideoFrame().right
- VideoFrame().left
+ 1);
1254 long int h
= (long)(VideoFrame().bottom
- VideoFrame().top
+ 1);
1256 if (buffer
->SizeAvailable() >= (size_t)w
* h
* 4) {
1257 // TODO: The Video Producer only outputs B_RGB32. This is OK for most
1258 // applications. This could be leveraged if applications can
1259 // consume B_YUV422.
1260 _DecodeColor((unsigned char*)buffer
->Data(),
1261 (unsigned char*)f
->Buffer(), w
, h
);
1269 UVCCamDevice::_DecodeColor(unsigned char* dst
, unsigned char* src
,
1270 int32 width
, int32 height
)
1273 unsigned char* rawpt
, * scanpt
;
1278 size
= width
*height
;
1280 for ( i
= 0; i
< size
; i
++ ) {
1281 if ( (i
/width
) % 2 == 0 ) {
1282 if ( (i
% 2) == 0 ) {
1284 if ( (i
> width
) && ((i
% width
) > 0) ) {
1285 *scanpt
++ = (*(rawpt
-width
-1)+*(rawpt
-width
+1)
1286 + *(rawpt
+width
-1)+*(rawpt
+width
+1))/4; /* R */
1287 *scanpt
++ = (*(rawpt
-1)+*(rawpt
+1)
1288 + *(rawpt
+width
)+*(rawpt
-width
))/4; /* G */
1289 *scanpt
++ = *rawpt
; /* B */
1291 /* first line or left column */
1292 *scanpt
++ = *(rawpt
+width
+1); /* R */
1293 *scanpt
++ = (*(rawpt
+1)+*(rawpt
+width
))/2; /* G */
1294 *scanpt
++ = *rawpt
; /* B */
1298 if ( (i
> width
) && ((i
% width
) < (width
-1)) ) {
1299 *scanpt
++ = (*(rawpt
+width
)+*(rawpt
-width
))/2; /* R */
1300 *scanpt
++ = *rawpt
; /* G */
1301 *scanpt
++ = (*(rawpt
-1)+*(rawpt
+1))/2; /* B */
1303 /* first line or right column */
1304 *scanpt
++ = *(rawpt
+width
); /* R */
1305 *scanpt
++ = *rawpt
; /* G */
1306 *scanpt
++ = *(rawpt
-1); /* B */
1310 if ( (i
% 2) == 0 ) {
1312 if ( (i
< (width
*(height
-1))) && ((i
% width
) > 0) ) {
1313 *scanpt
++ = (*(rawpt
-1)+*(rawpt
+1))/2; /* R */
1314 *scanpt
++ = *rawpt
; /* G */
1315 *scanpt
++ = (*(rawpt
+width
)+*(rawpt
-width
))/2; /* B */
1317 /* bottom line or left column */
1318 *scanpt
++ = *(rawpt
+1); /* R */
1319 *scanpt
++ = *rawpt
; /* G */
1320 *scanpt
++ = *(rawpt
-width
); /* B */
1324 if ( i
< (width
*(height
-1)) && ((i
% width
) < (width
-1)) ) {
1325 *scanpt
++ = *rawpt
; /* R */
1326 *scanpt
++ = (*(rawpt
-1)+*(rawpt
+1)
1327 + *(rawpt
-width
)+*(rawpt
+width
))/4; /* G */
1328 *scanpt
++ = (*(rawpt
-width
-1)+*(rawpt
-width
+1)
1329 + *(rawpt
+width
-1)+*(rawpt
+width
+1))/4; /* B */
1331 /* bottom line or right column */
1332 *scanpt
++ = *rawpt
; /* R */
1333 *scanpt
++ = (*(rawpt
-1)+*(rawpt
-width
))/2; /* G */
1334 *scanpt
++ = *(rawpt
-width
-1); /* B */
1345 UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn
* webcam
)
1346 : CamDeviceAddon(webcam
)
1348 printf("UVCCamDeviceAddon::UVCCamDeviceAddon(WebCamMediaAddOn* webcam)\n");
1349 SetSupportedDevices(kSupportedDevices
);
1353 UVCCamDeviceAddon::~UVCCamDeviceAddon()
1359 UVCCamDeviceAddon::BrandName()
1361 printf("UVCCamDeviceAddon::BrandName()\n");
1362 return "USB Video Class";
1367 UVCCamDeviceAddon::Instantiate(CamRoster
& roster
, BUSBDevice
* from
)
1369 printf("UVCCamDeviceAddon::Instantiate()\n");
1370 return new UVCCamDevice(*this, from
);
1375 B_WEBCAM_MKINTFUNC(uvccam
)
1376 (WebCamMediaAddOn
* webcam
, CamDeviceAddon
**addon
)
1378 *addon
= new UVCCamDeviceAddon(webcam
);