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
viewvideo.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2014 The Paparazzi Community
3  * 2015 Freek van Tienen <freek.v.tienen@gmail.com>
4  *
5  * This file is part of Paparazzi.
6  *
7  * Paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * Paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, see
19  * <http://www.gnu.org/licenses/>.
20  *
21  */
22 
32 // Own header
35 
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <sys/time.h>
41 #include <math.h>
42 
43 // Video
44 #include "lib/vision/image.h"
45 #include "lib/encoding/jpeg.h"
46 #include "lib/encoding/rtp.h"
47 #include "udp_socket.h"
48 
49 #include BOARD_CONFIG
50 
51 
52 // Downsize factor for video stream
53 #ifndef VIEWVIDEO_DOWNSIZE_FACTOR
54 #define VIEWVIDEO_DOWNSIZE_FACTOR 4
55 #endif
56 PRINT_CONFIG_VAR(VIEWVIDEO_DOWNSIZE_FACTOR)
57 
58 // From 0 to 99 (99=high)
59 #ifndef VIEWVIDEO_QUALITY_FACTOR
60 #define VIEWVIDEO_QUALITY_FACTOR 50
61 #endif
62 PRINT_CONFIG_VAR(VIEWVIDEO_QUALITY_FACTOR)
63 
64 // RTP time increment at 90kHz (default: 0 for automatic)
65 #ifndef VIEWVIDEO_RTP_TIME_INC
66 #define VIEWVIDEO_RTP_TIME_INC 0
67 #endif
68 PRINT_CONFIG_VAR(VIEWVIDEO_RTP_TIME_INC)
69 
70 // Default image folder
71 #ifndef VIEWVIDEO_SHOT_PATH
72 #ifdef VIDEO_THREAD_SHOT_PATH
73 #define VIEWVIDEO_SHOT_PATH VIDEO_THREAD_SHOT_PATH
74 #else
75 #define VIEWVIDEO_SHOT_PATH /data/video/images
76 #endif
77 #endif
78 PRINT_CONFIG_VAR(VIEWVIDEO_SHOT_PATH)
79 
80 // Define stream framerate
81 #ifndef VIEWVIDEO_FPS
82 #define VIEWVIDEO_FPS 10
83 #endif
84 PRINT_CONFIG_VAR(VIEWVIDEO_FPS)
85 
86 // Define stream priority
87 #ifndef VIEWVIDEO_NICE_LEVEL
88 #define VIEWVIDEO_NICE_LEVEL 5
89 #endif
90 PRINT_CONFIG_VAR(VIEWVIDEO_FPS)
91 
92 // Check if we are using netcat instead of RTP/UDP
93 #ifndef VIEWVIDEO_USE_NETCAT
94 #define VIEWVIDEO_USE_NETCAT FALSE
95 #endif
96 
97 #if !VIEWVIDEO_USE_NETCAT && !(defined VIEWVIDEO_USE_RTP)
98 #define VIEWVIDEO_USE_RTP TRUE
99 #endif
100 
101 #if VIEWVIDEO_USE_NETCAT
102 #include <sys/wait.h>
103 PRINT_CONFIG_MSG("[viewvideo] Using netcat.")
104 #else
106 PRINT_CONFIG_MSG("[viewvideo] Using RTP/UDP stream.")
107 PRINT_CONFIG_VAR(VIEWVIDEO_USE_RTP)
108 #endif
109 
110 /* These are defined with configure */
111 PRINT_CONFIG_VAR(VIEWVIDEO_HOST)
112 PRINT_CONFIG_VAR(VIEWVIDEO_PORT_OUT)
113 
114 // Initialize the viewvideo structure with the defaults
116  .is_streaming = FALSE,
117  .downsize_factor = VIEWVIDEO_DOWNSIZE_FACTOR,
118  .quality_factor = VIEWVIDEO_QUALITY_FACTOR,
119 #if !VIEWVIDEO_USE_NETCAT
120  .use_rtp = VIEWVIDEO_USE_RTP,
121 #endif
122 };
123 
128 struct image_t *viewvideo_function(struct image_t *img);
129 struct image_t *viewvideo_function(struct image_t *img)
130 {
131  // Resize image if needed
132  struct image_t img_small;
133  image_create(&img_small,
134  img->w / viewvideo.downsize_factor,
135  img->h / viewvideo.downsize_factor,
136  IMAGE_YUV422);
137 
138  // Create the JPEG encoded image
139  struct image_t img_jpeg;
140  image_create(&img_jpeg, img_small.w, img_small.h, IMAGE_JPEG);
141 
142 #if VIEWVIDEO_USE_NETCAT
143  char nc_cmd[64];
144  sprintf(nc_cmd, "nc %s %d 2>/dev/null", STRINGIFY(VIEWVIDEO_HOST), VIEWVIDEO_PORT_OUT);
145 #endif
146 
147  if (viewvideo.is_streaming) {
148 
149  // Only resize when needed
150  if (viewvideo.downsize_factor != 1) {
153  } else {
155  }
156 
157 #if VIEWVIDEO_USE_NETCAT
158  // Open process to send using netcat (in a fork because sometimes kills itself???)
159  pid_t pid = fork();
160 
161  if (pid < 0) {
162  printf("[viewvideo] Could not create netcat fork.\n");
163  } else if (pid == 0) {
164  // We are the child and want to send the image
165  FILE *netcat = popen(nc_cmd, "w");
166  if (netcat != NULL) {
167  fwrite(img_jpeg.buf, sizeof(uint8_t), img_jpeg.buf_size, netcat);
168  pclose(netcat); // Ignore output, because it is too much when not connected
169  } else {
170  printf("[viewvideo] Failed to open netcat process.\n");
171  }
172 
173  // Exit the program since we don't want to continue after transmitting
174  exit(0);
175  } else {
176  // We want to wait until the child is finished
177  wait(NULL);
178  }
179 #else
180  if (viewvideo.use_rtp) {
181 
182  // Send image with RTP
184  &video_sock, // UDP socket
185  &img_jpeg,
186  0, // Format 422
187  VIEWVIDEO_QUALITY_FACTOR, // Jpeg-Quality
188  0, // DRI Header
189  VIEWVIDEO_RTP_TIME_INC // 90kHz time increment
190  );
191  // Extra note: when the time increment is set to 0,
192  // it is automaticaly calculated by the send_rtp_frame function
193  // based on gettimeofday value. This seems to introduce some lag or jitter.
194  // An other way is to compute the time increment and set the correct value.
195  // It seems that a lower value is also working (when the frame is received
196  // the timestamp is always "late" so the frame is displayed immediately).
197  // Here, we set the time increment to the lowest possible value
198  // (1 = 1/90000 s) which is probably stupid but is actually working.
199  }
200 #endif
201 
202  }
203 
204  // Free all buffers
205  image_free(&img_jpeg);
206  image_free(&img_small);
207  return NULL; // No new images were created
208 }
209 
213 void viewvideo_init(void)
214 {
215  char save_name[512];
216 
218  listener->maximum_fps = VIEWVIDEO_FPS;
219 
220  viewvideo.is_streaming = true;
221 
222 #if VIEWVIDEO_USE_NETCAT
223  // Create an Netcat receiver file for the streaming
224  sprintf(save_name, "%s/netcat-recv.sh", STRINGIFY(VIEWVIDEO_SHOT_PATH));
225  FILE *fp = fopen(save_name, "w");
226  if (fp != NULL) {
227  fprintf(fp, "i=0\n");
228  fprintf(fp, "while true\n");
229  fprintf(fp, "do\n");
230  fprintf(fp, "\tn=$(printf \"%%04d\" $i)\n");
231  fprintf(fp, "\tnc -l 0.0.0.0 %d > img_${n}.jpg\n", (int)(VIEWVIDEO_PORT_OUT));
232  fprintf(fp, "\ti=$((i+1))\n");
233  fprintf(fp, "done\n");
234  fclose(fp);
235  } else {
236  printf("[viewvideo] Failed to create netcat receiver file.\n");
237  }
238 #else
239  // Open udp socket
240  udp_socket_create(&video_sock, STRINGIFY(VIEWVIDEO_HOST), VIEWVIDEO_PORT_OUT, -1, VIEWVIDEO_BROADCAST);
241 
242  // Create an SDP file for the streaming
243  sprintf(save_name, "%s/stream.sdp", STRINGIFY(VIEWVIDEO_SHOT_PATH));
244  FILE *fp = fopen(save_name, "w");
245  if (fp != NULL) {
246  fprintf(fp, "v=0\n");
247  fprintf(fp, "m=video %d RTP/AVP 26\n", (int)(VIEWVIDEO_PORT_OUT));
248  fprintf(fp, "c=IN IP4 0.0.0.0\n");
249  fclose(fp);
250  } else {
251  printf("[viewvideo] Failed to create SDP file.\n");
252  }
253 #endif
254 }
255 
struct video_listener * cv_add_to_device_async(struct video_config_t *device, cv_function func, int nice_level)
Definition: cv.c:80
uint32_t buf_size
The buffer size.
Definition: image.h:50
struct viewvideo_t viewvideo
Definition: viewvideo.c:115
bool use_rtp
Stream over RTP.
Definition: viewvideo.h:42
void image_yuv422_downsample(struct image_t *input, struct image_t *output, uint16_t downsample)
Simplified high-speed low CPU downsample function without averaging downsample factor must be 1...
Definition: image.c:213
#define VIEWVIDEO_RTP_TIME_INC
Definition: viewvideo.c:66
uint16_t maximum_fps
Definition: cv.h:58
#define VIEWVIDEO_QUALITY_FACTOR
Definition: viewvideo.c:60
#define VIEWVIDEO_DOWNSIZE_FACTOR
Definition: viewvideo.c:54
void image_free(struct image_t *img)
Free the image.
Definition: image.c:63
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
Easily create and use UDP sockets.
Definition: image.h:42
#define VIEWVIDEO_SHOT_PATH
Definition: viewvideo.c:75
#define VIEWVIDEO_FPS
Definition: viewvideo.c:82
#define VIEWVIDEO_USE_NETCAT
Definition: viewvideo.c:94
void rtp_frame_send(struct UdpSocket *udp, struct image_t *img, uint8_t format_code, uint8_t quality_code, uint8_t has_dri_header, uint32_t delta_t)
Send an RTP frame.
Definition: rtp.c:97
#define FALSE
Definition: std.h:5
struct video_listener * listener
Definition: colorfilter.c:32
Image helper functions like resizing, color filter, converters...
uint16_t w
Image width.
Definition: image.h:44
Computer vision framework for onboard processing.
uint16_t h
Image height.
Definition: image.h:45
struct UdpSocket video_sock
Definition: viewvideo.c:105
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
void * buf
Image buffer (depending on the image_type)
Definition: image.h:51
volatile bool is_streaming
When the device is streaming.
Definition: viewvideo.h:39
#define VIEWVIDEO_USE_RTP
Definition: viewvideo.c:98
#define VIEWVIDEO_NICE_LEVEL
Definition: viewvideo.c:88
Encode images with the use of the JPEG encoding.
void viewvideo_init(void)
Initialize the view video.
Definition: viewvideo.c:213
Get live images from a RTP/UDP stream and save pictures on internal memory.
unsigned char uint8_t
Definition: types.h:14
void jpeg_encode_image(struct image_t *in, struct image_t *out, uint32_t quality_factor, bool add_dri_header)
Encode an YUV422 image.
Definition: jpeg.c:408
UYVY format (uint16 per pixel)
Definition: image.h:35
uint8_t downsize_factor
Downsize factor during the stream.
Definition: viewvideo.h:40
Encodes a vide stream with RTP (JPEG)
struct image_t * viewvideo_function(struct image_t *img)
Handles all the video streaming and saving of the image shots This is a sepereate thread...
Definition: viewvideo.c:129
int udp_socket_create(struct UdpSocket *sock, char *host, int port_out, int port_in, bool broadcast)
Create UDP socket and bind it.
Definition: udp_socket.c:49
An JPEG encoded image (not per pixel encoded)
Definition: image.h:37