Line | Count | Source |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2016-2018 The TokTok team. |
3 | | * Copyright © 2013-2015 Tox project. |
4 | | */ |
5 | | #ifndef C_TOXCORE_TOXAV_RTP_H |
6 | | #define C_TOXCORE_TOXAV_RTP_H |
7 | | |
8 | | #include <stdbool.h> |
9 | | |
10 | | #include "bwcontroller.h" |
11 | | |
12 | | #include "../toxcore/Messenger.h" |
13 | | #include "../toxcore/logger.h" |
14 | | #include "../toxcore/tox.h" |
15 | | |
16 | | #ifdef __cplusplus |
17 | | extern "C" { |
18 | | #endif |
19 | | |
20 | | /** |
21 | | * RTPHeader serialised size in bytes. |
22 | | */ |
23 | 2.36k | #define RTP_HEADER_SIZE 80 |
24 | | |
25 | | /** |
26 | | * Number of 32 bit padding fields between @ref RTPHeader::offset_lower and |
27 | | * everything before it. |
28 | | */ |
29 | 4.29k | #define RTP_PADDING_FIELDS 11 |
30 | | |
31 | | /** |
32 | | * Payload type identifier. Also used as rtp callback prefix. |
33 | | */ |
34 | | typedef enum RTP_Type { |
35 | | RTP_TYPE_AUDIO = 192, |
36 | | RTP_TYPE_VIDEO = 193, |
37 | | } RTP_Type; |
38 | | |
39 | | /** |
40 | | * A bit mask (up to 64 bits) specifying features of the current frame affecting |
41 | | * the behaviour of the decoder. |
42 | | */ |
43 | | typedef enum RTPFlags { |
44 | | /** |
45 | | * Support frames larger than 64KiB. The full 32 bit length and offset are |
46 | | * set in @ref RTPHeader::data_length_full and @ref RTPHeader::offset_full. |
47 | | */ |
48 | | RTP_LARGE_FRAME = 1 << 0, |
49 | | /** |
50 | | * Whether the packet is part of a key frame. |
51 | | */ |
52 | | RTP_KEY_FRAME = 1 << 1, |
53 | | } RTPFlags; |
54 | | |
55 | | |
56 | | struct RTPHeader { |
57 | | /* Standard RTP header */ |
58 | | unsigned ve: 2; /* Version has only 2 bits! */ |
59 | | unsigned pe: 1; /* Padding */ |
60 | | unsigned xe: 1; /* Extra header */ |
61 | | unsigned cc: 4; /* Contributing sources count */ |
62 | | |
63 | | unsigned ma: 1; /* Marker */ |
64 | | unsigned pt: 7; /* Payload type */ |
65 | | |
66 | | uint16_t sequnum; |
67 | | uint32_t timestamp; |
68 | | uint32_t ssrc; |
69 | | |
70 | | /* Non-standard Tox-specific fields */ |
71 | | |
72 | | /** |
73 | | * Bit mask of `RTPFlags` setting features of the current frame. |
74 | | */ |
75 | | uint64_t flags; |
76 | | |
77 | | /** |
78 | | * The full 32 bit data offset of the current data chunk. The @ref |
79 | | * offset_lower data member contains the lower 16 bits of this value. For |
80 | | * frames smaller than 64KiB, @ref offset_full and @ref offset_lower are |
81 | | * equal. |
82 | | */ |
83 | | uint32_t offset_full; |
84 | | /** |
85 | | * The full 32 bit payload length without header and packet id. |
86 | | */ |
87 | | uint32_t data_length_full; |
88 | | /** |
89 | | * Only the receiver uses this field (why do we have this?). |
90 | | */ |
91 | | uint32_t received_length_full; |
92 | | |
93 | | /** |
94 | | * Data offset of the current part (lower bits). |
95 | | */ |
96 | | uint16_t offset_lower; |
97 | | /** |
98 | | * Total message length (lower bits). |
99 | | */ |
100 | | uint16_t data_length_lower; |
101 | | }; |
102 | | |
103 | | |
104 | | struct RTPMessage { |
105 | | /** |
106 | | * This is used in the old code that doesn't deal with large frames, i.e. |
107 | | * the audio code or receiving code for old 16 bit messages. We use it to |
108 | | * record the number of bytes received so far in a multi-part message. The |
109 | | * multi-part message in the old code is stored in `RTPSession::mp`. |
110 | | */ |
111 | | uint16_t len; |
112 | | |
113 | | struct RTPHeader header; |
114 | | uint8_t data[]; |
115 | | }; |
116 | | |
117 | 137 | #define USED_RTP_WORKBUFFER_COUNT 3 |
118 | | |
119 | | /** |
120 | | * One slot in the work buffer list. Represents one frame that is currently |
121 | | * being assembled. |
122 | | */ |
123 | | struct RTPWorkBuffer { |
124 | | /** |
125 | | * Whether this slot contains a key frame. This is true iff |
126 | | * `buf->header.flags & RTP_KEY_FRAME`. |
127 | | */ |
128 | | bool is_keyframe; |
129 | | /** |
130 | | * The number of bytes received so far, regardless of which pieces. I.e. we |
131 | | * could have received the first 1000 bytes and the last 1000 bytes with |
132 | | * 4000 bytes in the middle still to come, and this number would be 2000. |
133 | | */ |
134 | | uint32_t received_len; |
135 | | /** |
136 | | * The message currently being assembled. |
137 | | */ |
138 | | struct RTPMessage *buf; |
139 | | }; |
140 | | |
141 | | struct RTPWorkBufferList { |
142 | | int8_t next_free_entry; |
143 | | struct RTPWorkBuffer work_buffer[USED_RTP_WORKBUFFER_COUNT]; |
144 | | }; |
145 | | |
146 | 137 | #define DISMISS_FIRST_LOST_VIDEO_PACKET_COUNT 10 |
147 | | |
148 | | typedef int rtp_m_cb(Mono_Time *mono_time, void *cs, struct RTPMessage *msg); |
149 | | |
150 | | /** |
151 | | * RTP control session. |
152 | | */ |
153 | | typedef struct RTPSession { |
154 | | uint8_t payload_type; |
155 | | uint16_t sequnum; /* Sending sequence number */ |
156 | | uint16_t rsequnum; /* Receiving sequence number */ |
157 | | uint32_t rtimestamp; |
158 | | uint32_t ssrc; // this seems to be unused!? |
159 | | struct RTPMessage *mp; /* Expected parted message */ |
160 | | struct RTPWorkBufferList *work_buffer_list; |
161 | | uint8_t first_packets_counter; /* dismiss first few lost video packets */ |
162 | | Messenger *m; |
163 | | Tox *tox; |
164 | | uint32_t friend_number; |
165 | | BWController *bwc; |
166 | | void *cs; |
167 | | rtp_m_cb *mcb; |
168 | | } RTPSession; |
169 | | |
170 | | |
171 | | /** |
172 | | * Serialise an RTPHeader to bytes to be sent over the network. |
173 | | * |
174 | | * @param rdata A byte array of length RTP_HEADER_SIZE. Does not need to be |
175 | | * initialised. All RTP_HEADER_SIZE bytes will be initialised after a call |
176 | | * to this function. |
177 | | * @param header The RTPHeader to serialise. |
178 | | */ |
179 | | size_t rtp_header_pack(uint8_t *rdata, const struct RTPHeader *header); |
180 | | |
181 | | /** |
182 | | * Deserialise an RTPHeader from bytes received over the network. |
183 | | * |
184 | | * @param data A byte array of length RTP_HEADER_SIZE. |
185 | | * @param header The RTPHeader to write the unpacked values to. |
186 | | */ |
187 | | size_t rtp_header_unpack(const uint8_t *data, struct RTPHeader *header); |
188 | | |
189 | | RTPSession *rtp_new(int payload_type, Messenger *m, Tox *tox, uint32_t friendnumber, |
190 | | BWController *bwc, void *cs, rtp_m_cb *mcb); |
191 | | void rtp_kill(RTPSession *session); |
192 | | int rtp_allow_receiving(RTPSession *session); |
193 | | int rtp_stop_receiving(RTPSession *session); |
194 | | /** |
195 | | * Send a frame of audio or video data, chunked in @ref RTPMessage instances. |
196 | | * |
197 | | * @param session The A/V session to send the data for. |
198 | | * @param data A byte array of length @p length. |
199 | | * @param length The number of bytes to send from @p data. |
200 | | * @param is_keyframe Whether this video frame is a key frame. If it is an |
201 | | * audio frame, this parameter is ignored. |
202 | | */ |
203 | | int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length, |
204 | | bool is_keyframe, const Logger *log); |
205 | | |
206 | | #ifdef __cplusplus |
207 | | } /* extern "C" */ |
208 | | #endif |
209 | | |
210 | | #endif /* C_TOXCORE_TOXAV_RTP_H */ |