]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8130 the bug that keeps on bugging, improve video nack
authorAnthony Minessale <anthm@freeswitch.org>
Sat, 19 Sep 2015 04:36:11 +0000 (23:36 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Sat, 19 Sep 2015 04:36:11 +0000 (23:36 -0500)
src/switch_jitterbuffer.c
src/switch_rtp.c

index de9e835a76e50ebfd5b78a4a10eb4516bdf4bcb7..2c776a61c23ba2033ee1debaa8186ccd7e35b189 100644 (file)
@@ -37,8 +37,8 @@
 #define MAX_MISSING_SEQ 20
 #define jb_debug(_jb, _level, _format, ...) if (_jb->debug_level >= _level) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(_jb->session), SWITCH_LOG_ALERT, "JB:%p:%s lv:%d ln:%d sz:%u/%u/%u c:%u %u/%u/%u/%u %.2f%% ->" _format, (void *) _jb, (jb->type == SJB_AUDIO ? "aud" : "vid"), _level, __LINE__,  _jb->min_frame_len, _jb->max_frame_len, _jb->frame_len, _jb->period_count, _jb->consec_good_count, _jb->period_good_count, _jb->consec_miss_count, _jb->period_miss_count, _jb->period_miss_pct, __VA_ARGS__)
 
-const char *TOKEN_1 = "ONE";
-const char *TOKEN_2 = "TWO";
+//const char *TOKEN_1 = "ONE";
+//const char *TOKEN_2 = "TWO";
 
 struct switch_jb_s;
 
@@ -71,6 +71,7 @@ struct switch_jb_s {
        uint32_t highest_frame_len;
        uint32_t period_miss_count;
        uint32_t consec_miss_count;
+       uint32_t period_miss_inc;
        double period_miss_pct;
        uint32_t period_good_count;
        uint32_t consec_good_count;
@@ -485,7 +486,7 @@ static inline int verify_oldest_frame(switch_jb_t *jb)
                        uint32_t val = (uint32_t)htons(ntohs(np->prev->packet.header.seq) + 1);
 
                        if (!switch_core_inthash_find(jb->missing_seq_hash, val)) {
-                               switch_core_inthash_insert(jb->missing_seq_hash, val, (void *) TOKEN_1);
+                               switch_core_inthash_insert(jb->missing_seq_hash, val, (void *) (intptr_t) 1);
                        }
                        break;
                }
@@ -634,7 +635,10 @@ static inline switch_status_t jb_next_packet_by_seq(switch_jb_t *jb, switch_jb_n
                if (jb->type == SJB_VIDEO) {
                        int x;
 
-                       jb_frame_inc(jb, 1);
+                       if (jb->period_miss_count > 1 && !jb->period_miss_inc) {
+                               jb->period_miss_inc++;
+                               jb_frame_inc(jb, 1);
+                       }
 
                        //if (jb->session) {
                        //      switch_core_session_request_video_refresh(jb->session);
@@ -795,6 +799,7 @@ SWITCH_DECLARE(void) switch_jb_reset(switch_jb_t *jb)
        jb->period_good_count = 0;
        jb->consec_good_count = 0;
        jb->period_count = 0;
+       jb->period_miss_inc = 0;
        jb->target_ts = 0;
        jb->last_target_ts = 0;
 
@@ -942,9 +947,8 @@ SWITCH_DECLARE(uint32_t) switch_jb_pop_nack(switch_jb_t *jb)
        switch_hash_index_t *hi = NULL;
        uint32_t nack = 0;
        uint16_t blp = 0;
-       uint16_t most = 0;
+       uint16_t least = 0;
        int i = 0;
-       
        void *val;
        const void *var;
 
@@ -954,42 +958,54 @@ SWITCH_DECLARE(uint32_t) switch_jb_pop_nack(switch_jb_t *jb)
 
        switch_mutex_lock(jb->mutex);
 
+ top:
+
        for (hi = switch_core_hash_first(jb->missing_seq_hash); hi; hi = switch_core_hash_next(&hi)) {
                uint16_t seq;
-               const char *token;
-               uint32_t ts;
-
+               //const char *token;
+               switch_time_t then = 0;
+               
                switch_core_hash_this(hi, &var, NULL, &val);
-               token = (const char *) val;
+               //token = (const char *) val;
 
-               if (token == TOKEN_2) {
+               //if (token == TOKEN_2) {
                        //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SKIP %u %s\n", ntohs(*((uint16_t *) var)), token);
                        //printf("WTf\n");
-                       continue;
-               }
-
-               ts = (intptr_t)val;
+               //      continue;
+               //}
+               
+               seq = ntohs(*((uint16_t *) var));
+               then = (intptr_t) val;
 
-               if (ts == jb->highest_wrote_ts) {
+               if (then != 1 && switch_time_now() - then < 100000) {
+                       //jb_debug(jb, 3, "NACKABLE seq %u too soon to repeat\n", seq);
                        continue;
                }
+               
+               //if (then != 1) {
+               //      jb_debug(jb, 3, "NACKABLE seq %u not too soon to repeat %lu\n", seq, switch_time_now() - then);
+               //}
+
+               if (seq < ntohs(jb->target_seq) - jb->frame_len) {
+                       jb_debug(jb, 3, "NACKABLE seq %u expired\n", seq);
+                       switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(seq));
+                       goto top;
+               }
 
-               seq = ntohs(*((uint16_t *) var));
-
-               if (!most || seq > most) {
-                       most = seq;
+               if (!least || seq < least) {
+                       least = seq;
                }
        }
 
-       if (most && switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(most))) {
-               jb_debug(jb, 3, "Found NACKABLE seq %u\n", most);
-               nack = (uint32_t) htons(most);
-               switch_core_inthash_insert(jb->missing_seq_hash, nack, (void *) TOKEN_2);
+       if (least && switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(least))) {
+               jb_debug(jb, 3, "Found NACKABLE seq %u\n", least);
+               nack = (uint32_t) htons(least);
+               switch_core_inthash_insert(jb->missing_seq_hash, nack, (void *) (intptr_t)switch_time_now());
 
                for(i = 0; i < 16; i++) {
-                       if (switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(most + i + 1))) {
-                               switch_core_inthash_insert(jb->missing_seq_hash, (uint32_t)htons(most + i + 1), (void *) TOKEN_2);
-                               jb_debug(jb, 3, "Found addtl NACKABLE seq %u\n", most + i + 1);
+                       if (switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(least + i + 1))) {
+                               switch_core_inthash_insert(jb->missing_seq_hash, (uint32_t)htons(least + i + 1), (void *)(intptr_t)switch_time_now());
+                               jb_debug(jb, 3, "Found addtl NACKABLE seq %u\n", least + i + 1);
                                blp |= (1 << i);
                        }
                }
@@ -1026,7 +1042,14 @@ SWITCH_DECLARE(switch_status_t) switch_jb_put_packet(switch_jb_t *jb, switch_rtp
                jb->next_seq = htons(got + 1);
        } else {
 
-               switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(got));
+               if (switch_core_inthash_delete(jb->missing_seq_hash, (uint32_t)htons(got))) {
+                       if (got < ntohs(jb->target_seq)) {
+                               jb_debug(jb, 2, "got nacked seq %u too late\n", got);
+                               jb_frame_inc(jb, 1);
+                       } else {
+                               jb_debug(jb, 2, "got nacked %u saved the day!\n", got);
+                       }
+               }
 
                if (got > want) {
                        if (got - want > jb->max_frame_len && got - want > 17) {
@@ -1036,11 +1059,16 @@ SWITCH_DECLARE(switch_status_t) switch_jb_put_packet(switch_jb_t *jb, switch_rtp
                                        switch_core_session_request_video_refresh(jb->session);
                                }
                        } else {
+
+                               if (jb->frame_len < got - want) {
+                                       jb_frame_inc(jb, got - want - jb->frame_len);
+                               }
+
                                jb_debug(jb, 2, "GOT %u WANTED %u; MARK SEQS MISSING %u - %u\n", got, want, want, got - 1);
                        
                                for (i = want; i < got; i++) {
                                        jb_debug(jb, 2, "MARK MISSING %u ts:%u\n", i, ntohl(packet->header.ts));
-                                       switch_core_inthash_insert(jb->missing_seq_hash, (uint32_t)htons(i), (void *)(intptr_t)packet->header.ts);
+                                       switch_core_inthash_insert(jb->missing_seq_hash, (uint32_t)htons(i), (void *) (intptr_t) 1);
                                }
                        }
                }
@@ -1104,13 +1132,14 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
                }
 
                jb->period_count = 1;
+               jb->period_miss_inc = 0;
                jb->period_miss_count = 0;
                jb->period_good_count = 0;
                jb->consec_miss_count = 0;
                jb->consec_good_count = 0;
-
+#if 0
                if (jb->type == SJB_VIDEO && jb->channel) {
-                       //switch_time_t now = switch_micro_time_now();
+                       //switch_time_t now = switch_time_now();
                        //int ok = (now - jb->last_bitrate_change) > 10000;
                        
                        if (switch_channel_test_flag(jb->channel, CF_VIDEO_BITRATE_UNMANAGABLE) && jb->frame_len == jb->min_frame_len) {
@@ -1132,6 +1161,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
                                
                        }
                }
+#endif
        }
 
        jb->period_miss_pct = ((double)jb->period_miss_count / jb->period_count) * 100;
index db772f061f4d76dd4c49277098bb973553ad5bef..8f4dc6f16529ffb312608436057aa999fe57735a 100644 (file)
@@ -1895,7 +1895,7 @@ static int using_ice(switch_rtp_t *rtp_session)
        return 0;
 }
 
-#define MAX_NACK 1
+#define MAX_NACK 10
 static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
 {
        int ret = 0;
@@ -3995,7 +3995,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_video_buffer_size(switch_rtp_t *r
        }
 
        if (!max_frames) {
-               max_frames = frames * 4;
+               max_frames = 40;
        }
 
        if (!rtp_session->vb) {
@@ -5395,9 +5395,14 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 
        if (rtp_session->flags[SWITCH_RTP_FLAG_KILL_JB]) {
                rtp_session->flags[SWITCH_RTP_FLAG_KILL_JB] = 0;
+
                if (rtp_session->jb) {
                        switch_jb_destroy(&rtp_session->jb);
                }
+
+               if (rtp_session->vb) {
+                       switch_jb_destroy(&rtp_session->vb);
+               }
        }
 
        if (rtp_session->recv_msg.header.version == 2 && *bytes) {
@@ -7300,7 +7305,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
                
                if (rtp_session->flags[SWITCH_RTP_FLAG_NACK]) {
                        if (!rtp_session->vbw) {
-                               switch_jb_create(&rtp_session->vbw, SJB_VIDEO, 10, 10, rtp_session->pool);
+                               switch_jb_create(&rtp_session->vbw, SJB_VIDEO, 30, 30, rtp_session->pool);
                                //switch_jb_debug_level(rtp_session->vbw, 10);
                        }
                        switch_jb_push_packet(rtp_session->vbw, (switch_rtp_packet_t *)send_msg, bytes);