summaryrefslogtreecommitdiff
path: root/thread_kinect.c
blob: fdd7f253facd9162022b908eb503083e493272ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <error.h>
#include <libfreenect/libfreenect.h>
#include <libusb-1.0/libusb.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

#include "main.h"

FILE *depth_stream = NULL;
FILE *video_stream = NULL;
FILE *accel_stream = NULL;

static
void dump_ffmpeg_24(FILE *stream, uint32_t timestamp UNUSED, void *data,
                    int data_size)
{
	fwrite(data, data_size, 1, stream);
}

static
void dump_ffmpeg_pad16(FILE *stream, uint32_t timestamp UNUSED, void *data,
                       int data_size)
{
	unsigned int z = 0;
	uint16_t* data_ptr = (uint16_t*)data;
	uint16_t* end = data_ptr + data_size;
	while (data_ptr < end) {
		z = *data_ptr;
		fwrite(((char*)(&z)), 3, 1, stream);
		data_ptr += 2;
	}
}

static
void handle_accel(freenect_device *dev UNUSED, freenect_raw_tilt_state* data)
{
	double x, y, z;
	freenect_get_mks_accel(data, &x, &y, &z);
	fprintf(accel_stream, "x=%f\ty=%f\tz=%f\n", x, y, z);
}

static
void handle_depth(freenect_device *dev UNUSED, void *depth, uint32_t timestamp)
{
	dump_ffmpeg_pad16(depth_stream, timestamp, depth,
	                  freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM,
	                                           FREENECT_DEPTH_11BIT).bytes);
}

static
void handle_video(freenect_device *dev, void *rgb, uint32_t timestamp)
{
	dump_ffmpeg_24(video_stream, timestamp, rgb,
	               freenect_get_current_video_mode(dev).bytes);
}

static
void print_mode(const char *name, freenect_frame_mode mode) {
	/* This is just a courtesy function to let the user know the mode
	   if it becomes a bother for maintainability just comment out the
	   code in its body.  It will only break if struct entries go missing.
	*/
	printf("%s Mode: {%d, %d, {%d}, %d, %d, %d, %d, %d, %d, %d}\n", name,
	       mode.reserved, (int)mode.resolution, (int)mode.video_format, mode.bytes, mode.width,
	       mode.height, mode.data_bits_per_pixel, mode.padding_bits_per_pixel,
	       mode.framerate, mode.is_valid);
}

void thread_kinect(int video_fd, int depth_fd, int accel_fd) {
	int res = 0;

	freenect_context *ctx;
	freenect_device *dev;

	pthread_setname_np(pthread_self(), "libusb");
	res = freenect_init(&ctx, 0);
	pthread_setname_np(pthread_self(), "kinect");
	if (res) {
		error(0, 0, "freenect_init: %s", libusb_strerror(res));
		goto end;
	}

	freenect_select_subdevices(ctx, (freenect_device_flags)(FREENECT_DEVICE_CAMERA | FREENECT_DEVICE_MOTOR));
	if ((res = freenect_open_device(ctx, &dev, 0))) {
		error(0, 0, "freenect_open_device: %s", libusb_strerror(res));
		goto end; 
	}

	print_mode("Depth", freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT));
	freenect_set_depth_mode(dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT));
	freenect_start_depth(dev);

	print_mode("Video", freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB));
	freenect_set_video_mode(dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB));
	freenect_start_video(dev);

	depth_stream = fdopen(depth_fd, "w");
	video_stream = fdopen(video_fd, "w");
	accel_stream = fdopen(accel_fd, "w");

	freenect_set_depth_callback(dev, handle_depth);
	freenect_set_video_callback(dev, handle_video);

	while (running && freenect_process_events(ctx) >= 0) {
		freenect_raw_tilt_state* state;
		freenect_update_tilt_state(dev);
		state = freenect_get_tilt_state(dev);
		handle_accel(dev, state);
	}

	freenect_stop_depth(dev);
	freenect_stop_video(dev);
	freenect_close_device(dev);

 end:
	freenect_shutdown(ctx);
	close(video_fd);
	close(depth_fd);
	close(accel_fd);
}