From 30471f19ef7dcf8e0c0a4005c01c48cda0ef585c Mon Sep 17 00:00:00 2001 From: gardners Date: Tue, 24 Apr 2012 20:49:59 +0930 Subject: [PATCH] added system for resending recent samples as a form of preemptive retransmission to deal with wifi packet loss. --- serval.h | 11 +++++++++++ vomp.c | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/serval.h b/serval.h index 45e171a0..99963755 100644 --- a/serval.h +++ b/serval.h @@ -1261,6 +1261,14 @@ typedef struct vomp_call_half { unsigned long long milliseconds_since_call_start; } vomp_call_half; +typedef struct vomp_sample_block { + unsigned int codec; + unsigned long long starttime; + unsigned long long endtime; + unsigned char bytes[1024]; +} vomp_sample_block; + +#define VOMP_MAX_RECENT_SAMPLES 8 typedef struct vomp_call_state { vomp_call_half local; vomp_call_half remote; @@ -1271,6 +1279,8 @@ typedef struct vomp_call_state { int last_sent_status; int next_status_time; unsigned char remote_codec_list[256]; + int recent_sample_rotor; + vomp_sample_block recent_samples[VOMP_MAX_RECENT_SAMPLES]; } vomp_call_state; #define VOMP_CODEC_NONE 0x00 @@ -1306,6 +1316,7 @@ char *vomp_describe_codec(int c); int vomp_tick(); int vomp_tick_interval(); int vomp_sample_size(int c); +int vomp_codec_timespan(int c); typedef struct command_line_option { int (*function)(int argc, const char *const *argv, struct command_line_option *o); diff --git a/vomp.c b/vomp.c index 5f2ac8b0..c307a046 100644 --- a/vomp.c +++ b/vomp.c @@ -230,15 +230,35 @@ int vomp_send_status(vomp_call_state *call,int flags,overlay_mdp_frame *arg) p[(*len)++]=(now_rel_call>>8)&0xff; p[(*len)++]=(now_rel_call>>0)&0xff; - /* now codec code and sample block */ - p[(*len)++]=arg->vompevent.audio_sample_codec; - int i; - for(i=0;ivompevent.audio_sample_bytes;i++) - p[(*len)++]=arg->vompevent.audio_bytes[i]; - } else { - WHYF("Sample bytes(%d) != codec specification(%d)", - arg->vompevent.audio_sample_bytes, - vomp_sample_size(arg->vompevent.audio_sample_codec)); + /* record sample in recent list */ + vomp_sample_block *sb=call->recent_samples; + int rotor=call->recent_sample_rotor%VOMP_MAX_RECENT_SAMPLES; + sb[rotor].codec=arg->vompevent.audio_sample_codec; + sb[rotor].endtime=now_rel_call; + sb[rotor].starttime=now_rel_call-vomp_codec_timespan(sb[rotor].codec); + bcopy(&arg->vompevent.audio_bytes[0],&sb[rotor].bytes[0], + vomp_sample_size(sb[rotor].codec)); + + /* stuff frame with most recent sample blocks as a form of preemptive + retransmission. But don't make the packets too large. */ + while ((*len)<256) { + WHYF("TOP rotor=%d, codec=%s, endtime=%lld", + rotor,vomp_describe_codec(sb[rotor].codec), + sb[rotor].endtime); + p[(*len)++]=sb[rotor].codec; + bcopy(&sb[rotor].bytes[0],&p[*len],vomp_sample_size(sb[rotor].codec)); + (*len)+=vomp_sample_size(sb[rotor].codec); + + rotor--; if (rotor<0) rotor+=VOMP_MAX_RECENT_SAMPLES; + rotor%=VOMP_MAX_RECENT_SAMPLES; + + WHYF("END rotor=%d, codec=%s, endtime=%lld", + rotor,vomp_describe_codec(sb[rotor].codec), + sb[rotor].endtime); + if ((!sb[rotor].endtime)||(sb[rotor].endtime==now_rel_call)) break; + } + call->recent_sample_rotor++; + call->recent_sample_rotor%=VOMP_MAX_RECENT_SAMPLES; } } @@ -299,7 +319,8 @@ int vomp_call_start_audio(vomp_call_state *call) int vomp_process_audio(vomp_call_state *call,overlay_mdp_frame *mdp) { int ofs=14; - WHYF("got here (payload has %d bytes)",mdp->in.payload_length); + if (mdp->in.payload_length>14) + WHYF("got here (payload has %d bytes)",mdp->in.payload_length); /* Get end time marker for sample block collection */ unsigned int e=0; @@ -643,7 +664,8 @@ int vomp_mdp_event(overlay_mdp_frame *mdp, WHY("Audio packet arrived"); vomp_call_state *call =vomp_find_call_by_session(mdp->vompevent.call_session_token); - return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_SENDAUDIO,mdp); + if (call) + return vomp_send_status(call,VOMP_TELLREMOTE|VOMP_SENDAUDIO,mdp); } break; default: