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
|