Paparazzi UAS  v5.8.2_stable-0-g6260b7c
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 // Downsize factor for video stream
50 #ifndef VIEWVIDEO_DOWNSIZE_FACTOR
51 #define VIEWVIDEO_DOWNSIZE_FACTOR 4
52 #endif
53 PRINT_CONFIG_VAR(VIEWVIDEO_DOWNSIZE_FACTOR)
54 
55 // From 0 to 99 (99=high)
56 #ifndef VIEWVIDEO_QUALITY_FACTOR
57 #define VIEWVIDEO_QUALITY_FACTOR 50
58 #endif
59 PRINT_CONFIG_VAR(VIEWVIDEO_QUALITY_FACTOR)
60 
61 // RTP time increment at 90kHz (default: 0 for automatic)
62 #ifndef VIEWVIDEO_RTP_TIME_INC
63 #define VIEWVIDEO_RTP_TIME_INC 0
64 #endif
65 PRINT_CONFIG_VAR(VIEWVIDEO_RTP_TIME_INC)
66 
67 // Default image folder
68 #ifndef VIEWVIDEO_SHOT_PATH
69 #ifdef VIDEO_THREAD_SHOT_PATH
70 #define VIEWVIDEO_SHOT_PATH VIDEO_THREAD_SHOT_PATH
71 #else
72 #define VIEWVIDEO_SHOT_PATH /data/video/images
73 #endif
74 #endif
75 PRINT_CONFIG_VAR(VIEWVIDEO_SHOT_PATH)
76 
77 // Check if we are using netcat instead of RTP/UDP
78 #ifndef VIEWVIDEO_USE_NETCAT
79 #define VIEWVIDEO_USE_NETCAT FALSE
80 #endif
81 
82 #if !VIEWVIDEO_USE_NETCAT && !(defined VIEWVIDEO_USE_RTP)
83 #define VIEWVIDEO_USE_RTP TRUE
84 #endif
85 
86 #if VIEWVIDEO_USE_NETCAT
87 #include <sys/wait.h>
88 PRINT_CONFIG_MSG("[viewvideo] Using netcat.")
89 #else
91 PRINT_CONFIG_MSG("[viewvideo] Using RTP/UDP stream.")
92 PRINT_CONFIG_VAR(VIEWVIDEO_USE_RTP)
93 #endif
94 
95 /* These are defined with configure */
96 PRINT_CONFIG_VAR(VIEWVIDEO_HOST)
97 PRINT_CONFIG_VAR(VIEWVIDEO_PORT_OUT)
98 
99 // Initialize the viewvideo structure with the defaults
101  .is_streaming = FALSE,
102  .downsize_factor = VIEWVIDEO_DOWNSIZE_FACTOR,
103  .quality_factor = VIEWVIDEO_QUALITY_FACTOR,
104 #if !VIEWVIDEO_USE_NETCAT
105  .use_rtp = VIEWVIDEO_USE_RTP,
106 #endif
107 };
108 
113 bool_t viewvideo_function(struct image_t *img);
114 bool_t viewvideo_function(struct image_t *img)
115 {
116  // Resize image if needed
117  struct image_t img_small;
118  image_create(&img_small,
119  img->w / viewvideo.downsize_factor,
120  img->h / viewvideo.downsize_factor,
121  IMAGE_YUV422);
122 
123  // Create the JPEG encoded image
124  struct image_t img_jpeg;
125  image_create(&img_jpeg, img_small.w, img_small.h, IMAGE_JPEG);
126 
127 #if VIEWVIDEO_USE_NETCAT
128  char nc_cmd[64];
129  sprintf(nc_cmd, "nc %s %d 2>/dev/null", STRINGIFY(VIEWVIDEO_HOST), VIEWVIDEO_PORT_OUT);
130 #endif
131 
132  if (viewvideo.is_streaming) {
133 
134  // Only resize when needed
135  if (viewvideo.downsize_factor != 1) {
138  } else {
140  }
141 
142 #if VIEWVIDEO_USE_NETCAT
143  // Open process to send using netcat (in a fork because sometimes kills itself???)
144  pid_t pid = fork();
145 
146  if (pid < 0) {
147  printf("[viewvideo] Could not create netcat fork.\n");
148  } else if (pid == 0) {
149  // We are the child and want to send the image
150  FILE *netcat = popen(nc_cmd, "w");
151  if (netcat != NULL) {
152  fwrite(img_jpeg.buf, sizeof(uint8_t), img_jpeg.buf_size, netcat);
153  pclose(netcat); // Ignore output, because it is too much when not connected
154  } else {
155  printf("[viewvideo] Failed to open netcat process.\n");
156  }
157 
158  // Exit the program since we don't want to continue after transmitting
159  exit(0);
160  } else {
161  // We want to wait until the child is finished
162  wait(NULL);
163  }
164 #else
165  if (viewvideo.use_rtp) {
166 
167  // Send image with RTP
169  &video_sock, // UDP socket
170  &img_jpeg,
171  0, // Format 422
172  VIEWVIDEO_QUALITY_FACTOR, // Jpeg-Quality
173  0, // DRI Header
174  VIEWVIDEO_RTP_TIME_INC // 90kHz time increment
175  );
176  // Extra note: when the time increment is set to 0,
177  // it is automaticaly calculated by the send_rtp_frame function
178  // based on gettimeofday value. This seems to introduce some lag or jitter.
179  // An other way is to compute the time increment and set the correct value.
180  // It seems that a lower value is also working (when the frame is received
181  // the timestamp is always "late" so the frame is displayed immediately).
182  // Here, we set the time increment to the lowest possible value
183  // (1 = 1/90000 s) which is probably stupid but is actually working.
184  }
185 #endif
186 
187  }
188 
189  // Free all buffers
190  image_free(&img_jpeg);
191  image_free(&img_small);
192  return TRUE;
193 }
194 
198 void viewvideo_init(void)
199 {
200  char save_name[512];
201 
203 
205 
206 #if VIEWVIDEO_USE_NETCAT
207  // Create an Netcat receiver file for the streaming
208  sprintf(save_name, "%s/netcat-recv.sh", STRINGIFY(VIEWVIDEO_SHOT_PATH));
209  FILE *fp = fopen(save_name, "w");
210  if (fp != NULL) {
211  fprintf(fp, "i=0\n");
212  fprintf(fp, "while true\n");
213  fprintf(fp, "do\n");
214  fprintf(fp, "\tn=$(printf \"%%04d\" $i)\n");
215  fprintf(fp, "\tnc -l 0.0.0.0 %d > img_${n}.jpg\n", (int)(VIEWVIDEO_PORT_OUT));
216  fprintf(fp, "\ti=$((i+1))\n");
217  fprintf(fp, "done\n");
218  fclose(fp);
219  } else {
220  printf("[viewvideo] Failed to create netcat receiver file.\n");
221  }
222 #else
223  // Open udp socket
224  udp_socket_create(&video_sock, STRINGIFY(VIEWVIDEO_HOST), VIEWVIDEO_PORT_OUT, -1, VIEWVIDEO_BROADCAST);
225 
226  // Create an SDP file for the streaming
227  sprintf(save_name, "%s/stream.sdp", STRINGIFY(VIEWVIDEO_SHOT_PATH));
228  FILE *fp = fopen(save_name, "w");
229  if (fp != NULL) {
230  fprintf(fp, "v=0\n");
231  fprintf(fp, "m=video %d RTP/AVP 26\n", (int)(VIEWVIDEO_PORT_OUT));
232  fprintf(fp, "c=IN IP4 0.0.0.0\n");
233  fclose(fp);
234  } else {
235  printf("[viewvideo] Failed to create SDP file.\n");
236  }
237 #endif
238 }
239 
uint32_t buf_size
The buffer size.
Definition: image.h:49
struct viewvideo_t viewvideo
Definition: viewvideo.c:100
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:63
#define VIEWVIDEO_QUALITY_FACTOR
Definition: viewvideo.c:57
#define VIEWVIDEO_DOWNSIZE_FACTOR
Definition: viewvideo.c:51
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:72
volatile bool_t is_streaming
When the device is streaming.
Definition: viewvideo.h:39
#define VIEWVIDEO_USE_NETCAT
Definition: viewvideo.c:79
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
void jpeg_encode_image(struct image_t *in, struct image_t *out, uint32_t quality_factor, bool_t add_dri_header)
Encode an YUV422 image.
Definition: jpeg.c:425
Image helper functions like resizing, color filter, converters...
#define TRUE
Definition: std.h:4
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:90
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
void * buf
Image buffer (depending on the image_type)
Definition: image.h:50
#define VIEWVIDEO_USE_RTP
Definition: viewvideo.c:83
bool_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:114
void cv_add(cvFunction func)
Definition: cv.c:35
Encode images with the use of the JPEG encoding.
void viewvideo_init(void)
Initialize the view video.
Definition: viewvideo.c:198
Get live images from a RTP/UDP stream and save pictures on internal memory.
unsigned char uint8_t
Definition: types.h:14
int udp_socket_create(struct UdpSocket *sock, char *host, int port_out, int port_in, bool_t broadcast)
Create UDP socket and bind it.
Definition: udp_socket.c:49
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)
bool_t use_rtp
Stream over RTP.
Definition: viewvideo.h:42
An JPEG encoded image (not per pixel encoded)
Definition: image.h:37