File: codec.h

package info (click to toggle)
rtpengine 13.5.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,676 kB
  • sloc: ansic: 86,764; perl: 59,422; python: 3,193; sh: 1,030; makefile: 693; asm: 211
file content (296 lines) | stat: -rw-r--r-- 10,357 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#ifndef __CODEC_H__
#define __CODEC_H__

#include <glib.h>
#include <sys/time.h>
#include <stdbool.h>

#include "str.h"
#include "codeclib.h"
#include "helpers.h"
#include "rtplib.h"
#include "timerthread.h"
#include "types.h"
#include "ssrc.h"

struct call_media;
struct codec_handler;
struct media_packet;
struct codec_ssrc_handler;
struct rtp_header;
struct stream_params;
struct supp_codec_tracker;
struct rtcp_timer;
struct mqtt_timer;
struct codec_store;
struct call_monologue;
struct delay_buffer;
struct sink_handler;


typedef int codec_handler_func(struct codec_handler *, struct media_packet *);


struct codec_handler_index {
	int payload_type;
	struct call_media *sink;
};

struct codec_pipeline_index {
	rtp_payload_type src;
	rtp_payload_type dst;
};

struct codec_handler {
	union {
		struct codec_pipeline_index pi;
		struct {
			rtp_payload_type source_pt;
			rtp_payload_type dest_pt;
		};
	};
	struct codec_handler_index i;
	int dtmf_payload_type;
	int real_dtmf_payload_type;
	int cn_payload_type;
	codec_handler_func *handler_func;
	bool passthrough:1;
	bool kernelize:1;
	bool transcoder:1;
	bool pcm_dtmf_detect:1;
	bool blackhole:1;

	size_t payload_len; // for short-packet blocking

	struct ssrc_hash ssrc_hash;
	struct codec_handler *input_handler; // == main handler for supp codecs
	struct codec_handler *output_handler; // == self, or other PT handler
	struct call_media *media;
#ifdef WITH_TRANSCODING
	int (*packet_encoded)(encoder_t *enc, void *u1, void *u2);
	int (*packet_decoded)(decoder_t *, AVFrame *, void *, void *);
#endif

	// for media playback
	struct codec_ssrc_handler *ssrc_handler;
	// for DTMF injection
	struct codec_handler *dtmf_injector;
	struct delay_buffer *delay_buffer;
	// for remote transcoding
	struct transcode_config *tcc;
	struct transform_handler *transform;

	// stats entry
	const char *stats_chain_suffix;
	const char *stats_chain_suffix_brief;
	char *stats_chain;
	struct codec_stats *stats_entry;
};

struct codec_packet {
	struct timerthread_queue_entry ttq_entry;
	codec_packet_list link;
	str s;
	str plain;
	struct rtp_header *rtp;
	unsigned long ts;
	unsigned int clockrate;
	struct ssrc_entry_call *ssrc_out;
	void (*free_func)(void *);
	void (*plain_free_func)(void *);
};

struct codec_scheduler {
	unsigned long first_ts; // for output TS scaling
	unsigned long last_ts; // to detect input lag and handle lost packets
	int64_t first_send;
	unsigned long first_send_ts;
	long output_skew;
	bool is_media_playback; // used to track media playback so we can skip skew calculation
};

struct transcode_config {
	char *src; // unparsed
	char *dst; // unparsed

	char *name; // of the config section

	struct codec_pipeline_index i; // parsed

	int preference; // default: 0

	// transform verdict
	endpoint_t transform;
	str local_interface;
	str remote_interface;

	// codec-chain verdict
	bool codec_chain:1;
};

typedef union {
	struct call_monologue *ml;
} codec_timer_callback_arg_t __attribute__ ((__transparent_union__));


void codecs_init(void);
void codecs_cleanup(void);
void codec_timers_launch(void);
void rtcp_timer_stop(struct rtcp_timer **);
void codec_timer_callback(call_t *, void (*)(call_t *, codec_timer_callback_arg_t),
		codec_timer_callback_arg_t, uint64_t delay);

void mqtt_timer_stop(struct mqtt_timer **);
void mqtt_timer_start(struct mqtt_timer **mqtp, call_t *call, struct call_media *media);

struct codec_handler *codec_handler_get(struct call_media *, int payload_type, struct call_media *sink,
		struct sink_handler *);
void codec_handlers_free(struct call_media *);
struct codec_handler *codec_handler_make_playback(const rtp_payload_type *src_pt,
		const rtp_payload_type *dst_pt, unsigned long ts, struct call_media *, uint32_t ssrc,
		str_case_value_ht codec_set);
struct codec_handler *codec_handler_make_media_player(const rtp_payload_type *src_pt,
		const rtp_payload_type *dst_pt, unsigned long ts, struct call_media *, uint32_t ssrc,
		str_case_value_ht codec_set);
struct codec_handler *codec_handler_make_dummy(const rtp_payload_type *dst_pt, struct call_media *media,
		str_case_value_ht codec_set);
void codec_calc_jitter(struct ssrc_entry_call *, unsigned long ts, unsigned int clockrate, int64_t);
void codec_update_all_handlers(struct call_monologue *ml);
void codec_update_all_source_handlers(struct call_monologue *ml, const sdp_ng_flags *flags, bool clear_delay_buffer);

struct codec_store_args {
	str_case_value_ht codec_set;
	bool answer_only;
	bool allow_asymmetric;
	struct codec_store *merge_cs;
};

__attribute__((nonnull(1)))
void codec_store_cleanup(struct codec_store *cs);
__attribute__((nonnull(1)))
void codec_store_init(struct codec_store *cs, struct call_media *);
__attribute__((nonnull(1, 2)))
void __codec_store_populate(struct codec_store *dst, struct codec_store *src, struct codec_store_args);
#define codec_store_populate(dst, src, ...) \
	__codec_store_populate(dst, src, (struct codec_store_args) {__VA_ARGS__})
__attribute__((nonnull(1, 2)))
void __codec_store_populate_reuse(struct codec_store *, struct codec_store *, struct codec_store_args);
#define codec_store_populate_reuse(dst, src, ...) \
	__codec_store_populate_reuse(dst, src, (struct codec_store_args) {__VA_ARGS__})
__attribute__((nonnull(1, 2)))
void codec_store_copy(struct codec_store *, struct codec_store *);
void codec_store_add_raw(struct codec_store *cs, rtp_payload_type *pt);
__attribute__((nonnull(1, 2)))
void codec_store_strip(struct codec_store *, str_q *strip, str_case_ht except);
__attribute__((nonnull(1, 2, 3)))
void codec_store_offer(struct codec_store *, str_q *, struct codec_store *);
__attribute__((nonnull(1, 2, 3)))
void codec_store_check_empty(struct codec_store *, struct codec_store *, sdp_ng_flags *);
__attribute__((nonnull(1, 2)))
void codec_store_accept(struct codec_store *, str_q *, struct codec_store *);
__attribute__((nonnull(1, 2)))
int codec_store_accept_one(struct codec_store *, str_q *, bool accept_any);
__attribute__((nonnull(1, 2)))
void codec_store_track(struct codec_store *, str_q *);
__attribute__((nonnull(1, 2, 3)))
void codec_store_transcode(struct codec_store *, str_q *, struct codec_store *);
__attribute__((nonnull(1, 2, 3)))
void __codec_store_answer(struct codec_store *dst, struct codec_store *src, sdp_ng_flags *flags,
		struct codec_store_args);
#define codec_store_answer(dst, src, flags, ...) \
	__codec_store_answer(dst, src, flags, (struct codec_store_args) {__VA_ARGS__})
__attribute__((nonnull(1, 2)))
void codec_store_synthesise(struct codec_store *dst, struct codec_store *opposite);
__attribute__((nonnull(1, 2)))
bool codec_store_is_full_answer(const struct codec_store *src, const struct codec_store *dst);

void codec_add_raw_packet(struct media_packet *mp, unsigned int clockrate);
void codec_packet_free(struct codec_packet *);
struct codec_packet *codec_packet_dup(struct codec_packet *p);
bool codec_packet_copy(struct codec_packet *p);

void payload_type_free(rtp_payload_type *p);
rtp_payload_type *rtp_payload_type_dup(const rtp_payload_type *pt);

G_DEFINE_AUTOPTR_CLEANUP_FUNC(rtp_payload_type, payload_type_free)


rtp_payload_type *codec_make_payload_type(const str *codec_str, enum media_type);
bool codec_parse_payload_type(rtp_payload_type *pt, const str *codec_str);

// handle string allocation
void codec_init_payload_type(rtp_payload_type *, enum media_type);
void payload_type_clear(rtp_payload_type *p);


struct chu_args {
	const sdp_ng_flags *flags;
	const struct stream_params *sp;
	bool allow_asymmetric;
	bool reset_transcoding;
	// when false (default if not passed) the delay buffer is flushed as normal
	// used by play-media to ensure media packets aren't sent alongside delayed packets
	bool clear_delay_buffer;
};
#define codec_handlers_update(r, s, ...) \
	__codec_handlers_update(r, s, (struct chu_args) {__VA_ARGS__})

bool codec_handler_transform(struct call_media *r, ng_codecs_q *);

#ifdef WITH_TRANSCODING

void ensure_codec_def(rtp_payload_type *pt, struct call_media *media);
void codec_handler_free(struct codec_handler **handler);
__attribute__((nonnull(1, 2)))
void __codec_handlers_update(struct call_media *receiver, struct call_media *sink, struct chu_args);
void codec_add_dtmf_event(struct codec_ssrc_handler *ch, int code, int level, uint64_t ts, bool injected);
uint64_t codec_last_dtmf_event(struct codec_ssrc_handler *ch);
uint64_t codec_encoder_pts(struct codec_ssrc_handler *ch, struct ssrc_entry_call *);
void codec_decoder_skip_pts(struct codec_ssrc_handler *ch, uint64_t);
uint64_t codec_decoder_unskip_pts(struct codec_ssrc_handler *ch);
void codec_tracker_update(struct codec_store *, struct codec_store *);
void codec_handlers_stop(codec_handlers_q *, struct call_media *sink, bool clear_delay_buffer);


void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, struct media_packet *mp,
		packetizer_f pkt_f, void *pkt_f_data, const struct fraction *cr_fact,
		void (*tx_f)(struct codec_ssrc_handler *, struct media_packet *, str *,
			char *, unsigned int, int64_t pts, int64_t duration,
			const struct fraction *cr_fact));
void codec_output_rtp(struct media_packet *mp, struct codec_scheduler *,
		struct codec_handler *handler, // normally == ch->handler except for DTMF
		char *buf, // malloc'd, room for rtp_header + filled-in payload
		unsigned int payload_len,
		unsigned long payload_ts,
		int marker, int seq, int seq_inc, int payload_type,
		unsigned long ts_delay);


INLINE struct codec_handler_index __codec_handler_lookup_struct(int pt, struct call_media *sink) {
	struct codec_handler_index lookup = {
		.payload_type = pt,
		.sink = sink,
	};
	return lookup;
}
INLINE struct codec_handler *codec_handler_lookup(codec_handlers_ht ht, int pt, struct call_media *sink) {
	struct codec_handler_index lookup = __codec_handler_lookup_struct(pt, sink);
	return t_hash_table_lookup(ht, &lookup);
}


#else

INLINE void __codec_handlers_update(struct call_media *receiver, struct call_media *sink, struct chu_args a)
{
}
INLINE void codec_handler_free(struct codec_handler **handler) { }
INLINE void codec_tracker_update(struct codec_store *cs, struct codec_store *ocs) { }
INLINE void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink, bool clear_delay_buffer) { }
INLINE void ensure_codec_def(rtp_payload_type *pt, struct call_media *media) { }

#endif



#endif