typedef struct switch_frame_node_s {
switch_frame_t *frame;
int inuse;
+ struct switch_frame_node_s *prev;
struct switch_frame_node_s *next;
} switch_frame_node_t;
switch_frame_node_t *head;
switch_memory_pool_t *pool;
switch_mutex_t *mutex;
+ uint32_t total;
};
static switch_frame_t *find_free_frame(switch_frame_buffer_t *fb, switch_frame_t *orig)
{
switch_frame_node_t *np;
+ int x = 0;
switch_mutex_lock(fb->mutex);
+
for (np = fb->head; np; np = np->next) {
+ x++;
+
if (!np->inuse && ((orig->packet && np->frame->packet) || (!orig->packet && !np->frame->packet))) {
+
+ if (np == fb->head) {
+ fb->head = np->next;
+ } else if (np->prev) {
+ np->prev->next = np->next;
+ }
+
+ if (np->next) {
+ np->next->prev = np->prev;
+ }
+
+ fb->total--;
+ np->prev = np->next = NULL;
break;
- }
+ }
}
-
+
if (!np) {
np = switch_core_alloc(fb->pool, sizeof(*np));
np->frame = switch_core_alloc(fb->pool, sizeof(*np->frame));
np->frame->data = switch_core_alloc(fb->pool, SWITCH_RTP_MAX_BUF_LEN);
np->frame->buflen = SWITCH_RTP_MAX_BUF_LEN;
}
- np->next = fb->head;
- fb->head = np;
}
-
np->frame->samples = orig->samples;
np->frame->rate = orig->rate;
np->frame->channels = orig->channels;
old_frame = *frameP;
*frameP = NULL;
-
+
node = (switch_frame_node_t *) old_frame->extra_data;
node->inuse = 0;
switch_img_free(&node->frame->img);
+
+ fb->total++;
+
+ if (fb->head) {
+ fb->head->prev = node;
+ }
+
+ node->next = fb->head;
+ node->prev = NULL;
+ fb->head = node;
+
+ switch_assert(node->next != node);
+ switch_assert(node->prev != node);
+
switch_mutex_unlock(fb->mutex);
switch_rtp_packet_t packet;
uint32_t len;
uint8_t visible;
+ struct switch_vb_node_s *prev;
struct switch_vb_node_s *next;
} switch_vb_node_t;
switch_inthash_t *missing_seq_hash;
switch_inthash_t *node_hash;
switch_mutex_t *mutex;
+ switch_mutex_t *list_mutex;
switch_memory_pool_t *pool;
int free_pool;
switch_vb_flag_t flags;
static inline switch_vb_node_t *new_node(switch_vb_t *vb)
{
- switch_vb_node_t *np, *last = NULL;
+ switch_vb_node_t *np;
+
+ switch_mutex_lock(vb->list_mutex);
for (np = vb->node_list; np; np = np->next) {
if (!np->visible) {
break;
}
- last = np;
}
if (!np) {
np = switch_core_alloc(vb->pool, sizeof(*np));
-
- if (last) {
- last->next = np;
- } else {
- vb->node_list = np;
+
+ np->next = vb->node_list;
+ if (np->next) {
+ np->next->prev = np;
}
-
+ vb->node_list = np;
+
}
switch_assert(np);
vb->visible_nodes++;
np->parent = vb;
+ switch_mutex_unlock(vb->list_mutex);
+
return np;
}
-#if 0
-static inline switch_vb_node_t *find_seq(switch_vb_t *vb, uint16_t seq)
+static inline void push_to_top(switch_vb_t *vb, switch_vb_node_t *node)
{
- switch_vb_node_t *np;
- for (np = vb->node_list; np; np = np->next) {
- if (!np->visible) continue;
+ if (node == vb->node_list) {
+ vb->node_list = node->next;
+ } else if (node->prev) {
+ node->prev->next = node->next;
+ }
- if (ntohs(np->packet.header.seq) == ntohs(seq)) {
- return np;
- }
+ if (node->next) {
+ node->next->prev = node->prev;
}
- return NULL;
+ node->next = vb->node_list;
+ node->prev = NULL;
+
+ if (node->next) {
+ node->next->prev = node;
+ }
+
+ vb->node_list = node;
+
+ switch_assert(node->next != node);
+ switch_assert(node->prev != node);
}
-#endif
-static inline void hide_node(switch_vb_node_t *node)
+static inline void hide_node(switch_vb_node_t *node, switch_bool_t pop)
{
+ switch_vb_t *vb = node->parent;
+
+ switch_mutex_lock(vb->list_mutex);
+
if (node->visible) {
node->visible = 0;
- node->parent->visible_nodes--;
+ vb->visible_nodes--;
+
+ if (pop) {
+ push_to_top(vb, node);
+ }
+ }
+
+ switch_core_inthash_delete(vb->node_hash, node->packet.header.seq);
+
+ switch_mutex_unlock(vb->list_mutex);
+}
+
+static inline void sort_free_nodes(switch_vb_t *vb)
+{
+ switch_vb_node_t *np, *this_np;
+ int start = 0;
+
+ switch_mutex_lock(vb->list_mutex);
+ np = vb->node_list;
+
+ while(np) {
+ this_np = np;
+ np = np->next;
+
+ if (this_np->visible) {
+ start++;
+ }
+
+ if (start && !this_np->visible) {
+ push_to_top(vb, this_np);
+ }
}
- switch_core_inthash_delete(node->parent->node_hash, node->packet.header.seq);
+
+ switch_mutex_unlock(vb->list_mutex);
}
static inline void hide_nodes(switch_vb_t *vb)
{
switch_vb_node_t *np;
+ switch_mutex_lock(vb->list_mutex);
for (np = vb->node_list; np; np = np->next) {
- hide_node(np);
+ hide_node(np, SWITCH_FALSE);
}
+ switch_mutex_unlock(vb->list_mutex);
}
static inline void drop_ts(switch_vb_t *vb, uint32_t ts)
switch_vb_node_t *np;
int x = 0;
+ switch_mutex_lock(vb->list_mutex);
for (np = vb->node_list; np; np = np->next) {
if (!np->visible) continue;
if (ts == np->packet.header.ts) {
- hide_node(np);
+ hide_node(np, SWITCH_FALSE);
x++;
}
}
+ if (x) {
+ sort_free_nodes(vb);
+ }
+
+ switch_mutex_unlock(vb->list_mutex);
+
if (x) vb->complete_frames--;
}
{
switch_vb_node_t *np, *lowest = NULL;
+ switch_mutex_lock(vb->list_mutex);
for (np = vb->node_list; np; np = np->next) {
if (!np->visible) continue;
lowest = np;
}
}
+ switch_mutex_unlock(vb->list_mutex);
return lowest ? lowest->packet.header.ts : 0;
}
{
switch_vb_node_t *np, *lowest = NULL;
+ switch_mutex_lock(vb->list_mutex);
for (np = vb->node_list; np; np = np->next) {
if (!np->visible) continue;
lowest = np;
}
}
+ switch_mutex_unlock(vb->list_mutex);
return lowest;
}
static inline void free_nodes(switch_vb_t *vb)
{
+ switch_mutex_lock(vb->list_mutex);
vb->node_list = NULL;
+ switch_mutex_unlock(vb->list_mutex);
}
SWITCH_DECLARE(void) switch_vb_set_flag(switch_vb_t *vb, switch_vb_flag_t flag)
switch_core_inthash_init(&vb->missing_seq_hash);
switch_core_inthash_init(&vb->node_hash);
switch_mutex_init(&vb->mutex, SWITCH_MUTEX_NESTED, pool);
-
+ switch_mutex_init(&vb->list_mutex, SWITCH_MUTEX_NESTED, pool);
*vbp = vb;
*packet = node->packet;
*len = node->len;
memcpy(packet->body, node->packet.body, node->len);
- hide_node(node);
+ hide_node(node, SWITCH_TRUE);
vb_debug(vb, 1, "GET packet ts:%u seq:%u %s\n", ntohl(packet->header.ts), ntohs(packet->header.seq), packet->header.m ? " <MARK>" : "");