Skip to content

Commit

Permalink
Merge pull request OpenKinect#332 from piedar/camera-flags
Browse files Browse the repository at this point in the history
Camera Flags - Auto Exposure, Auto White Balance, Raw Color, & Mirror
  • Loading branch information
piedar committed Jul 13, 2013
2 parents 35d1fc1 + 37758b2 commit bd66645
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 118 deletions.
22 changes: 22 additions & 0 deletions examples/glview.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,27 @@ void keyPressed(unsigned char key, int x, int y)
freenect_angle = -30;
}
}
if (key == 'e') {
static freenect_flag_value auto_exposure = FREENECT_ON;
freenect_set_flag(f_dev, FREENECT_AUTO_EXPOSURE, auto_exposure);
auto_exposure = !auto_exposure;
}
if (key == 'b') {
static freenect_flag_value white_balance = FREENECT_ON;
freenect_set_flag(f_dev, FREENECT_AUTO_WHITE_BALANCE, white_balance);
white_balance = !white_balance;
}
if (key == 'r') {
static freenect_flag_value raw_color = FREENECT_ON;
freenect_set_flag(f_dev, FREENECT_RAW_COLOR, raw_color);
raw_color = !raw_color;
}
if (key == 'm') {
static freenect_flag_value mirror = FREENECT_ON;
freenect_set_flag(f_dev, FREENECT_MIRROR_DEPTH, mirror);
freenect_set_flag(f_dev, FREENECT_MIRROR_VIDEO, mirror);
mirror = !mirror;
}
if (key == '1') {
freenect_set_led(f_dev,LED_GREEN);
}
Expand Down Expand Up @@ -349,6 +370,7 @@ void *freenect_threadfunc(void *arg)
freenect_start_video(f_dev);

printf("'w'-tilt up, 's'-level, 'x'-tilt down, '0'-'6'-select LED mode, 'f'-video format\n");
printf("'e' - auto exposure, 'b' - white balance, 'r' - raw color, 'm' - mirror\n");

while (!die && freenect_process_events(f_ctx) >= 0) {
//Throttle the text output
Expand Down
27 changes: 27 additions & 0 deletions include/libfreenect.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ typedef enum {
FREENECT_DEPTH_DUMMY = 2147483647, /**< Dummy value to force enum to be 32 bits wide */
} freenect_depth_format;

/// Enumeration of flags to toggle features with freenect_set_flag()
typedef enum {
// values written to the CMOS register
FREENECT_AUTO_EXPOSURE = 1 << 14,
FREENECT_AUTO_WHITE_BALANCE = 1 << 1,
FREENECT_RAW_COLOR = 1 << 4,
// registers to be written with 0 or 1
FREENECT_MIRROR_DEPTH = 0x0017,
FREENECT_MIRROR_VIDEO = 0x0047,
} freenect_flag;

/// Possible values for setting each `freenect_flag`
typedef enum {
FREENECT_OFF = 0,
FREENECT_ON = 1,
} freenect_flag_value;

/// Structure to give information about the width, height, bitrate,
/// framerate, and buffer size of a frame in a particular mode, as
/// well as the total number of bytes needed to hold a single frame.
Expand Down Expand Up @@ -614,6 +631,16 @@ FREENECTAPI freenect_frame_mode freenect_find_depth_mode(freenect_resolution res
*/
FREENECTAPI int freenect_set_depth_mode(freenect_device* dev, const freenect_frame_mode mode);

/**
* Enables or disables the specified flag.
*
* @param flag Feature to set
* @param value `FREENECT_OFF` or `FREENECT_ON`
*
* @return 0 on success, < 0 if error
*/
FREENECTAPI int freenect_set_flag(freenect_device *dev, freenect_flag flag, freenect_flag_value value);

#ifdef __cplusplus
}
#endif
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ set(CMAKE_C_FLAGS "-Wall")

include_directories(${LIBUSB_1_INCLUDE_DIRS})
IF(WIN32)
LIST(APPEND SRC core.c tilt.c cameras.c usb_libusb10.c registration.c ../platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp ../platform/windows/libusb10emu/libusb-1.0/failguard.cpp)
LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c ../platform/windows/libusb10emu/libusb-1.0/libusbemu.cpp ../platform/windows/libusb10emu/libusb-1.0/failguard.cpp)
set_source_files_properties(${SRC} PROPERTIES LANGUAGE CXX)
ELSE(WIN32)
LIST(APPEND SRC core.c tilt.c cameras.c usb_libusb10.c registration.c)
LIST(APPEND SRC core.c tilt.c cameras.c flags.c usb_libusb10.c registration.c)
ENDIF(WIN32)

IF(BUILD_AUDIO)
Expand Down
117 changes: 1 addition & 116 deletions src/cameras.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "freenect_internal.h"
#include "registration.h"
#include "cameras.h"
#include "flags.h"

#define MAKE_RESERVED(res, fmt) (uint32_t)(((res & 0xff) << 8) | (((fmt & 0xff))))
#define RESERVED_TO_RESOLUTION(reserved) (freenect_resolution)((reserved >> 8) & 0xff)
Expand Down Expand Up @@ -650,122 +651,6 @@ static void video_process(freenect_device *dev, uint8_t *pkt, int len)
dev->video_cb(dev, dev->video.proc_buf, dev->video.timestamp);
}

typedef struct {
uint8_t magic[2];
uint16_t len;
uint16_t cmd;
uint16_t tag;
} cam_hdr;

static int send_cmd(freenect_device *dev, uint16_t cmd, void *cmdbuf, unsigned int cmd_len, void *replybuf, int reply_len)
{
freenect_context *ctx = dev->parent;
int res, actual_len;
uint8_t obuf[0x400];
uint8_t ibuf[0x200];
cam_hdr *chdr = (cam_hdr*)obuf;
cam_hdr *rhdr = (cam_hdr*)ibuf;

if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
FN_ERROR("send_cmd: Invalid command length (0x%x)\n", cmd_len);
return -1;
}

chdr->magic[0] = 0x47;
chdr->magic[1] = 0x4d;
chdr->cmd = fn_le16(cmd);
chdr->tag = fn_le16(dev->cam_tag);
chdr->len = fn_le16(cmd_len / 2);

memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);

res = fnusb_control(&dev->usb_cam, 0x40, 0, 0, 0, obuf, cmd_len + sizeof(*chdr));
FN_SPEW("Control cmd=%04x tag=%04x len=%04x: %d\n", cmd, dev->cam_tag, cmd_len, res);
if (res < 0) {
FN_ERROR("send_cmd: Output control transfer failed (%d)\n", res);
return res;
}

do {
actual_len = fnusb_control(&dev->usb_cam, 0xc0, 0, 0, 0, ibuf, 0x200);
FN_FLOOD("actual_len: %d\n", actual_len);
} while ((actual_len == 0) || (actual_len == 0x200));
FN_SPEW("Control reply: %d\n", res);
if (actual_len < (int)sizeof(*rhdr)) {
FN_ERROR("send_cmd: Input control transfer failed (%d)\n", res);
return res;
}
actual_len -= sizeof(*rhdr);

if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
FN_ERROR("send_cmd: Bad magic %02x %02x\n", rhdr->magic[0], rhdr->magic[1]);
return -1;
}
if (rhdr->cmd != chdr->cmd) {
FN_ERROR("send_cmd: Bad cmd %02x != %02x\n", rhdr->cmd, chdr->cmd);
return -1;
}
if (rhdr->tag != chdr->tag) {
FN_ERROR("send_cmd: Bad tag %04x != %04x\n", rhdr->tag, chdr->tag);
return -1;
}
if (fn_le16(rhdr->len) != (actual_len/2)) {
FN_ERROR("send_cmd: Bad len %04x != %04x\n", fn_le16(rhdr->len), (int)(actual_len/2));
return -1;
}

if (actual_len > reply_len) {
FN_WARNING("send_cmd: Data buffer is %d bytes long, but got %d bytes\n", reply_len, actual_len);
memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
} else {
memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
}

dev->cam_tag++;

return actual_len;
}

static int write_register(freenect_device *dev, uint16_t reg, uint16_t data)
{
freenect_context *ctx = dev->parent;
uint16_t reply[2];
uint16_t cmd[2];
int res;

cmd[0] = fn_le16(reg);
cmd[1] = fn_le16(data);

FN_DEBUG("Write Reg 0x%04x <= 0x%02x\n", reg, data);
res = send_cmd(dev, 0x03, cmd, 4, reply, 4);
if (res < 0)
return res;
if (res != 2) {
FN_WARNING("send_cmd returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]);
}
return 0;
}

// This function is here for completeness. We don't actually use it for anything right now.
static uint16_t read_register(freenect_device *dev, uint16_t reg)
{
freenect_context *ctx = dev->parent;
uint16_t reply[2];
uint16_t cmd;
int res;

cmd = fn_le16(reg);

FN_DEBUG("Read Reg 0x%04x =>\n", reg);
res = send_cmd(dev, 0x02, &cmd, 2, reply, 4);
if (res < 0)
FN_ERROR("read_register: send_cmd() failed: %d\n", res);
if (res != 4)
FN_WARNING("send_cmd returned %d [%04x %04x], 0000 expected\n", res, reply[0], reply[1]);

return reply[1];
}

static int freenect_fetch_reg_info(freenect_device *dev)
{
freenect_context *ctx = dev->parent;
Expand Down
Loading

0 comments on commit bd66645

Please sign in to comment.