Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera Flags - Auto Exposure, Auto White Balance, Raw Color, & Mirror #332

Merged
merged 2 commits into from
Jul 13, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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