uint16_t bad_seq; /* tentatively next expected sequence for resync */
uint16_t max_seq; /* next expected sequence */
+ uint16_t last_seq; /* sequence of the last dequeued packet */
block_t *blocks; /* re-ordered blocks queue */
void *opaque[0]; /* Per-source private payload data */
};
source->ssrc = ssrc;
source->max_seq = source->bad_seq = init_seq;
+ source->last_seq = init_seq - 1;
source->blocks = NULL;
/* Initializes all payload */
tab[session->srcc++] = src;
}
+ /* Be optimistic for the first packet. Certain codec, such as Vorbis
+ * do not like loosing the first packet(s), so we cannot just wait
+ * for proper sequence synchronization. And we don't want to assume that
+ * the sender starts at seq=0 either. */
+ if (src->blocks == NULL)
+ src->max_seq = seq - p_sys->max_dropout;
+
/* Check sequence number */
/* NOTE: the sequence number is per-source,
* but is independent from the payload type. */
goto drop;
}
}
+ else
+ if (delta_seq < 0x8000)
+ src->max_seq = seq;
/* Queues the block in sequence order,
* hence there is a single queue for all payload types. */
block_t **pp = &src->blocks;
for (block_t *prev = *pp; prev != NULL; prev = *pp)
{
- if ((int16_t)(seq - rtp_seq (*pp)) >= 0)
+ if ((int16_t)(seq - rtp_seq (*pp)) < 0)
break;
pp = &prev->p_next;
}
src->blocks = block->p_next;
block->p_next = NULL;
+ /* Discontinuity detection */
+ if (((src->last_seq + 1) & 0xffff) != rtp_seq (block))
+ block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+ src->last_seq = rtp_seq (block);
+
/* Match the payload type */
const rtp_pt_t *pt = NULL;
void *pt_data = NULL;