mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
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:
parent
b5f1cf664d
commit
7667a989d3
5 changed files with 586 additions and 122 deletions
32
ChangeLog
32
ChangeLog
|
@ -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>
|
||||
|
||||
* gst/sine/gstsinesrc.c: (gst_sinesrc_src_query):
|
||||
|
|
|
@ -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) {
|
||||
//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);
|
||||
headts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_head (queue)));
|
||||
tailts = gst_rtpbuffer_get_timestamp (GST_BUFFER (g_queue_peek_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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
#define GST_RTP_HEADER_LEN 12
|
||||
|
||||
static GstBufferClass *parent_class;
|
||||
|
||||
GType
|
||||
gst_rtpbuffer_get_type (void)
|
||||
typedef struct _GstRTPHeader
|
||||
{
|
||||
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)) {
|
||||
static const GTypeInfo rtpbuffer_info = {
|
||||
sizeof (GstRTPBufferClass),
|
||||
NULL,
|
||||
NULL,
|
||||
gst_rtpbuffer_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstRTPBuffer),
|
||||
0,
|
||||
gst_rtpbuffer_init,
|
||||
NULL
|
||||
};
|
||||
#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])
|
||||
|
||||
_gst_rtpbuffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
||||
"GstRTPBuffer", &rtpbuffer_info, 0);
|
||||
#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;
|
||||
}
|
||||
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
|
||||
gst_rtpbuffer_class_init (gpointer g_class, gpointer class_data)
|
||||
gboolean
|
||||
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;
|
||||
mo_class->finalize = (GstMiniObjectFinalizeFunction) gst_rtpbuffer_finalize;
|
||||
data = GST_BUFFER_DATA (buffer);
|
||||
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
|
||||
gst_rtpbuffer_finalize (GstRTPBuffer * nbuf)
|
||||
guint
|
||||
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 *
|
||||
gst_rtpbuffer_copy (GstRTPBuffer * nbuf)
|
||||
guint8
|
||||
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 =
|
||||
(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;
|
||||
return GST_RTP_HEADER_VERSION (buffer);
|
||||
}
|
||||
|
||||
GstRTPBuffer *
|
||||
gst_rtpbuffer_new (void)
|
||||
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);
|
||||
|
||||
return buf;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
/* GStreamer
|
||||
* 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
|
||||
* 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
|
||||
|
||||
#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))
|
||||
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 */
|
||||
|
||||
/* buffer for use rtp packets
|
||||
*
|
||||
* It contains the payload type, timestamp, timestamp increment
|
||||
* and mark of the rtp packet
|
||||
*/
|
||||
/* Video: */
|
||||
GST_RTP_PAYLOAD_MPV = 32, /* Video MPEG 1 & 2 */
|
||||
|
||||
struct _GstRTPBuffer {
|
||||
GstBuffer buffer;
|
||||
|
||||
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];
|
||||
};
|
||||
/* BOTH */
|
||||
GST_RTP_PAYLOAD_BMPEG = 34 /* Not Standard */
|
||||
} GstRTPPayload;
|
||||
|
||||
/* 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
|
||||
|
||||
|
|
Loading…
Reference in a new issue