mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41:48 +00:00
tests: Add AVTP CVF payloader tests
In these tests, some specially crafted buffers are sent to the payloader, simulating some scenarios and checking what comes out from it.
This commit is contained in:
parent
c427fd1aec
commit
b34acc0c8c
3 changed files with 653 additions and 2 deletions
|
@ -40,7 +40,7 @@ check_assrender =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if USE_AVTP
|
if USE_AVTP
|
||||||
check_avtp = elements/avtpaafpay elements/avtpaafdepay elements/avtpsink elements/avtpsrc
|
check_avtp = elements/avtpaafpay elements/avtpaafdepay elements/avtpcvfpay elements/avtpsink elements/avtpsrc
|
||||||
else
|
else
|
||||||
check_avtp =
|
check_avtp =
|
||||||
endif
|
endif
|
||||||
|
@ -287,7 +287,6 @@ check_PROGRAMS = \
|
||||||
elements/h263parse \
|
elements/h263parse \
|
||||||
elements/h264parse \
|
elements/h264parse \
|
||||||
elements/mpegtsmux \
|
elements/mpegtsmux \
|
||||||
elements/mpegvideoparse \
|
|
||||||
elements/mpeg4videoparse \
|
elements/mpeg4videoparse \
|
||||||
elements/mxfdemux \
|
elements/mxfdemux \
|
||||||
elements/mxfmux \
|
elements/mxfmux \
|
||||||
|
@ -510,6 +509,9 @@ elements_avtpaafpay_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LDADD) $
|
||||||
elements_avtpaafdepay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) $(AVTP_CFLAGS)
|
elements_avtpaafdepay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) $(AVTP_CFLAGS)
|
||||||
elements_avtpaafdepay_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LDADD) $(AVTP_LIBS)
|
elements_avtpaafdepay_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LDADD) $(AVTP_LIBS)
|
||||||
|
|
||||||
|
elements_avtpcvfpay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) $(AVTP_CFLAGS)
|
||||||
|
elements_avtpcvfpay_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LDADD) $(AVTP_LIBS)
|
||||||
|
|
||||||
elements_avtpsink_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
elements_avtpsink_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||||
elements_avtpsink_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LDADD)
|
elements_avtpsink_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(LDADD)
|
||||||
|
|
||||||
|
|
648
tests/check/elements/avtpcvfpay.c
Normal file
648
tests/check/elements/avtpcvfpay.c
Normal file
|
@ -0,0 +1,648 @@
|
||||||
|
/*
|
||||||
|
* GStreamer AVTP Plugin
|
||||||
|
* Copyright (C) 2019 Intel Corporation
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/check/gstcheck.h>
|
||||||
|
#include <gst/check/gstharness.h>
|
||||||
|
|
||||||
|
#include <avtp.h>
|
||||||
|
#include <avtp_cvf.h>
|
||||||
|
|
||||||
|
#define AVTP_CVF_H264_HEADER_SIZE (sizeof(struct avtp_stream_pdu) + sizeof(guint32))
|
||||||
|
#define STREAM_ID 0xAABBCCDDEEFF0001
|
||||||
|
|
||||||
|
/* Simple codec data, with only the NAL size len, no SPS/PPS. */
|
||||||
|
static GstCaps *
|
||||||
|
generate_caps (guint8 nal_size_len)
|
||||||
|
{
|
||||||
|
GstBuffer *codec_data;
|
||||||
|
GstMapInfo map;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
/* 7 is the minimal codec_data size, when no SPS/PPS is sent */
|
||||||
|
codec_data = gst_buffer_new_allocate (NULL, 7, NULL);
|
||||||
|
gst_buffer_map (codec_data, &map, GST_MAP_READWRITE);
|
||||||
|
|
||||||
|
memset (map.data, 0, map.size);
|
||||||
|
map.data[0] = 1; /* version */
|
||||||
|
map.data[4] = (nal_size_len - 1) | 0xfc; /* Other 6 bits are 1 */
|
||||||
|
map.data[5] = 0xe0; /* first 3 bits are 1 */
|
||||||
|
|
||||||
|
gst_buffer_unmap (codec_data, &map);
|
||||||
|
|
||||||
|
caps = gst_caps_new_simple ("video/x-h264",
|
||||||
|
"stream-format", G_TYPE_STRING, "avc",
|
||||||
|
"alignment", G_TYPE_STRING, "au",
|
||||||
|
"codec_data", GST_TYPE_BUFFER, codec_data, NULL);
|
||||||
|
gst_buffer_unref (codec_data);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill (guint8 * buf, gsize size)
|
||||||
|
{
|
||||||
|
guint8 i = 0;
|
||||||
|
|
||||||
|
while (size--)
|
||||||
|
*buf++ = i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_nal_filling (GstBuffer * buffer, guint8 first)
|
||||||
|
{
|
||||||
|
GstMapInfo map;
|
||||||
|
gint i;
|
||||||
|
gsize offset = AVTP_CVF_H264_HEADER_SIZE + 1;
|
||||||
|
gboolean result = TRUE;
|
||||||
|
|
||||||
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
if ((map.data[AVTP_CVF_H264_HEADER_SIZE] & 0x1f) == 28)
|
||||||
|
offset++; /* Fragmented NALs have 2 bytes header */
|
||||||
|
|
||||||
|
for (i = offset; i < map.size; i++) {
|
||||||
|
if (map.data[i] != first++) {
|
||||||
|
result = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_nal (GstBuffer * buffer, gsize size, guint type, gsize offset)
|
||||||
|
{
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
|
||||||
|
|
||||||
|
map.data[offset] = map.data[offset + 1] = 0;
|
||||||
|
map.data[offset + 2] = size >> 8;
|
||||||
|
map.data[offset + 3] = size & 0xff;
|
||||||
|
map.data[offset + 4] = type & 0x1f;
|
||||||
|
fill (&map.data[offset + 5], size - 1);
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function assumes that NAL size len is 2 */
|
||||||
|
static void
|
||||||
|
add_nal_2 (GstBuffer * buffer, gsize size, guint type, gsize offset)
|
||||||
|
{
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
|
||||||
|
|
||||||
|
map.data[offset] = size >> 8;
|
||||||
|
map.data[offset + 1] = size & 0xff;
|
||||||
|
map.data[offset + 2] = type & 0x1f;
|
||||||
|
fill (&map.data[offset + 3], size - 1);
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
compare_h264_avtpdu (struct avtp_stream_pdu *pdu, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
GstMapInfo map;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
/* buffer must have at least the header size */
|
||||||
|
if (map.size < AVTP_CVF_H264_HEADER_SIZE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
result = memcmp (map.data, pdu, AVTP_CVF_H264_HEADER_SIZE) == 0;
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_no_codec_data)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstCaps *caps;
|
||||||
|
GstBuffer *in;
|
||||||
|
|
||||||
|
/* Caps without codec_data */
|
||||||
|
caps = gst_caps_new_simple ("video/x-h264",
|
||||||
|
"stream-format", G_TYPE_STRING, "avc",
|
||||||
|
"alignment", G_TYPE_STRING, "au", NULL);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
|
||||||
|
gst_harness_set_src_caps (h, caps);
|
||||||
|
|
||||||
|
/* No buffer should come out when we send input */
|
||||||
|
in = gst_harness_create_buffer (h, 8);
|
||||||
|
add_nal (in, 4, 1, 0);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
gst_harness_push (h, in);
|
||||||
|
fail_unless_equals_int (gst_harness_buffers_received (h), 0);
|
||||||
|
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_invalid_caps)
|
||||||
|
{
|
||||||
|
GstBuffer *codec_data;
|
||||||
|
GstElement *element;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
GstMapInfo map;
|
||||||
|
GstCaps *caps;
|
||||||
|
GstHarness *h;
|
||||||
|
|
||||||
|
/* 7 is the minimal codec_data size, when no SPS/PPS is sent */
|
||||||
|
codec_data = gst_buffer_new_allocate (NULL, 7, NULL);
|
||||||
|
gst_buffer_map (codec_data, &map, GST_MAP_READWRITE);
|
||||||
|
|
||||||
|
memset (map.data, 0, map.size);
|
||||||
|
map.data[0] = 0; /* version */
|
||||||
|
map.data[4] = 0x03 | 0xfc; /* Other 6 bits are 1 */
|
||||||
|
map.data[5] = 0xe0; /* first 3 bits are 1 */
|
||||||
|
|
||||||
|
gst_buffer_unmap (codec_data, &map);
|
||||||
|
|
||||||
|
caps = gst_caps_new_simple ("video/x-h264",
|
||||||
|
"stream-format", G_TYPE_STRING, "avc",
|
||||||
|
"alignment", G_TYPE_STRING, "au",
|
||||||
|
"codec_data", GST_TYPE_BUFFER, codec_data, NULL);
|
||||||
|
gst_buffer_unref (codec_data);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000");
|
||||||
|
element = gst_harness_find_element (h, "avtpcvfpay");
|
||||||
|
sinkpad = gst_element_get_static_pad (element, "sink");
|
||||||
|
|
||||||
|
/* 'codec_data' caps has invalid version */
|
||||||
|
gst_harness_push_event (h, gst_event_new_caps (caps));
|
||||||
|
fail_unless (gst_pad_get_current_caps (sinkpad) == NULL);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
/* Send a 'codec_data' too small */
|
||||||
|
codec_data = gst_buffer_new_allocate (NULL, 6, NULL);
|
||||||
|
caps = gst_caps_new_simple ("video/x-h264",
|
||||||
|
"stream-format", G_TYPE_STRING, "avc",
|
||||||
|
"alignment", G_TYPE_STRING, "au",
|
||||||
|
"codec_data", GST_TYPE_BUFFER, codec_data, NULL);
|
||||||
|
gst_buffer_unref (codec_data);
|
||||||
|
|
||||||
|
gst_harness_push_event (h, gst_event_new_caps (caps));
|
||||||
|
fail_unless (gst_pad_get_current_caps (sinkpad) == NULL);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_incomplete_nal)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstBuffer *in, *out;
|
||||||
|
GstMapInfo map;
|
||||||
|
struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
|
||||||
|
const gint DATA_LEN = sizeof (guint32) + 3;
|
||||||
|
|
||||||
|
/* Create the 'expected' header */
|
||||||
|
avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
|
||||||
|
gst_harness_set_src_caps (h, generate_caps (4));
|
||||||
|
|
||||||
|
/* Buffer must have the nal len (4 bytes) and the nal (3 bytes) */
|
||||||
|
in = gst_harness_create_buffer (h, 7);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
gst_buffer_map (in, &map, GST_MAP_READWRITE);
|
||||||
|
map.data[0] = map.data[1] = map.data[2] = 0;
|
||||||
|
map.data[3] = 8; /* Lie that NAL size is 8, when buffer is only 7 (so NAL is 3) */
|
||||||
|
map.data[4] = 1; /* Some dummy vcl NAL type */
|
||||||
|
map.data[5] = 0x0;
|
||||||
|
map.data[6] = 0x1;
|
||||||
|
|
||||||
|
out = gst_harness_push_and_pull (h, in);
|
||||||
|
|
||||||
|
/* avtpcvfpay will happily payload the three byte nal. Now, we check it */
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_properties)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstElement *element;
|
||||||
|
guint mtu, mtt, tu;
|
||||||
|
guint64 streamid, processing_deadline;
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=2000000 mtu=100 processing-deadline=5000");
|
||||||
|
|
||||||
|
/* Check if all properties were properly set up */
|
||||||
|
element = gst_harness_find_element (h, "avtpcvfpay");
|
||||||
|
g_object_get (G_OBJECT (element), "mtt", &mtt, NULL);
|
||||||
|
fail_unless_equals_uint64 (mtt, 1000000);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (element), "mtu", &mtu, NULL);
|
||||||
|
fail_unless_equals_uint64 (mtu, 100);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (element), "tu", &tu, NULL);
|
||||||
|
fail_unless_equals_uint64 (tu, 2000000);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (element), "streamid", &streamid, NULL);
|
||||||
|
fail_unless_equals_uint64 (streamid, 0xAABBCCDDEEFF0001);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (element), "processing-deadline", &processing_deadline,
|
||||||
|
NULL);
|
||||||
|
fail_unless_equals_uint64 (processing_deadline, 5000);
|
||||||
|
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
GST_START_TEST (test_payloader_single_and_fragment_edge)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstBuffer *in, *out;
|
||||||
|
struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
|
||||||
|
const gint DATA_LEN_1 = sizeof (guint32) + 100;
|
||||||
|
const gint DATA_LEN_2 = sizeof (guint32) + 100;
|
||||||
|
const gint DATA_LEN_3 = sizeof (guint32) + 4;
|
||||||
|
|
||||||
|
/* Create the 'expected' header */
|
||||||
|
avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay. Setting mtu=128 ensures that
|
||||||
|
* NAL units will be broken roughly at 100 bytes. More details below. */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 mtu=128 processing-deadline=0");
|
||||||
|
gst_harness_set_src_caps (h, generate_caps (4));
|
||||||
|
|
||||||
|
/* Create a buffer to contain the multiple NAL units. This buffer
|
||||||
|
* will hold two NAL units, with 100 and 101 bytes, each preceded
|
||||||
|
* by a 4 bytes header */
|
||||||
|
in = gst_harness_create_buffer (h, 100 + 101 + 2 * 4);
|
||||||
|
add_nal (in, 100, 7, 0);
|
||||||
|
add_nal (in, 101, 1, 104);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
/* We now push the buffer, and check if we get three from the avtpcvfpay */
|
||||||
|
gst_harness_push (h, in);
|
||||||
|
fail_unless (gst_harness_buffers_received (h) == 3);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
/* DATA_LEN_3 is 4 because only 98 bytes from the original NAL unit are
|
||||||
|
* sent on the first buffer (due 2 bytes header), and the two remaining
|
||||||
|
* bytes are preceded by the 2 bytes header. Note that the first byte of
|
||||||
|
* the NAL is stripped before the fragmentation (see comment on
|
||||||
|
* test_payloader_single_and_fragment below for more details). */
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_single_and_fragment)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstBuffer *in, *out;
|
||||||
|
struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
|
||||||
|
const gint DATA_LEN_1 = sizeof (guint32) + 4;
|
||||||
|
const gint DATA_LEN_2 = sizeof (guint32) + 100;
|
||||||
|
const gint DATA_LEN_3 = sizeof (guint32) + 100;
|
||||||
|
const gint DATA_LEN_4 = sizeof (guint32) + 55;
|
||||||
|
|
||||||
|
/* Create the 'expected' header */
|
||||||
|
avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 4000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 5000000);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay. Setting mtu=128 ensures that
|
||||||
|
* NAL units will be broken roughly at 100 bytes. More details below. */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=1000000 mtu=128");
|
||||||
|
gst_harness_set_src_caps (h, generate_caps (4));
|
||||||
|
|
||||||
|
/* Create a buffer to contain the multiple NAL units. This buffer
|
||||||
|
* will hold two NAL units, with 4 and 250 bytes, each preceded
|
||||||
|
* by a 4 bytes header */
|
||||||
|
in = gst_harness_create_buffer (h, 4 + 250 + 2 * 4);
|
||||||
|
add_nal (in, 4, 7, 0);
|
||||||
|
add_nal (in, 250, 1, 8);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
/* We now push the buffer, and check if we get four from the avtpcvfpay */
|
||||||
|
gst_harness_push (h, in);
|
||||||
|
fail_unless (gst_harness_buffers_received (h) == 4);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 98) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
/* For those wondering why DATA_LEN_4 is 55 and not 50 - or why
|
||||||
|
* comment above states that NAL units are broken "rougly" at 100 bytes:
|
||||||
|
* With mtu=128, there are only 100 bytes left for NAL units, so anything
|
||||||
|
* bigger will be broken. But AVTP NAL units fragments have a header with
|
||||||
|
* two bytes, so NAL units will use only 98 bytes. This leaves the last
|
||||||
|
* fragment with 54 bytes. However, instead of being 56 (54 bytes plus
|
||||||
|
* 2 bytes header), it is 55 (53 bytes plus 2 bytes header) due to the
|
||||||
|
* fact that the first byte of the NAL unit (the NAL unit header) is
|
||||||
|
* in fact stripped from the NAL unit before the fragmentation. */
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_4);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 3);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 4000000);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 196) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_multiple_single_2)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstBuffer *in, *out;
|
||||||
|
struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
|
||||||
|
const gint DATA_LEN_1 = sizeof (guint32) + 32;
|
||||||
|
const gint DATA_LEN_2 = sizeof (guint32) + 16;
|
||||||
|
const gint DATA_LEN_3 = sizeof (guint32) + 8;
|
||||||
|
|
||||||
|
/* Create the 'expected' header */
|
||||||
|
avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
|
||||||
|
gst_harness_set_src_caps (h, generate_caps (2));
|
||||||
|
|
||||||
|
/* Create a buffer to contain the multiple NAL units. This buffer
|
||||||
|
* will hold three NAL units, with 32, 16 and 8 bytes, each preceded
|
||||||
|
* by a 2 bytes header */
|
||||||
|
in = gst_harness_create_buffer (h, 32 + 16 + 8 + 4 * 2);
|
||||||
|
add_nal_2 (in, 32, 7, 0);
|
||||||
|
add_nal_2 (in, 16, 7, 34);
|
||||||
|
add_nal_2 (in, 8, 1, 52);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
/* We now push the buffer, and check if we get three from the avtpcvfpay */
|
||||||
|
gst_harness_push (h, in);
|
||||||
|
fail_unless (gst_harness_buffers_received (h) == 3);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_multiple_single)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstBuffer *in, *out;
|
||||||
|
struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
|
||||||
|
const gint DATA_LEN_1 = sizeof (guint32) + 32;
|
||||||
|
const gint DATA_LEN_2 = sizeof (guint32) + 16;
|
||||||
|
const gint DATA_LEN_3 = sizeof (guint32) + 8;
|
||||||
|
|
||||||
|
/* Create the 'expected' header */
|
||||||
|
avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
|
||||||
|
gst_harness_set_src_caps (h, generate_caps (4));
|
||||||
|
|
||||||
|
/* Create a buffer to contain the multiple NAL units. This buffer
|
||||||
|
* will hold three NAL units, with 32, 16 and 8 bytes, each preceded
|
||||||
|
* by a 4 bytes header */
|
||||||
|
in = gst_harness_create_buffer (h, 32 + 16 + 8 + 4 * 4);
|
||||||
|
add_nal (in, 32, 7, 0);
|
||||||
|
add_nal (in, 16, 7, 36);
|
||||||
|
add_nal (in, 8, 1, 56);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
/* We now push the buffer, and check if we get three from the avtpcvfpay */
|
||||||
|
gst_harness_push (h, in);
|
||||||
|
fail_unless (gst_harness_buffers_received (h) == 3);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
out = gst_harness_pull (h);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_payloader_single)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstBuffer *in, *out;
|
||||||
|
struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
|
||||||
|
const gint DATA_LEN = sizeof (guint32) + 4;
|
||||||
|
|
||||||
|
/* Create the 'expected' header */
|
||||||
|
avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
|
||||||
|
|
||||||
|
/* Create the harness for the avtpcvfpay */
|
||||||
|
h = gst_harness_new_parse
|
||||||
|
("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
|
||||||
|
gst_harness_set_src_caps (h, generate_caps (4));
|
||||||
|
|
||||||
|
/* Buffer must have the nal len (4 bytes) and the nal (4 bytes) */
|
||||||
|
in = gst_harness_create_buffer (h, 8);
|
||||||
|
add_nal (in, 4, 1, 0);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
out = gst_harness_push_and_pull (h, in);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
|
||||||
|
/* Now test if, when nal_type is not vcl (not between 1 and 5), M is not set.
|
||||||
|
* Also, as we're using the same element, seqnum should increase by one */
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
|
||||||
|
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
|
||||||
|
|
||||||
|
in = gst_harness_create_buffer (h, 8);
|
||||||
|
add_nal (in, 4, 6, 0);
|
||||||
|
GST_BUFFER_DTS (in) = 1000000;
|
||||||
|
GST_BUFFER_PTS (in) = 2000000;
|
||||||
|
|
||||||
|
out = gst_harness_push_and_pull (h, in);
|
||||||
|
fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
|
||||||
|
fail_unless (check_nal_filling (out, 0) == TRUE);
|
||||||
|
gst_buffer_unref (out);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
static Suite *
|
||||||
|
avtpcvfpay_suite (void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create ("avtpcvfpay");
|
||||||
|
TCase *tc_chain = tcase_create ("general");
|
||||||
|
|
||||||
|
suite_add_tcase (s, tc_chain);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_single);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_multiple_single);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_multiple_single_2);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_single_and_fragment);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_single_and_fragment_edge);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_incomplete_nal);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_invalid_caps);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_properties);
|
||||||
|
tcase_add_test (tc_chain, test_payloader_no_codec_data);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CHECK_MAIN (avtpcvfpay);
|
|
@ -72,6 +72,7 @@ if host_machine.system() != 'windows'
|
||||||
[['elements/assrender.c'], not ass_dep.found(), [ass_dep]],
|
[['elements/assrender.c'], not ass_dep.found(), [ass_dep]],
|
||||||
[['elements/avtpaafpay.c'], not avtp_dep.found(), [avtp_dep]],
|
[['elements/avtpaafpay.c'], not avtp_dep.found(), [avtp_dep]],
|
||||||
[['elements/avtpaafdepay.c'], not avtp_dep.found(), [avtp_dep]],
|
[['elements/avtpaafdepay.c'], not avtp_dep.found(), [avtp_dep]],
|
||||||
|
[['elements/avtpcvfpay.c'], not avtp_dep.found(), [avtp_dep]],
|
||||||
[['elements/avtpsink.c'], not avtp_dep.found(), [avtp_dep]],
|
[['elements/avtpsink.c'], not avtp_dep.found(), [avtp_dep]],
|
||||||
[['elements/avtpsrc.c'], not avtp_dep.found(), [avtp_dep]],
|
[['elements/avtpsrc.c'], not avtp_dep.found(), [avtp_dep]],
|
||||||
[['elements/ccconverter.c']],
|
[['elements/ccconverter.c']],
|
||||||
|
|
Loading…
Reference in a new issue