CGR Localization
 All Classes Namespaces Files Functions Variables Macros Pages
cameras.c
1 /*
2  * This file is part of the OpenKinect Project. http://www.openkinect.org
3  *
4  * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file
5  * for details.
6  *
7  * This code is licensed to you under the terms of the Apache License, version
8  * 2.0, or, at your option, the terms of the GNU General Public License,
9  * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
10  * or the following URLs:
11  * http://www.apache.org/licenses/LICENSE-2.0
12  * http://www.gnu.org/licenses/gpl-2.0.txt
13  *
14  * If you redistribute this file in source form, modified or unmodified, you
15  * may:
16  * 1) Leave this header intact and distribute it under the same terms,
17  * accompanying it with the APACHE20 and GPL20 files, or
18  * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
19  * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
20  * In all cases you must keep the copyright notice intact and include a copy
21  * of the CONTRIB file.
22  *
23  * Binary distributions must follow the binary distribution requirements of
24  * either License.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 
32 #include "freenect_internal.h"
33 
34 struct pkt_hdr {
35  uint8_t magic[2];
36  uint8_t pad;
37  uint8_t flag;
38  uint8_t unk1;
39  uint8_t seq;
40  uint8_t unk2;
41  uint8_t unk3;
42  uint32_t timestamp;
43 };
44 
45 extern const struct caminit inits[];
46 extern const int num_inits;
47 
48 static int stream_process(packet_stream *strm, uint8_t *pkt, int len)
49 {
50  if (len < 12)
51  return 0;
52 
53  struct pkt_hdr *hdr = (void*)pkt;
54  uint8_t *data = pkt + sizeof(*hdr);
55  int datalen = len - sizeof(*hdr);
56 
57  if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
58  //printf("[Stream %02x] Invalid magic %02x%02x\n", strm->flag, hdr->magic[0], hdr->magic[1]);
59  return 0;
60  }
61 
62  //printf("[Stream %02x] %02x\n", strm->flag, hdr->flag);
63 
64  uint8_t sof = strm->flag|1;
65  uint8_t mof = strm->flag|2;
66  uint8_t eof = strm->flag|5;
67 
68  // sync if required, dropping packets until SOF
69  if (!strm->synced) {
70  if (hdr->flag != sof) {
71  //printf("[Stream %02x] not synced yet...\n", strm->flag);
72  return 0;
73  }
74  strm->synced = 1;
75  strm->seq = hdr->seq;
76  strm->pkt_num = 0;
77  strm->valid_pkts = 0;
78  strm->got_pkts = 0;
79  }
80 
81  int got_frame = 0;
82 
83  // handle lost packets
84  if (strm->seq != hdr->seq) {
85  uint8_t lost = strm->seq - hdr->seq;
86  //printf("[Stream %02x] lost %d packets\n", strm->flag, lost);
87  if (lost > 5) {
88  //printf("[Stream %02x] lost too many packets, resyncing...\n", strm->flag);
89  strm->synced = 0;
90  return 0;
91  }
92  strm->seq = hdr->seq;
93  int left = strm->pkts_per_frame - strm->pkt_num;
94  if (left <= lost) {
95  strm->pkt_num = lost - left;
96  strm->valid_pkts = strm->got_pkts;
97  strm->got_pkts = 0;
98  got_frame = 1;
99  strm->timestamp = strm->last_timestamp;
100  } else {
101  strm->pkt_num += lost;
102  }
103  }
104 
105  // check the header to make sure it's what we expect
106  if (!(strm->pkt_num == 0 && hdr->flag == sof) &&
107  !(strm->pkt_num == strm->pkts_per_frame-1 && hdr->flag == eof) &&
108  !(strm->pkt_num > 0 && strm->pkt_num < strm->pkts_per_frame-1 && hdr->flag == mof)) {
109  //printf("[Stream %02x] Inconsistent flag %02x with %d packets in buf (%d total), resyncing...\n",
110  // strm->flag, hdr->flag, strm->pkt_num, strm->pkts_per_frame);
111  strm->synced = 0;
112  return 0;
113  }
114 
115  // copy data
116  if (datalen > strm->pkt_size) {
117  //printf("[Stream %02x] Expected %d data bytes, but got %d. Dropping...\n", strm->flag, strm->pkt_size, datalen);
118  return 0;
119  }
120 
121  //if (datalen != strm->pkt_size && hdr->flag != eof)
122  //printf("[Stream %02x] Expected %d data bytes, but got only %d\n", strm->flag, strm->pkt_size, datalen);
123 
124  uint8_t *dbuf = strm->buf + strm->pkt_num * strm->pkt_size;
125  memcpy(dbuf, data, datalen);
126 
127  strm->pkt_num++;
128  strm->seq++;
129  strm->got_pkts++;
130 
131  strm->last_timestamp = hdr->timestamp;
132 
133  if (strm->pkt_num == strm->pkts_per_frame) {
134  strm->pkt_num = 0;
135  strm->valid_pkts = strm->got_pkts;
136  strm->got_pkts = 0;
137  strm->timestamp = hdr->timestamp;
138  return 1;
139  } else {
140  return got_frame;
141  }
142 }
143 
144 // Unpack buffer of (vw bit) data into padded 16bit buffer.
145 #define CONVERT_PACKED_BUFFER_TO_16_BIT(depth_raw, depth_frame, vw) {\
146  const int mask = (1 << vw) - 1; \
147  int i; \
148  int bitshift = 0; \
149  for (i=0; i<(640*480); i++) { \
150  int idx = (i*vw)/8; \
151  uint32_t word = (depth_raw[idx]<<(16)) | (depth_raw[idx+1]<<8) | depth_raw[idx+2]; \
152  depth_frame[i] = ((word >> (((3*8)-vw)-bitshift)) & mask); \
153  bitshift = (bitshift + vw) % 8; \
154  } \
155 }
156 
157 int depthImageIdx[FREENECT_FRAME_PIX];
158 uint8_t depthImageBitShift[FREENECT_FRAME_PIX];
159 
160 static void init_lookups()
161 {
162  int i;
163  int bitshift = 0;
164  for(i=0; i<FREENECT_FRAME_PIX; i++){
165  depthImageIdx[i] = (i*11)/8;
166  depthImageBitShift[i] = 13-bitshift;
167  bitshift = (bitshift + 11) % 8;
168  }
169 }
170 
171 uint16_t unpack_depth(uint8_t* depth_raw, int row, int column)
172 {
173  const int mask = 0x7FF;
174  unsigned int idx = row*FREENECT_FRAME_W + column;
175  if(idx>FREENECT_FRAME_PIX-1)
176  return 0;
177 
178  int rawidx = depthImageIdx[idx];
179  int bitshift = depthImageBitShift[idx];
180  uint32_t word = (depth_raw[rawidx]<<(16)) | (depth_raw[rawidx+1]<<8) | depth_raw[rawidx+2];
181  uint16_t depth = ((word >> (13-bitshift)) & mask);
182  return depth;
183 }
184 
185 static inline void unpack(uint8_t* depth_raw, uint16_t*depth_frame)
186 {
187  int d0, d1, d2;
188  __asm__ __volatile__(
189  "1:\tlodsb\n\t"
190  "stosb\n\t"
191  "testb %%al,%%al\n\t"
192  "jne 1b"
193  : "=&S" (d0), "=&D" (d1), "=&a" (d2)
194  : "0" (depth_raw),"1" (depth_frame)
195  : "memory");
196  return;
197 }
198 
199 static void depth_process(freenect_device *dev, uint8_t *pkt, int len)
200 {
201  if (len == 0)
202  return;
203 
204  int got_frame = stream_process(&dev->depth_stream, pkt, len);
205 
206  if (!got_frame)
207  return;
208 
209  //printf("GOT DEPTH FRAME %d/%d packets arrived, TS %08x\n",
210  // dev->depth_stream.valid_pkts, dev->depth_stream.pkts_per_frame, dev->depth_stream.timestamp);
211 
212  if (dev->depth_raw_cb){
213  dev->depth_raw_cb(dev,dev->depth_raw, dev->depth_stream.timestamp);
214  return;
215  }
216 
217  //CONVERT_PACKED_BUFFER_TO_16_BIT(dev->depth_raw, dev->depth_frame, 11);
218 
219  uint8_t* depth_raw = dev->depth_raw;
220  uint16_t* depth_frame = dev->depth_frame;
221  const int mask = 0x7FF;
222  int i;
223  int idx = 0;
224  int bitshift = 0;
225  uint32_t word = 0;
226 
227  for (i=0; i<FREENECT_FRAME_PIX; i++) {
228  idx = depthImageIdx[i];
229  bitshift = depthImageBitShift[i];
230  word = (depth_raw[idx]<<16) | (depth_raw[idx+1]<<8) | depth_raw[idx+2];
231  depth_frame[i] = ((word >> bitshift) & mask);
232  }
233 
234  if (dev->depth_cb)
235  dev->depth_cb(dev, dev->depth_frame, dev->depth_stream.timestamp);
236 }
237 
238 static void rgb_process(freenect_device *dev, uint8_t *pkt, int len)
239 {
240  int x,y,i;
241  if (len == 0)
242  return;
243 
244  int got_frame = stream_process(&dev->rgb_stream, pkt, len);
245 
246  if (!got_frame)
247  return;
248 
249  //printf("GOT RGB FRAME %d/%d packets arrived, TS %08x\n", dev->rgb_stream.valid_pkts,
250  // dev->rgb_stream.pkts_per_frame, dev->rgb_stream.timestamp);
251 
252  uint8_t *rgb_frame = NULL;
253 
254  if (dev->rgb_format == FREENECT_FORMAT_BAYER) {
255  rgb_frame = dev->rgb_raw;
256  } else {
257  rgb_frame = dev->rgb_frame;
258  /* Pixel arrangement:
259  * G R G R G R G R
260  * B G B G B G B G
261  * G R G R G R G R
262  * B G B G B G B G
263  * G R G R G R G R
264  * B G B G B G B G
265  */
266 
267  int pixelType=0;
268  int rOffset[] = {1 , 0, -639, -640};
269  int gOffset[] = {0 , -1, -640, 0};
270  int bOffset[] = {640 , 639, 0, -1};
271 
272  uint8_t* rgb_raw = dev->rgb_raw;
273  for (y=1; y<479; y++) {
274  for (x=1; x<639; x++) {
275  i = (y*640+x);
276  pixelType = ((y&1)<<1) + (x&1);
277  rgb_frame[3*i+0] = rgb_raw[i+rOffset[pixelType]];
278  rgb_frame[3*i+1] = rgb_raw[i+gOffset[pixelType]];
279  rgb_frame[3*i+2] = rgb_raw[i+bOffset[pixelType]];
280  }
281  }
282  }
283 
284  if (dev->rgb_cb)
285  dev->rgb_cb(dev, rgb_frame, dev->rgb_stream.timestamp);
286 }
287 
288 struct cam_hdr {
289  uint8_t magic[2];
290  uint16_t len;
291  uint16_t cmd;
292  uint16_t tag;
293 };
294 
295 static void send_init(freenect_device *dev)
296 {
297  int i, j, ret;
298  uint8_t obuf[0x400];
299  uint8_t ibuf[0x200];
300  struct cam_hdr *chdr = (void*)obuf;
301  struct cam_hdr *rhdr = (void*)ibuf;
302 
303  ret = fnusb_control(&dev->usb_cam, 0x80, 0x06, 0x3ee, 0, ibuf, 0x12);
304  //printf("First xfer: %d\n", ret);
305 
306  chdr->magic[0] = 0x47;
307  chdr->magic[1] = 0x4d;
308 
309  for (i=0; i<num_inits; i++) {
310  const struct caminit *ip = &inits[i];
311  chdr->cmd = ip->command;
312  chdr->tag = ip->tag;
313  chdr->len = ip->cmdlen / 2;
314  memcpy(obuf+sizeof(*chdr), ip->cmddata, ip->cmdlen);
315 
316  if( i==6 )
317  {
318  // Choose 10bit or 11 bit depth output
319  obuf[sizeof(*chdr) + 2] = dev->depth_format == FREENECT_FORMAT_11_BIT ? 0x03 : 0x02;
320  }
321 
322  ret = fnusb_control(&dev->usb_cam, 0x40, 0, 0, 0, obuf, ip->cmdlen + sizeof(*chdr));
323  //printf("CTL CMD %04x %04x = %d\n", chdr->cmd, chdr->tag, ret);
324  do {
325  ret = fnusb_control(&dev->usb_cam, 0xc0, 0, 0, 0, ibuf, 0x200);
326  } while (ret == 0);
327  //printf("CTL RES = %d\n", ret);
328  if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
329  //printf("Bad magic %02x %02x\n", rhdr->magic[0], rhdr->magic[1]);
330  continue;
331  }
332  if (rhdr->cmd != chdr->cmd) {
333  //printf("Bad cmd %02x != %02x\n", rhdr->cmd, chdr->cmd);
334  continue;
335  }
336  if (rhdr->tag != chdr->tag) {
337  //printf("Bad tag %04x != %04x\n", rhdr->tag, chdr->tag);
338  continue;
339  }
340  if (rhdr->len != (ret-sizeof(*rhdr))/2) {
341  //printf("Bad len %04x != %04x\n", rhdr->len, (int)(ret-sizeof(*rhdr))/2);
342  continue;
343  }
344  if (rhdr->len != (ip->replylen/2) || memcmp(ibuf+sizeof(*rhdr), ip->replydata, ip->replylen)) {
345  //printf("Expected: ");
346  for (j=0; j<ip->replylen; j++) {
347  //printf("%02x ", ip->replydata[j]);
348  }
349  //printf("\nGot: ");
350  for (j=0; j<(rhdr->len*2); j++) {
351  //printf("%02x ", ibuf[j+sizeof(*rhdr)]);
352  }
353  //printf("\n");
354  }
355  }
356  dev->cam_inited = 1;
357 }
358 
359 int freenect_start_depth(freenect_device *dev)
360 {
361  int res;
362 
363  init_lookups();
364 
365  dev->depth_stream.buf = dev->depth_raw;
366  dev->depth_stream.pkts_per_frame =
367  dev->depth_format == FREENECT_FORMAT_11_BIT ?
368  DEPTH_PKTS_11_BIT_PER_FRAME : DEPTH_PKTS_10_BIT_PER_FRAME;
369  dev->depth_stream.pkt_size = DEPTH_PKTDSIZE;
370  dev->depth_stream.synced = 0;
371  dev->depth_stream.flag = 0x70;
372 
373  res = fnusb_start_iso(&dev->usb_cam, &dev->depth_isoc, depth_process, 0x82, NUM_XFERS, PKTS_PER_XFER, DEPTH_PKTBUF);
374 
375  if(!dev->cam_inited)
376  send_init(dev);
377  return res;
378 }
379 
380 int freenect_start_rgb(freenect_device *dev)
381 {
382  int res;
383 
384  dev->rgb_stream.buf = dev->rgb_raw;
385  dev->rgb_stream.pkts_per_frame = RGB_PKTS_PER_FRAME;
386  dev->rgb_stream.pkt_size = RGB_PKTDSIZE;
387  dev->rgb_stream.synced = 0;
388  dev->rgb_stream.flag = 0x80;
389 
390  res = fnusb_start_iso(&dev->usb_cam, &dev->rgb_isoc, rgb_process, 0x81, NUM_XFERS, PKTS_PER_XFER, RGB_PKTBUF);
391 
392  if(!dev->cam_inited)
393  send_init(dev);
394  return res;
395 }
396 
397 int freenect_stop_depth(freenect_device *dev)
398 {
399  printf("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
400  return 0;
401 }
402 int freenect_stop_rgb(freenect_device *dev)
403 {
404  printf("%s NOT IMPLEMENTED YET\n", __FUNCTION__);
405  return 0;
406 }
407 
408 void freenect_set_depth_callback(freenect_device *dev, freenect_depth_cb cb)
409 {
410  dev->depth_cb = cb;
411 }
412 
413 void freenect_set_depth_raw_callback(freenect_device *dev, freenect_depth_raw_cb cb)
414 {
415  dev->depth_raw_cb = cb;
416 }
417 
418 void freenect_set_rgb_callback(freenect_device *dev, freenect_rgb_cb cb)
419 {
420  dev->rgb_cb = cb;
421 }
422 
423 int freenect_set_rgb_format(freenect_device *dev, freenect_rgb_format fmt)
424 {
425  dev->rgb_format = fmt;
426  return 0;
427 }
428 
429 int freenect_set_depth_format(freenect_device *dev, freenect_depth_format fmt)
430 {
431  dev->depth_format = fmt;
432  return 0;
433 }