FreeCalypso > hg > themwi-rtp-lib
comparison src/twjit_out.c @ 5:1bb26347e253
twjit: split into separate base/in/out modules
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 05 Jul 2024 21:24:56 +0000 |
parents | src/twjit.c@d10ea5dc61b3 |
children | 4f82b9c07ddb |
comparison
equal
deleted
inserted
replaced
4:be04d84f5468 | 5:1bb26347e253 |
---|---|
1 /* | |
2 * Themyscira Wireless jitter buffer implementation: | |
3 * output to the fixed timing system. | |
4 */ | |
5 | |
6 #include <stdint.h> | |
7 #include <stdbool.h> | |
8 #include <string.h> | |
9 | |
10 #include <osmocom/core/linuxlist.h> | |
11 #include <osmocom/core/msgb.h> | |
12 #include <osmocom/core/utils.h> | |
13 | |
14 #include <themwi/rtp/twjit.h> | |
15 | |
16 static bool starting_sb_is_ready(struct twrtp_jibuf_inst *twjit) | |
17 { | |
18 struct twrtp_jibuf_sub *sb = &twjit->sb[twjit->write_sb]; | |
19 | |
20 if (sb->depth < sb->conf.bd_start) | |
21 return false; | |
22 if (sb->delta_ms < sb->conf.start_min_delta) | |
23 return false; | |
24 return true; | |
25 } | |
26 | |
27 static bool read_sb_is_empty(struct twrtp_jibuf_inst *twjit) | |
28 { | |
29 struct twrtp_jibuf_sub *sb = &twjit->sb[twjit->read_sb]; | |
30 | |
31 return sb->depth == 0; | |
32 } | |
33 | |
34 static struct msgb *pull_from_read_sb(struct twrtp_jibuf_inst *twjit) | |
35 { | |
36 struct twrtp_jibuf_sub *sb = &twjit->sb[twjit->read_sb]; | |
37 struct msgb *msg; | |
38 | |
39 OSMO_ASSERT(!llist_empty(&sb->queue)); | |
40 OSMO_ASSERT(sb->depth > 0); | |
41 msg = llist_entry(sb->queue.next, struct msgb, list); | |
42 if (msg->cb[0] == sb->head_ts) { | |
43 llist_del(&msg->list); | |
44 twjit->stats.delivered_pkt++; | |
45 twjit->stats.delivered_bytes += msg->len; | |
46 } else { | |
47 msg = NULL; | |
48 twjit->stats.output_gaps++; | |
49 } | |
50 sb->head_ts += twjit->ts_quantum; | |
51 sb->depth--; | |
52 return msg; | |
53 } | |
54 | |
55 static void read_sb_thinning(struct twrtp_jibuf_inst *twjit) | |
56 { | |
57 struct twrtp_jibuf_sub *sb = &twjit->sb[twjit->read_sb]; | |
58 struct msgb *msg; | |
59 | |
60 if (sb->drop_int_count) { | |
61 sb->drop_int_count--; | |
62 return; | |
63 } | |
64 if (sb->depth <= sb->conf.bd_hiwat) | |
65 return; | |
66 twjit->stats.thinning_drops++; | |
67 msg = pull_from_read_sb(twjit); | |
68 if (msg) | |
69 msgb_free(msg); | |
70 sb->drop_int_count = sb->conf.thinning_int - 2; | |
71 } | |
72 | |
73 static void toss_read_queue(struct twrtp_jibuf_inst *twjit) | |
74 { | |
75 struct twrtp_jibuf_sub *sb = &twjit->sb[twjit->read_sb]; | |
76 | |
77 msgb_queue_free(&sb->queue); | |
78 sb->depth = 0; | |
79 } | |
80 | |
81 struct msgb *twrtp_jibuf_output(struct twrtp_jibuf_inst *twjit) | |
82 { | |
83 switch (twjit->state) { | |
84 case TWJIT_STATE_EMPTY: | |
85 return NULL; | |
86 case TWJIT_STATE_HUNT: | |
87 if (!starting_sb_is_ready(twjit)) | |
88 return NULL; | |
89 twjit->state = TWJIT_STATE_FLOWING; | |
90 twjit->read_sb = twjit->write_sb; | |
91 return pull_from_read_sb(twjit); | |
92 case TWJIT_STATE_FLOWING: | |
93 if (read_sb_is_empty(twjit)) { | |
94 twjit->state = TWJIT_STATE_EMPTY; | |
95 twjit->stats.underruns++; | |
96 return NULL; | |
97 } | |
98 read_sb_thinning(twjit); | |
99 return pull_from_read_sb(twjit); | |
100 case TWJIT_STATE_HANDOVER: | |
101 if (starting_sb_is_ready(twjit)) { | |
102 toss_read_queue(twjit); | |
103 twjit->state = TWJIT_STATE_FLOWING; | |
104 twjit->read_sb = twjit->write_sb; | |
105 return pull_from_read_sb(twjit); | |
106 } | |
107 if (read_sb_is_empty(twjit)) { | |
108 twjit->state = TWJIT_STATE_HUNT; | |
109 twjit->stats.underruns++; | |
110 return NULL; | |
111 } | |
112 read_sb_thinning(twjit); | |
113 return pull_from_read_sb(twjit); | |
114 default: | |
115 OSMO_ASSERT(0); | |
116 } | |
117 } |