struct stfu_queue *old_queue;
struct stfu_frame *last_frame;
uint32_t cur_ts;
+ uint16_t cur_seq;
uint32_t last_wr_ts;
uint32_t last_rd_ts;
uint32_t samples_per_packet;
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;
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_ts = i->out_queue->array[x].seq;
break;
}
if (i->cur_ts == 0) {
}
} 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) {
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))) {
i->cur_ts = rframe->ts;
+ i->cur_seq = rframe->seq;
}
if (stfu_log != null_logger && i->debug) {
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) {
return rframe;
}
+int32_t stfu_n_copy_next_frame(stfu_instance_t *jb, uint32_t timestamp, uint16_t seq, uint16_t distance, stfu_frame_t *next_frame)
+{
+ uint32_t i = 0, j = 0;
+ stfu_queue_t *queues[] = { jb->out_queue, jb->in_queue, jb->old_queue};
+ stfu_queue_t *queue = NULL;
+ stfu_frame_t *frame = NULL;
+
+ uint32_t target_ts = 0;
+
+ if (!next_frame) return 0;
+
+ target_ts = timestamp + (distance - 1) * jb->samples_per_packet;
+
+ for (i = 0; i < sizeof(queues)/sizeof(queues[0]); i++) {
+ queue = queues[i];
+
+ if (!queue) continue;
+
+ for(j = 0; j < queue->array_size; j++) {
+ frame = &queue->array[j];
+ /* FIXME: ts rollover happened? bad luck */
+ if (frame->ts > target_ts) {
+ memcpy(next_frame, frame, sizeof(stfu_frame_t));
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
#ifdef WIN32
#ifndef vsnprintf
#define vsnprintf _vsnprintf
}
-
/* For Emacs:
* Local Variables:
* mode:c
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, uint16_t seq, uint32_t pt, void *data, size_t datalen, uint32_t timer_ts, int last);
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i);
+int32_t stfu_n_copy_next_frame(stfu_instance_t *jb, uint32_t timestamp, uint16_t seq, uint16_t distance, stfu_frame_t *next_frame);
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);
LOCAL_CFLAGS=-I$(SILK_DIR)/src -I$(SILK_DIR)/interface
SILK_LA=$(SILK_BUILDDIR)/.libs/libSKP_SILK_SDK.la
LOCAL_LIBADD=$(SILK_LA)
+LOCAL_OBJS=$(BASE)/libs/stfu/stfu.o
include $(BASE)/build/modmake.rules
$(SILK_LA): $(SILK_DIR)/.update
*/
#include "switch.h"
+#include "stfu.h"
#include "SKP_Silk_SDK_API.h"
SWITCH_MODULE_LOAD_FUNCTION(mod_silk_load);
SKP_int16 ret, len;
int16_t *target = decoded_data;
switch_core_session_t *session = codec->session;
- stfu_instance_t *jb;
+ stfu_instance_t *jb = NULL;
- *decoded_data_len = 0;
+ SKP_int lost_flag = (*flag & SFF_PLC);
+ stfu_frame_t next_frame;
- if (session) {
- jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO);
- }
+ SKP_uint8 recbuff[STFU_DATALEN];
+ SKP_int16 reclen;
+ int32_t found_frame;
+ switch_bool_t did_lbrr = SWITCH_FALSE;
- if (jb) {
- /* to allow compile */
- jb = NULL;
+ *decoded_data_len = 0;
+
+ if (lost_flag) {
+ if (session) {
+ jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO);
+ }
+ if (jb && codec && codec->cur_frame) {
+ for (int i = 1; i <= MAX_LBRR_DELAY; i++) {
+ found_frame = stfu_n_copy_next_frame(jb, codec->cur_frame->timestamp, codec->cur_frame->seq, i, &next_frame);
+ if (found_frame) {
+ SKP_Silk_SDK_search_for_LBRR(next_frame.data, next_frame.dlen, i, (SKP_uint8*) &recbuff, &reclen);
+ if (reclen) {
+ encoded_data = &recbuff;
+ encoded_data_len = reclen;
+ lost_flag = SKP_FALSE;
+ did_lbrr = SWITCH_TRUE;
+ break;
+ }
+ }
+ }
+ }
}
do {
ret = SKP_Silk_SDK_Decode(context->dec_state,
&context->decoder_object,
- ((*flag & SFF_PLC)),
+ lost_flag,
encoded_data,
encoded_data_len,
target,
if (ret){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Decode returned %d!\n", ret);
printSilkError(ret);
+ /* if FEC was activated, we can ignore bit errors*/
+ if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr))
return SWITCH_STATUS_FALSE;
}