Coverage Report

Created: 2025-10-08 19:34

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