void _stfu_n_reset(stfu_instance_t *i, const char *file, const char *func, int line) { if (stfu_log != null_logger && i->debug) { stfu_log(file, func, line, STFU_LOG_LEVEL_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); stfu_n_sync(i, 1); i->cur_ts = 0; i->cur_seq = 0; i->last_wr_ts = 0; i->last_rd_ts = 0; i->miss_count = 0; i->packet_count = 0; i->ts_offset = 0; }
void stfu_n_reset(stfu_instance_t *i) { 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); stfu_n_sync(i, 1); i->cur_ts = 0; i->last_wr_ts = 0; i->last_rd_ts = 0; i->miss_count = 0; i->packet_count = 0; }
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) { return NULL; } if (!i->ready) { if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s JITTERBUFFER NOT READY: IGNORING FRAME\n", i->name); } return NULL; } 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; i->cur_seq = i->out_queue->array[x].seq; break; } if (i->cur_ts == 0) { if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s JITTERBUFFER ERROR: PUNTING\n", i->name); return NULL; } } } } else { i->cur_ts = i->cur_ts + i->samples_per_packet; i->cur_seq++; } found = stfu_n_find_frame(i, i->out_queue, i->last_wr_ts, i->cur_ts, &rframe); if (!found) { found = stfu_n_find_frame(i, i->in_queue, i->last_wr_ts, i->cur_ts, &rframe); if (!found) { found = stfu_n_find_frame(i, i->old_queue, i->last_wr_ts, i->cur_ts, &rframe); } } if (found) { i->cur_ts = rframe->ts; i->cur_seq = rframe->seq; } if (i->sync_out) { if (!found) { if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe, 1))) { i->cur_ts = rframe->ts; i->cur_seq = rframe->seq; } 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 (!i->cur_ts) { if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name); } return NULL; } if (!found && i->samples_per_packet) { uint32_t y; stfu_frame_t *frame = NULL; int32_t delay = i->cur_ts - i->last_rd_ts; uint32_t need = abs(delay) / i->samples_per_packet; i->period_missing_count++; i->session_missing_count++; i->period_need_range += need; 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; } if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s ------------\n", i->name); for(y = 0; y < i->out_queue->array_len; y++) { frame = &i->out_queue->array[y]; stfu_log(STFU_LOG_EMERG, "%s\t%u:%u\n", i->name, frame->ts, frame->ts / i->samples_per_packet); } stfu_log(STFU_LOG_EMERG, "%s ------------\n\n\n", i->name); stfu_log(STFU_LOG_EMERG, "%s ------------\n", i->name); for(y = 0; y < i->in_queue->array_len; y++) { frame = &i->in_queue->array[y]; stfu_log(STFU_LOG_EMERG, "%s\t%u:%u\n", i->name, frame->ts, frame->ts / i->samples_per_packet); } stfu_log(STFU_LOG_EMERG, "%s\n\n\n", i->name); } } 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); } } if (found) { i->consecutive_good_count++; i->period_good_count++; i->consecutive_bad_count = 0; } else { i->consecutive_bad_count++; i->period_bad_count++; i->consecutive_good_count = 0; } if (found) { i->last_frame = rframe; 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 { int force = 0; if (i->consecutive_bad_count > (i->max_qlen / 2)) { force = 1; } if (stfu_n_find_any_frame(i, i->out_queue, &rframe, force)) { i->cur_ts = rframe->ts; i->cur_seq = rframe->seq; i->last_wr_ts = i->cur_ts; i->miss_count = 0; if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s AUTOCORRECT %d %d %ld %u:%u\n", i->name, i->miss_count, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet); } } else { if (force) { stfu_log(STFU_LOG_EMERG, "%s NO PACKETS HARD RESETTING\n", i->name); stfu_n_reset(i); } else { i->last_wr_ts = i->cur_ts; rframe = &i->out_queue->int_frame; rframe->dlen = i->plc_len; rframe->pt = i->plc_pt; rframe->ts = i->cur_ts; rframe->seq = i->cur_seq; i->miss_count++; if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s PLC %d/%d %d %ld %u:%u\n", i->name, i->miss_count, i->max_qlen, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet); } } } if (i->miss_count > i->max_qlen) { if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s TOO MANY MISS %d/%d SYNC...\n", i->name, i->miss_count, i->max_qlen); } stfu_n_sync(i, 1); } } return rframe; }
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint16_t seq, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last) { uint32_t index = 0; stfu_frame_t *frame; size_t cplen = 0; int good_ts = 0; if (!i->samples_per_packet && ts && i->last_rd_ts) { i->ts_diff = ts - i->last_rd_ts; if (i->last_ts_diff == i->ts_diff) { if (++i->same_ts == 5) { i->samples_per_packet = i->ts_diff; if (i->max_drift && i->samples_per_packet) { i->drift_max_dropped = (i->samples_per_second * 2) / i->samples_per_packet; } } } else { i->same_ts = 0; } i->last_ts_diff = i->ts_diff; if (!i->samples_per_packet) { i->last_rd_ts = ts; return STFU_IT_FAILED; } } if (timer_ts) { if (ts && !i->ts_offset) { i->ts_offset = timer_ts - ts; } i->ts_drift = ts + (i->ts_offset - timer_ts); if (i->ts_offset && i->ts_drift > 0) { i->ts_offset = timer_ts - ts; i->ts_drift = ts + (i->ts_offset - timer_ts); } if (i->max_drift) { if (i->ts_drift < i->max_drift) { if (++i->drift_dropped_packets < i->drift_max_dropped) { stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts); stfu_n_sync(i, 1); //return STFU_ITS_TOO_LATE; } } else { i->drift_dropped_packets = 0; } } } 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 > 4294900000u && ts < 5000)) { good_ts = 1; } if (i->last_wr_ts) { if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) { if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts); } stfu_n_sync(i, 1); return STFU_ITS_TOO_LATE; } } } if (good_ts) { i->period_clean_count++; i->session_clean_count++; } i->period_packet_in_count++; i->session_packet_in_count++; i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count); if (i->period_missing_count > i->qlen * 2) { 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 { if (i->qlen > i->orig_qlen && (i->consecutive_good_count > i->decrement_time || i->period_clean_count > i->decrement_time)) { stfu_n_resize(i, i->qlen - 1); stfu_n_reset_counters(i); stfu_n_sync(i, i->qlen); } } i->diff = 0; if (i->last_wr_ts) { if (ts < 1000 && i->last_wr_ts > (UINT_MAX - 1000)) { i->diff = abs((int)(((UINT_MAX - i->last_wr_ts) + ts) / i->samples_per_packet)); } else if (ts) { i->diff = abs((int)(i->last_wr_ts - ts)) / i->samples_per_packet; } } i->diff_total += i->diff; if ((i->period_packet_in_count > i->period_time)) { i->period_packet_in_count = 0; if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) { stfu_n_resize(i, i->qlen - 1); stfu_n_sync(i, i->qlen); } stfu_n_reset_counters(i); } if (stfu_log != null_logger && i->debug) { stfu_log(STFU_LOG_EMERG, "I: %s %u/%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d/%d\n", i->name, i->qlen, i->max_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), i->ts_drift, i->max_drift); } if (last || i->in_queue->array_len == i->in_queue->array_size) { stfu_n_swap(i); } if (last) { return STFU_IM_DONE; } 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_rd_ts = ts; i->packet_count++; memcpy(frame->data, data, cplen); frame->pt = pt; frame->ts = ts; frame->seq = seq; frame->dlen = cplen; frame->was_read = 0; return STFU_IT_WORKED; }