| 29 | |
| 30 | ==== Burst level ==== |
| 31 | |
| 32 | In the jitter buffer operation, packets are added-to and removed-from jitter buffer continuously. Ideally the adding & removing operations are done alternatingly one after another, this is when burst level is 1. |
| 33 | |
| 34 | However, at least from our experience, this is rarely the case. Network jitter happens and it may change from time to time. We have also seen jitter in sound device clock, permanently or temporary (e.g: due to CPU load spike). The combined jitters, i.e: from network (packet producer) and from sound-device (packet consumer), will cause add/remove operation bursts. The burst level represents the number of consecutive add/remove operations in a row, for example, burst level 3 means the jitter buffer will tend to see three {{{add}}} operations in a row before seeing {{{remove}}} operation and vice versa. We consider the burst level is very important for optimum latency calculation, i.e: the latency should not be shorter than the burst level as otherwise the sound-device/consumer may suffer from starvation (no packet available in the jitter buffer when needed). |
| 35 | |
| 36 | As the network condition may change continuously and so does the sound device clock, the burst level needs to be monitored continuously. As mentioned before that the burst level is very important for latency calculation, we need to be careful in changing the burst level, which eventually will cause jitter buffer to adjust the latency. To avoid starvation, increasing burst level should be done instantly and decreasing it should be done slowly. |
| 37 | |
| 38 | ==== Progressive discard ==== |
| 39 | |
| 40 | We consider that the optimum latency at any time should be about the burst level, for example when burst level is 3, the latency should be about 60ms (for audio frame length 20ms). So when the latency (or the number of frames buffered by jitter buffer) is longer than the burst level, we should discard some frames to reach the optimum latency. The progressive discard will drop frames at various rates depending on the difference between the actual latency and the optimum/target latency. There are some configurable macro settings that affects the discard rate: [https://docs.pjsip.org/en/latest/api/generated/pjmedia/group/group__PJMEDIA__CONFIG.html#c.PJMEDIA_JBUF_PRO_DISC_MIN_BURST PJMEDIA_JBUF_PRO_DISC_MIN_BURST & PJMEDIA_JBUF_PRO_DISC_MAX_BURST], [https://docs.pjsip.org/en/latest/api/generated/pjmedia/group/group__PJMEDIA__CONFIG.html#c.PJMEDIA_JBUF_PRO_DISC_T1 PJMEDIA_JBUF_PRO_DISC_T1 & PJMEDIA_JBUF_PRO_DISC_T2], [https://docs.pjsip.org/en/latest/api/generated/pjmedia/group/group__PJMEDIA__CONFIG.html#c.PJMEDIA_JBUF_DISC_MIN_GAP PJMEDIA_JBUF_DISC_MIN_GAP]. |
| 41 | |
| 42 | For example, when the optimum/target latency is 3 frames (or 60ms) and current latency is 10 frames, the jitter buffer will schedule to discard a frame with calculation as follow: |
| 43 | - {{{Overflow}}} or difference between actual & target latencies = 10 - 3 frames = 7 frames. |
| 44 | - Use the following formula for calculating the target time for adjusting the latency (i.e: by discarding the overflow of 7 frames above): |
| 45 | {{{ |
| 46 | T = PJMEDIA_JBUF_PRO_DISC_T1 + |
| 47 | (PJMEDIA_JBUF_PRO_DISC_T2 - PJMEDIA_JBUF_PRO_DISC_T1) * |
| 48 | (burst_level - PJMEDIA_JBUF_PRO_DISC_MIN_BURST) / |
| 49 | (PJMEDIA_JBUF_PRO_DISC_MAX_BURST-PJMEDIA_JBUF_PRO_DISC_MIN_BURST); |
| 50 | |
| 51 | /* |
| 52 | Default settings: |
| 53 | PJMEDIA_JBUF_PRO_DISC_T1 = 2000ms |
| 54 | PJMEDIA_JBUF_PRO_DISC_T2 = 10000ms |
| 55 | PJMEDIA_JBUF_PRO_DISC_MIN_BURST = 1 |
| 56 | PJMEDIA_JBUF_PRO_DISC_MIN_BURST = 100 |
| 57 | */ |
| 58 | }}} |
| 59 | At this point, the target time is 2000 + (8000 * 3/99) = 2242ms or discard rate is {{{target-time / overflow}}} = 2242 / 7 = 320 ms per frame. So the jitter buffer will discard a frame with timestamp 320ms (or frame to be played 320ms later). |
| 60 | Few notes: |
| 61 | - If the frame with that timestamp is not available in the jitter buffer yet, the calculation will be done again later. If the burst level is changed when the calculation is redone, the frame to discard may be changed too (no longer frame with timestamp 320ms). |
| 62 | - If the scheduled frame timestamp is lower than {{{PJMEDIA_JBUF_DISC_MIN_GAP}}} (i.e: 200ms), the jitter buffer will use {{{PJMEDIA_JBUF_DISC_MIN_GAP}}} instead, so the discard rate will not be faster than be faster than {{{PJMEDIA_JBUF_DISC_MIN_GAP}}}. |
| 63 | |
| 64 | ==== Static discard ==== |
| 65 | |
| 66 | The jitter buffer also provides a more conservative discard algoritm. With this algo, the optimum latency at any time should be twice the burst level (as comparison, the progressive discard algo above assumes optimum latency should be about equal to the burst level). This algorithm discard rate is fixed to {{{PJMEDIA_JBUF_DISC_MIN_GAP}}}, so it will discard a frame every 200ms (the default value) until the target/optimum latency is reached. |
| 67 | |