- pad_len;
}
-/*
- * 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
+/**
+ * gst_rtp_buffer_map:
+ * @buffer: a #GstBuffer
+ * @flags: #GstMapFlags
+ * @rtp: (out): a #GstRTPBuffer
*
- * Checks if @data is a valid RTP packet.
+ * Map the contents of @buffer into @rtp.
*
- * Returns: TRUE if @data is a valid RTP packet
+ * Returns: %TRUE if @buffer could be mapped.
*/
-static gboolean
-validate_data (guint8 * data, guint len, guint8 * payload, guint payload_len)
+gboolean
+gst_rtp_buffer_map (GstBuffer * buffer, GstMapFlags flags, GstRTPBuffer * rtp)
{
guint8 padding;
guint8 csrc_count;
guint header_len;
guint8 version;
+ guint8 *data;
+ guint size;
+ gsize bufsize, skip;
+ guint idx, length;
- g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
+ g_return_val_if_fail (rtp != NULL, FALSE);
+ g_return_val_if_fail (rtp->buffer == NULL, FALSE);
+
+ /* map first memory, this should be the header */
+ if (!gst_buffer_map_range (buffer, 0, 1, &rtp->map[0], flags))
+ goto map_failed;
+
+ data = rtp->data[0] = rtp->map[0].data;
+ size = rtp->map[0].size;
header_len = GST_RTP_HEADER_LEN;
- if (G_UNLIKELY (len < header_len))
+ if (G_UNLIKELY (size < header_len))
goto wrong_length;
/* check version */
csrc_count = (data[0] & 0x0f);
header_len += csrc_count * sizeof (guint32);
+ rtp->size[0] = header_len;
+
+ bufsize = gst_buffer_get_size (buffer);
+
/* calc extension length when present. */
if (data[0] & 0x10) {
- guint8 *extpos;
+ guint8 *extdata;
guint16 extlen;
- /* this points to the extension bits and header length */
- extpos = &data[header_len];
-
- /* skip the header and check that we have enough space */
- header_len += 4;
- if (G_UNLIKELY (len < header_len))
+ /* find memory for the extension bits */
+ if (!gst_buffer_find_memory (buffer, header_len, 4, &idx, &length, &skip))
goto wrong_length;
+ if (!gst_buffer_map_range (buffer, idx, length, &rtp->map[1], flags))
+ goto map_failed;
+
+ extdata = rtp->data[1] = rtp->map[1].data + skip;
/* skip id */
- extpos += 2;
+ extdata += 2;
/* read length as the number of 32 bits words */
- extlen = GST_READ_UINT16_BE (extpos);
+ extlen = GST_READ_UINT16_BE (extdata);
+
+ rtp->size[1] = extlen * sizeof (guint32);
- header_len += extlen * sizeof (guint32);
+ header_len += rtp->size[1];
+ } else {
+ rtp->data[1] = NULL;
+ rtp->size[1] = 0;
}
/* check for padding */
if (data[0] & 0x20) {
- if (payload)
- padding = payload[payload_len - 1];
- else
- padding = data[len - 1];
+ /* find memory for the padding bits */
+ if (!gst_buffer_find_memory (buffer, bufsize - 1, 1, &idx, &length, &skip))
+ goto wrong_length;
+
+ if (!gst_buffer_map_range (buffer, idx, length, &rtp->map[3], flags))
+ goto map_failed;
+
+ padding = rtp->map[3].data[skip];
+ if (skip + 1 < padding)
+ goto wrong_length;
+
+ rtp->data[3] = rtp->map[3].data + skip + 1 - padding;
+ rtp->size[3] = padding;
} else {
+ rtp->data[3] = NULL;
+ rtp->size[3] = 0;
padding = 0;
}
/* check if padding and header not bigger than packet length */
- if (G_UNLIKELY (len < padding + header_len))
+ if (G_UNLIKELY (bufsize < padding + header_len))
goto wrong_padding;
+ rtp->buffer = buffer;
+ /* we have not yet mapped the payload */
+ rtp->data[2] = NULL;
+ rtp->size[2] = 0;
+ rtp->state = 0;
+ rtp->n_map = 1;
+
return TRUE;
/* ERRORS */
+map_failed:
+ {
+ GST_ERROR ("failed to map memory");
+ return FALSE;
+ }
wrong_length:
{
- GST_DEBUG ("len < header_len check failed (%d < %d)", len, header_len);
+ GST_DEBUG ("length check failed");
goto dump_packet;
}
wrong_version:
}
wrong_padding:
{
- GST_DEBUG ("padding check failed (%d - %d < %d)", len, header_len, padding);
+ GST_DEBUG ("padding check failed (%d - %d < %d)", bufsize, header_len,
+ padding);
goto dump_packet;
}
dump_packet:
{
- GST_MEMDUMP ("buffer", data, len);
+ GST_MEMDUMP ("buffer", data, size);
return FALSE;
}
}
/**
- * gst_rtp_buffer_validate_data:
- * @data: (array length=len) (element-type guint8): 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.
- */
-gboolean
-gst_rtp_buffer_validate_data (guint8 * data, gsize 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().
- * Use this function to validate a packet before using the other functions in
- * this module.
+ * gst_rtp_buffer_unmap:
+ * @rtp: a #GstRTPBuffer
*
- * Returns: TRUE if @buffer is a valid RTP packet.
+ * Unmap @rtp previously mapped with gst_rtp_buffer_map().
*/
-gboolean
-gst_rtp_buffer_validate (GstBuffer * buffer)
-{
- gboolean res;
- GstMapInfo map;
-
- g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
-
- gst_buffer_map (buffer, &map, GST_MAP_READ);
- res = validate_data (map.data, map.size, NULL, 0);
- gst_buffer_unmap (buffer, &map);
-
- return res;
-}
-
-gboolean
-gst_rtp_buffer_map (GstBuffer * buffer, GstMapFlags flags, GstRTPBuffer * rtp)
-{
- g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
- g_return_val_if_fail (rtp != NULL, FALSE);
- g_return_val_if_fail (rtp->buffer == NULL, FALSE);
-
- if (!gst_buffer_map (buffer, &rtp->map[0], flags))
- return FALSE;
-
- rtp->buffer = buffer;
- rtp->state = 0;
- rtp->n_map = 1;
-
- return TRUE;
-}
-
-gboolean
+void
gst_rtp_buffer_unmap (GstRTPBuffer * rtp)
{
- g_return_val_if_fail (rtp != NULL, FALSE);
- g_return_val_if_fail (rtp->buffer != NULL, FALSE);
+ gint i;
+
+ g_return_if_fail (rtp != NULL);
+ g_return_if_fail (rtp->buffer != NULL);
- gst_buffer_unmap (rtp->buffer, &rtp->map[0]);
+ for (i = 0; i < 4; i++) {
+ if (rtp->data[i])
+ gst_buffer_unmap (rtp->buffer, &rtp->map[i]);
+ }
rtp->buffer = NULL;
rtp->n_map = 0;
-
- return TRUE;
}
{
guint8 *data;
- data = rtp->map[0].data;
+ data = rtp->data[0];
+
+ /* FIXME */
if (rtp->map[0].maxsize <= len) {
/* FIXME, realloc bigger space */
guint
gst_rtp_buffer_get_header_len (GstRTPBuffer * rtp)
{
- guint len;
- guint8 *data;
-
- data = rtp->map[0].data;
-
- 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;
+ return rtp->size[0] + rtp->size[1];
}
/**
guint8
gst_rtp_buffer_get_version (GstRTPBuffer * rtp)
{
- return GST_RTP_HEADER_VERSION (rtp->map[0].data);
+ return GST_RTP_HEADER_VERSION (rtp->data[0]);
}
/**
{
g_return_if_fail (version < 0x04);
- GST_RTP_HEADER_VERSION (rtp->map[0].data) = version;
+ GST_RTP_HEADER_VERSION (rtp->data[0]) = version;
}
/**
gboolean
gst_rtp_buffer_get_padding (GstRTPBuffer * rtp)
{
- return GST_RTP_HEADER_PADDING (rtp->map[0].data);
+ return GST_RTP_HEADER_PADDING (rtp->data[0]);
}
/**
void
gst_rtp_buffer_set_padding (GstRTPBuffer * rtp, gboolean padding)
{
- GST_RTP_HEADER_PADDING (rtp->map[0].data) = padding;
+ GST_RTP_HEADER_PADDING (rtp->data[0]) = padding;
}
/**
{
guint8 *data;
- data = rtp->map[0].data;
+ data = rtp->data[0];
if (len > 0)
GST_RTP_HEADER_PADDING (data) = TRUE;
gboolean
gst_rtp_buffer_get_extension (GstRTPBuffer * rtp)
{
- return GST_RTP_HEADER_EXTENSION (rtp->map[0].data);
+ return GST_RTP_HEADER_EXTENSION (rtp->data[0]);
}
/**
void
gst_rtp_buffer_set_extension (GstRTPBuffer * rtp, gboolean extension)
{
- GST_RTP_HEADER_EXTENSION (rtp->map[0].data) = extension;
+ GST_RTP_HEADER_EXTENSION (rtp->data[0]) = extension;
}
/**
gst_rtp_buffer_get_extension_data (GstRTPBuffer * rtp, guint16 * bits,
gpointer * data, guint * wordlen)
{
- guint len;
guint8 *pdata;
- pdata = rtp->map[0].data;
-
- if (!GST_RTP_HEADER_EXTENSION (pdata))
- return FALSE;
-
/* move to the extension */
- len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (pdata);
- pdata += len;
+ pdata = rtp->data[1];
+ if (!pdata)
+ return FALSE;
if (bits)
*bits = GST_READ_UINT16_BE (pdata);
guint32 min_size = 0;
guint8 *data;
- data = rtp->map[0].data;
+ /* FIXME, we should allocate and map the extension data */
+ data = rtp->data[0];
/* check if the buffer is big enough to hold the extension */
- min_size =
- GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data) + 4 +
- length * sizeof (guint32);
- if (G_UNLIKELY (min_size > rtp->map[0].size))
+ min_size = 4 + length * sizeof (guint32);
+ if (G_UNLIKELY (min_size > rtp->size[1]))
goto too_small;
/* now we can set the extension bit */
- GST_RTP_HEADER_EXTENSION (rtp->map[0].data) = TRUE;
+ GST_RTP_HEADER_EXTENSION (data) = TRUE;
- data += GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data);
+ data = rtp->data[1];
GST_WRITE_UINT16_BE (data, bits);
GST_WRITE_UINT16_BE (data + 2, length);
{
g_warning
("rtp buffer too small: need more than %d bytes but only have %"
- G_GSIZE_FORMAT " bytes", min_size, rtp->map[0].size);
+ G_GSIZE_FORMAT " bytes", min_size, rtp->size[1]);
return FALSE;
}
}
guint32
gst_rtp_buffer_get_ssrc (GstRTPBuffer * rtp)
{
- return g_ntohl (GST_RTP_HEADER_SSRC (rtp->map[0].data));
+ return g_ntohl (GST_RTP_HEADER_SSRC (rtp->data[0]));
}
/**
void
gst_rtp_buffer_set_ssrc (GstRTPBuffer * rtp, guint32 ssrc)
{
- GST_RTP_HEADER_SSRC (rtp->map[0].data) = g_htonl (ssrc);
+ GST_RTP_HEADER_SSRC (rtp->data[0]) = g_htonl (ssrc);
}
/**
guint8
gst_rtp_buffer_get_csrc_count (GstRTPBuffer * rtp)
{
- return GST_RTP_HEADER_CSRC_COUNT (rtp->map[0].data);
+ return GST_RTP_HEADER_CSRC_COUNT (rtp->data[0]);
}
/**
{
guint8 *data;
- data = rtp->map[0].data;
+ data = rtp->data[0];
g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data), 0);
{
guint8 *data;
- data = rtp->map[0].data;
+ data = rtp->data[0];
g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data));
gboolean
gst_rtp_buffer_get_marker (GstRTPBuffer * rtp)
{
- return GST_RTP_HEADER_MARKER (rtp->map[0].data);
+ return GST_RTP_HEADER_MARKER (rtp->data[0]);
}
/**
void
gst_rtp_buffer_set_marker (GstRTPBuffer * rtp, gboolean marker)
{
- GST_RTP_HEADER_MARKER (rtp->map[0].data) = marker;
+ GST_RTP_HEADER_MARKER (rtp->data[0]) = marker;
}
/**
guint8
gst_rtp_buffer_get_payload_type (GstRTPBuffer * rtp)
{
- return GST_RTP_HEADER_PAYLOAD_TYPE (rtp->map[0].data);
+ return GST_RTP_HEADER_PAYLOAD_TYPE (rtp->data[0]);
}
/**
{
g_return_if_fail (payload_type < 0x80);
- GST_RTP_HEADER_PAYLOAD_TYPE (rtp->map[0].data) = payload_type;
+ GST_RTP_HEADER_PAYLOAD_TYPE (rtp->data[0]) = payload_type;
}
/**
guint16
gst_rtp_buffer_get_seq (GstRTPBuffer * rtp)
{
- return g_ntohs (GST_RTP_HEADER_SEQ (rtp->map[0].data));
+ return g_ntohs (GST_RTP_HEADER_SEQ (rtp->data[0]));
}
/**
void
gst_rtp_buffer_set_seq (GstRTPBuffer * rtp, guint16 seq)
{
- GST_RTP_HEADER_SEQ (rtp->map[0].data) = g_htons (seq);
+ GST_RTP_HEADER_SEQ (rtp->data[0]) = g_htons (seq);
}
/**
guint32
gst_rtp_buffer_get_timestamp (GstRTPBuffer * rtp)
{
- return g_ntohl (GST_RTP_HEADER_TIMESTAMP (rtp->map[0].data));
+ return g_ntohl (GST_RTP_HEADER_TIMESTAMP (rtp->data[0]));
}
/**
void
gst_rtp_buffer_set_timestamp (GstRTPBuffer * rtp, guint32 timestamp)
{
- GST_RTP_HEADER_TIMESTAMP (rtp->map[0].data) = g_htonl (timestamp);
+ GST_RTP_HEADER_TIMESTAMP (rtp->data[0]) = g_htonl (timestamp);
}
guint
gst_rtp_buffer_get_payload_len (GstRTPBuffer * rtp)
{
- guint len, size;
- guint8 *data;
-
- size = rtp->map[0].size;
- data = rtp->map[0].data;
-
- len = size - gst_rtp_buffer_get_header_len (rtp);
-
- if (GST_RTP_HEADER_PADDING (data))
- len -= data[size - 1];
-
- return len;
+ return gst_buffer_get_size (rtp->buffer) - gst_rtp_buffer_get_header_len (rtp)
+ - rtp->size[3];
}
/**
gpointer
gst_rtp_buffer_get_payload (GstRTPBuffer * rtp)
{
- return rtp->map[0].data + gst_rtp_buffer_get_header_len (rtp);
+ guint hlen, plen;
+ guint idx, length;
+ gsize skip;
+
+ if (rtp->data[2])
+ return rtp->data[2];
+
+ hlen = gst_rtp_buffer_get_header_len (rtp);
+ plen = gst_buffer_get_size (rtp->buffer) - hlen - rtp->size[3];
+
+ if (!gst_buffer_find_memory (rtp->buffer, hlen, plen, &idx, &length, &skip))
+ return NULL;
+
+ if (!gst_buffer_map_range (rtp->buffer, idx, length, &rtp->map[2],
+ rtp->map[0].flags))
+ return NULL;
+
+ rtp->data[2] = rtp->map[2].data + skip;
+ rtp->size[2] = plen;
+
+ return rtp->data[2];
}
/**