From 7667a989d35589308d9b61738d36713dc5990adb Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 18 Aug 2005 10:23:54 +0000 Subject: [PATCH] gst-libs/gst/rtp/gstbasertpdepayload.*: Fix for RTPBuffer changes. Original commit message from CVS: * gst-libs/gst/rtp/gstbasertpdepayload.c: (gst_base_rtp_depayload_chain), (gst_base_rtp_depayload_add_to_queue), (gst_base_rtp_depayload_push), (gst_base_rtp_depayload_queue_release): * gst-libs/gst/rtp/gstbasertpdepayload.h: Fix for RTPBuffer changes. * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtpbuffer_allocate_data), (gst_rtpbuffer_new_take_data), (gst_rtpbuffer_new_copy_data), (gst_rtpbuffer_new_allocate), (gst_rtpbuffer_new_allocate_len), (gst_rtpbuffer_calc_header_len), (gst_rtpbuffer_calc_packet_len), (gst_rtpbuffer_calc_payload_len), (gst_rtpbuffer_validate_data), (gst_rtpbuffer_validate), (gst_rtpbuffer_set_packet_len), (gst_rtpbuffer_get_packet_len), (gst_rtpbuffer_get_version), (gst_rtpbuffer_set_version), (gst_rtpbuffer_get_padding), (gst_rtpbuffer_set_padding), (gst_rtpbuffer_pad_to), (gst_rtpbuffer_get_extension), (gst_rtpbuffer_set_extension), (gst_rtpbuffer_get_ssrc), (gst_rtpbuffer_set_ssrc), (gst_rtpbuffer_get_csrc_count), (gst_rtpbuffer_get_csrc), (gst_rtpbuffer_set_csrc), (gst_rtpbuffer_get_marker), (gst_rtpbuffer_set_marker), (gst_rtpbuffer_get_payload_type), (gst_rtpbuffer_set_payload_type), (gst_rtpbuffer_get_seq), (gst_rtpbuffer_set_seq), (gst_rtpbuffer_get_timestamp), (gst_rtpbuffer_set_timestamp), (gst_rtpbuffer_get_payload_len), (gst_rtpbuffer_get_payload): * gst-libs/gst/rtp/gstrtpbuffer.h: Don't subclass GstBuffer but add methods and helper functions to construct and manipulate RTP packets in regular GstBuffers. --- ChangeLog | 32 +++ gst-libs/gst/rtp/gstbasertpdepayload.c | 75 +++-- gst-libs/gst/rtp/gstbasertpdepayload.h | 4 +- gst-libs/gst/rtp/gstrtpbuffer.c | 487 +++++++++++++++++++++++++++++---- gst-libs/gst/rtp/gstrtpbuffer.h | 102 ++++--- 5 files changed, 582 insertions(+), 118 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6794bb1..293cbcc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2005-08-18 Wim Taymans + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_add_to_queue), + (gst_base_rtp_depayload_push), + (gst_base_rtp_depayload_queue_release): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Fix for RTPBuffer changes. + + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtpbuffer_allocate_data), + (gst_rtpbuffer_new_take_data), (gst_rtpbuffer_new_copy_data), + (gst_rtpbuffer_new_allocate), (gst_rtpbuffer_new_allocate_len), + (gst_rtpbuffer_calc_header_len), (gst_rtpbuffer_calc_packet_len), + (gst_rtpbuffer_calc_payload_len), (gst_rtpbuffer_validate_data), + (gst_rtpbuffer_validate), (gst_rtpbuffer_set_packet_len), + (gst_rtpbuffer_get_packet_len), (gst_rtpbuffer_get_version), + (gst_rtpbuffer_set_version), (gst_rtpbuffer_get_padding), + (gst_rtpbuffer_set_padding), (gst_rtpbuffer_pad_to), + (gst_rtpbuffer_get_extension), (gst_rtpbuffer_set_extension), + (gst_rtpbuffer_get_ssrc), (gst_rtpbuffer_set_ssrc), + (gst_rtpbuffer_get_csrc_count), (gst_rtpbuffer_get_csrc), + (gst_rtpbuffer_set_csrc), (gst_rtpbuffer_get_marker), + (gst_rtpbuffer_set_marker), (gst_rtpbuffer_get_payload_type), + (gst_rtpbuffer_set_payload_type), (gst_rtpbuffer_get_seq), + (gst_rtpbuffer_set_seq), (gst_rtpbuffer_get_timestamp), + (gst_rtpbuffer_set_timestamp), (gst_rtpbuffer_get_payload_len), + (gst_rtpbuffer_get_payload): + * gst-libs/gst/rtp/gstrtpbuffer.h: + Don't subclass GstBuffer but add methods and helper functions + to construct and manipulate RTP packets in regular GstBuffers. + 2005-08-18 Stefan Kost * gst/sine/gstsinesrc.c: (gst_sinesrc_src_query): diff --git a/gst-libs/gst/rtp/gstbasertpdepayload.c b/gst-libs/gst/rtp/gstbasertpdepayload.c index a3d61b8..c24f1b2 100644 --- a/gst-libs/gst/rtp/gstbasertpdepayload.c +++ b/gst-libs/gst/rtp/gstbasertpdepayload.c @@ -51,7 +51,7 @@ static void gst_base_rtp_depayload_init (GstBaseRTPDepayload * filter, gpointer g_class); static void gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, - GstRTPBuffer * rtp_buf); + GstBuffer * rtp_buf); GType gst_base_rtp_depayload_get_type (void) @@ -91,7 +91,7 @@ static GstFlowReturn gst_base_rtp_depayload_chain (GstPad * pad, static GstElementStateReturn gst_base_rtp_depayload_change_state (GstElement * element); static GstFlowReturn gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * - filter, GstRTPBuffer * in); + filter, GstBuffer * in); static void gst_base_rtp_depayload_set_gst_timestamp (GstBaseRTPDepayload * filter, guint32 timestamp, GstBuffer * buf); @@ -221,24 +221,21 @@ gst_base_rtp_depayload_chain (GstPad * pad, GstBuffer * in) g_return_val_if_fail (filter->clock_rate > 0, GST_FLOW_ERROR); - // must supply RTPBuffers here - g_return_val_if_fail (GST_IS_RTPBUFFER (in), GST_FLOW_ERROR); - GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); if (filter->process_only) { GST_DEBUG ("Pushing directly!"); - gst_base_rtp_depayload_push (filter, GST_RTPBUFFER (in)); + gst_base_rtp_depayload_push (filter, in); } else { if (bclass->add_to_queue) - ret = bclass->add_to_queue (filter, GST_RTPBUFFER (in)); + ret = bclass->add_to_queue (filter, in); } return ret; } static GstFlowReturn gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter, - GstRTPBuffer * in) + GstBuffer * in) { GQueue *queue = filter->queue; @@ -246,39 +243,55 @@ gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter, QUEUE_LOCK (filter); if (g_queue_is_empty (queue)) { g_queue_push_tail (queue, in); - } else + } else { + guint16 seqnum, queueseq; + guint32 timestamp; + + seqnum = gst_rtpbuffer_get_seq (in); + queueseq = gst_rtpbuffer_get_seq (GST_BUFFER (g_queue_peek_head (queue))); + // not our first packet - { // let us make sure it is not very late - if (in->seqnum < GST_RTPBUFFER (g_queue_peek_head (queue))->seqnum) { - // we need to drop this one - GST_DEBUG ("Packet arrived to late, dropping"); - return GST_FLOW_OK; - } + if (seqnum < queueseq) + goto too_late; + // look for right place to insert it int i = 0; - while (in->seqnum < GST_RTPBUFFER (g_queue_peek_nth (queue, i))->seqnum) + while (seqnum < queueseq) { i++; + queueseq = + gst_rtpbuffer_get_seq (GST_BUFFER (g_queue_peek_nth (queue, i))); + } + // now insert it at that place g_queue_push_nth (queue, in, i); - GST_DEBUG ("Packet added to queue %d at pos %d timestamp %u sn %d", - g_queue_get_length (queue), i, in->timestamp, in->seqnum); + timestamp = gst_rtpbuffer_get_timestamp (in); + + GST_DEBUG ("Packet added to queue %d at pos %d timestamp %u sn %d", + g_queue_get_length (queue), i, timestamp, seqnum); } QUEUE_UNLOCK (filter); return GST_FLOW_OK; + +too_late: + { + QUEUE_UNLOCK (filter); + // we need to drop this one + GST_DEBUG ("Packet arrived to late, dropping"); + return GST_FLOW_OK; + } } static void -gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, - GstRTPBuffer * rtp_buf) +gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, GstBuffer * rtp_buf) { GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); GstBuffer *out_buf; // let's send it out to processing - out_buf = bclass->process (filter, GST_RTPBUFFER (rtp_buf)); + out_buf = bclass->process (filter, rtp_buf); if (out_buf) { // set the caps gst_buffer_set_caps (GST_BUFFER (out_buf), @@ -330,6 +343,8 @@ static void gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter) { GQueue *queue = filter->queue; + guint32 headts, tailts; + GstBaseRTPDepayloadClass *bclass; if (g_queue_is_empty (queue)) return; @@ -341,18 +356,22 @@ gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter) guint maxtsunits = (gfloat) filter->clock_rate * q_size_secs; //GST_DEBUG("maxtsunit is %u", maxtsunits); - //GST_DEBUG("ts %d %d %d", GST_RTPBUFFER(g_queue_peek_head (queue))->timestamp, GST_RTPBUFFER(g_queue_peek_tail (queue))->timestamp); + //GST_DEBUG("ts %d %d %d", GST_BUFFER(g_queue_peek_head (queue))->timestamp, GST_BUFFER(g_queue_peek_tail (queue))->timestamp); QUEUE_LOCK (filter); - while (GST_RTPBUFFER (g_queue_peek_head (queue))->timestamp - - GST_RTPBUFFER (g_queue_peek_tail (queue))->timestamp > maxtsunits) { + headts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_head (queue))); + tailts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_tail (queue))); + + bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); + + while (headts - tailts > maxtsunits) { //GST_DEBUG("Poping packet from queue"); - GstBaseRTPDepayloadClass *bclass = - GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); if (bclass->process) { - GstRTPBuffer *in = g_queue_pop_tail (queue); + GstBuffer *in = g_queue_pop_tail (queue); - gst_base_rtp_depayload_push (filter, GST_RTPBUFFER (in)); + gst_base_rtp_depayload_push (filter, in); } + tailts = + gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_tail (queue))); } QUEUE_UNLOCK (filter); } diff --git a/gst-libs/gst/rtp/gstbasertpdepayload.h b/gst-libs/gst/rtp/gstbasertpdepayload.h index 5190973..ad9f1a4 100644 --- a/gst-libs/gst/rtp/gstbasertpdepayload.h +++ b/gst-libs/gst/rtp/gstbasertpdepayload.h @@ -89,11 +89,11 @@ struct _GstBaseRTPDepayloadClass // non-pure function, default implementation in base class // this does buffering, reordering and dropping - GstFlowReturn (*add_to_queue) (GstBaseRTPDepayload *filter, GstRTPBuffer *in); + GstFlowReturn (*add_to_queue) (GstBaseRTPDepayload *filter, GstBuffer *in); // pure virtual function, child must use this to process incoming // rtp packets - GstBuffer * (*process) (GstBaseRTPDepayload *base, GstRTPBuffer *in); + GstBuffer * (*process) (GstBaseRTPDepayload *base, GstBuffer *in); // non-pure function used to convert from RTP timestamp to GST timestamp // this function is used by the child class before gst_pad_pushing diff --git a/gst-libs/gst/rtp/gstrtpbuffer.c b/gst-libs/gst/rtp/gstrtpbuffer.c index 0f03a6f..62e8fd4 100644 --- a/gst-libs/gst/rtp/gstrtpbuffer.c +++ b/gst-libs/gst/rtp/gstrtpbuffer.c @@ -19,84 +19,457 @@ #include "gstrtpbuffer.h" -static void gst_rtpbuffer_init (GTypeInstance * instance, gpointer g_class); -static void gst_rtpbuffer_class_init (gpointer g_class, gpointer class_data); -static void gst_rtpbuffer_finalize (GstRTPBuffer * nbuf); -static GstRTPBuffer *gst_rtpbuffer_copy (GstRTPBuffer * nbuf); - -static GstBufferClass *parent_class; - -GType -gst_rtpbuffer_get_type (void) -{ - static GType _gst_rtpbuffer_type = 0; - - if (G_UNLIKELY (_gst_rtpbuffer_type == 0)) { - static const GTypeInfo rtpbuffer_info = { - sizeof (GstRTPBufferClass), - NULL, - NULL, - gst_rtpbuffer_class_init, - NULL, - NULL, - sizeof (GstRTPBuffer), - 0, - gst_rtpbuffer_init, - NULL - }; - - _gst_rtpbuffer_type = g_type_register_static (GST_TYPE_BUFFER, - "GstRTPBuffer", &rtpbuffer_info, 0); +#define GST_RTP_HEADER_LEN 12 + +typedef struct _GstRTPHeader +{ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + unsigned int csrc_count:4; /* CSRC count */ + unsigned int extension:1; /* header extension flag */ + unsigned int padding:1; /* padding flag */ + unsigned int version:2; /* protocol version */ + unsigned int payload_type:7; /* payload type */ + unsigned int marker:1; /* marker bit */ +#elif G_BYTE_ORDER == G_BIG_ENDIAN + unsigned int version:2; /* protocol version */ + unsigned int padding:1; /* padding flag */ + unsigned int extension:1; /* header extension flag */ + unsigned int csrc_count:4; /* CSRC count */ + unsigned int marker:1; /* marker bit */ + unsigned int payload_type:7; /* payload type */ +#else +#error "G_BYTE_ORDER should be big or little endian." +#endif + guint16 seq; /* sequence number */ + guint32 timestamp; /* timestamp */ + guint32 ssrc; /* synchronization source */ + guint32 csrc[1]; /* optional CSRC list */ +} GstRTPHeader; + +#define GST_RTP_HEADER_VERSION(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->version) +#define GST_RTP_HEADER_PADDING(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->padding) +#define GST_RTP_HEADER_EXTENSION(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->extension) +#define GST_RTP_HEADER_CSRC_COUNT(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc_count) +#define GST_RTP_HEADER_MARKER(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->marker) +#define GST_RTP_HEADER_PAYLOAD_TYPE(buf)(((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->payload_type) +#define GST_RTP_HEADER_SEQ(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->seq) +#define GST_RTP_HEADER_TIMESTAMP(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->timestamp) +#define GST_RTP_HEADER_SSRC(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->ssrc) +#define GST_RTP_HEADER_CSRC(buf,i) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc[i]) + +#define GST_RTP_HEADER_CSRC_SIZE(buf) (GST_RTP_HEADER_CSRC_COUNT(buf) * sizeof (guint32)) + +void +gst_rtpbuffer_allocate_data (GstBuffer * buffer, guint payload_len, + guint8 pad_len, guint8 csrc_count) +{ + guint len; + + g_return_if_fail (csrc_count <= 15); + g_return_if_fail (GST_IS_BUFFER (buffer)); + + len = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32) + + payload_len + pad_len; + + GST_BUFFER_MALLOCDATA (buffer) = g_malloc (len); + GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer); + GST_BUFFER_SIZE (buffer) = len; + + /* fill in defaults */ + GST_RTP_HEADER_VERSION (buffer) = GST_RTP_VERSION; + GST_RTP_HEADER_PADDING (buffer) = FALSE; + GST_RTP_HEADER_EXTENSION (buffer) = FALSE; + GST_RTP_HEADER_CSRC_COUNT (buffer) = 0; + GST_RTP_HEADER_MARKER (buffer) = FALSE; + GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = 0; + GST_RTP_HEADER_SEQ (buffer) = 0; + GST_RTP_HEADER_TIMESTAMP (buffer) = 0; + GST_RTP_HEADER_SSRC (buffer) = 0; +} + +GstBuffer * +gst_rtpbuffer_new_take_data (gpointer data, guint len) +{ + GstBuffer *result; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + + result = gst_buffer_new (); + + GST_BUFFER_MALLOCDATA (result) = data; + GST_BUFFER_DATA (result) = data; + GST_BUFFER_SIZE (result) = len; + + return result; +} + +GstBuffer * +gst_rtpbuffer_new_copy_data (gpointer data, guint len) +{ + return gst_rtpbuffer_new_take_data (g_memdup (data, len), len); +} + +GstBuffer * +gst_rtpbuffer_new_allocate (guint payload_len, guint8 pad_len, + guint8 csrc_count) +{ + GstBuffer *result; + + g_return_val_if_fail (csrc_count <= 15, NULL); + + result = gst_buffer_new (); + gst_rtpbuffer_allocate_data (result, payload_len, pad_len, csrc_count); + + return result; +} + +GstBuffer * +gst_rtpbuffer_new_allocate_len (guint packet_len, guint8 pad_len, + guint8 csrc_count) +{ + guint len; + + g_return_val_if_fail (csrc_count <= 15, NULL); + + len = gst_rtpbuffer_calc_payload_len (packet_len, pad_len, csrc_count); + + return gst_rtpbuffer_new_allocate (len, pad_len, csrc_count); +} + +guint +gst_rtpbuffer_calc_header_len (guint8 csrc_count) +{ + g_return_val_if_fail (csrc_count <= 15, 0); + + return GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32)); +} + +guint +gst_rtpbuffer_calc_packet_len (guint payload_len, guint8 pad_len, + guint8 csrc_count) +{ + g_return_val_if_fail (csrc_count <= 15, 0); + + return payload_len + GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32)) + + pad_len; +} + +guint +gst_rtpbuffer_calc_payload_len (guint packet_len, guint8 pad_len, + guint8 csrc_count) +{ + g_return_val_if_fail (csrc_count <= 15, 0); + + return packet_len - GST_RTP_HEADER_LEN - (csrc_count * sizeof (guint32)) + - pad_len; +} + +gboolean +gst_rtpbuffer_validate_data (guint8 * data, guint len) +{ + guint8 padding; + guint8 csrc_count; + guint header_len; + guint8 version; + + g_return_val_if_fail (data != NULL, FALSE); + + header_len = GST_RTP_HEADER_LEN; + if (len < header_len) { + GST_DEBUG ("len < header_len check failed (%d < %d)", len, header_len); + return FALSE; + } + + /* check version */ + version = (data[0] & 0xc0) >> 6; + if (version != GST_RTP_VERSION) { + GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION); + return FALSE; + } + + /* calc header length with csrc */ + csrc_count = (data[0] & 0x0f); + header_len += csrc_count * sizeof (guint32); + + /* check for padding */ + if (data[0] & 0x40) + padding = data[len - 1]; + else + padding = 0; + + /* check if padding not bigger than packet and header */ + if (len - header_len <= padding) { + GST_DEBUG ("padding check failed (%d - %d <= %d)", + len, header_len, padding); + return FALSE; + } + + return TRUE; +} + +gboolean +gst_rtpbuffer_validate (GstBuffer * buffer) +{ + guint8 *data; + guint len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + + data = GST_BUFFER_DATA (buffer); + len = GST_BUFFER_SIZE (buffer); + + return gst_rtpbuffer_validate_data (data, len); +} + + +void +gst_rtpbuffer_set_packet_len (GstBuffer * buffer, guint len) +{ + guint oldlen; + + g_return_if_fail (GST_IS_BUFFER (buffer)); + + oldlen = GST_BUFFER_SIZE (buffer); + + if (oldlen < len) { + guint8 *newdata; + + newdata = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len); + GST_BUFFER_MALLOCDATA (buffer) = newdata; + GST_BUFFER_DATA (buffer) = newdata; } - return _gst_rtpbuffer_type; + GST_BUFFER_SIZE (buffer) = len; + + /* remove any padding */ + GST_RTP_HEADER_PADDING (buffer) = FALSE; + +} + +guint +gst_rtpbuffer_get_packet_len (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + + return GST_BUFFER_SIZE (buffer); +} + +guint8 +gst_rtpbuffer_get_version (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + + return GST_RTP_HEADER_VERSION (buffer); +} + +void +gst_rtpbuffer_set_version (GstBuffer * buffer, guint8 version) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (version < 0x04); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + GST_RTP_HEADER_VERSION (buffer) = version; +} + + +gboolean +gst_rtpbuffer_get_padding (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE); + + return GST_RTP_HEADER_PADDING (buffer); +} + +void +gst_rtpbuffer_set_padding (GstBuffer * buffer, gboolean padding) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + GST_RTP_HEADER_PADDING (buffer) = padding; +} + +void +gst_rtpbuffer_pad_to (GstBuffer * buffer, guint len) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + if (len > 0) + GST_RTP_HEADER_PADDING (buffer) = TRUE; + else + GST_RTP_HEADER_PADDING (buffer) = FALSE; +} + + +gboolean +gst_rtpbuffer_get_extension (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE); + + return GST_RTP_HEADER_EXTENSION (buffer); +} + +void +gst_rtpbuffer_set_extension (GstBuffer * buffer, gboolean extension) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + GST_RTP_HEADER_EXTENSION (buffer) = extension; +} + +guint32 +gst_rtpbuffer_get_ssrc (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_SSRC (buffer)); +} + +void +gst_rtpbuffer_set_ssrc (GstBuffer * buffer, guint32 ssrc) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + GST_RTP_HEADER_SSRC (buffer) = g_htonl (ssrc); +} + +guint8 +gst_rtpbuffer_get_csrc_count (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + + return GST_RTP_HEADER_CSRC_COUNT (buffer); +} + +guint32 +gst_rtpbuffer_get_csrc (GstBuffer * buffer, guint8 idx) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + g_return_val_if_fail (GST_RTP_HEADER_CSRC_COUNT (buffer) < idx, 0); + + return g_ntohl (GST_RTP_HEADER_CSRC (buffer, idx)); +} + +void +gst_rtpbuffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + g_return_if_fail (GST_RTP_HEADER_CSRC_COUNT (buffer) < idx); + + GST_RTP_HEADER_CSRC (buffer, idx) = g_htonl (csrc); +} + +gboolean +gst_rtpbuffer_get_marker (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE); + + return GST_RTP_HEADER_MARKER (buffer); +} + +void +gst_rtpbuffer_set_marker (GstBuffer * buffer, gboolean marker) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + GST_RTP_HEADER_MARKER (buffer) = marker; } -static void -gst_rtpbuffer_class_init (gpointer g_class, gpointer class_data) + +guint8 +gst_rtpbuffer_get_payload_type (GstBuffer * buffer) { - GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class); + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + + return GST_RTP_HEADER_PAYLOAD_TYPE (buffer); +} - parent_class = g_type_class_ref (GST_TYPE_BUFFER); +void +gst_rtpbuffer_set_payload_type (GstBuffer * buffer, guint8 payload_type) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + g_return_if_fail (payload_type < 0x80); - mo_class->copy = (GstMiniObjectCopyFunction) gst_rtpbuffer_copy; - mo_class->finalize = (GstMiniObjectFinalizeFunction) gst_rtpbuffer_finalize; + GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = payload_type; } -static void -gst_rtpbuffer_init (GTypeInstance * instance, gpointer g_class) + +guint16 +gst_rtpbuffer_get_seq (GstBuffer * buffer) { + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + + return g_ntohs (GST_RTP_HEADER_SEQ (buffer)); } -static void -gst_rtpbuffer_finalize (GstRTPBuffer * nbuf) +void +gst_rtpbuffer_set_seq (GstBuffer * buffer, guint16 seq) { - GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (nbuf)); + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + + GST_RTP_HEADER_SEQ (buffer) = g_htons (seq); } -static GstRTPBuffer * -gst_rtpbuffer_copy (GstRTPBuffer * nbuf) + +guint32 +gst_rtpbuffer_get_timestamp (GstBuffer * buffer) { - GstRTPBuffer *copy; + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); - copy = - (GstRTPBuffer *) GST_MINI_OBJECT_CLASS (parent_class)-> - copy (GST_MINI_OBJECT (nbuf)); + return g_ntohl (GST_RTP_HEADER_TIMESTAMP (buffer)); +} - copy->pt = nbuf->pt; - copy->seqnum = nbuf->seqnum; - copy->timestamp = nbuf->timestamp; - copy->timestampinc = nbuf->timestampinc; - copy->mark = nbuf->mark; +void +gst_rtpbuffer_set_timestamp (GstBuffer * buffer, guint32 timestamp) +{ + g_return_if_fail (GST_IS_BUFFER (buffer)); + g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); - return copy; + GST_RTP_HEADER_TIMESTAMP (buffer) = g_htonl (timestamp); } -GstRTPBuffer * -gst_rtpbuffer_new (void) + +guint +gst_rtpbuffer_get_payload_len (GstBuffer * buffer) { - GstRTPBuffer *buf; + guint len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + + len = GST_BUFFER_SIZE (buffer) + - GST_RTP_HEADER_LEN - GST_RTP_HEADER_CSRC_SIZE (buffer); - buf = (GstRTPBuffer *) gst_mini_object_new (GST_TYPE_RTPBUFFER); + if (GST_RTP_HEADER_PADDING (buffer)) + len -= ((guint8 *) GST_BUFFER_DATA (buffer))[GST_BUFFER_SIZE (buffer) - 1]; + + return len; +} + +gpointer +gst_rtpbuffer_get_payload (GstBuffer * buffer) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL); - return buf; + return GST_BUFFER_DATA (buffer) + GST_RTP_HEADER_LEN + + GST_RTP_HEADER_CSRC_SIZE (buffer); } diff --git a/gst-libs/gst/rtp/gstrtpbuffer.h b/gst-libs/gst/rtp/gstrtpbuffer.h index 097a37a..8bc3f5a 100644 --- a/gst-libs/gst/rtp/gstrtpbuffer.h +++ b/gst-libs/gst/rtp/gstrtpbuffer.h @@ -1,5 +1,9 @@ /* GStreamer * Copyright (C) <2005> Philippe Khalaf + * <2005> Wim Taymans + * + * gstrtpbuffer.h: various helper functions to manipulate buffers + * with RTP payload. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,46 +28,82 @@ G_BEGIN_DECLS -typedef struct _GstRTPBuffer GstRTPBuffer; -typedef struct _GstRTPBufferClass GstRTPBufferClass; +#define GST_RTP_VERSION 2 + +typedef enum +{ + /* Audio: */ + GST_RTP_PAYLOAD_PCMU = 0, /* ITU-T G.711. mu-law audio (RFC 3551) */ + GST_RTP_PAYLOAD_GSM = 3, + GST_RTP_PAYLOAD_PCMA = 8, /* ITU-T G.711 A-law audio (RFC 3551) */ + GST_RTP_PAYLOAD_L16_STEREO = 10, + GST_RTP_PAYLOAD_L16_MONO = 11, + GST_RTP_PAYLOAD_MPA = 14, /* Audio MPEG 1-3 */ + GST_RTP_PAYLOAD_G723_63 = 16, /* Not standard */ + GST_RTP_PAYLOAD_G723_53 = 17, /* Not standard */ + GST_RTP_PAYLOAD_TS48 = 18, /* Not standard */ + GST_RTP_PAYLOAD_TS41 = 19, /* Not standard */ + GST_RTP_PAYLOAD_G728 = 20, /* Not standard */ + GST_RTP_PAYLOAD_G729 = 21, /* Not standard */ + + /* Video: */ + GST_RTP_PAYLOAD_MPV = 32, /* Video MPEG 1 & 2 */ + + /* BOTH */ + GST_RTP_PAYLOAD_BMPEG = 34 /* Not Standard */ +} GstRTPPayload; -#define GST_TYPE_RTPBUFFER (gst_rtpbuffer_get_type()) -#define GST_IS_RTPBUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTPBUFFER)) -#define GST_IS_RTPBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTPBUFFER)) -#define GST_RTPBUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTPBUFFER, GstRTPBufferClass)) -#define GST_RTPBUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTPBUFFER, GstRTPBuffer)) -#define GST_RTPBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTPBUFFER, GstRTPBufferClass)) +/* creating buffers */ +GstBuffer* gst_rtpbuffer_new (void); +void gst_rtpbuffer_allocate_data (GstBuffer *buffer, guint payload_len, + guint8 pad_len, guint8 csrc_count); -/* buffer for use rtp packets - * - * It contains the payload type, timestamp, timestamp increment - * and mark of the rtp packet - */ +GstBuffer* gst_rtpbuffer_new_take_data (gpointer data, guint len); +GstBuffer* gst_rtpbuffer_new_copy_data (gpointer data, guint len); +GstBuffer* gst_rtpbuffer_new_allocate (guint payload_len, guint8 pad_len, guint8 csrc_count); +GstBuffer* gst_rtpbuffer_new_allocate_len (guint packet_len, guint8 pad_len, guint8 csrc_count); -struct _GstRTPBuffer { - GstBuffer buffer; +guint gst_rtpbuffer_calc_header_len (guint8 csrc_count); +guint gst_rtpbuffer_calc_packet_len (guint payload_len, guint8 pad_len, guint8 csrc_count); +guint gst_rtpbuffer_calc_payload_len (guint packet_len, guint8 pad_len, guint8 csrc_count); - guint8 pt; - guint16 seqnum; - guint32 timestamp; - guint32 timestampinc; - gboolean mark; +gboolean gst_rtpbuffer_validate_data (guint8 *data, guint len); +gboolean gst_rtpbuffer_validate (GstBuffer *buffer); - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; +void gst_rtpbuffer_set_packet_len (GstBuffer *buffer, guint len); +guint gst_rtpbuffer_get_packet_len (GstBuffer *buffer); -struct _GstRTPBufferClass { - GstBufferClass buffer_class; +guint8 gst_rtpbuffer_get_version (GstBuffer *buffer); +void gst_rtpbuffer_set_version (GstBuffer *buffer, guint8 version); - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; +gboolean gst_rtpbuffer_get_padding (GstBuffer *buffer); +void gst_rtpbuffer_set_padding (GstBuffer *buffer, gboolean padding); +void gst_rtpbuffer_pad_to (GstBuffer *buffer, guint len); -/* creating buffers */ -GType gst_rtpbuffer_get_type (void); +gboolean gst_rtpbuffer_get_extension (GstBuffer *buffer); +void gst_rtpbuffer_set_extension (GstBuffer *buffer, gboolean extension); + +guint32 gst_rtpbuffer_get_ssrc (GstBuffer *buffer); +void gst_rtpbuffer_set_ssrc (GstBuffer *buffer, guint32 ssrc); + +guint8 gst_rtpbuffer_get_csrc_count (GstBuffer *buffer); +guint32 gst_rtpbuffer_get_csrc (GstBuffer *buffer, guint8 idx); +void gst_rtpbuffer_set_csrc (GstBuffer *buffer, guint8 idx, guint32 csrc); + +gboolean gst_rtpbuffer_get_marker (GstBuffer *buffer); +void gst_rtpbuffer_set_marker (GstBuffer *buffer, gboolean marker); + +guint8 gst_rtpbuffer_get_payload_type (GstBuffer *buffer); +void gst_rtpbuffer_set_payload_type (GstBuffer *buffer, guint8 payload_type); + +guint16 gst_rtpbuffer_get_seq (GstBuffer *buffer); +void gst_rtpbuffer_set_seq (GstBuffer *buffer, guint16 seq); + +guint32 gst_rtpbuffer_get_timestamp (GstBuffer *buffer); +void gst_rtpbuffer_set_timestamp (GstBuffer *buffer, guint32 timestamp); -GstRTPBuffer* gst_rtpbuffer_new (void); +guint gst_rtpbuffer_get_payload_len (GstBuffer *buffer); +gpointer gst_rtpbuffer_get_payload (GstBuffer *buffer); G_END_DECLS -- 2.7.4