diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2007-08-10 17:16:53 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2007-08-10 17:16:53 +0000 |
commit | 9e50d836d4173f127adc56446fa74f1e103fa673 (patch) | |
tree | cdde2fad6fe1ea9945bdcc179438c94d6e425805 /gst/rtpmanager/rtpjitterbuffer.c | |
parent | a9090746e58e9a994d7f07f61452602b31461e1e (diff) | |
download | gst-plugins-bad-9e50d836d4173f127adc56446fa74f1e103fa673.tar.gz gst-plugins-bad-9e50d836d4173f127adc56446fa74f1e103fa673.tar.bz2 gst-plugins-bad-9e50d836d4173f127adc56446fa74f1e103fa673.zip |
gst/rtpmanager/: Remove complicated async queue and replace with more simple jitterbuffer code while also fixing some...
Original commit message from CVS:
* gst/rtpmanager/Makefile.am:
* gst/rtpmanager/async_jitter_queue.c:
* gst/rtpmanager/async_jitter_queue.h:
* gst/rtpmanager/rtpjitterbuffer.c: (rtp_jitter_buffer_class_init),
(rtp_jitter_buffer_init), (rtp_jitter_buffer_finalize),
(rtp_jitter_buffer_new), (compare_seqnum),
(rtp_jitter_buffer_insert), (rtp_jitter_buffer_pop),
(rtp_jitter_buffer_flush), (rtp_jitter_buffer_num_packets),
(rtp_jitter_buffer_get_ts_diff):
* gst/rtpmanager/rtpjitterbuffer.h:
Remove complicated async queue and replace with more simple jitterbuffer
code while also fixing some bugs.
* gst/rtpmanager/gstrtpbin-marshal.list:
* gst/rtpmanager/gstrtpbin.c: (on_new_ssrc), (on_ssrc_collision),
(on_ssrc_validated), (on_bye_ssrc), (on_bye_timeout), (on_timeout),
(create_session), (gst_rtp_bin_class_init), (create_recv_rtp),
(create_send_rtp):
* gst/rtpmanager/gstrtpbin.h:
* gst/rtpmanager/gstrtpjitterbuffer.c:
(gst_rtp_jitter_buffer_init), (gst_rtp_jitter_buffer_dispose),
(gst_jitter_buffer_sink_parse_caps),
(gst_rtp_jitter_buffer_flush_start),
(gst_rtp_jitter_buffer_flush_stop),
(gst_rtp_jitter_buffer_change_state),
(gst_rtp_jitter_buffer_sink_event), (gst_rtp_jitter_buffer_chain),
(gst_rtp_jitter_buffer_loop), (gst_rtp_jitter_buffer_set_property):
* gst/rtpmanager/gstrtpsession.c: (on_new_ssrc),
(on_ssrc_collision), (on_ssrc_validated), (on_bye_ssrc),
(on_bye_timeout), (on_timeout), (gst_rtp_session_class_init),
(gst_rtp_session_init):
* gst/rtpmanager/gstrtpsession.h:
* gst/rtpmanager/rtpsession.c: (on_bye_ssrc), (session_cleanup):
Use new jitterbuffer code.
Expose some new signals in preparation for handling EOS.
Diffstat (limited to 'gst/rtpmanager/rtpjitterbuffer.c')
-rw-r--r-- | gst/rtpmanager/rtpjitterbuffer.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c new file mode 100644 index 00000000..f90811b4 --- /dev/null +++ b/gst/rtpmanager/rtpjitterbuffer.c @@ -0,0 +1,237 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans <wim@fluendo.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <string.h> + +#include <gst/rtp/gstrtpbuffer.h> +#include <gst/rtp/gstrtcpbuffer.h> + +#include "rtpjitterbuffer.h" + +GST_DEBUG_CATEGORY_STATIC (rtp_jitter_buffer_debug); +#define GST_CAT_DEFAULT rtp_jitter_buffer_debug + +/* signals and args */ +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0 +}; + +/* GObject vmethods */ +static void rtp_jitter_buffer_finalize (GObject * object); + +/* static guint rtp_jitter_buffer_signals[LAST_SIGNAL] = { 0 }; */ + +G_DEFINE_TYPE (RTPJitterBuffer, rtp_jitter_buffer, G_TYPE_OBJECT); + +static void +rtp_jitter_buffer_class_init (RTPJitterBufferClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = rtp_jitter_buffer_finalize; + + GST_DEBUG_CATEGORY_INIT (rtp_jitter_buffer_debug, "rtpjitterbuffer", 0, + "RTP Jitter Buffer"); +} + +static void +rtp_jitter_buffer_init (RTPJitterBuffer * jbuf) +{ + jbuf->packets = g_queue_new (); +} + +static void +rtp_jitter_buffer_finalize (GObject * object) +{ + RTPJitterBuffer *jbuf; + + jbuf = RTP_JITTER_BUFFER_CAST (object); + + rtp_jitter_buffer_flush (jbuf); + g_queue_free (jbuf->packets); + + G_OBJECT_CLASS (rtp_jitter_buffer_parent_class)->finalize (object); +} + +/** + * rtp_jitter_buffer_new: + * + * Create an #RTPJitterBuffer. + * + * Returns: a new #RTPJitterBuffer. Use g_object_unref() after usage. + */ +RTPJitterBuffer * +rtp_jitter_buffer_new (void) +{ + RTPJitterBuffer *jbuf; + + jbuf = g_object_new (RTP_TYPE_JITTER_BUFFER, NULL); + + return jbuf; +} + +static gint +compare_seqnum (GstBuffer * a, GstBuffer * b, RTPJitterBuffer * jbuf) +{ + guint16 seq1, seq2; + + seq1 = gst_rtp_buffer_get_seq (a); + seq2 = gst_rtp_buffer_get_seq (b); + + /* check if diff more than half of the 16bit range */ + if (abs (seq2 - seq1) > (1 << 15)) { + /* one of a/b has wrapped */ + return seq1 - seq2; + } else { + return seq2 - seq1; + } +} + +/** + * rtp_jitter_buffer_insert: + * @jbuf: an #RTPJitterBuffer + * @buf: a buffer + * + * Inserts @buf into the packet queue of @jbuf. The sequence number of the + * packet will be used to sort the packets. This function takes ownerhip of + * @buf when the function returns %TRUE. + * + * Returns: %FALSE if a packet with the same number already existed. + */ +gboolean +rtp_jitter_buffer_insert (RTPJitterBuffer * jbuf, GstBuffer * buf) +{ + GList *list; + gint func_ret = 1; + + g_return_val_if_fail (jbuf != NULL, FALSE); + g_return_val_if_fail (buf != NULL, FALSE); + + /* loop the list to skip strictly smaller seqnum buffers */ + list = jbuf->packets->head; + while (list + && (func_ret = + compare_seqnum (GST_BUFFER_CAST (list->data), buf, jbuf)) < 0) + list = list->next; + + /* we hit a packet with the same seqnum, return FALSE to notify a duplicate */ + if (func_ret == 0) + return FALSE; + + if (list) + g_queue_insert_before (jbuf->packets, list, buf); + else + g_queue_push_tail (jbuf->packets, buf); + + return TRUE; +} + +/** + * rtp_jitter_buffer_pop: + * @jbuf: an #RTPJitterBuffer + * + * Pops the oldest buffer from the packet queue of @jbuf. + * + * Returns: a #GstBuffer or %NULL when there was no packet in the queue. + */ +GstBuffer * +rtp_jitter_buffer_pop (RTPJitterBuffer * jbuf) +{ + GstBuffer *buf; + + g_return_val_if_fail (jbuf != NULL, FALSE); + + buf = g_queue_pop_tail (jbuf->packets); + + return buf; +} + +/** + * rtp_jitter_buffer_flush: + * @jbuf: an #RTPJitterBuffer + * + * Flush all packets from the jitterbuffer. + */ +void +rtp_jitter_buffer_flush (RTPJitterBuffer * jbuf) +{ + GstBuffer *buffer; + + g_return_if_fail (jbuf != NULL); + + while ((buffer = g_queue_pop_head (jbuf->packets))) + gst_buffer_unref (buffer); +} + +/** + * rtp_jitter_buffer_num_packets: + * @jbuf: an #RTPJitterBuffer + * + * Get the number of packets currently in "jbuf. + * + * Returns: The number of packets in @jbuf. + */ +guint +rtp_jitter_buffer_num_packets (RTPJitterBuffer * jbuf) +{ + g_return_val_if_fail (jbuf != NULL, 0); + + return jbuf->packets->length; +} + +/** + * rtp_jitter_buffer_get_ts_diff: + * @jbuf: an #RTPJitterBuffer + * + * Get the difference between the timestamps of first and last packet in the + * jitterbuffer. + * + * Returns: The difference expressed in the timestamp units of the packets. + */ +guint32 +rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer * jbuf) +{ + guint32 high_ts, low_ts; + GstBuffer *high_buf, *low_buf; + + g_return_val_if_fail (jbuf != NULL, 0); + + high_buf = g_queue_peek_head (jbuf->packets); + low_buf = g_queue_peek_tail (jbuf->packets); + + if (!high_buf || !low_buf || high_buf == low_buf) + return 0; + + high_ts = gst_rtp_buffer_get_timestamp (high_buf); + low_ts = gst_rtp_buffer_get_timestamp (low_buf); + + /* it needs to work if ts wraps */ + if (high_ts >= low_ts) { + return high_ts - low_ts; + } else { + return high_ts + G_MAXUINT32 + 1 - low_ts; + } +} |