Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
video_thread.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2015
3 *
4 * This file is part of Paparazzi.
5 *
6 * Paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21 
26 // Own header
28 
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <math.h>
37 
38 // Video
39 #include "lib/v4l/v4l2.h"
40 #include "lib/vision/image.h"
41 #include "lib/vision/bayer.h"
42 
43 #include "mcu_periph/sys_time.h"
44 
45 // include board for bottom_camera and front_camera on ARDrone2 and Bebop
46 #include BOARD_CONFIG
47 
48 // Bebop uses ISP
49 #ifdef BOARD_BEBOP
50 #include "lib/isp/libisp.h"
51 #endif
52 
53 // Threaded computer vision
54 #include <pthread.h>
55 #include "rt_priority.h"
56 
57 // Frames Per Seconds
58 #ifndef VIDEO_THREAD_NICE_LEVEL
59 #define VIDEO_THREAD_NICE_LEVEL 5
60 #endif
61 PRINT_CONFIG_VAR(VIDEO_THREAD_NICE_LEVEL)
62 
63 // The amount of cameras we can have
64 #ifndef VIDEO_THREAD_MAX_CAMERAS
65 #define VIDEO_THREAD_MAX_CAMERAS 4
66 #endif
67 PRINT_CONFIG_VAR(VIDEO_THREAD_MAX_CAMERAS)
68 
70 
71 // Main thread
72 static void *video_thread_function(void *data);
73 static bool initialize_camera(struct video_config_t *camera);
74 static void start_video_thread(struct video_config_t *camera);
75 static void stop_video_thread(struct video_config_t *device);;
76 
78 {
79  /* currently no direct periodic functionality */
80 }
81 
82 
87 static void *video_thread_function(void *data)
88 {
89  struct video_config_t *vid = (struct video_config_t *)data;
90 
91  char print_tag[80];
92  snprintf(print_tag, 80, "video_thread-%s", vid->dev_name);
93 
94  struct image_t img_color;
95 
96  // create the images
97  if (vid->filters & VIDEO_FILTER_DEBAYER) {
98  // fixme: don't hardcode size, works for bebop front camera for now
99 #define IMG_FLT_SIZE 272
101  }
102 
103  // Start the streaming of the V4L2 device
104  if (!v4l2_start_capture(vid->thread.dev)) {
105  fprintf(stderr, "[%s] Could not start capture.\n", print_tag);
106  return 0;
107  }
108 
109 #ifdef BOARD_BEBOP
110  // Configure ISP if needed
111  if (vid->filters & VIDEO_FILTER_ISP) {
112  configure_isp(vid->thread.dev);
113  }
114 #endif
115 
116  // be nice to the more important stuff
118  fprintf(stdout, "[%s] Set nice level to %i.\n", print_tag, VIDEO_THREAD_NICE_LEVEL);
119 
120  // Initialize timing
121  struct timespec time_now;
122  struct timespec time_prev;
123  clock_gettime(CLOCK_MONOTONIC, &time_prev);
124 
125  // Start streaming
126  vid->thread.is_running = true;
127  while (vid->thread.is_running) {
128 
129  // get time in us since last run
130  clock_gettime(CLOCK_MONOTONIC, &time_now);
131  uint32_t dt_us = sys_time_elapsed_us(&time_prev, &time_now);
132  time_prev = time_now;
133 
134  // sleep remaining time to limit to specified fps
135  if (vid->fps != 0) {
136  uint32_t fps_period_us = 1000000 / vid->fps;
137  if (dt_us < fps_period_us) {
138  usleep(fps_period_us - dt_us);
139  } else {
140  fprintf(stderr, "[%s] desired %i fps, only managing %.1f fps\n", print_tag, vid->fps, 1000000.f / dt_us);
141  }
142  }
143 
144  // Wait for a new frame (blocking)
145  struct image_t img;
146  v4l2_image_get(vid->thread.dev, &img);
147 
148  // pointer to the final image to pass for saving and further processing
149  struct image_t *img_final = &img;
150 
151  // run selected filters
152  if (vid->filters & VIDEO_FILTER_DEBAYER) {
153  BayerToYUV(&img, &img_color, 0, 0);
154  // use color image for further processing
155  img_final = &img_color;
156  }
157 
158  // Run processing if required
159  cv_run_device(vid, img_final);
160 
161  // Free the image
162  v4l2_image_free(vid->thread.dev, &img);
163  }
164 
165  image_free(&img_color);
166 
167  return 0;
168 }
169 
170 static bool initialize_camera(struct video_config_t *camera)
171 {
172  // Initialize the V4L2 subdevice if needed
173  if (camera->subdev_name != NULL) {
174  // FIXME! add subdev format to config, only needed on bebop front camera so far
175  if (!v4l2_init_subdev(camera->subdev_name, 0, camera->subdev_format, camera->sensor_size)) {
176  printf("[video_thread] Could not initialize the %s subdevice.\n", camera->subdev_name);
177  return false;
178  }
179  }
180 
181  // Initialize the V4L2 device
182  camera->thread.dev = v4l2_init(camera->dev_name, camera->output_size, camera->crop, camera->buf_cnt, camera->format);
183  if (camera->thread.dev == NULL) {
184  printf("[video_thread] Could not initialize the %s V4L2 device.\n", camera->dev_name);
185  return false;
186  }
187 
188  // Initialize OK
189  return true;
190 }
191 
192 /*
193  * Add a new video device to the list
194  */
195 bool add_video_device(struct video_config_t *device)
196 {
197  // Loop over camera array
198  for (int i = 0; i < VIDEO_THREAD_MAX_CAMERAS; ++i) {
199  // If device is already registered, break
200  if (cameras[i] == device) {
201  break;
202  }
203 
204  // If camera slot is already used, continue
205  if (cameras[i] != NULL) {
206  continue;
207  }
208 
209  // Initialize the camera
210  if (!initialize_camera(device)) {
211  return false;
212  }
213 
214  // Store device pointer
215  cameras[i] = device;
216 
217  // Debug statement
218  printf("[video_thread] Added %s to camera array.\n", device->dev_name);
219 
220  // Successfully initialized
221  return true;
222  }
223 
224  // Camera array is full
225  return false;
226 }
227 
228 /*
229  * Start a new video thread for a camera
230  */
231 static void start_video_thread(struct video_config_t *camera)
232 {
233  if (!camera->thread.is_running) {
234  // Start the streaming thread for a camera
235  pthread_t tid;
236  if (pthread_create(&tid, NULL, video_thread_function, (void *)(camera)) != 0) {
237  printf("[viewvideo] Could not create streaming thread for camera %s: Reason: %d.\n", camera->dev_name, errno);
238  return;
239  }
240  }
241 }
242 
243 /*
244  * Stop a video thread for a camera
245  */
246 static void stop_video_thread(struct video_config_t *device)
247 {
248  if (device->thread.is_running) {
249  // Stop the streaming thread
250  device->thread.is_running = false;
251 
252  // Stop the capturing
253  if (!v4l2_stop_capture(device->thread.dev)) {
254  printf("[video_thread] Could not stop capture of %s.\n", device->thread.dev->name);
255  return;
256  }
257  }
258 
259 }
260 
265 {
266 }
267 
272 {
273  // Start every known camera device
274  for (int indexCameras = 0; indexCameras < VIDEO_THREAD_MAX_CAMERAS; indexCameras++) {
275  if (cameras[indexCameras] != NULL) {
276  start_video_thread(cameras[indexCameras]);
277  }
278  }
279 }
280 
281 
287 {
288  for (int indexCameras = 0; indexCameras < VIDEO_THREAD_MAX_CAMERAS; indexCameras++) {
289  if (cameras[indexCameras] != NULL) {
290  stop_video_thread(cameras[indexCameras]);
291  }
292  }
293 
294  // TODO: wait for the thread to finish to be able to start the thread again!
295 }
uint32_t format
Video format.
Definition: video_device.h:50
struct crop_t crop
Cropped area definition.
Definition: video_device.h:47
void v4l2_image_free(struct v4l2_device *dev, struct image_t *img)
Free the image and enqueue the buffer (Thread safe) This must be done after processing the image...
Definition: v4l2.c:406
struct img_size_t output_size
Output image size.
Definition: video_device.h:45
void v4l2_image_get(struct v4l2_device *dev, struct image_t *img)
Get the latest image buffer and lock it (Thread safe, BLOCKING) This functions blocks until image acc...
Definition: v4l2.c:332
void image_free(struct image_t *img)
Free the image.
Definition: image.c:63
Capture images from a V4L2 device (Video for Linux 2)
static struct video_config_t * cameras[VIDEO_THREAD_MAX_CAMERAS]
Definition: video_thread.c:69
void image_create(struct image_t *img, uint16_t width, uint16_t height, enum image_type type)
Create a new image.
Definition: image.c:38
Start a Video thread and grab images.
Definition: image.h:43
void video_thread_stop()
Stops the streaming of all cameras This could take some time, because the thread is stopped asynchron...
Definition: video_thread.c:286
char * dev_name
path to device
Definition: video_device.h:48
uint8_t filters
filters to use (bitfield with VIDEO_FILTER_x)
Definition: video_device.h:53
struct v4l2_device * v4l2_init(char *device_name, struct img_size_t size, struct crop_t crop, uint8_t buffers_cnt, uint32_t _pixelformat)
Initialize a V4L2(Video for Linux 2) device.
Definition: v4l2.c:183
Functions to obtain rt priority or set the nice level.
uint8_t buf_cnt
Amount of V4L2 video device buffers.
Definition: video_device.h:52
bool v4l2_stop_capture(struct v4l2_device *dev)
Stop capturing of the image stream (Thread safe) This function is blocking until capturing thread is ...
Definition: v4l2.c:486
Image helper functions like resizing, color filter, converters...
int configure_isp(struct v4l2_device *dev)
Definition: libisp.c:163
static void start_video_thread(struct video_config_t *camera)
Definition: video_thread.c:231
Architecture independent timing functions.
struct img_size_t sensor_size
Original sensor size.
Definition: video_device.h:46
void video_thread_init(void)
Initialize the view video.
Definition: video_thread.c:264
void BayerToYUV(struct image_t *Input, struct image_t *out, int RedX, int RedY)
Decode Bayer Pattern.
Definition: bayer.h:55
unsigned long uint32_t
Definition: types.h:18
char * subdev_name
path to sub device
Definition: video_device.h:49
static unsigned int sys_time_elapsed_us(struct timespec *prev, struct timespec *now)
elapsed time in microsecs between two timespecs
Definition: sys_time_arch.h:53
#define VIDEO_FILTER_DEBAYER
Enable software debayer.
Definition: video_device.h:34
static void * video_thread_function(void *data)
Handles all the video streaming and saving of the image shots This is a separate thread, so it needs to be thread safe!
Definition: video_thread.c:87
static bool initialize_camera(struct video_config_t *camera)
Definition: video_thread.c:170
int fps
Target FPS.
Definition: video_device.h:56
void video_thread_start()
Starts the streaming of a all cameras.
Definition: video_thread.c:271
char * name
The name of the device.
Definition: v4l2.h:50
void cv_run_device(struct video_config_t *device, struct image_t *img)
Definition: cv.c:162
#define VIDEO_FILTER_ISP
Enable ISP.
Definition: video_device.h:35
bool v4l2_init_subdev(char *subdev_name, uint8_t pad, uint16_t code, struct img_size_t size)
Initialize a V4L2 subdevice.
Definition: v4l2.c:136
volatile bool is_running
When the device is running.
Definition: video_device.h:39
bool v4l2_start_capture(struct v4l2_device *dev)
Start capturing images in streaming mode (Thread safe)
Definition: v4l2.c:427
#define IMG_FLT_SIZE
UYVY format (uint16 per pixel)
Definition: image.h:36
static void stop_video_thread(struct video_config_t *device)
Definition: video_thread.c:246
struct v4l2_device * dev
The V4L2 device that is used for the video stream.
Definition: video_device.h:40
#define VIDEO_THREAD_MAX_CAMERAS
Definition: video_thread.c:65
uint32_t subdev_format
Subdevice video format.
Definition: video_device.h:51
bool add_video_device(struct video_config_t *device)
Definition: video_thread.c:195
#define VIDEO_THREAD_NICE_LEVEL
Definition: video_thread.c:59
static int set_nice_level(int level)
Definition: rt_priority.h:69
V4L2 device settings.
Definition: video_device.h:44
struct video_thread_t thread
Information about the thread this camera is running on.
Definition: video_device.h:54
void video_thread_periodic(void)
A dummy for now.
Definition: video_thread.c:77