Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cv.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 
28 #include <stdlib.h> // for malloc
29 #include <stdio.h>
30 
31 #include "cv.h"
32 #include "rt_priority.h"
33 
34 
35 void cv_attach_listener(struct video_config_t *device, struct video_listener *new_listener);
36 void cv_async_function(struct cv_async *async, struct image_t *img);
37 void *cv_async_thread(void *args);
38 
39 
40 static inline uint32_t timeval_diff(struct timeval *A, struct timeval *B) {
41  return (B->tv_sec - A->tv_sec) * 1000000 + (B->tv_usec - A->tv_usec);
42 }
43 
44 
46 {
47  // Create a new video listener
48  struct video_listener *new_listener = malloc(sizeof(struct video_listener));
49 
50  // Assign function to listener
51  new_listener->active = true;
52  new_listener->func = func;
53  new_listener->next = NULL;
54  new_listener->async = NULL;
55  new_listener->maximum_fps = 0;
56 
57  // Initialise the device that we want our function to use
58  add_video_device(device);
59 
60  // Check if device already has a listener
61  if (device->cv_listener == NULL) {
62  // Add as first listener
63  device->cv_listener = new_listener;
64  } else {
65  // Create pointer to first listener
66  struct video_listener *listener = device->cv_listener;
67 
68  // Loop through linked list to last listener
69  while (listener->next != NULL)
70  listener = listener->next;
71 
72  // Add listener to end
73  listener->next = new_listener;
74  }
75 
76  return new_listener;
77 }
78 
79 
80 struct video_listener *cv_add_to_device_async(struct video_config_t *device, cv_function func, int nice_level) {
81  // Create a normal listener
82  struct video_listener *listener = cv_add_to_device(device, func);
83 
84  // Add asynchronous structure to override default synchronous behavior
85  listener->async = malloc(sizeof(struct cv_async));
86  listener->async->thread_priority = nice_level;
87 
88  // Explicitly mark img_copy as uninitialized
89  listener->async->img_copy.buf_size = 0;
90 
91  // Initialize mutex and condition variable
92  pthread_mutex_init(&listener->async->img_mutex, NULL);
93  pthread_cond_init(&listener->async->img_available, NULL);
94 
95  // Create new processing thread
96  pthread_create(&listener->async->thread_id, NULL, cv_async_thread, listener);
97 
98  return listener;
99 }
100 
101 
102 void cv_async_function(struct cv_async *async, struct image_t *img) {
103  // If the previous image is not yet processed, return
104  if (pthread_mutex_trylock(&async->img_mutex) != 0 || !async->img_processed) {
105  return;
106  }
107 
108  // If the image has not been initialized, do it
109  if (async->img_copy.buf_size == 0) {
110  image_create(&async->img_copy, img->w, img->h, img->type);
111  }
112 
113  // Copy image
114  image_copy(img, &async->img_copy);
115 
116  // Inform thread of new image
117  async->img_processed = false;
118  pthread_cond_signal(&async->img_available);
119  pthread_mutex_unlock(&async->img_mutex);
120 }
121 
122 
123 void *cv_async_thread(void *args) {
124  struct video_listener *listener = args;
125  struct cv_async *async = listener->async;
126  async->thread_running = true;
127 
129 
130  // Request new image from video thread
131  pthread_mutex_lock(&async->img_mutex);
132  async->img_processed = true;
133 
134  while (async->thread_running) {
135  // Wait for img available signal
136  pthread_cond_wait(&async->img_available, &async->img_mutex);
137 
138  // Img might have been processed already (spurious wake-ups)
139  if (async->img_processed) {
140  continue;
141  }
142 
143  // Execute vision function from this thread
144  listener->func(&async->img_copy);
145 
146  // Mark image as processed
147  async->img_processed = true;
148  }
149 
150  pthread_mutex_unlock(&async->img_mutex);
151  pthread_exit(NULL);
152 }
153 
154 
155 void cv_run_device(struct video_config_t *device, struct image_t *img)
156 {
157  struct image_t *result;
158 
159  // Loop through computer vision pipeline
160  for (struct video_listener *listener = device->cv_listener; listener != NULL; listener = listener->next) {
161  // If the listener is not active, skip it
162  if (!listener->active) {
163  continue;
164  }
165 
166  // If the desired frame time for this listener is not reached, skip it
167  if (listener->maximum_fps > 0 && timeval_diff(&listener->ts, &img->ts) < (1000000 / listener->maximum_fps)) {
168  continue;
169  }
170 
171  // Store timestamp
172  listener->ts = img->ts;
173 
174  if (listener->async != NULL) {
175  // Send image to asynchronous thread
177  } else {
178  // Execute the cvFunction and catch result
179  result = listener->func(img);
180 
181  // If result gives an image pointer, use it in the next stage
182  if (result != NULL)
183  img = result;
184  }
185  }
186 }
struct video_listener * cv_add_to_device_async(struct video_config_t *device, cv_function func, int nice_level)
Definition: cv.c:80
volatile bool active
Definition: cv.h:59
pthread_t thread_id
Definition: cv.h:42
uint32_t buf_size
The buffer size.
Definition: image.h:50
volatile bool thread_running
Definition: cv.h:43
uint16_t maximum_fps
Definition: cv.h:58
struct cv_async * async
Definition: cv.h:53
void cv_attach_listener(struct video_config_t *device, struct video_listener *new_listener)
struct video_listener * cv_add_to_device(struct video_config_t *device, cv_function func)
Definition: cv.c:45
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
Definition: image.h:42
void image_copy(struct image_t *input, struct image_t *output)
Copy an image from inut to output This will only work if the formats are the same.
Definition: image.c:77
#define B
Functions to obtain rt priority or set the nice level.
struct video_listener * listener
Definition: colorfilter.c:32
struct video_listener * cv_listener
The first computer vision listener in the linked list for this video device.
Definition: video_device.h:55
uint16_t w
Image width.
Definition: image.h:44
unsigned long uint32_t
Definition: types.h:18
Computer vision framework for onboard processing.
uint16_t h
Image height.
Definition: image.h:45
volatile int thread_priority
Definition: cv.h:44
bool add_video_device(struct video_config_t *device)
Definition: video_thread.c:189
static uint32_t timeval_diff(struct timeval *A, struct timeval *B)
Definition: cv.c:40
pthread_cond_t img_available
Definition: cv.h:46
struct timeval ts
Definition: cv.h:54
struct image_t *(* cv_function)(struct image_t *img)
Definition: cv.h:39
void cv_run_device(struct video_config_t *device, struct image_t *img)
Definition: cv.c:155
volatile bool img_processed
Definition: cv.h:47
struct timeval ts
The timestamp of creation.
Definition: image.h:46
void * cv_async_thread(void *args)
Definition: cv.c:123
cv_function func
Definition: cv.h:55
pthread_mutex_t img_mutex
Definition: cv.h:45
void cv_async_function(struct cv_async *async, struct image_t *img)
Definition: cv.c:102
#define A
struct video_listener * next
Definition: cv.h:52
struct image_t img_copy
Definition: cv.h:48
static int set_nice_level(int level)
Definition: rt_priority.h:69
Definition: cv.h:41
V4L2 device settings.
Definition: video_device.h:44
enum image_type type
The image type.
Definition: image.h:43