1 /*
2  * This file is part of the OpenKinect Project. http://www.openkinect.org
3  *
4  * Copyright (c) 2010 Brandyn White (bwhite@dappervision.com)
5  *
6  * This code is licensed to you under the terms of the Apache License, version
7  * 2.0, or, at your option, the terms of the GNU General Public License,
8  * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
9  * or the following URLs:
10  * http://www.apache.org/licenses/LICENSE-2.0
11  * http://www.gnu.org/licenses/gpl-2.0.txt
12  *
13  * If you redistribute this file in source form, modified or unmodified, you
14  * may:
15  *   1) Leave this header intact and distribute it under the same terms,
16  *      accompanying it with the APACHE20 and GPL20 files, or
17  *   2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
18  *   3) Delete the GPL v2 clause and accompany it with the APACHE20 file
19  * In all cases you must keep the copyright notice intact and include a copy
20  * of the CONTRIB file.
21  *
22  * Binary distributions must follow the binary distribution requirements of
23  * either License.
24  */
25 
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <libfreenect.h>
29 #include <stdio.h>
30 #include <signal.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <sys/time.h>
34 
35 char *out_dir;
36 volatile sig_atomic_t running = 1;
37 uint32_t last_timestamp = 0;
38 FILE *index_fp = NULL;
39 
40 
get_time()41 double get_time()
42 {
43 	struct timeval cur;
44 	gettimeofday(&cur, NULL);
45 	return cur.tv_sec + cur.tv_usec / 1000000.;
46 }
47 
dump_depth(FILE * fp,void * data,int data_size)48 void dump_depth(FILE *fp, void *data, int data_size)
49 {
50 	fprintf(fp, "P5 %d %d 65535\n", FREENECT_FRAME_W, FREENECT_FRAME_H);
51 	fwrite(data, data_size, 1, fp);
52 }
53 
dump_rgb(FILE * fp,void * data,int data_size)54 void dump_rgb(FILE *fp, void *data, int data_size)
55 {
56 	fprintf(fp, "P6 %d %d 255\n", FREENECT_FRAME_W, FREENECT_FRAME_H);
57 	fwrite(data, data_size, 1, fp);
58 }
59 
open_dump(char type,double cur_time,uint32_t timestamp,int data_size,const char * extension)60 FILE *open_dump(char type, double cur_time, uint32_t timestamp, int data_size, const char *extension)
61 {
62 	char *fn = malloc(strlen(out_dir) + 50);
63 	sprintf(fn, "%c-%f-%u.%s", type, cur_time, timestamp, extension);
64 	fprintf(index_fp, "%s\n", fn);
65 	sprintf(fn, "%s/%c-%f-%u.%s", out_dir, type, cur_time, timestamp, extension);
66 	FILE* fp = fopen(fn, "w");
67 	if (!fp) {
68 		printf("Error: Cannot open file [%s]\n", fn);
69 		exit(1);
70 	}
71 	printf("%s\n", fn);
72 	free(fn);
73 	return fp;
74 }
75 
dump(char type,uint32_t timestamp,void * data,int data_size)76 void dump(char type, uint32_t timestamp, void *data, int data_size)
77 {
78 	// timestamp can be at most 10 characters, we have a few extra
79 	double cur_time = get_time();
80 	FILE *fp;
81 	last_timestamp = timestamp;
82 	switch (type) {
83 		case 'd':
84 			fp = open_dump(type, cur_time, timestamp, data_size, "pgm");
85 			dump_depth(fp, data, data_size);
86 			fclose(fp);
87 			break;
88 		case 'r':
89 			fp = open_dump(type, cur_time, timestamp, data_size, "ppm");
90 			dump_rgb(fp, data, data_size);
91 			fclose(fp);
92 			break;
93 		case 'a':
94 			fp = open_dump(type, cur_time, timestamp, data_size, "dump");
95 			fwrite(data, data_size, 1, fp);
96 			fclose(fp);
97 			break;
98 	}
99 }
100 
snapshot_accel(freenect_device * dev)101 void snapshot_accel(freenect_device *dev)
102 {
103 	if (!last_timestamp)
104 		return;
105 	freenect_raw_tilt_state* state;
106 	freenect_update_tilt_state(dev);
107 	state = freenect_get_tilt_state(dev);
108 	dump('a', last_timestamp, state, sizeof *state);
109 }
110 
111 
depth_cb(freenect_device * dev,void * depth,uint32_t timestamp)112 void depth_cb(freenect_device *dev, void *depth, uint32_t timestamp)
113 {
114 	dump('d', timestamp, depth, FREENECT_DEPTH_11BIT_SIZE);
115 }
116 
117 
rgb_cb(freenect_device * dev,void * rgb,uint32_t timestamp)118 void rgb_cb(freenect_device *dev, void *rgb, uint32_t timestamp)
119 {
120 	dump('r', timestamp, rgb, FREENECT_VIDEO_RGB_SIZE);
121 }
122 
init()123 void init()
124 {
125 	freenect_context *ctx;
126 	freenect_device *dev;
127 	if (freenect_init(&ctx, 0)) {
128 		printf("Error: Cannot get context\n");
129 		return;
130 	}
131 
132 	if (freenect_open_device(ctx, &dev, 0)) {
133 		printf("Error: Cannot get device\n");
134 		return;
135 	}
136 	freenect_set_depth_format(dev, FREENECT_DEPTH_11BIT);
137 	freenect_start_depth(dev);
138 	freenect_set_video_format(dev, FREENECT_VIDEO_RGB);
139 	freenect_start_video(dev);
140 	freenect_set_depth_callback(dev, depth_cb);
141 	freenect_set_video_callback(dev, rgb_cb);
142 	while (running && freenect_process_events(ctx) >= 0)
143 		snapshot_accel(dev);
144 	freenect_stop_depth(dev);
145 	freenect_stop_video(dev);
146 	freenect_close_device(dev);
147 	freenect_shutdown(ctx);
148 }
149 
signal_cleanup(int num)150 void signal_cleanup(int num)
151 {
152 	running = 0;
153 	printf("Caught signal, cleaning up\n");
154 	signal(SIGINT, signal_cleanup);
155 }
156 
main(int argc,char ** argv)157 int main(int argc, char **argv)
158 {
159 	if (argc != 2) {
160 		printf("Records the Kinect sensor data to a directory\nResult can be used as input to Fakenect\nUsage: ./record <out_dir>\n");
161 		return 1;
162 	}
163 	out_dir = argv[1];
164 	mkdir(out_dir, S_IRWXU | S_IRWXG | S_IRWXO);
165 	signal(SIGINT, signal_cleanup);
166 	char *fn = malloc(strlen(out_dir) + 50);
167 	sprintf(fn, "%s/INDEX.txt", out_dir);
168 	index_fp = fopen(fn, "r");
169 	if (index_fp) {
170 		printf("Error: Index already exists, to avoid overwriting use a different directory.\n");
171 		return 1;
172 	}
173 	index_fp = fopen(fn, "w");
174 	if (!index_fp) {
175 		printf("Error: Cannot open file [%s]\n", fn);
176 		return 1;
177 	}
178 	free(fn);
179 	init();
180 	fclose(index_fp);
181 	return 0;
182 }
183