[Freeswitch-svn] [commit] r5087 - freeswitch/trunk/libs/stfu
Freeswitch SVN
anthm at freeswitch.org
Fri May 4 17:11:28 EDT 2007
Author: anthm
Date: Fri May 4 17:11:27 2007
New Revision: 5087
Added:
freeswitch/trunk/libs/stfu/
freeswitch/trunk/libs/stfu/stfu.c
freeswitch/trunk/libs/stfu/stfu.h
Log:
STFU
Added: freeswitch/trunk/libs/stfu/stfu.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/stfu/stfu.c Fri May 4 17:11:27 2007
@@ -0,0 +1,256 @@
+/*
+ * STFU (S)ort (T)ransportable (F)ramed (U)tterances
+ * Copyright (c) 2007 Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * THOSE WHO DISAGREE MAY CERTIANLY STFU
+ */
+#include "stfu.h"
+
+struct stfu_queue {
+ struct stfu_frame *array;
+ struct stfu_frame int_frame;
+ uint32_t array_size;
+ uint32_t array_len;
+ uint32_t wr_len;
+ uint32_t last_index;
+};
+typedef struct stfu_queue stfu_queue_t;
+
+struct stfu_instance {
+ struct stfu_queue a_queue;
+ struct stfu_queue b_queue;
+ struct stfu_queue *in_queue;
+ struct stfu_queue *out_queue;
+ uint32_t last_ts;
+ uint32_t interval;
+ uint32_t miss_count;
+ uint8_t running;
+};
+
+
+static void stfu_n_init_aqueue(stfu_queue_t *queue, uint32_t qlen)
+{
+ queue->array = calloc(qlen, sizeof(struct stfu_frame));
+ assert(queue->array != NULL);
+ memset(queue->array, 0, sizeof(struct stfu_frame) * qlen);
+ queue->array_size = qlen;
+ queue->int_frame.plc = 1;
+}
+
+void stfu_n_destroy(stfu_instance_t **i)
+{
+ stfu_instance_t *ii;
+
+ if (i && *i) {
+ ii = *i;
+ *i = NULL;
+ free(ii->a_queue.array);
+ free(ii->b_queue.array);
+ free(ii);
+ }
+}
+
+stfu_instance_t *stfu_n_init(uint32_t qlen)
+{
+ struct stfu_instance *i;
+
+ i = malloc(sizeof(*i));
+ assert(i != NULL);
+ memset(i, 0, sizeof(*i));
+ stfu_n_init_aqueue(&i->a_queue, qlen);
+ stfu_n_init_aqueue(&i->b_queue, qlen);
+ i->in_queue = &i->a_queue;
+ i->out_queue = &i->b_queue;
+ return i;
+}
+
+static int32_t stfu_n_measure_interval(stfu_instance_t *i, stfu_queue_t *queue)
+{
+ uint32_t index;
+ int32_t d, most = 0, last = 0, this, track[STFU_MAX_TRACK] = {0};
+
+ for(index = 0; index < queue->array_len; index++) {
+ this = queue->array[index].ts;
+ if (last) {
+
+ if ((d = this - last) > 0 && d / 10 < STFU_MAX_TRACK) {
+ track[(d/10)]++;
+ }
+ }
+
+ last = this;
+ }
+
+ for(index = 0; index < STFU_MAX_TRACK; index++) {
+ if (track[index] > most) {
+ most = index;
+ }
+ }
+
+ return most * 10;
+
+}
+
+static int16_t stfu_n_process(stfu_instance_t *i, stfu_queue_t *queue)
+{
+ if (!i->interval && !(i->interval = stfu_n_measure_interval(i, queue))) {
+ return -1;
+ }
+
+ return 0;
+}
+
+stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, void *data, size_t datalen, int last)
+{
+ uint32_t index;
+ stfu_frame_t *frame;
+ size_t cplen = 0;
+
+
+ if (last || i->in_queue->array_len == i->in_queue->array_size) {
+ stfu_queue_t *other_queue;
+
+ if (i->out_queue->wr_len < i->out_queue->array_len) {
+ return STFU_IT_FAILED;
+ }
+
+ 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->out_queue->last_index = 0;
+ i->miss_count = 0;
+
+ if (stfu_n_process(i, i->out_queue) < 0) {
+ return STFU_IT_FAILED;
+ }
+ for(index = 0; index < i->out_queue->array_len; index++) {
+ i->out_queue->array[index].was_read = 0;
+ }
+ }
+
+ if (last) {
+ return STFU_IM_DONE;
+ }
+
+ index = i->in_queue->array_len++;
+ frame = &i->in_queue->array[index];
+
+ if ((cplen = datalen) > sizeof(frame->data)) {
+ cplen = sizeof(frame->data);
+ }
+
+
+ memcpy(frame->data, data, cplen);
+ frame->ts = ts;
+ frame->dlen = cplen;
+ frame->was_read = 0;
+
+ return STFU_IT_WORKED;
+}
+
+stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
+{
+ uint32_t index, index2;
+ uint32_t should_have = 0;
+ stfu_frame_t *frame = NULL, *rframe = NULL;
+
+
+ if ((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len) {
+ return NULL;
+ }
+
+ if (i->running) {
+ should_have = i->last_ts + i->interval;
+ }
+
+ for(index = 0; index < i->out_queue->array_len; index++) {
+ if (i->out_queue->array[index].was_read) {
+ continue;
+ }
+
+ frame = &i->out_queue->array[index];
+
+ if (frame->ts != should_have) {
+ int tried = 0;
+ for (index2 = 0; index2 < i->out_queue->array_len; index2++) {
+ if (i->out_queue->array[index2].was_read) {
+ continue;
+ }
+ tried++;
+ if (i->out_queue->array[index2].ts == should_have) {
+ rframe = &i->out_queue->array[index2];
+ i->out_queue->last_index = index2;
+ goto done;
+ }
+ }
+ for (index2 = 0; index2 < i->in_queue->array_len; index2++) {
+ if (i->in_queue->array[index2].was_read) {
+ continue;
+ }
+ tried++;
+ if (i->in_queue->array[index2].ts == should_have) {
+ rframe = &i->in_queue->array[index2];
+ goto done;
+ }
+ }
+
+ i->miss_count++;
+
+ if (i->miss_count > 10) {
+ i->out_queue->wr_len = i->out_queue->array_len;
+ i->last_ts = should_have = frame->ts;
+ return NULL;
+ }
+ i->last_ts = should_have;
+ rframe = &i->out_queue->int_frame;
+ rframe->dlen = i->out_queue->array[i->out_queue->last_index].dlen;
+ /* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */
+ memcpy(rframe->data, i->out_queue->array[i->out_queue->last_index].data, rframe->dlen);
+ rframe->ts = should_have;
+ i->out_queue->wr_len++;
+ i->running = 1;
+ return rframe;
+ } else {
+ rframe = &i->out_queue->array[index];
+ i->out_queue->last_index = index;
+ goto done;
+ }
+ }
+
+ done:
+
+ if (rframe) {
+ i->out_queue->wr_len++;
+ i->last_ts = rframe->ts;
+ rframe->was_read = 1;
+ i->running = 1;
+ }
+
+ return rframe;
+}
+
+
Added: freeswitch/trunk/libs/stfu/stfu.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/stfu/stfu.h Fri May 4 17:11:27 2007
@@ -0,0 +1,96 @@
+/*
+ * STFU (S)ort (T)ransportable (F)ramed (U)tterances
+ * Copyright (c) 2007 Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * THOSE WHO DISAGREE MAY CERTIANLY STFU
+ */
+
+#ifndef STFU_H
+#define STFU_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __STUPIDFORMATBUG__
+}
+#endif
+
+#include <stdio.h>
+
+#ifdef _MSC_VER
+#ifndef uint32_t
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned long in_addr_t;
+#endif
+#define snprintf _snprintf
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <inttypes.h>
+#endif
+#include <assert.h>
+
+#define STFU_DATALEN 16384
+#define STFU_QLEN 300
+#define STFU_MAX_TRACK 256
+
+typedef enum {
+ STFU_IT_FAILED,
+ STFU_IT_WORKED,
+ STFU_IM_DONE
+} stfu_status_t;
+
+struct stfu_frame {
+ uint32_t ts;
+ uint8_t data[STFU_DATALEN];
+ size_t dlen;
+ uint8_t was_read;
+ uint8_t plc;
+};
+typedef struct stfu_frame stfu_frame_t;
+
+struct stfu_instance;
+typedef struct stfu_instance stfu_instance_t;
+
+void stfu_n_destroy(stfu_instance_t **i);
+stfu_instance_t *stfu_n_init(uint32_t qlen);
+stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, void *data, size_t datalen, int last);
+stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i);
+#define stfu_im_done() stfu_n_add_data(i, 0, NULL, 0, 1)
+#define stfu_n_eat(i,t,d,l) stfu_n_add_data(i, t, d, l, 0)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*STFU_H*/
+
More information about the Freeswitch-svn
mailing list