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
rtp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2014 The Paparazzi Community
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 <stdint.h>
29 #include <string.h>
30 #include <sys/time.h>
31 
32 #include "rtp.h"
33 
34 static void rtp_packet_send(struct UdpSocket *udp, uint8_t *Jpeg, int JpegLen, uint32_t m_SequenceNumber,
35  uint32_t m_Timestamp, uint32_t m_offset, uint8_t marker_bit, int w, int h, uint8_t format_code, uint8_t quality_code,
36  uint8_t has_dri_header);
37 
38 // http://www.ietf.org/rfc/rfc3550.txt
39 
40 #define KJpegCh1ScanDataLen 32
41 #define KJpegCh2ScanDataLen 56
42 
43 // RGB JPEG images as RTP payload - 64x48 pixel
45  0xf8, 0xbe, 0x8a, 0x28, 0xaf, 0xe5, 0x33, 0xfd,
46  0xfc, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
47  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
48  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
49  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
50  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
51  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x3f, 0xff, 0xd9
52 };
54  0xf5, 0x8a, 0x28, 0xa2, 0xbf, 0xca, 0xf3, 0xfc,
55  0x53, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
56  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
57  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
58  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
59  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2,
60  0x80, 0x0a, 0x28, 0xa2, 0x80, 0x3f, 0xff, 0xd9
61 };
62 
67 void rtp_frame_test(struct UdpSocket *udp)
68 {
69  static uint32_t framecounter = 0;
70  static uint32_t timecounter = 0;
71  static uint8_t toggle = 0;
72  toggle = ! toggle;
73 
74  uint8_t format_code = 0x01;
75  uint8_t quality_code = 0x54;
76 
77  if (toggle) {
78  rtp_packet_send(udp, JpegScanDataCh2A, KJpegCh2ScanDataLen, framecounter, timecounter, 0, 1, 64, 48, format_code,
79  quality_code, 0);
80  } else {
81  rtp_packet_send(udp, JpegScanDataCh2B, KJpegCh2ScanDataLen, framecounter, timecounter, 0, 1, 64, 48, format_code,
82  quality_code, 0);
83  }
84  framecounter++;
85  timecounter += 3600;
86 }
87 
98 void rtp_frame_send(struct UdpSocket *udp, struct image_t *img, uint8_t format_code,
99  uint8_t quality_code, uint8_t has_dri_header, uint32_t frame_time, uint32_t *packet_number)
100 {
101  uint32_t offset = 0;
102  uint32_t jpeg_size = img->buf_size;
103  uint8_t *jpeg_ptr = img->buf;
104 
105 #define MAX_PACKET_SIZE 1400
106 
107  if (frame_time <= 0) {
108  struct timeval tv;
109  gettimeofday(&tv, 0);
110  frame_time = (tv.tv_sec % (256 * 256)) + tv.tv_usec;
111  }
112 
113  // Split frame into packets
114  for (; jpeg_size > 0;) {
116  uint8_t lastpacket = 0;
117 
118  if (jpeg_size <= len) {
119  lastpacket = 1;
120  len = jpeg_size;
121  }
122 
123  rtp_packet_send(udp, jpeg_ptr, len, (*packet_number)++, frame_time, offset, lastpacket, img->w, img->h, format_code,
124  quality_code, has_dri_header);
125 
126  jpeg_size -= len;
127  jpeg_ptr += len;
128  offset += len;
129  }
130 }
131 
132 /*
133  * The same timestamp MUST appear in each fragment of a given frame.
134  * The RTP marker bit MUST be set in the last packet of a frame.
135  * Extra note: When the time difference between frames is non-constant,
136  there seems to introduce some lag or jitter in the video streaming.
137  One way to solve this is to send the timestamp in units of 90000Hz
138  rather than 100000 (when the frame is received the timestamp is always
139  "late" so the frame is displayed immediately). (1 = 1/90000 s) which
140  is probably stupid but is actually working.
141  * @param[in] *udp The UDP socket to send the RTP packet over
142  * @param[in] *Jpeg JPEG encoded image byte buffer
143  * @param[in] JpegLen The length of the byte buffer
144  * @param[in] m_SequenceNumber RTP sequence number
145  * @param[in] m_Timestamp Timestamp of the image in usec
146  * @param[in] m_offset 3 byte fragmentation offset for fragmented images
147  * @param[in] marker_bit RTP marker bit
148  * @param[in] w The width of the JPEG image
149  * @param[in] h The height of the image
150  * @param[in] format_code 0 for YUV422 and 1 for YUV421
151  * @param[in] quality_code The JPEG encoding quality
152  * @param[in] has_dri_header Whether we have an DRI header or not
153  */
154 static void rtp_packet_send(
155  struct UdpSocket *udp,
156  uint8_t *Jpeg, int JpegLen,
157  uint32_t m_SequenceNumber, uint32_t m_Timestamp,
158  uint32_t m_offset, uint8_t marker_bit,
159  int w, int h,
160  uint8_t format_code, uint8_t quality_code,
161  uint8_t has_dri_header)
162 {
163 
164 #define KRtpHeaderSize 12 // size of the RTP header
165 #define KJpegHeaderSize 8 // size of the special JPEG payload header
166 
167  uint8_t RtpBuf[2048];
168  int RtpPacketSize = JpegLen + KRtpHeaderSize + KJpegHeaderSize;
169 
170  memset(RtpBuf, 0x00, sizeof(RtpBuf));
171 
172  /*
173  The RTP header has the following format:
174 
175  0 1 2 3
176  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
177  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178  |V=2|P|X| CC |M| PT | sequence number |
179  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180  | timestamp |
181  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
182  | synchronization source (SSRC) identifier |
183  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
184  | contributing source (CSRC) identifiers |
185  | .... |
186  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187  * */
188 
189  m_Timestamp *= 9 / 100; // convert timestamp to units of 1 / 90000 Hz
190  // Prepare the 12 byte RTP header
191  RtpBuf[0] = 0x80; // RTP version
192  RtpBuf[1] = 0x1a + (marker_bit << 7); // JPEG payload (26) and marker bit
193  RtpBuf[2] = m_SequenceNumber >> 8;
194  RtpBuf[3] = m_SequenceNumber & 0x0FF; // each packet is counted with a sequence counter
195  RtpBuf[4] = (m_Timestamp & 0xFF000000) >> 24; // each image gets a timestamp
196  RtpBuf[5] = (m_Timestamp & 0x00FF0000) >> 16;
197  RtpBuf[6] = (m_Timestamp & 0x0000FF00) >> 8;
198  RtpBuf[7] = (m_Timestamp & 0x000000FF);
199  RtpBuf[8] = 0x13; // 4 byte SSRC (sychronization source identifier)
200  RtpBuf[9] = 0xf9; // we just an arbitrary number here to keep it simple
201  RtpBuf[10] = 0x7e;
202  RtpBuf[11] = 0x67;
203 
204  /* JPEG header", are as follows:
205  *
206  * http://tools.ietf.org/html/rfc2435
207 
208  0 1 2 3
209  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
210  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
211  | Type-specific | Fragment Offset |
212  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213  | Type | Q | Width | Height |
214  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215  */
216 
217  // Prepare the 8 byte payload JPEG header
218  RtpBuf[12] = 0x00; // type specific
219  RtpBuf[13] = (m_offset & 0x00FF0000) >> 16; // 3 byte fragmentation offset for fragmented images
220  RtpBuf[14] = (m_offset & 0x0000FF00) >> 8;
221  RtpBuf[15] = (m_offset & 0x000000FF);
222  RtpBuf[16] = 0x00; // type: 0 422 or 1 421
223  RtpBuf[17] = 60; // quality scale factor
224  RtpBuf[16] = format_code; // type: 0 422 or 1 421
225  if (has_dri_header) {
226  RtpBuf[16] |= 0x40; // DRI flag
227  }
228  RtpBuf[17] = quality_code; // quality scale factor
229  RtpBuf[18] = w / 8; // width / 8 -> 48 pixel
230  RtpBuf[19] = h / 8; // height / 8 -> 32 pixel
231  // append the JPEG scan data to the RTP buffer
232  memcpy(&RtpBuf[20], Jpeg, JpegLen);
233 
234  udp_socket_send_dontwait(udp, RtpBuf, RtpPacketSize);
235 };
int udp_socket_send_dontwait(struct UdpSocket *sock, uint8_t *buffer, uint32_t len)
Send a packet from buffer, non-blocking.
Definition: udp_socket.c:141
uint32_t buf_size
The buffer size.
Definition: image.h:52
static void rtp_packet_send(struct UdpSocket *udp, uint8_t *Jpeg, int JpegLen, uint32_t m_SequenceNumber, uint32_t m_Timestamp, uint32_t m_offset, uint8_t marker_bit, int w, int h, uint8_t format_code, uint8_t quality_code, uint8_t has_dri_header)
Definition: rtp.c:154
#define KJpegCh2ScanDataLen
Definition: rtp.c:41
Definition: image.h:43
#define MAX_PACKET_SIZE
static const float offset[]
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 frame_time, uint32_t *packet_number)
Send an RTP frame.
Definition: rtp.c:98
uint16_t w
Image width.
Definition: image.h:45
unsigned long uint32_t
Definition: types.h:18
uint16_t h
Image height.
Definition: image.h:46
void * buf
Image buffer (depending on the image_type)
Definition: image.h:53
uint8_t JpegScanDataCh2A[KJpegCh2ScanDataLen]
Definition: rtp.c:44
static void h(const real32_T x[7], const real32_T q[4], real32_T y[6])
unsigned char uint8_t
Definition: types.h:14
uint8_t JpegScanDataCh2B[KJpegCh2ScanDataLen]
Definition: rtp.c:53
Encodes a vide stream with RTP (JPEG)
#define KJpegHeaderSize
#define KRtpHeaderSize
void rtp_frame_test(struct UdpSocket *udp)
Send a test RTP frame.
Definition: rtp.c:67