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.
This commit is contained in:
Wim Taymans 2005-08-18 10:23:54 +00:00
parent b5f1cf664d
commit 7667a989d3
5 changed files with 586 additions and 122 deletions

View file

@ -1,3 +1,35 @@
2005-08-18 Wim Taymans <wim@fluendo.com>
* 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 <ensonic@users.sf.net> 2005-08-18 Stefan Kost <ensonic@users.sf.net>
* gst/sine/gstsinesrc.c: (gst_sinesrc_src_query): * gst/sine/gstsinesrc.c: (gst_sinesrc_src_query):

View file

@ -51,7 +51,7 @@ static void gst_base_rtp_depayload_init (GstBaseRTPDepayload * filter,
gpointer g_class); gpointer g_class);
static void gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, static void gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter,
GstRTPBuffer * rtp_buf); GstBuffer * rtp_buf);
GType GType
gst_base_rtp_depayload_get_type (void) 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 * static GstElementStateReturn gst_base_rtp_depayload_change_state (GstElement *
element); element);
static GstFlowReturn gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * 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 static void gst_base_rtp_depayload_set_gst_timestamp
(GstBaseRTPDepayload * filter, guint32 timestamp, GstBuffer * buf); (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); 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); GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
if (filter->process_only) { if (filter->process_only) {
GST_DEBUG ("Pushing directly!"); GST_DEBUG ("Pushing directly!");
gst_base_rtp_depayload_push (filter, GST_RTPBUFFER (in)); gst_base_rtp_depayload_push (filter, in);
} else { } else {
if (bclass->add_to_queue) if (bclass->add_to_queue)
ret = bclass->add_to_queue (filter, GST_RTPBUFFER (in)); ret = bclass->add_to_queue (filter, in);
} }
return ret; return ret;
} }
static GstFlowReturn static GstFlowReturn
gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter, gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter,
GstRTPBuffer * in) GstBuffer * in)
{ {
GQueue *queue = filter->queue; GQueue *queue = filter->queue;
@ -246,39 +243,55 @@ gst_base_rtp_depayload_add_to_queue (GstBaseRTPDepayload * filter,
QUEUE_LOCK (filter); QUEUE_LOCK (filter);
if (g_queue_is_empty (queue)) { if (g_queue_is_empty (queue)) {
g_queue_push_tail (queue, in); 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 // not our first packet
{
// let us make sure it is not very late // let us make sure it is not very late
if (in->seqnum < GST_RTPBUFFER (g_queue_peek_head (queue))->seqnum) { if (seqnum < queueseq)
// we need to drop this one goto too_late;
GST_DEBUG ("Packet arrived to late, dropping");
return GST_FLOW_OK;
}
// look for right place to insert it // look for right place to insert it
int i = 0; int i = 0;
while (in->seqnum < GST_RTPBUFFER (g_queue_peek_nth (queue, i))->seqnum) while (seqnum < queueseq) {
i++; i++;
queueseq =
gst_rtpbuffer_get_seq (GST_BUFFER (g_queue_peek_nth (queue, i)));
}
// now insert it at that place // now insert it at that place
g_queue_push_nth (queue, in, i); 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); QUEUE_UNLOCK (filter);
return GST_FLOW_OK; 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 static void
gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, GstBuffer * rtp_buf)
GstRTPBuffer * rtp_buf)
{ {
GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); GstBaseRTPDepayloadClass *bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
GstBuffer *out_buf; GstBuffer *out_buf;
// let's send it out to processing // 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) { if (out_buf) {
// set the caps // set the caps
gst_buffer_set_caps (GST_BUFFER (out_buf), gst_buffer_set_caps (GST_BUFFER (out_buf),
@ -330,6 +343,8 @@ static void
gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter) gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter)
{ {
GQueue *queue = filter->queue; GQueue *queue = filter->queue;
guint32 headts, tailts;
GstBaseRTPDepayloadClass *bclass;
if (g_queue_is_empty (queue)) if (g_queue_is_empty (queue))
return; return;
@ -341,18 +356,22 @@ gst_base_rtp_depayload_queue_release (GstBaseRTPDepayload * filter)
guint maxtsunits = (gfloat) filter->clock_rate * q_size_secs; guint maxtsunits = (gfloat) filter->clock_rate * q_size_secs;
//GST_DEBUG("maxtsunit is %u", maxtsunits); //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); QUEUE_LOCK (filter);
while (GST_RTPBUFFER (g_queue_peek_head (queue))->timestamp - headts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_head (queue)));
GST_RTPBUFFER (g_queue_peek_tail (queue))->timestamp > maxtsunits) { tailts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_tail (queue)));
//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);
gst_base_rtp_depayload_push (filter, GST_RTPBUFFER (in)); bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
while (headts - tailts > maxtsunits) {
//GST_DEBUG("Poping packet from queue");
if (bclass->process) {
GstBuffer *in = g_queue_pop_tail (queue);
gst_base_rtp_depayload_push (filter, in);
} }
tailts =
gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_tail (queue)));
} }
QUEUE_UNLOCK (filter); QUEUE_UNLOCK (filter);
} }

View file

@ -89,11 +89,11 @@ struct _GstBaseRTPDepayloadClass
// non-pure function, default implementation in base class // non-pure function, default implementation in base class
// this does buffering, reordering and dropping // 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 // pure virtual function, child must use this to process incoming
// rtp packets // 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 // non-pure function used to convert from RTP timestamp to GST timestamp
// this function is used by the child class before gst_pad_pushing // this function is used by the child class before gst_pad_pushing

View file

@ -19,84 +19,457 @@
#include "gstrtpbuffer.h" #include "gstrtpbuffer.h"
static void gst_rtpbuffer_init (GTypeInstance * instance, gpointer g_class); #define GST_RTP_HEADER_LEN 12
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; typedef struct _GstRTPHeader
GType
gst_rtpbuffer_get_type (void)
{ {
static GType _gst_rtpbuffer_type = 0; #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;
if (G_UNLIKELY (_gst_rtpbuffer_type == 0)) { #define GST_RTP_HEADER_VERSION(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->version)
static const GTypeInfo rtpbuffer_info = { #define GST_RTP_HEADER_PADDING(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->padding)
sizeof (GstRTPBufferClass), #define GST_RTP_HEADER_EXTENSION(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->extension)
NULL, #define GST_RTP_HEADER_CSRC_COUNT(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc_count)
NULL, #define GST_RTP_HEADER_MARKER(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->marker)
gst_rtpbuffer_class_init, #define GST_RTP_HEADER_PAYLOAD_TYPE(buf)(((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->payload_type)
NULL, #define GST_RTP_HEADER_SEQ(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->seq)
NULL, #define GST_RTP_HEADER_TIMESTAMP(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->timestamp)
sizeof (GstRTPBuffer), #define GST_RTP_HEADER_SSRC(buf) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->ssrc)
0, #define GST_RTP_HEADER_CSRC(buf,i) (((GstRTPHeader *)(GST_BUFFER_DATA (buf)))->csrc[i])
gst_rtpbuffer_init,
NULL
};
_gst_rtpbuffer_type = g_type_register_static (GST_TYPE_BUFFER, #define GST_RTP_HEADER_CSRC_SIZE(buf) (GST_RTP_HEADER_CSRC_COUNT(buf) * sizeof (guint32))
"GstRTPBuffer", &rtpbuffer_info, 0);
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;
} }
return _gst_rtpbuffer_type;
/* 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;
} }
static void gboolean
gst_rtpbuffer_class_init (gpointer g_class, gpointer class_data) gst_rtpbuffer_validate (GstBuffer * buffer)
{ {
GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class); guint8 *data;
guint len;
parent_class = g_type_class_ref (GST_TYPE_BUFFER); g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
mo_class->copy = (GstMiniObjectCopyFunction) gst_rtpbuffer_copy; data = GST_BUFFER_DATA (buffer);
mo_class->finalize = (GstMiniObjectFinalizeFunction) gst_rtpbuffer_finalize; len = GST_BUFFER_SIZE (buffer);
return gst_rtpbuffer_validate_data (data, len);
} }
static void
gst_rtpbuffer_init (GTypeInstance * instance, gpointer g_class) 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;
}
GST_BUFFER_SIZE (buffer) = len;
/* remove any padding */
GST_RTP_HEADER_PADDING (buffer) = FALSE;
} }
static void guint
gst_rtpbuffer_finalize (GstRTPBuffer * nbuf) gst_rtpbuffer_get_packet_len (GstBuffer * buffer)
{ {
GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (nbuf)); g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
return GST_BUFFER_SIZE (buffer);
} }
static GstRTPBuffer * guint8
gst_rtpbuffer_copy (GstRTPBuffer * nbuf) gst_rtpbuffer_get_version (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 = return GST_RTP_HEADER_VERSION (buffer);
(GstRTPBuffer *) GST_MINI_OBJECT_CLASS (parent_class)->
copy (GST_MINI_OBJECT (nbuf));
copy->pt = nbuf->pt;
copy->seqnum = nbuf->seqnum;
copy->timestamp = nbuf->timestamp;
copy->timestampinc = nbuf->timestampinc;
copy->mark = nbuf->mark;
return copy;
} }
GstRTPBuffer * void
gst_rtpbuffer_new (void) gst_rtpbuffer_set_version (GstBuffer * buffer, guint8 version)
{ {
GstRTPBuffer *buf; g_return_if_fail (GST_IS_BUFFER (buffer));
g_return_if_fail (version < 0x04);
g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL);
buf = (GstRTPBuffer *) gst_mini_object_new (GST_TYPE_RTPBUFFER); GST_RTP_HEADER_VERSION (buffer) = version;
}
return buf;
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;
}
guint8
gst_rtpbuffer_get_payload_type (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_PAYLOAD_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);
GST_RTP_HEADER_PAYLOAD_TYPE (buffer) = payload_type;
}
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));
}
void
gst_rtpbuffer_set_seq (GstBuffer * buffer, guint16 seq)
{
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);
}
guint32
gst_rtpbuffer_get_timestamp (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_TIMESTAMP (buffer));
}
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);
GST_RTP_HEADER_TIMESTAMP (buffer) = g_htonl (timestamp);
}
guint
gst_rtpbuffer_get_payload_len (GstBuffer * buffer)
{
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);
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 GST_BUFFER_DATA (buffer) + GST_RTP_HEADER_LEN
+ GST_RTP_HEADER_CSRC_SIZE (buffer);
} }

View file

@ -1,5 +1,9 @@
/* GStreamer /* GStreamer
* Copyright (C) <2005> Philippe Khalaf <burger@speedy.org> * Copyright (C) <2005> Philippe Khalaf <burger@speedy.org>
* <2005> Wim Taymans <wim@fluendo.com>
*
* gstrtpbuffer.h: various helper functions to manipulate buffers
* with RTP payload.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -24,46 +28,82 @@
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _GstRTPBuffer GstRTPBuffer; #define GST_RTP_VERSION 2
typedef struct _GstRTPBufferClass GstRTPBufferClass;
#define GST_TYPE_RTPBUFFER (gst_rtpbuffer_get_type()) typedef enum
#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)) /* Audio: */
#define GST_RTPBUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTPBUFFER, GstRTPBufferClass)) GST_RTP_PAYLOAD_PCMU = 0, /* ITU-T G.711. mu-law audio (RFC 3551) */
#define GST_RTPBUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTPBUFFER, GstRTPBuffer)) GST_RTP_PAYLOAD_GSM = 3,
#define GST_RTPBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTPBUFFER, GstRTPBufferClass)) 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 */
/* buffer for use rtp packets /* Video: */
* GST_RTP_PAYLOAD_MPV = 32, /* Video MPEG 1 & 2 */
* It contains the payload type, timestamp, timestamp increment
* and mark of the rtp packet
*/
struct _GstRTPBuffer { /* BOTH */
GstBuffer buffer; GST_RTP_PAYLOAD_BMPEG = 34 /* Not Standard */
} GstRTPPayload;
guint8 pt;
guint16 seqnum;
guint32 timestamp;
guint32 timestampinc;
gboolean mark;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstRTPBufferClass {
GstBufferClass buffer_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
/* creating buffers */ /* creating buffers */
GType gst_rtpbuffer_get_type (void); GstBuffer* gst_rtpbuffer_new (void);
void gst_rtpbuffer_allocate_data (GstBuffer *buffer, guint payload_len,
guint8 pad_len, guint8 csrc_count);
GstRTPBuffer* gst_rtpbuffer_new (void); 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);
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);
gboolean gst_rtpbuffer_validate_data (guint8 *data, guint len);
gboolean gst_rtpbuffer_validate (GstBuffer *buffer);
void gst_rtpbuffer_set_packet_len (GstBuffer *buffer, guint len);
guint gst_rtpbuffer_get_packet_len (GstBuffer *buffer);
guint8 gst_rtpbuffer_get_version (GstBuffer *buffer);
void gst_rtpbuffer_set_version (GstBuffer *buffer, guint8 version);
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);
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);
guint gst_rtpbuffer_get_payload_len (GstBuffer *buffer);
gpointer gst_rtpbuffer_get_payload (GstBuffer *buffer);
G_END_DECLS G_END_DECLS