1 /*
2 * Copyright (C) 2004 Nathan Lutchansky <lutchann@litech.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include <config.h>
20
21 #include <sys/types.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <pthread.h>
28
29 #include <libraw1394/raw1394.h>
30 #include <libdc1394/dc1394_control.h>
31
32 #include <event.h>
33 #include <log.h>
34 #include <frame.h>
35 #include <stream.h>
36 #include <inputs.h>
37 #include <conf_parse.h>
38
39 #define WIDTH 320
40 #define HEIGHT 240
41
42 struct dc1394_cam {
43 raw1394handle_t handle;
44 int running;
45 struct soft_queue *outq;
46 struct stream *output;
47 };
48
49 struct dc1394_input {
50 struct dc1394_cam cam[16];
51 dc1394_cameracapture camera[16];
52 int cam_count;
53 pthread_t thread;
54 };
55
capture_loop(void * d)56 static void *capture_loop( void *d )
57 {
58 struct dc1394_input *conf = (struct dc1394_input *)d;
59 struct frame *f;
60 int cam;
61
62 for(;;)
63 {
64 dc1394_dma_multi_capture( conf->camera, conf->cam_count );
65 for( cam = 0; cam < conf->cam_count; ++cam )
66 {
67 if( conf->cam[cam].running && ( f = new_frame() ) )
68 {
69 f->length = HEIGHT * WIDTH * 2;
70 f->format = FORMAT_RAW_UYVY;
71 f->width = WIDTH;
72 f->height = HEIGHT;
73 f->key = 1;
74
75 memcpy( f->d, conf->camera[cam].capture_buffer,
76 f->length );
77
78 if( soft_queue_add( conf->cam[cam].outq, f ) < 0 )
79 unref_frame( f );
80 }
81 dc1394_dma_done_with_buffer( &conf->camera[cam] );
82 }
83 }
84
85 return NULL;
86 }
87
get_back_frame(struct event_info * ei,void * d)88 static void get_back_frame( struct event_info *ei, void *d )
89 {
90 struct dc1394_cam *cam = (struct dc1394_cam *)d;
91 struct frame *f = (struct frame *)ei->data;
92
93 deliver_frame_to_stream( f, cam->output );
94 }
95
cam_setup(struct dc1394_input * conf,int cam,int port,nodeid_t node,int dma_chan)96 static int cam_setup( struct dc1394_input *conf, int cam, int port,
97 nodeid_t node, int dma_chan )
98 {
99 unsigned int channel;
100 unsigned int speed;
101
102 conf->cam[cam].running = 0;
103 conf->camera[cam].node = node;
104 conf->cam[cam].handle = dc1394_create_handle( port );
105 if( ! conf->cam[cam].handle )
106 {
107 spook_log( SL_ERR, "dc1394: unable to create a camera handle" );
108 return -1;
109 }
110 if( dc1394_get_iso_channel_and_speed( conf->cam[cam].handle, node,
111 &channel, &speed ) != DC1394_SUCCESS )
112 {
113 spook_log( SL_ERR, "dc1394: unable to create an ISO channel" );
114 return -1;
115 }
116
117 if( dc1394_dma_setup_capture( conf->cam[cam].handle, node, dma_chan,
118 FORMAT_VGA_NONCOMPRESSED, MODE_320x240_YUV422,
119 SPEED_400, FRAMERATE_30, 8 /* num buffers */,
120 #ifdef DC1394_EXTRA_BUFFERING_FLAG
121 0 /* do_extra_buffering */,
122 #endif
123 1 /* drop frames */, NULL /* device name */,
124 &conf->camera[cam] ) != DC1394_SUCCESS )
125 {
126 spook_log( SL_ERR, "dc1394: unable to set up DMA for camera" );
127 return -1;
128 }
129 if( dc1394_start_iso_transmission( conf->cam[cam].handle,
130 conf->camera[cam].node ) != DC1394_SUCCESS )
131 {
132 spook_log( SL_ERR,
133 "dc1394: unable to start ISO transfer from camera" );
134 return -1;
135 }
136 conf->cam[cam].outq = new_soft_queue( 16 );
137 add_softqueue_event( conf->cam[cam].outq, 0,
138 get_back_frame, &conf->cam[cam] );
139 return 0;
140 }
141
dc1394_setup(struct dc1394_input * conf)142 static int dc1394_setup( struct dc1394_input *conf )
143 {
144 raw1394handle_t raw_handle;
145 nodeid_t *camera_nodes = NULL;
146 int numPorts;
147 int actual_count = 0, c, i;
148 struct raw1394_portinfo ports[16];
149
150 raw_handle = raw1394_new_handle();
151 if( ! raw_handle )
152 {
153 spook_log( SL_ERR,
154 "dc1394: unable to acquire a raw1394 handle" );
155 return -1;
156 }
157
158 numPorts = raw1394_get_port_info( raw_handle, ports, 16 );
159 raw1394_destroy_handle( raw_handle );
160 for( i = 0; i < numPorts; ++i )
161 {
162 int camCount = 0;
163
164 raw_handle = raw1394_new_handle();
165 raw1394_set_port( raw_handle, i );
166 camera_nodes = dc1394_get_camera_nodes( raw_handle,
167 &camCount, 1 );
168 raw1394_destroy_handle( raw_handle );
169 spook_log( SL_INFO, "dc1394: found %d cams on port %d",
170 camCount, i );
171 for( c = 0; c < camCount; ++c )
172 {
173 if( cam_setup( conf, actual_count, i,
174 camera_nodes[c], c ) < 0 )
175 return -1;
176 if( ++actual_count == conf->cam_count ) return 0;
177 }
178 // this doesn't work, fix later (just a li'l memory leak...)
179 //dc1394_free_camera_nodes( camera_nodes );
180 }
181
182 if( actual_count == 0 )
183 {
184 spook_log( SL_ERR, "dc1394: did not find any IIDC cameras" );
185 return -1;
186 }
187
188 if( actual_count < conf->cam_count )
189 spook_log( SL_WARN,
190 "dc1394: only found %d cameras, some outputs will be inactive",
191 actual_count );
192
193 return 0;
194 }
195
get_framerate(struct stream * s,int * fincr,int * fbase)196 static void get_framerate( struct stream *s, int *fincr, int *fbase )
197 {
198 struct dc1394_cam *cam = (struct dc1394_cam *)s->private;
199
200 *fincr = 1;
201 *fbase = 30;
202 }
203
set_running(struct stream * s,int running)204 static void set_running( struct stream *s, int running )
205 {
206 struct dc1394_cam *cam = (struct dc1394_cam *)s->private;
207
208 cam->running = running;
209 }
210
211 #if 0
212 void dc1394_close(void)
213 {
214 fprintf( stderr, "closing down..." );
215 dc1394_dma_unlisten( handle, &camera );
216 dc1394_dma_release_camera( handle, &camera );
217 dc1394_destroy_handle( handle );
218 fprintf( stderr, "done!\n" );
219 }
220 #endif
221
222 /************************ CONFIGURATION DIRECTIVES ************************/
223
start_block(void)224 static void *start_block(void)
225 {
226 struct dc1394_input *conf;
227
228 conf = (struct dc1394_input *)malloc( sizeof( struct dc1394_input ) );
229 conf->cam_count = 0;
230
231 return conf;
232 }
233
end_block(void * d)234 static int end_block( void *d )
235 {
236 struct dc1394_input *conf = (struct dc1394_input *)d;
237
238 if( conf->cam_count == 0 )
239 {
240 spook_log( SL_ERR, "dc1394: missing output stream name" );
241 return -1;
242 }
243 if( dc1394_setup( conf ) < 0 )
244 {
245 spook_log( SL_ERR, "dc1394: unable to initialize video input" );
246 return -1;
247 }
248 pthread_create( &conf->thread, NULL, capture_loop, conf );
249
250 return 0;
251 }
252
set_output(int num_tokens,struct token * tokens,void * d)253 static int set_output( int num_tokens, struct token *tokens, void *d )
254 {
255 struct dc1394_input *conf = (struct dc1394_input *)d;
256
257 conf->cam[conf->cam_count].output = new_stream( tokens[1].v.str,
258 FORMAT_RAW_UYVY, &conf->cam[conf->cam_count] );
259 if( ! conf->cam[conf->cam_count].output )
260 {
261 spook_log( SL_ERR, "dc1394: unable to create stream \"%s\"",
262 tokens[1].v.str );
263 return -1;
264 }
265 conf->cam[conf->cam_count].output->get_framerate = get_framerate;
266 conf->cam[conf->cam_count].output->set_running = set_running;
267 ++conf->cam_count;
268 return 0;
269 }
270
271 static struct statement config_statements[] = {
272 /* directive name, process function, min args, max args, arg types */
273 { "output", set_output, 1, 1, { TOKEN_STR } },
274
275 /* empty terminator -- do not remove */
276 { NULL, NULL, 0, 0, {} }
277 };
278
dc1394_init(void)279 void dc1394_init(void)
280 {
281 register_config_context( "input", "dc1394", start_block, end_block,
282 config_statements );
283 }
284