diff -r 9b2c3c7a1a9c -r 567bb019e3e3 gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c --- a/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c Wed Mar 31 22:03:18 2010 +0300 +++ b/gst_plugins_base/gst-libs/gst/rtp/gstrtpbuffer.c Tue Aug 31 15:30:33 2010 +0300 @@ -69,20 +69,19 @@ guint8 csrclist[4]; /* optional CSRC list, 32 bits each */ } 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_LIST_OFFSET(buf,i) \ - GST_BUFFER_DATA (buf) + \ - G_STRUCT_OFFSET(GstRTPHeader, csrclist) + \ +#define GST_RTP_HEADER_VERSION(data) (((GstRTPHeader *)(data))->version) +#define GST_RTP_HEADER_PADDING(data) (((GstRTPHeader *)(data))->padding) +#define GST_RTP_HEADER_EXTENSION(data) (((GstRTPHeader *)(data))->extension) +#define GST_RTP_HEADER_CSRC_COUNT(data) (((GstRTPHeader *)(data))->csrc_count) +#define GST_RTP_HEADER_MARKER(data) (((GstRTPHeader *)(data))->marker) +#define GST_RTP_HEADER_PAYLOAD_TYPE(data) (((GstRTPHeader *)(data))->payload_type) +#define GST_RTP_HEADER_SEQ(data) (((GstRTPHeader *)(data))->seq) +#define GST_RTP_HEADER_TIMESTAMP(data) (((GstRTPHeader *)(data))->timestamp) +#define GST_RTP_HEADER_SSRC(data) (((GstRTPHeader *)(data))->ssrc) +#define GST_RTP_HEADER_CSRC_LIST_OFFSET(data,i) \ + data + G_STRUCT_OFFSET(GstRTPHeader, csrclist) + \ ((i) * sizeof(guint32)) -#define GST_RTP_HEADER_CSRC_SIZE(buf) (GST_RTP_HEADER_CSRC_COUNT(buf) * sizeof (guint32)) +#define GST_RTP_HEADER_CSRC_SIZE(data) (GST_RTP_HEADER_CSRC_COUNT(data) * sizeof (guint32)) /** * gst_rtp_buffer_allocate_data: @@ -105,6 +104,7 @@ guint8 pad_len, guint8 csrc_count) { guint len; + guint8 *data; g_return_if_fail (csrc_count <= 15); g_return_if_fail (GST_IS_BUFFER (buffer)); @@ -112,22 +112,23 @@ 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); + data = g_malloc (len); + GST_BUFFER_MALLOCDATA (buffer) = data; + GST_BUFFER_DATA (buffer) = data; 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) = csrc_count; - memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, 0), 0, + GST_RTP_HEADER_VERSION (data) = GST_RTP_VERSION; + GST_RTP_HEADER_PADDING (data) = FALSE; + GST_RTP_HEADER_EXTENSION (data) = FALSE; + GST_RTP_HEADER_CSRC_COUNT (data) = csrc_count; + memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, 0), 0, csrc_count * sizeof (guint32)); - 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; + GST_RTP_HEADER_MARKER (data) = FALSE; + GST_RTP_HEADER_PAYLOAD_TYPE (data) = 0; + GST_RTP_HEADER_SEQ (data) = 0; + GST_RTP_HEADER_TIMESTAMP (data) = 0; + GST_RTP_HEADER_SSRC (data) = 0; } /** @@ -316,23 +317,18 @@ } /** - * gst_rtp_buffer_validate_data: + * validate_data: * @data: the data to validate * @len: the length of @data to validate + * @payload: the payload if @data represents the header only + * @payload_len: the len of the payload * - * Check if the @data and @size point to the data of a valid RTP packet. - * This function checks the length, version and padding of the packet data. - * Use this function to validate a packet before using the other functions in - * this module. + * Checks if @data is a valid RTP packet. * - * Returns: TRUE if the data points to a valid RTP packet. + * Returns: TRUE if @data is a valid RTP packet */ -#ifdef __SYMBIAN32__ -EXPORT_C -#endif - -gboolean -gst_rtp_buffer_validate_data (guint8 * data, guint len) +static gboolean +validate_data (guint8 * data, guint len, guint8 * payload, guint payload_len) { guint8 padding; guint8 csrc_count; @@ -346,8 +342,8 @@ goto wrong_length; /* check version */ - version = (data[0] & 0xc0) >> 6; - if (G_UNLIKELY (version != GST_RTP_VERSION)) + version = (data[0] & 0xc0); + if (G_UNLIKELY (version != (GST_RTP_VERSION << 6))) goto wrong_version; /* calc header length with csrc */ @@ -376,13 +372,17 @@ } /* check for padding */ - if (data[0] & 0x20) - padding = data[len - 1]; - else + if (data[0] & 0x20) { + if (payload) + padding = payload[payload_len - 1]; + else + padding = data[len - 1]; + } else { padding = 0; + } - /* check if padding not bigger than packet and header */ - if (G_UNLIKELY (len - header_len < padding)) + /* check if padding and header not bigger than packet length */ + if (G_UNLIKELY (len < padding + header_len)) goto wrong_padding; return TRUE; @@ -406,11 +406,35 @@ } /** + * gst_rtp_buffer_validate_data: + * @data: the data to validate + * @len: the length of @data to validate + * + * Check if the @data and @size point to the data of a valid RTP packet. + * This function checks the length, version and padding of the packet data. + * Use this function to validate a packet before using the other functions in + * this module. + * + * Returns: TRUE if the data points to a valid RTP packet. + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +gboolean +gst_rtp_buffer_validate_data (guint8 * data, guint len) +{ + return validate_data (data, len, NULL, 0); +} + +/** * gst_rtp_buffer_validate: * @buffer: the buffer to validate * * Check if the data pointed to by @buffer is a valid RTP packet using - * gst_rtp_buffer_validate_data(). + * validate_data(). + * Use this function to validate a packet before using the other functions in + * this module. * * Returns: TRUE if @buffer is a valid RTP packet. */ @@ -429,7 +453,99 @@ data = GST_BUFFER_DATA (buffer); len = GST_BUFFER_SIZE (buffer); - return gst_rtp_buffer_validate_data (data, len); + return validate_data (data, len, NULL, 0); +} + +/** + * gst_rtp_buffer_list_validate: + * @list: the buffer list to validate + * + * Check if all RTP packets in the @list are valid using validate_data(). + * Use this function to validate an list before using the other functions in + * this module. + * + * Returns: TRUE if @list consists only of valid RTP packets. + * + * Since: 0.10.24 + */ + + #ifdef __SYMBIAN32__ +EXPORT_C +#endif + +gboolean +gst_rtp_buffer_list_validate (GstBufferList * list) +{ + guint16 prev_seqnum = 0; + GstBufferListIterator *it; + guint i = 0; + + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE); + + it = gst_buffer_list_iterate (list); + g_return_val_if_fail (it != NULL, FALSE); + + /* iterate through all the RTP packets in the list */ + while (gst_buffer_list_iterator_next_group (it)) { + GstBuffer *rtpbuf; + GstBuffer *paybuf; + guint8 *packet_header; + guint8 *packet_payload; + guint payload_size; + guint packet_size; + + /* each group should consists of 2 buffers: one containing the RTP header + * and the other one the payload, FIXME, relax the requirement of only one + * payload buffer. */ + if (gst_buffer_list_iterator_n_buffers (it) != 2) + goto invalid_list; + + /* get the RTP header */ + rtpbuf = gst_buffer_list_iterator_next (it); + packet_header = GST_BUFFER_DATA (rtpbuf); + if (packet_header == NULL) + goto invalid_list; + + /* get the payload */ + paybuf = gst_buffer_list_iterator_next (it); + packet_payload = GST_BUFFER_DATA (paybuf); + if (packet_payload == NULL) { + goto invalid_list; + } + payload_size = GST_BUFFER_SIZE (paybuf); + if (payload_size == 0) { + goto invalid_list; + } + + /* the size of the RTP packet within the current group */ + packet_size = GST_BUFFER_SIZE (rtpbuf) + payload_size; + + /* check the sequence number */ + if (G_UNLIKELY (i == 0)) { + prev_seqnum = g_ntohs (GST_RTP_HEADER_SEQ (packet_header)); + i++; + } else { + if (++prev_seqnum != g_ntohs (GST_RTP_HEADER_SEQ (packet_header))) + goto invalid_list; + } + + /* validate packet */ + if (!validate_data (packet_header, packet_size, packet_payload, + payload_size)) { + goto invalid_list; + } + } + + gst_buffer_list_iterator_free (it); + + return TRUE; + + /* ERRORS */ +invalid_list: + { + gst_buffer_list_iterator_free (it); + return FALSE; + } } /** @@ -448,22 +564,20 @@ gst_rtp_buffer_set_packet_len (GstBuffer * buffer, guint len) { guint oldlen; - - g_return_if_fail (GST_IS_BUFFER (buffer)); + guint8 *data; oldlen = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); if (oldlen < len) { - guint8 *newdata; - - newdata = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len); - GST_BUFFER_MALLOCDATA (buffer) = newdata; - GST_BUFFER_DATA (buffer) = newdata; + data = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len); + GST_BUFFER_MALLOCDATA (buffer) = data; + GST_BUFFER_DATA (buffer) = data; } GST_BUFFER_SIZE (buffer) = len; /* remove any padding */ - GST_RTP_HEADER_PADDING (buffer) = FALSE; + GST_RTP_HEADER_PADDING (data) = FALSE; } /** @@ -481,8 +595,6 @@ guint gst_rtp_buffer_get_packet_len (GstBuffer * buffer) { - g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); - return GST_BUFFER_SIZE (buffer); } @@ -503,12 +615,13 @@ gst_rtp_buffer_get_header_len (GstBuffer * buffer) { guint len; + guint8 *data; - g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + data = GST_BUFFER_DATA (buffer); - len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (buffer); - if (GST_RTP_HEADER_EXTENSION (buffer)) - len += GST_READ_UINT16_BE (GST_BUFFER_DATA (buffer) + len + 2) * 4 + 4; + len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data); + if (GST_RTP_HEADER_EXTENSION (data)) + len += GST_READ_UINT16_BE (data + len + 2) * 4 + 4; return len; } @@ -528,10 +641,7 @@ guint8 gst_rtp_buffer_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); + return GST_RTP_HEADER_VERSION (GST_BUFFER_DATA (buffer)); } /** @@ -548,11 +658,9 @@ void gst_rtp_buffer_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; + GST_RTP_HEADER_VERSION (GST_BUFFER_DATA (buffer)) = version; } /** @@ -570,10 +678,7 @@ gboolean gst_rtp_buffer_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); + return GST_RTP_HEADER_PADDING (GST_BUFFER_DATA (buffer)); } /** @@ -590,10 +695,7 @@ void gst_rtp_buffer_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; + GST_RTP_HEADER_PADDING (GST_BUFFER_DATA (buffer)) = padding; } /** @@ -613,13 +715,14 @@ void gst_rtp_buffer_pad_to (GstBuffer * buffer, guint len) { - g_return_if_fail (GST_IS_BUFFER (buffer)); - g_return_if_fail (GST_BUFFER_DATA (buffer) != NULL); + guint8 *data; + + data = GST_BUFFER_DATA (buffer); if (len > 0) - GST_RTP_HEADER_PADDING (buffer) = TRUE; + GST_RTP_HEADER_PADDING (data) = TRUE; else - GST_RTP_HEADER_PADDING (buffer) = FALSE; + GST_RTP_HEADER_PADDING (data) = FALSE; /* FIXME, set the padding byte at the end of the payload data */ } @@ -639,10 +742,7 @@ gboolean gst_rtp_buffer_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); + return GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer)); } /** @@ -659,10 +759,7 @@ void gst_rtp_buffer_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; + GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer)) = extension; } /** @@ -694,15 +791,14 @@ guint len; guint8 *pdata; - g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); - g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE); + pdata = GST_BUFFER_DATA (buffer); - if (!GST_RTP_HEADER_EXTENSION (buffer)) + if (!GST_RTP_HEADER_EXTENSION (pdata)) return FALSE; /* move to the extension */ - len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (buffer); - pdata = GST_BUFFER_DATA (buffer) + len; + len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (pdata); + pdata += len; if (bits) *bits = GST_READ_UINT16_BE (pdata); @@ -740,27 +836,32 @@ guint32 min_size = 0; guint8 *data; - g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); - g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, FALSE); + data = GST_BUFFER_DATA (buffer); - gst_rtp_buffer_set_extension (buffer, TRUE); + /* check if the buffer is big enough to hold the extension */ min_size = - GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (buffer) + 4 + + GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data) + 4 + length * sizeof (guint32); + if (G_UNLIKELY (min_size > GST_BUFFER_SIZE (buffer))) + goto too_small; + + /* now we can set the extension bit */ + gst_rtp_buffer_set_extension (buffer, TRUE); - if (min_size > GST_BUFFER_SIZE (buffer)) { - GST_WARNING_OBJECT (buffer, - "rtp buffer too small: need more than %d bytes but only have %d bytes", + data += GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data); + GST_WRITE_UINT16_BE (data, bits); + GST_WRITE_UINT16_BE (data + 2, length); + + return TRUE; + + /* ERRORS */ +too_small: + { + g_warning + ("rtp buffer too small: need more than %d bytes but only have %d bytes", min_size, GST_BUFFER_SIZE (buffer)); return FALSE; } - - data = - GST_BUFFER_DATA (buffer) + GST_RTP_HEADER_LEN + - GST_RTP_HEADER_CSRC_SIZE (buffer); - GST_WRITE_UINT16_BE (data, bits); - GST_WRITE_UINT16_BE (data + 2, length); - return TRUE; } /** @@ -778,10 +879,34 @@ guint32 gst_rtp_buffer_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 (GST_BUFFER_DATA (buffer))); +} - return g_ntohl (GST_RTP_HEADER_SSRC (buffer)); +/** + * gst_rtp_buffer_list_get_ssrc: + * @list: the buffer list + * + * Get the SSRC of the first RTP packet in @list. + * All RTP packets within @list have the same SSRC. + * + * Returns: the SSRC of @list in host order. + * + * Since: 0.10.24 + */ + + #ifdef __SYMBIAN32__ +EXPORT_C +#endif + +guint32 +gst_rtp_buffer_list_get_ssrc (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer))); } /** @@ -798,10 +923,32 @@ void gst_rtp_buffer_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 (GST_BUFFER_DATA (buffer)) = g_htonl (ssrc); +} + +static GstBufferListItem +set_ssrc_header (GstBuffer ** buffer, guint group, guint idx, guint32 * ssrc) +{ + GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (*buffer)) = g_htonl (*ssrc); + return GST_BUFFER_LIST_SKIP_GROUP; +} - GST_RTP_HEADER_SSRC (buffer) = g_htonl (ssrc); +/** + * gst_rtp_buffer_list_set_ssrc: + * @list: the buffer list + * @ssrc: the new SSRC + * + * Set the SSRC on each RTP packet in @list to @ssrc. + * + * Since: 0.10.24 + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif +void +gst_rtp_buffer_list_set_ssrc (GstBufferList * list, guint32 ssrc) +{ + gst_buffer_list_foreach (list, (GstBufferListFunc) set_ssrc_header, &ssrc); } /** @@ -819,10 +966,7 @@ guint8 gst_rtp_buffer_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); + return GST_RTP_HEADER_CSRC_COUNT (GST_BUFFER_DATA (buffer)); } /** @@ -841,11 +985,13 @@ guint32 gst_rtp_buffer_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 (idx < GST_RTP_HEADER_CSRC_COUNT (buffer), 0); + guint8 *data; + + data = GST_BUFFER_DATA (buffer); - return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, idx)); + g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data), 0); + + return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx)); } /** @@ -863,11 +1009,13 @@ void gst_rtp_buffer_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 (idx < GST_RTP_HEADER_CSRC_COUNT (buffer)); + guint8 *data; + + data = GST_BUFFER_DATA (buffer); - GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (buffer, idx), csrc); + g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data)); + + GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx), csrc); } /** @@ -885,10 +1033,7 @@ gboolean gst_rtp_buffer_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); + return GST_RTP_HEADER_MARKER (GST_BUFFER_DATA (buffer)); } /** @@ -905,10 +1050,7 @@ void gst_rtp_buffer_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; + GST_RTP_HEADER_MARKER (GST_BUFFER_DATA (buffer)) = marker; } /** @@ -926,10 +1068,34 @@ guint8 gst_rtp_buffer_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 (GST_BUFFER_DATA (buffer)); +} - return GST_RTP_HEADER_PAYLOAD_TYPE (buffer); +/** + * gst_rtp_buffer_list_get_payload_type: + * @list: the buffer list + * + * Get the payload type of the first RTP packet in @list. + * All packets in @list should have the same payload type. + * + * Returns: The payload type. + * + * Since: 0.10.24 + */ + + #ifdef __SYMBIAN32__ +EXPORT_C +#endif + +guint8 +gst_rtp_buffer_list_get_payload_type (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer)); } /** @@ -946,11 +1112,39 @@ void gst_rtp_buffer_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; + GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer)) = payload_type; +} + +static GstBufferListItem +set_pt_header (GstBuffer ** buffer, guint group, guint idx, guint8 * pt) +{ + GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (*buffer)) = *pt; + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/** + * gst_rtp_buffer_list_set_payload_type: + * @list: the buffer list + * @payload_type: the new type + * + * Set the payload type of each RTP packet in @list to @payload_type. + * + * Since: 0.10.24 + */ + +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_rtp_buffer_list_set_payload_type (GstBufferList * list, guint8 payload_type) +{ + g_return_if_fail (payload_type < 0x80); + + gst_buffer_list_foreach (list, (GstBufferListFunc) set_pt_header, + &payload_type); } /** @@ -968,10 +1162,7 @@ guint16 gst_rtp_buffer_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)); + return g_ntohs (GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer))); } /** @@ -988,13 +1179,69 @@ void gst_rtp_buffer_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 (GST_BUFFER_DATA (buffer)) = g_htons (seq); +} + +static GstBufferListItem +set_seq_header (GstBuffer ** buffer, guint group, guint idx, guint16 * seq) +{ + GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (*buffer)) = g_htons (*seq); + (*seq)++; + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/** + * gst_rtp_buffer_list_set_seq: + * @list: the buffer list + * @seq: the new sequence number + * + * Set the sequence number of each RTP packet in @list to @seq. + * + * Returns: The seq number of the last packet in the list + 1. + * + * Since: 0.10.24 + */ + + #ifdef __SYMBIAN32__ +EXPORT_C +#endif - GST_RTP_HEADER_SEQ (buffer) = g_htons (seq); +guint16 +gst_rtp_buffer_list_set_seq (GstBufferList * list, guint16 seq) +{ + gst_buffer_list_foreach (list, (GstBufferListFunc) set_seq_header, &seq); + return seq; } /** + * gst_rtp_buffer_list_get_seq: + * @list: the buffer list + * + * Get the sequence number of the first RTP packet in @list. + * All packets within @list have the same sequence number. + * + * Returns: The seq number + * + * Since: 0.10.24 + */ + +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +guint16 +gst_rtp_buffer_list_get_seq (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer))); +} + + +/** * gst_rtp_buffer_get_timestamp: * @buffer: the buffer * @@ -1009,10 +1256,34 @@ guint32 gst_rtp_buffer_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 (GST_BUFFER_DATA (buffer))); +} - return g_ntohl (GST_RTP_HEADER_TIMESTAMP (buffer)); +/** + * gst_rtp_buffer_list_get_timestamp: + * @list: the buffer list + * + * Get the timestamp of the first RTP packet in @list. + * All packets within @list have the same timestamp. + * + * Returns: The timestamp in host order. + * + * Since: 0.10.24 + */ + + #ifdef __SYMBIAN32__ +EXPORT_C +#endif + +guint32 +gst_rtp_buffer_list_get_timestamp (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer))); } /** @@ -1029,10 +1300,37 @@ void gst_rtp_buffer_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 (GST_BUFFER_DATA (buffer)) = g_htonl (timestamp); +} + + +static GstBufferListItem +set_timestamp_header (GstBuffer ** buffer, guint group, guint idx, + guint32 * timestamp) +{ + GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (*buffer)) = g_htonl (*timestamp); + return GST_BUFFER_LIST_SKIP_GROUP; +} - GST_RTP_HEADER_TIMESTAMP (buffer) = g_htonl (timestamp); +/** + * gst_rtp_buffer_list_set_timestamp: + * @list: the buffer list + * @timestamp: the new timestamp + * + * Set the timestamp of each RTP packet in @list to @timestamp. + * + * Since: 0.10.24 + */ + + #ifdef __SYMBIAN32__ +EXPORT_C +#endif + +void +gst_rtp_buffer_list_set_timestamp (GstBufferList * list, guint32 timestamp) +{ + gst_buffer_list_foreach (list, (GstBufferListFunc) set_timestamp_header, + ×tamp); } /** @@ -1059,15 +1357,10 @@ { guint poffset, plen; - g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); - g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL); - plen = gst_rtp_buffer_get_payload_len (buffer); /* we can't go past the length */ - if (G_UNLIKELY (offset >= plen)) { - GST_WARNING ("offset=%u should be less then plen=%u", offset, plen); - return (NULL); - } + if (G_UNLIKELY (offset >= plen)) + goto wrong_offset; /* apply offset */ poffset = gst_rtp_buffer_get_header_len (buffer) + offset; @@ -1078,6 +1371,13 @@ plen = len; return gst_buffer_create_sub (buffer, poffset, plen); + + /* ERRORS */ +wrong_offset: + { + g_warning ("offset=%u should be less then plen=%u", offset, plen); + return NULL; + } } /** @@ -1116,16 +1416,58 @@ gst_rtp_buffer_get_payload_len (GstBuffer * buffer) { guint len, size; - - g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); - g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, 0); + guint8 *data; size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); len = size - gst_rtp_buffer_get_header_len (buffer); - if (GST_RTP_HEADER_PADDING (buffer)) - len -= GST_BUFFER_DATA (buffer)[size - 1]; + if (GST_RTP_HEADER_PADDING (data)) + len -= data[size - 1]; + + return len; +} + +/** + * gst_rtp_buffer_list_get_payload_len: + * @list: the buffer list + * + * Get the length of the payload of the RTP packet in @list. + * + * Returns: The length of the payload in @list. + * + * Since: 0.10.24 + */ + +#ifdef __SYMBIAN32__ +EXPORT_C +#endif + +guint +gst_rtp_buffer_list_get_payload_len (GstBufferList * list) +{ + guint len; + GstBufferListIterator *it; + + it = gst_buffer_list_iterate (list); + len = 0; + + while (gst_buffer_list_iterator_next_group (it)) { + guint i; + GstBuffer *buf; + + i = 0; + while ((buf = gst_buffer_list_iterator_next (it))) { + /* skip the RTP header */ + if (!i++) + continue; + /* take the size of the current buffer */ + len += GST_BUFFER_SIZE (buf); + } + } + + gst_buffer_list_iterator_free (it); return len; } @@ -1146,9 +1488,6 @@ gpointer gst_rtp_buffer_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_buffer_get_header_len (buffer); } @@ -1190,10 +1529,11 @@ * @seqnum1: a sequence number * @seqnum2: a sequence number * - * Compare two sequence numbers, taking care of wraparounds. + * Compare two sequence numbers, taking care of wraparounds. This function + * returns the difference between @seqnum1 and @seqnum2. * - * Returns: -1 if @seqnum1 is before @seqnum2, 0 if they are equal or 1 if - * @seqnum1 is bigger than @segnum2. + * Returns: a negative value if @seqnum1 is bigger than @seqnum2, 0 if they + * are equal or a positive value if @seqnum1 is smaller than @segnum2. * * Since: 0.10.15 */ @@ -1204,13 +1544,7 @@ gint gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2) { - /* check if diff more than half of the 16bit range */ - if (abs (seqnum2 - seqnum1) > (1 << 15)) { - /* one of a/b has wrapped */ - return seqnum1 - seqnum2; - } else { - return seqnum2 - seqnum1; - } + return (gint16) (seqnum2 - seqnum1); } /**