mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +00:00
tests/onvif: improve robustness
The previous iteration of the code was inferring the type of the frame by looking at the overall size of the gst-payloaded packet. It is more robust to actually parse the payload and look at the actual data buffers it contains. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2303>
This commit is contained in:
parent
9689693534
commit
4cd3830bc8
1 changed files with 256 additions and 26 deletions
|
@ -154,8 +154,8 @@ test_src_create (GstPushSrc * psrc, GstBuffer ** buffer)
|
||||||
duration =
|
duration =
|
||||||
MAX (duration * 10,
|
MAX (duration * 10,
|
||||||
duration * ROUND_UP_TO_10 (src->trickmode_interval));
|
duration * ROUND_UP_TO_10 (src->trickmode_interval));
|
||||||
} else if ((src->segment->
|
} else if ((src->
|
||||||
flags & GST_SEGMENT_FLAG_TRICKMODE_FORWARD_PREDICTED)) {
|
segment->flags & GST_SEGMENT_FLAG_TRICKMODE_FORWARD_PREDICTED)) {
|
||||||
duration *= 5;
|
duration *= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,6 +571,219 @@ typedef struct
|
||||||
#define EXTENSION_ID 0xABAC
|
#define EXTENSION_ID 0xABAC
|
||||||
#define EXTENSION_SIZE 3
|
#define EXTENSION_SIZE 3
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
read_length (guint8 * data, guint size, guint * length, guint * skip)
|
||||||
|
{
|
||||||
|
guint b, len, offset;
|
||||||
|
|
||||||
|
/* start reading the length, we need this to skip to the data later */
|
||||||
|
len = offset = 0;
|
||||||
|
do {
|
||||||
|
if (offset >= size)
|
||||||
|
return FALSE;
|
||||||
|
b = data[offset++];
|
||||||
|
len = (len << 7) | (b & 0x7f);
|
||||||
|
} while (b & 0x80);
|
||||||
|
|
||||||
|
/* check remaining buffer size */
|
||||||
|
if (size - offset < len)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*length = len;
|
||||||
|
*skip = offset;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
read_caps (GstBuffer * buf, guint * skip)
|
||||||
|
{
|
||||||
|
guint offset, length;
|
||||||
|
GstCaps *caps;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
|
|
||||||
|
if (!read_length (map.data, map.size, &length, &offset))
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
|
if (length == 0 || map.data[offset + length - 1] != '\0')
|
||||||
|
goto invalid_buffer;
|
||||||
|
|
||||||
|
/* parse and store in cache */
|
||||||
|
caps = gst_caps_from_string ((gchar *) & map.data[offset]);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
|
*skip = length + offset;
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
|
||||||
|
too_small:
|
||||||
|
{
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
invalid_buffer:
|
||||||
|
{
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstEvent *
|
||||||
|
read_event (guint type, GstBuffer * buf, guint * skip)
|
||||||
|
{
|
||||||
|
guint offset, length;
|
||||||
|
GstStructure *s;
|
||||||
|
GstEvent *event;
|
||||||
|
GstEventType etype;
|
||||||
|
gchar *end;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
|
|
||||||
|
if (!read_length (map.data, map.size, &length, &offset))
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
goto invalid_buffer;
|
||||||
|
/* backward compat, old payloader did not put 0-byte at the end */
|
||||||
|
if (map.data[offset + length - 1] != '\0'
|
||||||
|
&& map.data[offset + length - 1] != ';')
|
||||||
|
goto invalid_buffer;
|
||||||
|
|
||||||
|
/* parse */
|
||||||
|
s = gst_structure_from_string ((gchar *) & map.data[offset], &end);
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
goto parse_failed;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 1:
|
||||||
|
etype = GST_EVENT_TAG;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
etype = GST_EVENT_CUSTOM_DOWNSTREAM;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
etype = GST_EVENT_CUSTOM_BOTH;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
etype = GST_EVENT_STREAM_START;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto unknown_event;
|
||||||
|
}
|
||||||
|
event = gst_event_new_custom (etype, s);
|
||||||
|
|
||||||
|
*skip = length + offset;
|
||||||
|
|
||||||
|
return event;
|
||||||
|
|
||||||
|
too_small:
|
||||||
|
{
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
invalid_buffer:
|
||||||
|
{
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
parse_failed:
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
unknown_event:
|
||||||
|
{
|
||||||
|
gst_structure_free (s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_gstpay_payload (GstRTPBuffer * rtp, GstEvent ** event, GstCaps ** caps,
|
||||||
|
GstBuffer ** outbuf)
|
||||||
|
{
|
||||||
|
gint payload_len;
|
||||||
|
guint8 *payload;
|
||||||
|
guint avail, offset;
|
||||||
|
|
||||||
|
payload_len = gst_rtp_buffer_get_payload_len (rtp);
|
||||||
|
|
||||||
|
if (payload_len <= 8)
|
||||||
|
goto empty_packet;
|
||||||
|
|
||||||
|
/* We don't need to deal with fragmentation */
|
||||||
|
fail_unless (gst_rtp_buffer_get_marker (rtp));
|
||||||
|
|
||||||
|
payload = gst_rtp_buffer_get_payload (rtp);
|
||||||
|
|
||||||
|
*outbuf = gst_rtp_buffer_get_payload_subbuffer (rtp, 8, -1);
|
||||||
|
avail = gst_buffer_get_size (*outbuf);
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
if (payload[0] & 0x80) {
|
||||||
|
guint size;
|
||||||
|
|
||||||
|
/* C bit, we have inline caps */
|
||||||
|
*caps = read_caps (*outbuf, &size);
|
||||||
|
if (*caps == NULL)
|
||||||
|
goto no_caps;
|
||||||
|
|
||||||
|
/* skip caps */
|
||||||
|
offset += size;
|
||||||
|
avail -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload[1]) {
|
||||||
|
guint size;
|
||||||
|
|
||||||
|
/* we have an event */
|
||||||
|
*event = read_event (payload[1], *outbuf, &size);
|
||||||
|
if (*event == NULL)
|
||||||
|
goto no_event;
|
||||||
|
|
||||||
|
/* no buffer after event */
|
||||||
|
avail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avail) {
|
||||||
|
if (offset != 0) {
|
||||||
|
GstBuffer *temp;
|
||||||
|
|
||||||
|
temp =
|
||||||
|
gst_buffer_copy_region (*outbuf, GST_BUFFER_COPY_ALL, offset, avail);
|
||||||
|
|
||||||
|
gst_buffer_unref (*outbuf);
|
||||||
|
*outbuf = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload[0] & 0x8)
|
||||||
|
GST_BUFFER_FLAG_SET (*outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
} else {
|
||||||
|
gst_buffer_unref (*outbuf);
|
||||||
|
*outbuf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
empty_packet:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
no_caps:
|
||||||
|
{
|
||||||
|
gst_buffer_unref (*outbuf);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
no_event:
|
||||||
|
{
|
||||||
|
gst_buffer_unref (*outbuf);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
test_play_response_200_and_check_data (GstRTSPClient * client,
|
test_play_response_200_and_check_data (GstRTSPClient * client,
|
||||||
GstRTSPMessage * response, gboolean close, gpointer user_data)
|
GstRTSPMessage * response, gboolean close, gpointer user_data)
|
||||||
|
@ -600,37 +813,55 @@ test_play_response_200_and_check_data (GstRTSPClient * client,
|
||||||
guint16 bits;
|
guint16 bits;
|
||||||
guint wordlen;
|
guint wordlen;
|
||||||
guint8 flags;
|
guint8 flags;
|
||||||
gint32 expected_interval;
|
gint32 expected_interval = 0;
|
||||||
gboolean is_custom_event = FALSE;
|
GstBuffer *outbuf = NULL;
|
||||||
|
GstCaps *outcaps = NULL;
|
||||||
|
GstEvent *outevent = NULL;
|
||||||
|
|
||||||
fail_unless (gst_rtsp_message_get_body (response, &body,
|
fail_unless (gst_rtsp_message_get_body (response, &body,
|
||||||
&body_size) == GST_RTSP_OK);
|
&body_size) == GST_RTSP_OK);
|
||||||
|
|
||||||
buf = gst_rtp_buffer_new_copy_data (body, body_size);
|
buf = gst_rtp_buffer_new_copy_data (body, body_size);
|
||||||
|
|
||||||
switch (body_size) {
|
fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp));
|
||||||
case 120: /* Ignore our serialized custom events */
|
|
||||||
is_custom_event = TRUE;
|
fail_unless (parse_gstpay_payload (&rtp, &outevent, &outcaps, &outbuf));
|
||||||
break;
|
|
||||||
case 56:
|
if (outbuf) {
|
||||||
expected_interval = check->expected_i_frame_ts_interval;
|
switch (gst_buffer_get_size (outbuf)) {
|
||||||
check->n_i_frames += 1;
|
case 20:
|
||||||
break;
|
expected_interval = check->expected_i_frame_ts_interval;
|
||||||
case 46:
|
check->n_i_frames += 1;
|
||||||
expected_interval = check->expected_ts_interval;
|
break;
|
||||||
check->n_p_frames += 1;
|
case 10:
|
||||||
break;
|
expected_interval = check->expected_ts_interval;
|
||||||
case 41:
|
check->n_p_frames += 1;
|
||||||
expected_interval = check->expected_ts_interval;
|
break;
|
||||||
check->n_b_frames += 1;
|
case 5:
|
||||||
break;
|
expected_interval = check->expected_ts_interval;
|
||||||
default:
|
check->n_b_frames += 1;
|
||||||
fail ("Invalid body size %u", body_size);
|
break;
|
||||||
|
default:
|
||||||
|
fail ("Invalid payload size %u", gst_buffer_get_size (outbuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_buffer_unref (outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_custom_event) {
|
if (outcaps) {
|
||||||
fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp));
|
gst_caps_unref (outcaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outevent) {
|
||||||
|
const GstStructure *s;
|
||||||
|
|
||||||
|
fail_unless (GST_EVENT_TYPE (outevent) == GST_EVENT_CUSTOM_DOWNSTREAM);
|
||||||
|
s = gst_event_get_structure (outevent);
|
||||||
|
fail_unless (gst_structure_has_name (s, "GstOnvifTimestamp"));
|
||||||
|
gst_event_unref (outevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected_interval) {
|
||||||
if (check->previous_ts) {
|
if (check->previous_ts) {
|
||||||
fail_unless_equals_int (gst_rtp_buffer_get_timestamp (&rtp) -
|
fail_unless_equals_int (gst_rtp_buffer_get_timestamp (&rtp) -
|
||||||
check->previous_ts, expected_interval);
|
check->previous_ts, expected_interval);
|
||||||
|
@ -646,8 +877,6 @@ test_play_response_200_and_check_data (GstRTSPClient * client,
|
||||||
|
|
||||||
flags = GST_READ_UINT8 (data + 8);
|
flags = GST_READ_UINT8 (data + 8);
|
||||||
|
|
||||||
gst_rtp_buffer_unmap (&rtp);
|
|
||||||
|
|
||||||
if (flags & (1 << 7)) {
|
if (flags & (1 << 7)) {
|
||||||
check->n_clean_points += 1;
|
check->n_clean_points += 1;
|
||||||
}
|
}
|
||||||
|
@ -669,6 +898,7 @@ test_play_response_200_and_check_data (GstRTSPClient * client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
} else if (channel == 1) { /* RTCP */
|
} else if (channel == 1) { /* RTCP */
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
Loading…
Reference in a new issue