rtpjitterbuffer: rework packet insert

Rework the packet queue so that the most common action (insert a packet
at the tail of the queue) goes very fast.

Report if a packet was inserted at the head instead of the tail so that
we can know when to retry _pop or _peek.
This commit is contained in:
Wim Taymans 2014-04-29 15:29:31 +02:00
parent 9994ff2c6c
commit 18b69419fd
2 changed files with 34 additions and 31 deletions

View file

@ -626,23 +626,20 @@ queue_do_insert (RTPJitterBuffer * jbuf, GList * list, GList * item)
{ {
GQueue *queue = jbuf->packets; GQueue *queue = jbuf->packets;
/* It's more likely that the packet was inserted in the front of the buffer */ /* It's more likely that the packet was inserted at the tail of the queue */
if (G_LIKELY (list)) { if (G_LIKELY (list)) {
item->prev = list->prev; item->prev = list;
item->next = list; item->next = list->next;
list->prev = item; list->next = item;
if (item->prev) {
item->prev->next = item;
} else {
queue->head = item;
}
} else { } else {
queue->tail = g_list_concat (queue->tail, item); item->prev = NULL;
if (queue->tail->next) item->next = queue->head;
queue->tail = queue->tail->next; queue->head = item;
else
queue->head = queue->tail;
} }
if (item->next)
item->next->prev = item;
else
queue->tail = item;
queue->length++; queue->length++;
} }
@ -650,20 +647,24 @@ queue_do_insert (RTPJitterBuffer * jbuf, GList * list, GList * item)
* rtp_jitter_buffer_insert: * rtp_jitter_buffer_insert:
* @jbuf: an #RTPJitterBuffer * @jbuf: an #RTPJitterBuffer
* @item: an #RTPJitterBufferItem to insert * @item: an #RTPJitterBufferItem to insert
* @tail: TRUE when the tail element changed. * @head: TRUE when the head element changed.
* @percent: the buffering percent after insertion * @percent: the buffering percent after insertion
* *
* Inserts @item into the packet queue of @jbuf. The sequence number of the * Inserts @item into the packet queue of @jbuf. The sequence number of the
* packet will be used to sort the packets. This function takes ownerhip of * packet will be used to sort the packets. This function takes ownerhip of
* @buf when the function returns %TRUE. * @buf when the function returns %TRUE.
* *
* When @head is %TRUE, the new packet was added at the head of the queue and
* will be available with the next call to rtp_jitter_buffer_pop() and
* rtp_jitter_buffer_peek().
*
* Returns: %FALSE if a packet with the same number already existed. * Returns: %FALSE if a packet with the same number already existed.
*/ */
gboolean gboolean
rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item, rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
gboolean * tail, gint * percent) gboolean * head, gint * percent)
{ {
GList *list = NULL; GList *list;
guint32 rtptime; guint32 rtptime;
guint16 seqnum; guint16 seqnum;
GstClockTime dts; GstClockTime dts;
@ -671,21 +672,22 @@ rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
g_return_val_if_fail (jbuf != NULL, FALSE); g_return_val_if_fail (jbuf != NULL, FALSE);
g_return_val_if_fail (item != NULL, FALSE); g_return_val_if_fail (item != NULL, FALSE);
list = jbuf->packets->tail;
/* no seqnum, simply append then */ /* no seqnum, simply append then */
if (item->seqnum == -1) { if (item->seqnum == -1)
goto append; goto append;
}
seqnum = item->seqnum; seqnum = item->seqnum;
/* loop the list to skip strictly smaller seqnum buffers */ /* loop the list to skip strictly larger seqnum buffers */
for (list = jbuf->packets->head; list; list = g_list_next (list)) { for (; list; list = g_list_previous (list)) {
guint16 qseq; guint16 qseq;
gint gap; gint gap;
RTPJitterBufferItem *qitem = (RTPJitterBufferItem *) list; RTPJitterBufferItem *qitem = (RTPJitterBufferItem *) list;
if (qitem->seqnum == -1) if (qitem->seqnum == -1)
continue; break;
qseq = qitem->seqnum; qseq = qitem->seqnum;
@ -696,8 +698,8 @@ rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, RTPJitterBufferItem * item,
if (G_UNLIKELY (gap == 0)) if (G_UNLIKELY (gap == 0))
goto duplicate; goto duplicate;
/* seqnum < qseq, we can stop looking */ /* seqnum > qseq, we can stop looking */
if (G_LIKELY (gap > 0)) if (G_LIKELY (gap < 0))
break; break;
} }
@ -762,10 +764,10 @@ append:
else if (percent) else if (percent)
*percent = -1; *percent = -1;
/* tail was changed when we did not find a previous packet, we set the return /* head was changed when we did not find a previous packet, we set the return
* flag when requested. */ * flag when requested. */
if (G_LIKELY (tail)) if (G_LIKELY (head))
*tail = (list == NULL); *head = (list == NULL);
return TRUE; return TRUE;
@ -821,9 +823,10 @@ rtp_jitter_buffer_pop (RTPJitterBuffer * jbuf, gint * percent)
* rtp_jitter_buffer_peek: * rtp_jitter_buffer_peek:
* @jbuf: an #RTPJitterBuffer * @jbuf: an #RTPJitterBuffer
* *
* Peek the oldest buffer from the packet queue of @jbuf. Register a callback * Peek the oldest buffer from the packet queue of @jbuf.
* with rtp_jitter_buffer_set_tail_changed() to be notified when an older packet *
* was inserted in the queue. * See rtp_jitter_buffer_insert() to check when an older packet was
* added.
* *
* Returns: a #GstBuffer or %NULL when there was no packet in the queue. * Returns: a #GstBuffer or %NULL when there was no packet in the queue.
*/ */

View file

@ -153,7 +153,7 @@ void rtp_jitter_buffer_reset_skew (RTPJitterBuffer *jbuf)
gboolean rtp_jitter_buffer_insert (RTPJitterBuffer *jbuf, gboolean rtp_jitter_buffer_insert (RTPJitterBuffer *jbuf,
RTPJitterBufferItem *item, RTPJitterBufferItem *item,
gboolean *tail, gint *percent); gboolean *head, gint *percent);
void rtp_jitter_buffer_disable_buffering (RTPJitterBuffer *jbuf, gboolean disabled); void rtp_jitter_buffer_disable_buffering (RTPJitterBuffer *jbuf, gboolean disabled);