Beispiel #1
0
static void
pb_validate(pb_t *pb)
{
#ifdef DEBUG
        pb_node_t	*stop, *curr;
        uint32_t	 cnt = 0;

        stop = pb->psentinel;
        curr = pb->psentinel->prev;
        while (curr != stop) {
		assert(curr->magic == PB_NODE_MAGIC);
		assert(curr->data  != NULL);
		assert(curr->data_len > 0);
		assert(curr->next->prev == curr);
		assert(curr->prev->next == curr);
		if (curr->next != stop) assert(ts_gt(curr->next->playout, curr->playout));
		if (curr->prev != stop) assert(ts_gt(curr->playout, curr->prev->playout));
                curr = curr->prev;
                cnt++;
        }
        assert(pb->n_nodes == cnt);

	assert(pb->n_iterators < PB_MAX_ITERATORS);
	for (cnt = 0; cnt < pb->n_iterators; cnt ++) {
		assert(pb->iterators[cnt].buffer == pb);
	}
#endif
	assert(pb->magic == PB_MAGIC);
}
Beispiel #2
0
int
layered_decoder_decode(u_char      *state,
                       struct s_pb *in,
                       struct s_pb *out,
                       timestamp_t  now)
{
        struct s_pb_iterator *pi;
        u_char               *c_get;
        channel_data         *c;
        uint32_t              clen;
        timestamp_t           playout;

        UNUSED(state);

        pb_iterator_create(in, &pi);
        assert(pi != NULL);

        while(pb_iterator_get_at(pi, &c_get, &clen, &playout)) {
                c = (channel_data*)c_get;
                assert(c != NULL);
                assert(clen == sizeof(channel_data));

                if (ts_gt(playout, now)) {
                        /* Playout point of unit is after now.  Stop! */
                        break;
                }
                pb_iterator_detach_at(pi, &c_get, &clen, &playout);
                layered_decoder_reorganise(c, out, playout);
        }

        pb_iterator_destroy(in, &pi);

        return TRUE;
}
Beispiel #3
0
int
redundancy_decoder_decode(u_char       *state,
                           struct s_pb *in,
                           struct s_pb *out,
                           timestamp_t  now)
{
        struct s_pb_iterator *pi;
        u_char               *c_get;
        channel_data         *c;
        uint32_t              clen;
        timestamp_t           cplayout;

        pb_iterator_create(in, &pi);
        assert(pi != NULL);

        assert(state == NULL); /* No decoder state necesssary */
        UNUSED(state);

        while(pb_iterator_get_at(pi, &c_get, &clen, &cplayout)) {
                c = (channel_data*)c_get;
                assert(c != NULL);
                assert(clen == sizeof(channel_data));
                if (ts_gt(cplayout, now)) {
                        break;
                }
                pb_iterator_detach_at(pi, &c_get, &clen, &cplayout);
                c = (channel_data*)c_get;
                assert(c->nelem == 1);
                redundancy_decoder_output(c->elem[0], out, cplayout);
                channel_data_destroy(&c, sizeof(channel_data));
        }

        pb_iterator_destroy(in, &pi);
        return TRUE;
}
Beispiel #4
0
static media_data *
red_media_data_create_or_get(struct s_pb *p, timestamp_t playout)
{
        struct s_pb_iterator *pi;
        u_char               *md_get;
        media_data           *md;
        uint32_t              md_len, success;
        timestamp_t           md_playout;

        pb_iterator_create(p, &pi);
        /* iterator is attached to sentinel - can move back or forwards */

        while(pb_iterator_retreat(pi)) {
                success = pb_iterator_get_at(pi, &md_get, &md_len, &md_playout);
                md = (media_data*)md_get;
                assert(success);
                if (ts_eq(md_playout, playout)) {
                        goto done;
                } else if (ts_gt(playout, md_playout)) {
                        /* we have gone too far back */
                        break;
                }
        }

        /* Not found in playout buffer */
        media_data_create(&md, 0);
        success = pb_add(p, (u_char*)md, sizeof(media_data), playout);
        assert(success);

done:
        pb_iterator_destroy(p, &pi);
        return md;
}
timestamp_t 
playout_calc(session_t *sp, uint32_t ssrc, timestamp_t transit, int new_spurt)
/*****************************************************************************/
/* The primary purpose of this function is to calculate the playout point    */
/* for new talkspurts (new_spurt).  It also maintains the jitter and transit */
/* time estimates from the source to us.  The value returned is the local    */
/* playout time.                                                             */
/*****************************************************************************/
{
        timestamp_t delta_transit;
        pdb_entry_t *e;

        pdb_item_get(sp->pdb, ssrc, &e);
        assert(e != NULL);

        delta_transit = ts_abs_diff(transit, e->avg_transit);
        if (ts_gt(transit, e->avg_transit)) {
                e->avg_transit = ts_add(e->avg_transit, ts_div(delta_transit,16));
        } else {
                e->avg_transit = ts_sub(e->avg_transit, ts_div(delta_transit,16));
        }

        if (new_spurt == TRUE) {
                timestamp_t hvar, jvar; /* Host and jitter components       */
                debug_msg("New talkspurt\n");
                hvar = playout_constraints_component(sp, e);
                jvar = ts_mul(e->jitter, PLAYOUT_JITTER_SCALE);
                if (ts_gt(hvar, jvar)) {
                        e->playout = hvar;
                } else {
                        e->playout = jvar;
                }
                e->transit = e->avg_transit;
        } else {
                /* delta_transit is abs((s[j+1] - d[j+1]) - (s[j] - d[j]))  */
                delta_transit   = ts_abs_diff(transit, e->last_transit);
                /* Update jitter estimate using                             */
                /*                  jitter = (7/8)jitter + (1/8) new_jitter */
                e->jitter = ts_mul(e->jitter, 7);
                e->jitter = ts_add(e->jitter, delta_transit);     
                e->jitter = ts_div(e->jitter, 8);

        }
        e->last_transit = transit;

        return e->playout;
}
Beispiel #6
0
int
pb_relevant (struct s_pb *pb, timestamp_t now)
{
        pb_node_t *last;

        last = pb->psentinel->prev; /* tail */

        if (last == pb->psentinel || ts_gt(now, last->playout)) {
                return FALSE;
        }

        return TRUE;
}
Beispiel #7
0
void
pb_shift_units_back_after(pb_t *pb, timestamp_t ref_ts, timestamp_t delta)
{
        pb_node_t *stop, *curr;

	pb_validate(pb);
        stop = pb->psentinel;
        curr = pb->psentinel->prev;
        while(curr != stop && ts_gt(curr->playout, ref_ts)) {
                curr->playout = ts_add(curr->playout, delta);
                curr = curr->prev;
        }
	pb_validate(pb);
}
Beispiel #8
0
int
pb_iterator_audit(pb_iterator_t *pi, timestamp_t history_len)
{
        timestamp_t cutoff;
        int  removed;
        pb_node_t *stop, *curr, *next;
        pb_t      *pb;

#ifdef DEBUG
        /* If we are debugging we check we are not deleting
         * nodes pointed to by other iterators since this *BAD*
         */
        uint16_t        i, n_iterators;
        pb_iterator_t *iterators = pi->buffer->iterators;
        n_iterators = pi->buffer->n_iterators;
#endif

	pb_validate(pi->buffer);

        pb   = pi->buffer;
        stop = pi->node;
        removed = 0;
        if (pi->node != pb->psentinel) {
                curr = pb->psentinel->next; /* head */;
                cutoff = ts_sub(pi->node->playout, history_len);
                while(ts_gt(cutoff, curr->playout)) {
                        /* About to erase a block an iterator is using! */
#ifdef DEBUG
                        for(i = 0; i < n_iterators; i++) {
                                assert(iterators[i].node != curr);
                        }
#endif
                        next = curr->next; 
                        curr->next->prev = curr->prev;
                        curr->prev->next = curr->next;
                        pb->freeproc(&curr->data, curr->data_len);
                        pb->n_nodes--;
                        block_free(curr, sizeof(pb_node_t));
                        curr = next;
                        removed ++;
                }
        }
        return removed;
}
Beispiel #9
0
int
vanilla_decoder_decode(u_char      *state,
                       struct s_pb *in,
                       struct s_pb *out,
                       timestamp_t         now)
{
        struct s_pb_iterator *pi;
        channel_unit *cu;
        u_char       *c_get;
        channel_data *c;
        uint32_t       clen;
        timestamp_t          playout;

        assert(state == NULL); /* No decoder state needed */
        UNUSED(state);

        pb_iterator_create(in, &pi);
        assert(pi != NULL);

        while(pb_iterator_get_at(pi, &c_get, &clen, &playout)) {
                c = (channel_data*)c_get;
                assert(c != NULL);
                assert(clen == sizeof(channel_data));

                if (ts_gt(playout, now)) {
                        /* Playout point of unit is after now.  Stop! */
                        break;
                }
                pb_iterator_detach_at(pi, &c_get, &clen, &playout);
                c = (channel_data*)c_get;
                assert(c != NULL);

                assert(c->nelem == 1);
                cu = c->elem[0];
                vanilla_decoder_output(cu, out, playout);
                channel_data_destroy(&c, sizeof(channel_data));
        }

        pb_iterator_destroy(in, &pi);

        return TRUE;
}
Beispiel #10
0
int 
pb_add (pb_t *pb, u_char *data, uint32_t data_len, timestamp_t playout)
{
        pb_node_t *curr, *stop, *made;
        
	assert(data != NULL);
	assert(data_len > 0);
	pb_validate(pb);

        /* Assuming that addition will be at the end of list (or near it) */
        stop = pb->psentinel;
        curr = stop->prev;    /* list tail */
        while (curr != stop && ts_gt(curr->playout, playout)) {
                curr = curr->prev;
        }

        /* Check if unit already exists */
        if (curr != stop && ts_eq(curr->playout, playout)) {
                debug_msg("Add failed - unit already exists\n");
                return FALSE;
        }

        made = (pb_node_t*)block_alloc(sizeof(pb_node_t));
        if (made) {
                made->playout  = playout;
                made->data     = data;
                made->data_len = data_len;
                made->prev = curr;                
                made->next = curr->next;
                made->next->prev = made;
                made->prev->next = made;
		made->magic      = PB_NODE_MAGIC;
                pb->n_nodes++;
		pb_validate(pb);
                return TRUE;
        } 
        debug_msg("Insufficient memory\n");
        return FALSE;
}
Beispiel #11
0
int
redundancy_encoder_encode (u_char      *state,
                           struct s_pb *in,
                           struct s_pb *out,
                           uint32_t      upp)
{
        uint32_t        m_len;
        timestamp_t           playout;
        struct s_pb_iterator *pi;
        u_char         *m_get;
        media_data     *m;
        red_enc_state  *re = (red_enc_state*)state;

        assert(upp != 0 && upp <= MAX_UNITS_PER_PACKET);

        pb_iterator_create(in, &pi);

        assert(pi != NULL);
        pb_iterator_advance(pi);
        while(pb_iterator_detach_at(pi, &m_get, &m_len, &playout)) {
                m = (media_data*)m_get;
                /* Remove element from playout buffer - it belongs to
                 * the redundancy encoder now.  */
#ifdef DEBUG_REDUNDANCY
                debug_msg("claimed %d, prev %d\n", playout.ticks, re->last_in.ticks);
#endif /* DEBUG_REDUNDANCY */
                assert(m != NULL);

                if (re->units_ready == 0) {
                        re->last_in = playout;
                        re->last_in.ticks--;
                }

                assert(ts_gt(playout, re->last_in));
                re->last_in = playout;

                if (m->nrep > 0) {
                        pb_add(re->media_buffer,
                               (u_char*)m,
                               m_len,
                               playout);
                        re->units_ready++;
                } else {
                        /* Incoming unit has no data so transmission is
                         * not happening.
                         */
#ifdef DEBUG_REDUNDANCY
                        debug_msg("No incoming data\n");
#endif /* DEBUG_REDUNDANCY */
                        media_data_destroy(&m, sizeof(media_data));
                        pb_flush(re->media_buffer);
                        re->units_ready = 0;
                        continue;
                }

                if (re->units_ready && (re->units_ready % upp) == 0) {
                        channel_data *cd;
                        int s;
                        cd = redundancy_encoder_output(re, upp);
                        assert(cd != NULL);
                        s  = pb_add(out, (u_char*)cd, sizeof(channel_data), playout);
#ifdef DEBUG_REDUNDANCY
                        debug_msg("Ready %d, Added %d\n", re->units_ready, playout.ticks);
#endif /* DEBUG_REDUNDANCY */
                        assert(s);
                }
        }

        pb_iterator_destroy(in, &pi);

        return TRUE;
}