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
|
#ifndef _SSRC_H_
#define _SSRC_H_
#include <sys/types.h>
#include <glib.h>
#include "compat.h"
#include "helpers.h"
#include "obj.h"
#include "codeclib.h"
#include "types.h"
#define MAX_SSRC_ENTRIES 20
struct call_media;
struct ssrc_entry;
struct ssrc_entry_call;
enum ssrc_dir;
typedef struct ssrc_entry *(*ssrc_create_func_t)(void *uptr);
struct ssrc_hash {
GQueue nq;
mutex_t lock;
ssrc_create_func_t create_func;
void *uptr;
struct ssrc_entry *precreat; // next used entry
unsigned int iters; // tracks changes
};
struct payload_tracker {
mutex_t lock;
unsigned char last[32]; // must be <= 255
unsigned int last_idx; // rolling index into pt_last
unsigned char count[128]; // how many of each pt
unsigned char idx[128]; // each pt's index into most[]
unsigned char most[128]; // sorted list of pts
unsigned int most_len; // idx for new entries
unsigned char last_pts[16];
int last_pt_idx;
};
struct ssrc_stats_block {
int64_t reported;
uint64_t jitter; // ms
uint64_t rtt; // us - combined from both sides
uint32_t rtt_leg; // RTT only for the leg receiving the RTCP report
uint64_t packetloss; // percent
uint64_t mos; // nominal range of 10 - 50 for MOS values 1.0 to 5.0
};
struct ssrc_entry {
struct obj obj;
GList link;
mutex_t lock;
uint32_t ssrc;
};
struct ssrc_entry_call {
struct ssrc_entry h; // must be first
struct payload_tracker tracker;
// XXX move entire crypto context in here?
// for transcoding
uint32_t ssrc_map_out;
uint16_t seq_out;
unsigned long ts_out;
// RTCP stats
struct ssrc_stats *stats;
// for per-second stats:
atomic64 last_sample,
sample_packets,
sample_octets,
sample_packets_lost,
sample_duplicates;
int64_t next_rtcp; // for self-generated RTCP reports
GQueue sender_reports; // as received via RTCP
GQueue rr_time_reports; // as received via RTCP
GQueue stats_blocks; // calculated
struct ssrc_stats_block *lowest_mos,
*highest_mos,
average_mos; // contains a running tally of all stats blocks
uint16_t no_mos_count; // how many time we where not able to compute MOS due to missing RTT
unsigned int last_rtt; // last calculated raw rtt without rtt from opposide side
unsigned int last_rtt_xr; // last rtt for both legs retrieved from RTCP-XR BT-7
// input only - tracking for passthrough handling
uint32_t last_seq_tracked;
uint32_t lost_bits; // sliding bitfield, [0] = ext_seq
uint32_t packets_lost; // RTCP cumulative number of packets lost
uint32_t duplicates;
// for transcoding
// input only
GHashTable *sequencers;
packet_sequencer_t *sequencer_cache; // to skip hash lookup
struct call_media *media_cache; // to skip hash lookup
uint32_t jitter, transit;
// output only
uint16_t seq_diff;
};
struct ssrc_time_item {
int64_t received;
uint32_t ntp_middle_bits; // to match up with lsr/dlrr
int32_t ntp_ts_lsw, ntp_ts_msw;
};
struct ssrc_sender_report {
uint32_t ssrc;
uint32_t ntp_msw;
uint32_t ntp_lsw;
uint32_t timestamp;
uint32_t packet_count;
uint32_t octet_count;
};
struct ssrc_sender_report_item {
struct ssrc_time_item time_item; // must be first;
struct ssrc_sender_report report;
};
struct ssrc_receiver_report {
uint32_t from;
uint32_t ssrc;
unsigned char fraction_lost;
uint32_t packets_lost;
uint32_t high_seq_received;
uint32_t jitter;
uint32_t lsr;
uint32_t dlsr;
};
//struct ssrc_receiver_report_item {
// struct timeval received;
// struct ssrc_receiver_report report;
//};
struct ssrc_xr_rr_time {
uint32_t ssrc;
uint32_t ntp_msw;
uint32_t ntp_lsw;
};
struct ssrc_rr_time_item {
struct ssrc_time_item time_item; // must be first;
};
struct ssrc_xr_dlrr {
uint32_t from;
uint32_t ssrc;
uint32_t lrr;
uint32_t dlrr;
};
struct ssrc_xr_voip_metrics {
uint32_t from;
uint32_t ssrc;
uint8_t loss_rate;
uint8_t discard_rate;
uint8_t burst_den;
uint8_t gap_den;
uint16_t burst_dur;
uint16_t gap_dur;
uint16_t rnd_trip_delay;
uint16_t end_sys_delay;
uint8_t signal_lvl;
uint8_t noise_lvl;
uint8_t rerl;
uint8_t gmin;
uint8_t r_factor;
uint8_t ext_r_factor;
uint8_t mos_lq;
uint8_t mos_cq;
uint8_t rx_config;
uint16_t jb_nom;
uint16_t jb_max;
uint16_t jb_abs_max;
};
struct crtt_args {
struct ssrc_hash *ht;
int64_t tv;
int *pt_p;
uint32_t ssrc;
uint32_t ntp_middle_bits;
uint32_t delay;
size_t reports_queue_offset;
};
void ssrc_hash_destroy(struct ssrc_hash *);
void ssrc_hash_foreach(struct ssrc_hash *, void (*)(void *, void *), void *);
void ssrc_hash_full_init(struct ssrc_hash *, ssrc_create_func_t, void *uptr); // pre-creates one object
void ssrc_hash_full_fast_init(struct ssrc_hash *, ssrc_create_func_t, void *uptr); // doesn't pre-create object
void ssrc_hash_call_init(struct ssrc_hash *);
void *get_ssrc_full(uint32_t, struct ssrc_hash *, bool *created); // creates new entry if not found
INLINE void *get_ssrc(uint32_t ssrc, struct ssrc_hash *ht) {
return get_ssrc_full(ssrc, ht, NULL);
}
INLINE struct ssrc_entry_call *call_get_first_ssrc(struct ssrc_hash *ht) {
return ht->nq.head ? ht->nq.head->data : NULL;
}
void ssrc_sender_report(struct call_media *, const struct ssrc_sender_report *, int64_t);
void ssrc_receiver_report(struct call_media *, stream_fd *, const struct ssrc_receiver_report *, int64_t);
void ssrc_receiver_rr_time(struct call_media *m, const struct ssrc_xr_rr_time *rr, int64_t);
void ssrc_receiver_dlrr(struct call_media *m, const struct ssrc_xr_dlrr *dlrr, int64_t);
void ssrc_voip_metrics(struct call_media *m, const struct ssrc_xr_voip_metrics *vm, int64_t);
void ssrc_collect_metrics(struct call_media *);
void payload_tracker_init(struct payload_tracker *t);
void payload_tracker_add(struct payload_tracker *, int);
#define ssrc_entry_release(c) do { \
if (c) { \
obj_put(&(c)->h); \
c = NULL; \
} \
} while (0)
#define ssrc_entry_hold(c) obj_hold(&(c)->h)
#endif
|