]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
doh
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 15 Dec 2010 15:39:42 +0000 (09:39 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 15 Dec 2010 15:39:52 +0000 (09:39 -0600)
libs/stfu/stfu.c
libs/stfu/stfu.h

index 547c3372781333bae76751cfa922cf42ea2cd17e..72459caad9d6f420a904854fac7ff1b6958e3b3c 100644 (file)
 #  define UINT_MAX        4294967295U
 #endif
 
+#ifndef UINT16_MAX
+#  define UINT16_MAX        65535
+#endif
+
 #ifdef _MSC_VER
 /* warning C4706: assignment within conditional expression*/
 #pragma warning(disable: 4706)
 #endif
 
+#define least1(_z) (_z ? _z : 1)
+
+static int stfu_log_level = 7;
+
 struct stfu_queue {
        struct stfu_frame *array;
        struct stfu_frame int_frame;
@@ -53,13 +61,13 @@ typedef struct stfu_queue stfu_queue_t;
 struct stfu_instance {
        struct stfu_queue a_queue;
        struct stfu_queue b_queue;
+       struct stfu_queue c_queue;
        struct stfu_queue *in_queue;
        struct stfu_queue *out_queue;
+       struct stfu_queue *old_queue;
     struct stfu_frame *last_frame;
        uint32_t cur_ts;
-       uint32_t cur_seq;
        uint32_t last_wr_ts;
-       uint32_t last_wr_seq;
        uint32_t last_rd_ts;
        uint32_t samples_per_packet;
        uint32_t samples_per_second;
@@ -76,6 +84,7 @@ struct stfu_instance {
     uint32_t period_packet_in_count;
     uint32_t period_packet_out_count;
     uint32_t period_missing_count;
+
     uint32_t period_need_range;
     uint32_t period_need_range_avg;
     uint32_t period_clean_count;
@@ -86,25 +95,55 @@ struct stfu_instance {
     uint32_t session_packet_in_count;
     uint32_t session_packet_out_count;
 
-    uint32_t sync;
+    uint32_t sync_out;
+    uint32_t sync_in;
 
 
     int32_t ts_diff;
     int32_t last_ts_diff;
     int32_t same_ts;
     
-    uint32_t last_seq;
-
     uint32_t period_time;
     uint32_t decrement_time;
     
     uint32_t plc_len;
+    uint32_t plc_pt;
+    uint32_t diff;
+    uint32_t diff_total;
+    uint8_t ready;
+    uint8_t debug;
 
+    char *name;
     stfu_n_call_me_t callback;
     void *udata;
 };
 
 static void stfu_n_reset_counters(stfu_instance_t *i);
+static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
+static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
+
+stfu_logger_t stfu_log = null_logger;
+
+void stfu_global_set_logger(stfu_logger_t logger)
+{
+       if (logger) {
+               stfu_log = logger;
+       } else {
+               stfu_log = null_logger;
+       }
+}
+
+void stfu_global_set_default_logger(int level)
+{
+       if (level < 0 || level > 7) {
+               level = 7;
+       }
+
+       stfu_log = default_logger;
+       stfu_log_level = level;
+}
+
+
 
 static stfu_status_t stfu_n_resize_aqueue(stfu_queue_t *queue, uint32_t qlen)
 {
@@ -151,12 +190,27 @@ void stfu_n_destroy(stfu_instance_t **i)
        if (i && *i) {
                ii = *i;
                *i = NULL;
+        if (ii->name) free(ii->name);
                free(ii->a_queue.array);
                free(ii->b_queue.array);
+               free(ii->c_queue.array);
                free(ii);
        }
 }
 
+void stfu_n_debug(stfu_instance_t *i, const char *name)
+{
+    if (i->name) free(i->name);
+
+    if (name) {
+        i->name = strdup(name);
+        i->debug = 1;
+    } else {
+        i->name = strdup("none");
+        i->debug = 0;
+    }
+}
+
 void stfu_n_report(stfu_instance_t *i, stfu_report_t *r)
 {
     assert(i);
@@ -172,7 +226,6 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
     stfu_status_t s;
 
     if (i->qlen == i->max_qlen) {
-        printf("FUCKER1\n");
         return STFU_IT_FAILED;
     }
     
@@ -180,13 +233,14 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
         if (i->qlen < i->max_qlen) {
             qlen = i->max_qlen;
         } else {
-            printf("FUCKER2\n");
             return STFU_IT_FAILED;
         }
     }
 
     if ((s = stfu_n_resize_aqueue(&i->a_queue, qlen)) == STFU_IT_WORKED) {
         s = stfu_n_resize_aqueue(&i->b_queue, qlen);
+        s = stfu_n_resize_aqueue(&i->c_queue, qlen);
+
         i->qlen = qlen;
         i->max_plc = 5;
         i->last_frame = NULL;
@@ -205,11 +259,6 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_
        }
        memset(i, 0, sizeof(*i));
 
-
-#ifdef DB_JB
-    printf("INIT %u %u\n", qlen, max_qlen);
-#endif
-
     i->qlen = qlen;
     i->max_qlen = max_qlen;
     i->orig_qlen = qlen;
@@ -217,8 +266,12 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_
 
        stfu_n_init_aqueue(&i->a_queue, qlen);
        stfu_n_init_aqueue(&i->b_queue, qlen);
+       stfu_n_init_aqueue(&i->c_queue, qlen);
+
        i->in_queue = &i->a_queue;
        i->out_queue = &i->b_queue;
+       i->old_queue = &i->c_queue;
+    i->name = strdup("none");
     
     i->max_plc = i->qlen / 2;
 
@@ -232,9 +285,9 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_
 
 static void stfu_n_reset_counters(stfu_instance_t *i)
 {
-#ifdef DB_JB
-    printf("COUNTER RESET........\n");
-#endif
+    if (stfu_log != null_logger && i->debug) {
+        stfu_log(STFU_LOG_EMERG, "%s COUNTER RESET........\n", i->name);
+    }
 
     if (i->callback) {
         i->callback(i, i->udata);
@@ -248,36 +301,44 @@ static void stfu_n_reset_counters(stfu_instance_t *i)
     i->period_packet_in_count = 0;
     i->period_packet_out_count = 0;
     i->period_missing_count = 0;
+
     i->period_need_range = 0;
     i->period_need_range_avg = 0;
+
+    i->diff = 0;
+    i->diff_total = 0;
+
 }
 
 void stfu_n_reset(stfu_instance_t *i)
 {
-#ifdef DB_JB
-    printf("RESET\n");
-#endif
+    if (stfu_log != null_logger && i->debug) {
+        stfu_log(STFU_LOG_EMERG, "%s RESET\n", i->name);
+    }
+
+    i->ready = 0;
        i->in_queue = &i->a_queue;
        i->out_queue = &i->b_queue;
+       i->old_queue = &i->c_queue;
+
        i->in_queue->array_len = 0;
        i->out_queue->array_len = 0;
        i->out_queue->wr_len = 0;
        i->last_frame = NULL;
-
     i->in_queue->last_jitter = 0;
     i->out_queue->last_jitter = 0;
 
-    stfu_n_reset_counters(i);
-
-    i->last_seq = 0;
 
+    stfu_n_reset_counters(i);
+    stfu_n_sync(i, 1);
+    
     i->cur_ts = 0;
-    i->cur_seq = 0;
        i->last_wr_ts = 0;
-       i->last_wr_seq = 0;
        i->last_rd_ts = 0;
        i->miss_count = 0;      
     i->packet_count = 0;
+
+
 }
 
 stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
@@ -286,20 +347,39 @@ stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
     if (packets > i->qlen) {
         stfu_n_reset(i);
     } else {
-        i->sync = packets;
+        i->sync_out = packets;
+        i->sync_in = packets;
     }
 
     return STFU_IT_WORKED;
 }
 
 
-stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last)
+static void stfu_n_swap(stfu_instance_t *i)
+{
+    stfu_queue_t *last_in = i->in_queue, *last_out = i->out_queue, *last_old = i->old_queue;
+    
+    i->ready = 1;
+    
+    i->in_queue = last_out;
+    i->out_queue = last_old;
+    i->old_queue = last_in;
+
+    i->in_queue->array_len = 0;
+    i->out_queue->wr_len = 0;
+    i->last_frame = NULL;
+    i->miss_count = 0;
+    i->in_queue->last_index = 0;
+    i->out_queue->last_index = 0;
+    i->out_queue->last_jitter = 0;
+}
+
+stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last)
 {
        uint32_t index = 0;
        stfu_frame_t *frame;
        size_t cplen = 0;
-    int good_seq = 0, good_ts = 0;
-    uint32_t min_seq = UINT_MAX, min_ts = UINT_MAX, min_index = 0;
+    int good_ts = 0;
 
     if (!i->samples_per_packet && ts && i->last_rd_ts) {
         i->ts_diff = ts - i->last_rd_ts;
@@ -320,16 +400,27 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
         }
     }
  
-    if ((seq && seq == i->last_seq + 1) || (i->last_seq > 65500 && seq == 0)) {
-        good_seq = 1;
-    }
-
-    if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) {
+    if (i->sync_in) {
         good_ts = 1;
-    }
+        i->sync_in = 0;
+    } else {
 
+        if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) {
+            good_ts = 1;
+        }
 
-    if (good_seq || good_ts) {
+        if (i->last_wr_ts) {
+            if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) {
+                stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts);
+                if (i->in_queue->array_len < i->in_queue->array_size) {
+                    i->in_queue->array_len++;
+                }
+                return STFU_ITS_TOO_LATE;
+            }
+        }
+    }
+
+    if (good_ts) {
         i->period_clean_count++;
         i->session_clean_count++;
     }
@@ -337,12 +428,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
     i->period_packet_in_count++;
     i->session_packet_in_count++;
 
-    i->period_need_range_avg = i->period_need_range / (i->period_missing_count || 1);
+    i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count);
 
     if (i->period_missing_count > i->qlen * 2) {
-#ifdef DB_JB
-        printf("resize %u %u\n", i->qlen, i->qlen + 1);
-#endif
+        if (stfu_log != null_logger && i->debug) {
+            stfu_log(STFU_LOG_EMERG, "%s resize %u %u\n", i->name, i->qlen, i->qlen + 1);
+        }
         stfu_n_resize(i, i->qlen + 1);
         stfu_n_reset_counters(i);
     } else {
@@ -353,7 +444,24 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
         }
     }
 
+    
+    i->diff = 0;
+    
+    if (i->last_wr_ts) {
+        if (ts < 1000 && i->last_wr_ts > (UINT_MAX - 1000)) {
+            i->diff = abs(((UINT_MAX - i->last_wr_ts) + ts) / i->samples_per_packet);
+        } else if (ts) {
+            i->diff = abs(i->last_wr_ts - ts) / i->samples_per_packet;
+        }
+    }
+    
+    i->diff_total += i->diff;
+
     if ((i->period_packet_in_count > i->period_time)) {
+        uint32_t avg;
+
+        avg = i->diff_total / least1(i->period_packet_in_count);
+
         i->period_packet_in_count = 0;
 
         if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) {
@@ -364,68 +472,38 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
         stfu_n_reset_counters(i);
     }
 
-#ifdef DB_JB
-    printf("%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u/%u - %u %d\n", 
-           i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, 
-           i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
-           seq, ts, 
-           i->period_missing_count, i->period_need_range_avg);
-#endif
 
+    
+
+    if (stfu_log != null_logger && i->debug) {
+        stfu_log(STFU_LOG_EMERG, "%s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d\n", i->name,
+               i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count, 
+               i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
+               ts, ts / i->samples_per_packet, 
+               i->period_missing_count, i->period_need_range_avg,
+               i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count));
+    }
 
        if (last || i->in_queue->array_len == i->in_queue->array_size) {
-               stfu_queue_t *other_queue;
-
-               other_queue = i->in_queue;
-               i->in_queue = i->out_queue;
-               i->out_queue = other_queue;
-
-               i->in_queue->array_len = 0;
-               i->out_queue->wr_len = 0;
-               i->last_frame = NULL;
-               i->miss_count = 0;
-        i->in_queue->last_index = 0;
-        i->out_queue->last_index = 0;
-        i->out_queue->last_jitter = 0;
+        stfu_n_swap(i);
     }
 
        if (last) {
                return STFU_IM_DONE;
        }
 
-    for(index = 0; index < i->in_queue->array_size; index++) {
-
-        if (i->in_queue->array[index].was_read) {
-            min_index = index;
-            break;
-        }
-        
-        if (i->in_queue->array[index].seq < min_seq) {
-            min_seq = i->in_queue->array[index].seq;
-            min_index = index;
-        }
-
-        if (i->in_queue->array[index].ts < min_ts) {
-            min_ts = i->in_queue->array[index].ts;
-            min_index = index;
-        }
-    }
-
-    index = min_index;
-    
-    if (i->in_queue->array_len < i->in_queue->array_size) {
-        i->in_queue->array_len++;
-    }
-
+    index = i->in_queue->array_len++;
     assert(index < i->in_queue->array_size);
-
        frame = &i->in_queue->array[index];
 
+       if (i->in_queue->array_len == i->in_queue->array_size) {
+        stfu_n_swap(i);
+    }
+
        if ((cplen = datalen) > sizeof(frame->data)) {
                cplen = sizeof(frame->data);
        }
 
-    i->last_seq = seq;
     i->last_rd_ts = ts;
     i->packet_count++;
 
@@ -433,61 +511,57 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uin
 
     frame->pt = pt;
        frame->ts = ts;
-    frame->seq = seq;
        frame->dlen = cplen;
        frame->was_read = 0;    
 
        return STFU_IT_WORKED;
 }
 
-static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_frame_t **r_frame)
+static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_frame_t **r_frame)
 {
     uint32_t i = 0;
     stfu_frame_t *frame = NULL;
-    stfu_queue_t *queue;
 
     assert(r_frame);
     
     *r_frame = NULL;
 
-    for (queue = in->out_queue ; queue && queue != in->in_queue ; queue = in->in_queue) {
-
-        for(i = 0; i < queue->real_array_size; i++) {
-            frame = &queue->array[i];
-            if (!frame->was_read) {
-                *r_frame = frame;
-                queue->last_index = i;
-                frame->was_read = 1;
-                in->period_packet_out_count++;
-                in->session_packet_out_count++;
-                return 1;
-            }
+    for(i = 0; i < queue->real_array_size; i++) {
+        frame = &queue->array[i];
+        if (!frame->was_read) {
+            *r_frame = frame;
+            queue->last_index = i;
+            frame->was_read = 1;
+            in->period_packet_out_count++;
+            in->session_packet_out_count++;
+            return 1;
         }
-
     }
 
     return 0;    
 }
 
 
-static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, uint32_t seq, stfu_frame_t **r_frame)
+static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame)
 {
     uint32_t i = 0;
     stfu_frame_t *frame = NULL;
 
-    assert(r_frame);
-    
-    *r_frame = NULL;
+    if (r_frame) {
+        *r_frame = NULL;
+    }
 
-    for(i = 0; i < queue->real_array_size; i++) {
+    for(i = 0; i < queue->array_size; i++) {
         frame = &queue->array[i];
         
-        if (((seq || in->last_seq) && frame->seq == seq) || frame->ts == ts) {
-            *r_frame = frame;
-            queue->last_index = i;
-            frame->was_read = 1;
-            in->period_packet_out_count++;
-            in->session_packet_out_count++;
+        if (frame->ts == ts) {
+            if (r_frame) {
+                *r_frame = frame;
+                queue->last_index = i;
+                frame->was_read = 1;
+                in->period_packet_out_count++;
+                in->session_packet_out_count++;
+            }
             return 1;
         }
     }
@@ -500,48 +574,76 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
        stfu_frame_t *rframe = NULL;
     int found = 0;
 
-       if (!i->samples_per_packet || !i->out_queue->array_len) {
-        //|| ((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) {
-               return NULL;
-       }
+       if (!i->samples_per_packet) {
+        return NULL;
+    }
+    
+    if (!i->ready) {
+        if (stfu_log != null_logger && i->debug) {
+            stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name);
+        }
+        return NULL;
+    }
+
 
-    if (i->cur_ts == 0) {
-               i->cur_ts = i->out_queue->array[0].ts;
+    if (i->cur_ts == 0 && i->last_wr_ts < 1000) {
+        uint32_t x = 0;
+        for (x = 0; x < i->out_queue->array_len; x++) {
+            if (!i->out_queue->array[x].was_read) {
+                i->cur_ts = i->out_queue->array[x].ts;
+                break;
+            }
+            if (i->cur_ts == 0) {
+                if (stfu_log != null_logger && i->debug) {
+                    stfu_log(STFU_LOG_EMERG, "%s XXXPUNT\n", i->name);
+                    return NULL;
+                }
+            }
+        }
     } else {
-               i->cur_ts += i->samples_per_packet;
+        i->cur_ts = i->cur_ts + i->samples_per_packet;
     }
     
-    if (i->cur_seq == 0) {
-        i->cur_seq = i->out_queue->array[0].seq;
+    found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, &rframe);
+
+    if (found) {
+        if (i->out_queue->array_len) {
+            i->out_queue->array_len--;
+        }
     } else {
-        i->cur_seq++; 
-        /* if we bother using this for anything that doesn't have 16 bit seq, we'll make this a param */
-        if (i->cur_seq == 65535) {
-            i->cur_seq = 0;
+        found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, &rframe);
+
+        if (!found) {
+            found = stfu_n_find_frame(i, i->old_queue, i->cur_ts, &rframe);
         }
     }
 
-    if (!(found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, i->cur_seq, &rframe))) {
-        found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, i->cur_seq, &rframe);
+    if (i->sync_out) {
+        if (!found) {
+            if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe))) {
+                i->cur_ts = rframe->ts;
+            }
+            
+            if (stfu_log != null_logger && i->debug) {
+                stfu_log(STFU_LOG_EMERG, "%s SYNC %u %u:%u\n", i->name, i->sync_out, i->cur_ts, i->cur_ts / i->samples_per_packet);
+            }
+
+        }
+        i->sync_out = 0;
     }
 
-    if (!found && i->sync) {
-#ifdef DB_JB
-        printf("SYNC %u\n", i->sync);
-#endif
-        if ((found = stfu_n_find_any_frame(i, &rframe))) {
-            i->cur_seq = rframe->seq;
-            i->cur_ts = rframe->ts;
+    if (!i->cur_ts) {
+        if (stfu_log != null_logger && i->debug) {
+            stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name);
         }
-        i->sync = 0;
+        return NULL;
     }
 
 
     if (!found && i->samples_per_packet) {
-#ifdef DB_JB
         int y;
         stfu_frame_t *frame = NULL;
-#endif
+
         int32_t delay = i->last_rd_ts - i->cur_ts;
         uint32_t need  = abs(i->last_rd_ts - i->cur_ts) / i->samples_per_packet;
 
@@ -550,30 +652,32 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
         i->session_missing_count++;
         i->period_need_range += need;
 
-#ifdef DB_JB        
-        printf("MISSING %u %u %u %u %d %u %d\n", i->cur_seq, i->cur_ts, i->packet_count, i->last_rd_ts, delay, i->qlen, need);        
-#endif
+        if (stfu_log != null_logger && i->debug) {        
+            stfu_log(STFU_LOG_EMERG, "%s MISSING %u:%u %u %u %d %u %d\n", i->name, 
+                     i->cur_ts, i->cur_ts / i->samples_per_packet, i->packet_count, i->last_rd_ts, delay, i->qlen, need);        
+        }
 
         if (i->packet_count > i->orig_qlen * 100 && delay > 0 && need > i->qlen && need < (i->qlen + 5)) {
             i->packet_count = 0;
         }
 
-#ifdef DB_JB        
-        for(y = 0; y < i->out_queue->array_size; y++) {
-            if ((y % 5) == 0) printf("\n");
-            frame = &i->out_queue->array[y];
-            printf("%u:%u\t", frame->seq, frame->ts);
-        }
-        printf("\n\n");
+        if (stfu_log != null_logger && i->debug) {        
+            for(y = 0; y < i->out_queue->array_size; y++) {
+                if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s", i->name);
+                frame = &i->out_queue->array[y];
+                stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
+            }
+            stfu_log(STFU_LOG_EMERG, "%s\n", i->name);
+
 
+            for(y = 0; y < i->in_queue->array_size; y++) {
+                if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s", i->name);
+                frame = &i->in_queue->array[y];
+                stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
+            }
+            stfu_log(STFU_LOG_EMERG, "%s\n\n\n", i->name);
 
-        for(y = 0; y < i->in_queue->array_size; y++) {
-            if ((y % 5) == 0) printf("\n");
-            frame = &i->in_queue->array[y];
-            printf("%u:%u\t", frame->seq, frame->ts);
         }
-        printf("\n\n");
-#endif
 
         if (delay < 0) {
             stfu_n_reset(i);
@@ -581,14 +685,11 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
         }
     }
 
-#ifdef DB_JB
-    if (found) {
-        printf("O: %u:%u %u %d\n", rframe->seq, rframe->ts, rframe->plc, rframe->seq - i->last_seq);
-    } else {
-        printf("DATA: %u %u %d %s %d\n", i->packet_count, i->consecutive_good_count, i->out_queue->last_jitter, found ? "found" : "not found", i->qlen);
+    if (stfu_log != null_logger && i->debug) {
+        if (found) {
+            stfu_log(STFU_LOG_EMERG, "%s O: %u:%u %u\n", i->name, rframe->ts, rframe->ts / i->samples_per_packet, rframe->plc);
+        }
     }
-#endif
-
 
     if (found) {
         i->consecutive_good_count++;
@@ -602,36 +703,28 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
 
     if (found) {
         i->last_frame = rframe;
-               i->out_queue->wr_len++;
-               i->last_wr_ts = rframe->ts;
-        i->last_wr_seq = rframe->seq;
-               i->miss_count = 0;
+        i->out_queue->wr_len++;
+        i->last_wr_ts = rframe->ts;
+
+        i->miss_count = 0;
         if (rframe->dlen) {
             i->plc_len = rframe->dlen;
         }
+
+        i->plc_pt = rframe->pt;
+
     } else {
         i->last_wr_ts = i->cur_ts;
-        i->last_wr_seq = i->cur_seq;
         rframe = &i->out_queue->int_frame;
         rframe->dlen = i->plc_len;
-        
-#if 0
-        if (i->last_frame) {
-            /* poor man's plc..  Copy the last frame, but we flag it so you can use a better one if you wish */
-            if (i->miss_count) {
-                memset(rframe->data, 255, rframe->dlen);
-            } else {
-                memcpy(rframe->data, i->last_frame->data, rframe->dlen);
-            }
-        }
-#endif
+        rframe->pt = i->plc_pt;
         rframe->ts = i->cur_ts;
-
         i->miss_count++;
-
-#ifdef DB_JB
-        printf("PLC %d %d %ld %u %u\n", i->miss_count, rframe->plc, rframe->dlen, rframe->seq, rframe->ts);
-#endif
+        
+        if (stfu_log != null_logger && i->debug) {
+            stfu_log(STFU_LOG_EMERG, "%s PLC %d %d %ld %u:%u\n", i->name, 
+                     i->miss_count, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet);
+        }
 
         if (i->miss_count > i->max_plc) {
             stfu_n_reset(i);
@@ -639,9 +732,138 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
         }
     }
 
-       return rframe;
+    return rframe;
 }
 
+#ifdef WIN32
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+#endif
+
+
+int vasprintf(char **ret, const char *format, va_list ap);
+
+int stfu_vasprintf(char **ret, const char *fmt, va_list ap)
+{
+#if !defined(WIN32) && !defined(__sun)
+       return vasprintf(ret, fmt, ap);
+#else
+       char *buf;
+       int len;
+       size_t buflen;
+       va_list ap2;
+       char *tmp = NULL;
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1500
+       /* hack for incorrect assumption in msvc header files for code analysis */
+       __analysis_assume(tmp);
+#endif
+       ap2 = ap;
+#else
+       va_copy(ap2, ap);
+#endif
+
+       len = vsnprintf(tmp, 0, fmt, ap2);
+
+       if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
+               len = vsnprintf(buf, buflen, fmt, ap);
+               *ret = buf;
+       } else {
+               *ret = NULL;
+               len = -1;
+       }
+
+       va_end(ap2);
+       return len;
+#endif
+}
+
+
+
+
+int stfu_snprintf(char *buffer, size_t count, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+
+       va_start(ap, fmt);
+       ret = vsnprintf(buffer, count-1, fmt, ap);
+       if (ret < 0)
+               buffer[count-1] = '\0';
+       va_end(ap);
+       return ret;
+}
+
+static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
+{
+       if (file && func && line && level && fmt) {
+               return;
+       }
+       return;
+}
+
+
+
+static const char *LEVEL_NAMES[] = {
+       "EMERG",
+       "ALERT",
+       "CRIT",
+       "ERROR",
+       "WARNING",
+       "NOTICE",
+       "INFO",
+       "DEBUG",
+       NULL
+};
+
+static const char *cut_path(const char *in)
+{
+       const char *p, *ret = in;
+       char delims[] = "/\\";
+       char *i;
+
+       for (i = delims; *i; i++) {
+               p = in;
+               while ((p = strchr(p, *i)) != 0) {
+                       ret = ++p;
+               }
+       }
+       return ret;
+}
+
+
+static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
+{
+       const char *fp;
+       char *data;
+       va_list ap;
+       int ret;
+       
+       if (level < 0 || level > 7) {
+               level = 7;
+       }
+       if (level > stfu_log_level) {
+               return;
+       }
+       
+       fp = cut_path(file);
+
+       va_start(ap, fmt);
+
+       ret = stfu_vasprintf(&data, fmt, ap);
+
+       if (ret != -1) {
+               fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
+               free(data);
+       }
+
+       va_end(ap);
+
+}
+
+
 /* For Emacs:
  * Local Variables:
  * mode:c
index d2760b27bc29285f33190dd13a43d5da3fb5da4d..f65511b5f49c6ea64cfa540e565ed750040ebcb3 100644 (file)
@@ -38,6 +38,8 @@ extern "C" {
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
+
 
 #ifdef  _MSC_VER
 #ifndef uint32_t
@@ -62,6 +64,85 @@ typedef unsigned long   in_addr_t;
 #endif
 #include <assert.h>
 
+
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+typedef SOCKET stfu_socket_t;
+typedef unsigned __int64 uint64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8 uint8_t;
+typedef __int64 int64_t;
+typedef __int32 int32_t;
+typedef __int16 int16_t;
+typedef __int8 int8_t;
+typedef intptr_t stfu_ssize_t;
+typedef int stfu_filehandle_t;
+#define STFU_SOCK_INVALID INVALID_SOCKET
+#define strerror_r(num, buf, size) strerror_s(buf, size, num)
+#if defined(STFU_DECLARE_STATIC)
+#define STFU_DECLARE(type)                     type __stdcall
+#define STFU_DECLARE_NONSTD(type)              type __cdecl
+#define STFU_DECLARE_DATA
+#elif defined(STFU_EXPORTS)
+#define STFU_DECLARE(type)                     __declspec(dllexport) type __stdcall
+#define STFU_DECLARE_NONSTD(type)              __declspec(dllexport) type __cdecl
+#define STFU_DECLARE_DATA                              __declspec(dllexport)
+#else
+#define STFU_DECLARE(type)                     __declspec(dllimport) type __stdcall
+#define STFU_DECLARE_NONSTD(type)              __declspec(dllimport) type __cdecl
+#define STFU_DECLARE_DATA                              __declspec(dllimport)
+#endif
+#else
+#define STFU_DECLARE(type) type
+#define STFU_DECLARE_NONSTD(type) type
+#define STFU_DECLARE_DATA
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdarg.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define STFU_SOCK_INVALID -1
+typedef int stfu_socket_t;
+typedef ssize_t stfu_ssize_t;
+typedef int stfu_filehandle_t;
+#endif
+
+
+#define STFU_PRE __FILE__, __FUNCTION__, __LINE__
+#define STFU_LOG_LEVEL_DEBUG 7
+#define STFU_LOG_LEVEL_INFO 6
+#define STFU_LOG_LEVEL_NOTICE 5
+#define STFU_LOG_LEVEL_WARNING 4
+#define STFU_LOG_LEVEL_ERROR 3
+#define STFU_LOG_LEVEL_CRIT 2
+#define STFU_LOG_LEVEL_ALERT 1
+#define STFU_LOG_LEVEL_EMERG 0
+
+#define STFU_LOG_DEBUG STFU_PRE, STFU_LOG_LEVEL_DEBUG
+#define STFU_LOG_INFO STFU_PRE, STFU_LOG_LEVEL_INFO
+#define STFU_LOG_NOTICE STFU_PRE, STFU_LOG_LEVEL_NOTICE
+#define STFU_LOG_WARNING STFU_PRE, STFU_LOG_LEVEL_WARNING
+#define STFU_LOG_ERROR STFU_PRE, STFU_LOG_LEVEL_ERROR
+#define STFU_LOG_CRIT STFU_PRE, STFU_LOG_LEVEL_CRIT
+#define STFU_LOG_ALERT STFU_PRE, STFU_LOG_LEVEL_ALERT
+#define STFU_LOG_EMERG STFU_PRE, STFU_LOG_LEVEL_EMERG
+typedef void (*stfu_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
+
+
+int stfu_vasprintf(char **ret, const char *fmt, va_list ap);
+
+STFU_DECLARE_DATA extern stfu_logger_t stfu_log;
+
+/*! Sets the logger for libstfu. Default is the null_logger */
+void stfu_global_set_logger(stfu_logger_t logger);
+/*! Sets the default log level for libstfu */
+void stfu_global_set_default_logger(int level);
+
 #define STFU_DATALEN 16384
 #define STFU_QLEN 300
 #define STFU_MAX_TRACK 256
@@ -69,13 +150,13 @@ typedef unsigned long   in_addr_t;
 typedef enum {
        STFU_IT_FAILED,
        STFU_IT_WORKED,
-       STFU_IM_DONE
+       STFU_IM_DONE,
+       STFU_ITS_TOO_LATE
 } stfu_status_t;
 
 struct stfu_frame {
        uint32_t ts;
        uint32_t pt;
-       uint32_t seq;
        uint8_t data[STFU_DATALEN];
        size_t dlen;
        uint8_t was_read;
@@ -100,14 +181,15 @@ void stfu_n_report(stfu_instance_t *i, stfu_report_t *r);
 void stfu_n_destroy(stfu_instance_t **i);
 stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second);
 stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen);
-stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t seq, uint32_t pt, void *data, size_t datalen, int last);
+stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last);
 stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i);
 void stfu_n_reset(stfu_instance_t *i);
 stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets);
 void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata);
+void stfu_n_debug(stfu_instance_t *i, const char *name);
 
 #define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1)
-#define stfu_n_eat(i,t,s,p,d,l) stfu_n_add_data(i, t, s, p, d, l, 0)
+#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0)
 
 #ifdef __cplusplus
 }