summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/libs/gst-plugins-base-libs-sections.txt3
-rw-r--r--gst-libs/gst/rtp/gstrtpbuffer.c281
-rw-r--r--gst-libs/gst/rtp/gstrtpbuffer.h11
3 files changed, 251 insertions, 44 deletions
diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt
index b9184f81c..ccd57a5ab 100644
--- a/docs/libs/gst-plugins-base-libs-sections.txt
+++ b/docs/libs/gst-plugins-base-libs-sections.txt
@@ -1359,12 +1359,13 @@ gst_rtp_buffer_list_set_timestamp
gst_rtp_buffer_get_extension_onebyte_header
gst_rtp_buffer_get_extension_twobytes_header
-
gst_rtp_buffer_add_extension_onebyte_header
gst_rtp_buffer_add_extension_twobytes_header
gst_rtp_buffer_list_get_extension_onebyte_header
gst_rtp_buffer_list_get_extension_twobytes_header
+gst_rtp_buffer_list_add_extension_onebyte_header
+gst_rtp_buffer_list_add_extension_twobytes_header
</SECTION>
# rtsp
diff --git a/gst-libs/gst/rtp/gstrtpbuffer.c b/gst-libs/gst/rtp/gstrtpbuffer.c
index 4919dc832..b4707307f 100644
--- a/gst-libs/gst/rtp/gstrtpbuffer.c
+++ b/gst-libs/gst/rtp/gstrtpbuffer.c
@@ -1543,6 +1543,43 @@ gst_rtp_buffer_get_extension_twobytes_header (GstBuffer * buffer,
return FALSE;
}
+static guint
+get_onebyte_header_end_offset (guint8 * pdata, guint wordlen)
+{
+ guint offset = 0;
+ guint bytelen = wordlen * 4;
+ guint paddingcount = 0;
+
+ while (offset + 1 < bytelen) {
+ guint8 read_id, read_len;
+
+ read_id = GST_READ_UINT8 (pdata + offset) >> 4;
+ read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1;
+ offset += 1;
+
+ /* ID 0 means its padding, skip */
+ if (read_id == 0) {
+ paddingcount++;
+ continue;
+ }
+
+ paddingcount = 0;
+
+ /* ID 15 is special and means we should stop parsing */
+ /* It also means we can't add an extra packet */
+ if (read_id == 15)
+ return 0;
+
+ /* Ignore extension headers where the size does not fit */
+ if (offset + read_len > bytelen)
+ return 0;
+
+ offset += read_len;
+ }
+
+ return offset - paddingcount;
+}
+
/**
* gst_rtp_buffer_add_extension_onebyte_header:
* @buffer: the buffer
@@ -1590,32 +1627,11 @@ gst_rtp_buffer_add_extension_onebyte_header (GstBuffer * buffer, guint8 id,
if (bits != 0xBEDE)
return FALSE;
- while (offset + 1 < bytelen) {
- guint8 read_id, read_len;
-
- read_id = GST_READ_UINT8 (pdata + offset) >> 4;
- read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1;
- offset += 1;
-
- /* ID 0 means its padding, skip */
- if (read_id == 0)
- continue;
-
- /* ID 15 is special and means we should stop parsing */
- /* It also means we can't add an extra packet */
- if (read_id == 15)
- return FALSE;
-
- /* Ignore extension headers where the size does not fit */
- if (offset + read_len > bytelen)
- return FALSE;
-
- offset += read_len;
-
- }
+ offset = get_onebyte_header_end_offset (pdata, wordlen);
+ if (offset == 0)
+ return FALSE;
nextext = pdata + offset;
-
offset = nextext - GST_BUFFER_DATA (buffer);
/* Don't add extra header if there isn't enough space */
@@ -1652,6 +1668,41 @@ gst_rtp_buffer_add_extension_onebyte_header (GstBuffer * buffer, guint8 id,
return TRUE;
}
+
+static guint
+get_twobytes_header_end_offset (guint8 * pdata, guint wordlen)
+{
+ guint offset = 0;
+ guint bytelen = wordlen * 4;
+ guint paddingcount = 0;
+
+ while (offset + 2 < bytelen) {
+ guint8 read_id, read_len;
+
+ read_id = GST_READ_UINT8 (pdata + offset);
+ offset += 1;
+
+ /* ID 0 means its padding, skip */
+ if (read_id == 0) {
+ paddingcount++;
+ continue;
+ }
+
+ paddingcount = 0;
+
+ read_len = GST_READ_UINT8 (pdata + offset);
+ offset += 1;
+
+ /* Ignore extension headers where the size does not fit */
+ if (offset + read_len > bytelen)
+ return 0;
+
+ offset += read_len;
+ }
+
+ return offset - paddingcount;
+}
+
/**
* gst_rtp_buffer_add_extension_twobytes_header:
* @buffer: the buffer
@@ -1700,25 +1751,7 @@ gst_rtp_buffer_add_extension_twobytes_header (GstBuffer * buffer,
if (bits != ((0x100 << 4) | (appbits & 0x0f)))
return FALSE;
- while (offset + 2 < bytelen) {
- guint8 read_id, read_len;
-
- read_id = GST_READ_UINT8 (pdata + offset);
- offset += 1;
-
- /* ID 0 means its padding, skip */
- if (read_id == 0)
- continue;
-
- read_len = GST_READ_UINT8 (pdata + offset);
- offset += 1;
-
- /* Ignore extension headers where the size does not fit */
- if (offset + read_len > bytelen)
- return FALSE;
-
- offset += read_len;
- }
+ offset = get_twobytes_header_end_offset (pdata, wordlen);
nextext = pdata + offset;
@@ -1827,3 +1860,165 @@ gst_rtp_buffer_list_get_extension_twobytes_header (GstBufferList * bufferlist,
return gst_rtp_buffer_get_extension_twobytes_header (buffer, appbits, id,
nth, data, size);
}
+
+/**
+ * gst_rtp_buffer_list_add_extension_onebyte_header:
+ * @it: a #GstBufferListIterator pointing right after the #GstBuffer where
+ * the header extension should be added
+ * @id: The ID of the header extension (between 1 and 14).
+ * @data: location for data
+ * @size: the size of the data in bytes
+ *
+ * Adds a RFC 5285 header extension with a one byte header to the end of the
+ * RTP header. If there is already a RFC 5285 header extension with a one byte
+ * header, the new extension will be appended.
+ * It will not work if there is already a header extension that does not follow
+ * the mecanism described in RFC 5285 or if there is a header extension with
+ * a two bytes header as described in RFC 5285. In that case, use
+ * gst_rtp_buffer_list_add_extension_twobytes_header()
+ *
+ * This function will not modify the data section of the RTP buffer, only
+ * the header.
+ *
+ * Returns: %TRUE if header extension could be added
+ *
+ * Since: 0.10.31
+ */
+
+gboolean
+gst_rtp_buffer_list_add_extension_onebyte_header (GstBufferListIterator * it,
+ guint8 id, gpointer data, guint size)
+{
+ GstBuffer *buffer;
+ guint16 bits;
+ guint8 *pdata;
+ guint wordlen;
+ gboolean retval;
+ guint endoffset = 0;
+
+ g_return_val_if_fail (gst_buffer_list_iterator_n_buffers (it) == 1, FALSE);
+ g_return_val_if_fail (id > 0 && id < 15, FALSE);
+ g_return_val_if_fail (size >= 1 && size <= 16, FALSE);
+
+ buffer = gst_buffer_list_iterator_steal (it);
+
+ if (GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer))) {
+ gst_rtp_buffer_get_extension_data (buffer, &bits, (gpointer) & pdata,
+ &wordlen);
+
+ if (bits != 0xBEDE)
+ return FALSE;
+
+ endoffset = get_onebyte_header_end_offset (pdata, wordlen);
+ if (endoffset == 0)
+ return FALSE;
+ endoffset += pdata - GST_BUFFER_DATA (buffer);
+ } else {
+ endoffset = GST_BUFFER_SIZE (buffer) + 4;
+ }
+
+ if (endoffset + size + 1 > GST_BUFFER_SIZE (buffer)) {
+ guint newsize;
+ GstBuffer *newbuffer;
+
+ newsize = endoffset + size + 1;
+ if (newsize % 4)
+ newsize += 4 - (newsize % 4);
+ newbuffer = gst_buffer_new_and_alloc (newsize);
+ memcpy (GST_BUFFER_DATA (newbuffer), GST_BUFFER_DATA (buffer),
+ GST_BUFFER_SIZE (buffer));
+ gst_buffer_copy_metadata (newbuffer, buffer, GST_BUFFER_COPY_ALL);
+ gst_buffer_unref (buffer);
+ buffer = newbuffer;
+ } else {
+ buffer = gst_buffer_make_writable (buffer);
+ }
+
+ retval = gst_rtp_buffer_add_extension_onebyte_header (buffer, id, data, size);
+
+ gst_buffer_list_iterator_take (it, buffer);
+
+ return retval;
+}
+
+/**
+ * gst_rtp_buffer_list_add_extension_twobytes_header:
+ * @it: a #GstBufferListIterator pointing right after the #GstBuffer where
+ * the header extension should be added
+ * @appbits: Application specific bits
+ * @id: The ID of the header extension
+ * @data: location for data
+ * @size: the size of the data in bytes
+ *
+ * Adds a RFC 5285 header extension with a two bytes header to the end of the
+ * RTP header. If there is already a RFC 5285 header extension with a two bytes
+ * header, the new extension will be appended.
+ * It will not work if there is already a header extension that does not follow
+ * the mecanism described in RFC 5285 or if there is a header extension with
+ * a one byte header as described in RFC 5285. In that case, use
+ * gst_rtp_buffer_add_extension_onebyte_header()
+ *
+ * This function will not modify the data section of the RTP buffer, only
+ * the header.
+ *
+ * Returns: %TRUE if header extension could be added
+ *
+ * Since: 0.10.31
+ */
+
+gboolean
+gst_rtp_buffer_list_add_extension_twobytes_header (GstBufferListIterator * it,
+ guint8 appbits, guint8 id, gpointer data, guint size)
+{
+ GstBuffer *buffer;
+ guint16 bits;
+ guint8 *pdata;
+ guint wordlen;
+ gboolean retval;
+ guint endoffset;
+
+ g_return_val_if_fail ((appbits & 0xF0) == 0, FALSE);
+ g_return_val_if_fail (size < 256, FALSE);
+ g_return_val_if_fail (gst_buffer_list_iterator_n_buffers (it) == 1, FALSE);
+
+ buffer = gst_buffer_list_iterator_steal (it);
+
+ if (GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer))) {
+ gst_rtp_buffer_get_extension_data (buffer, &bits, (gpointer) & pdata,
+ &wordlen);
+
+ if (bits != ((0x100 << 4) | (appbits & 0x0f)))
+ return FALSE;
+
+ endoffset = get_twobytes_header_end_offset (pdata, wordlen);
+ if (endoffset == 0)
+ return FALSE;
+ endoffset += pdata - GST_BUFFER_DATA (buffer);
+ } else {
+ endoffset = GST_BUFFER_SIZE (buffer) + 4;
+ }
+
+ if (endoffset + size + 2 > GST_BUFFER_SIZE (buffer)) {
+ guint newsize;
+ GstBuffer *newbuffer;
+
+ newsize = endoffset + size + 2;
+ if (newsize % 4)
+ newsize += 4 - newsize % 4;
+ newbuffer = gst_buffer_new_and_alloc (newsize);
+ memcpy (GST_BUFFER_DATA (newbuffer), GST_BUFFER_DATA (buffer),
+ GST_BUFFER_SIZE (buffer));
+ gst_buffer_copy_metadata (newbuffer, buffer, GST_BUFFER_COPY_ALL);
+ gst_buffer_unref (buffer);
+ buffer = newbuffer;
+ } else {
+ buffer = gst_buffer_make_writable (buffer);
+ }
+
+ retval = gst_rtp_buffer_add_extension_twobytes_header (buffer, appbits, id,
+ data, size);
+
+ gst_buffer_list_iterator_take (it, buffer);
+
+ return retval;
+}
diff --git a/gst-libs/gst/rtp/gstrtpbuffer.h b/gst-libs/gst/rtp/gstrtpbuffer.h
index a1e5ee6ac..064a908e7 100644
--- a/gst-libs/gst/rtp/gstrtpbuffer.h
+++ b/gst-libs/gst/rtp/gstrtpbuffer.h
@@ -146,6 +146,17 @@ gboolean gst_rtp_buffer_list_get_extension_twobytes_header (GstBufferList
gpointer * data,
guint * size);
+gboolean gst_rtp_buffer_list_add_extension_onebyte_header (GstBufferListIterator * it,
+ guint8 id,
+ gpointer data,
+ guint size);
+gboolean gst_rtp_buffer_list_add_extension_twobytes_header (GstBufferListIterator * it,
+ guint8 appbits,
+ guint8 id,
+ gpointer data,
+ guint size);
+
+
G_END_DECLS
#endif /* __GST_RTPBUFFER_H__ */