gstreamer/tests/check/elements/avtpcrfsync.c
Vedang Patel 551258b2c4 tests: Add tests for CRF Synchronizer element
This adds tests to validate whether the avtpcrfsync element applies the
adjustment correctly.

Also, the infrastructure to include additional source files while compiling
is added. This change is exactly the same as the one in gst-plugins-good.
2020-04-30 23:31:25 +00:00

364 lines
11 KiB
C

/*
* 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 "../../../ext/avtp/gstavtpcrfsync.c"
#undef GST_CAT_DEFAULT
#include <avtp.h>
#include <avtp_crf.h>
#include <avtp_aaf.h>
#include <avtp_cvf.h>
#include <gst/check/gstcheck.h>
#include <gst/check/gstharness.h>
#include "../../../ext/avtp/gstavtpcrfutil.h"
#define STREAM_ID 0xDEADC0DEDEADC0DE
struct buffer_tstamps
{
GstClockTime buf_pts;
GstClockTime buf_dts;
GstClockTime avtp_ts;
GstClockTime h264_ts;
};
static GstHarness *
setup_harness (void)
{
GstHarness *h;
h = gst_harness_new_parse ("avtpcrfsync streamid=0xDEADC0DEDEADC0DE");
gst_harness_set_src_caps_str (h, "application/x-avtp");
return h;
}
static void
fill_buffer_video_data (struct avtp_stream_pdu *pdu)
{
const gint DATA_LEN = sizeof (guint32) + 3;
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, 0);
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 0);
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
}
static void
fill_buffer_audio_data (struct avtp_stream_pdu *pdu)
{
const int DATA_LEN = 4;
avtp_aaf_pdu_init (pdu);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TV, 1);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_ID, 0xDEADC0DEDEADC0DE);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_FORMAT, AVTP_AAF_FORMAT_INT_16BIT);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_NSR, AVTP_AAF_PCM_NSR_48KHZ);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, 2);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_BIT_DEPTH, 16);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_SP, AVTP_AAF_PCM_SP_NORMAL);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TIMESTAMP, 0);
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, DATA_LEN);
}
static GstBuffer *
create_input_buffer (GstHarness * h, guint32 subtype)
{
struct avtp_stream_pdu *pdu;
GstMapInfo info;
GstBuffer *buf;
const gint DATA_LEN = sizeof (guint32) + 3;
buf = gst_harness_create_buffer (h, sizeof (struct avtp_stream_pdu) +
DATA_LEN);
gst_buffer_map (buf, &info, GST_MAP_WRITE);
pdu = (struct avtp_stream_pdu *) info.data;
if (subtype == AVTP_SUBTYPE_AAF)
fill_buffer_audio_data (pdu);
else if (subtype == AVTP_SUBTYPE_CVF)
fill_buffer_video_data (pdu);
gst_buffer_unmap (buf, &info);
return buf;
}
static void
set_buffer_tstamps (GstBuffer * buf, struct buffer_tstamps *orig)
{
struct avtp_stream_pdu *pdu;
GstMapInfo info;
guint32 type;
gst_buffer_map (buf, &info, GST_MAP_WRITE);
pdu = (struct avtp_stream_pdu *) info.data;
GST_BUFFER_PTS (buf) = orig->buf_pts;
GST_BUFFER_DTS (buf) = orig->buf_dts;
avtp_pdu_get ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE, &type);
if (type == AVTP_SUBTYPE_AAF)
avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TIMESTAMP, orig->avtp_ts);
else if (type == AVTP_SUBTYPE_CVF) {
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, orig->avtp_ts);
avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, orig->h264_ts);
}
gst_buffer_unmap (buf, &info);
}
static void
validate_tstamps (GstAvtpCrfBase * avtpcrfbase, GstBuffer * buf,
struct buffer_tstamps *expected)
{
GstClockTime tstamp;
struct avtp_stream_pdu *pdu;
GstMapInfo info;
int res;
gst_buffer_map (buf, &info, GST_MAP_READ);
pdu = (struct avtp_stream_pdu *) info.data;
fail_unless_equals_uint64 (GST_BUFFER_PTS (buf), expected->buf_pts);
fail_unless_equals_uint64 (GST_BUFFER_DTS (buf), expected->buf_dts);
tstamp = get_avtp_tstamp (avtpcrfbase, pdu);
fail_unless_equals_uint64 (tstamp, expected->avtp_ts);
if (h264_tstamp_valid (pdu)) {
res = avtp_cvf_pdu_get (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, &tstamp);
fail_unless (res == 0);
fail_unless_equals_uint64 (tstamp, expected->h264_ts);
}
gst_buffer_unmap (buf, &info);
}
static void
test_crf_tstamps (GstHarness * h, GstBuffer * buf, struct buffer_tstamps *orig,
struct buffer_tstamps *expected)
{
GstAvtpCrfBase *avtpcrfbase;
GstBuffer *bufout;
avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfsync");
set_buffer_tstamps (buf, orig);
bufout = gst_harness_push_and_pull (h, buf);
validate_tstamps (avtpcrfbase, bufout, expected);
}
GST_START_TEST (test_properties)
{
const guint64 streamid = 0xAABBCCDDEEFF0001;
const gchar *address = "01:AA:BB:CC:DD:EE";
const gchar *ifname = "enp1s0";
GstElement *element;
guint64 val64;
gchar *str;
element = gst_check_setup_element ("avtpcrfsync");
g_object_set (G_OBJECT (element), "ifname", ifname, NULL);
g_object_get (G_OBJECT (element), "ifname", &str, NULL);
fail_unless_equals_string (str, ifname);
g_free (str);
g_object_set (G_OBJECT (element), "address", address, NULL);
g_object_get (G_OBJECT (element), "address", &str, NULL);
fail_unless_equals_string (str, address);
g_free (str);
g_object_set (G_OBJECT (element), "streamid", streamid, NULL);
g_object_get (G_OBJECT (element), "streamid", &val64, NULL);
fail_unless_equals_uint64_hex (val64, streamid);
}
GST_END_TEST;
GST_START_TEST (test_set_avtp_tstamp)
{
GstAvtpCrfSync *avtpcrfsync = g_object_new (GST_TYPE_AVTP_CRF_SYNC, NULL);
struct avtp_stream_pdu pdu;
GstClockTime tstamp;
int res;
avtp_aaf_pdu_init (&pdu);
avtp_aaf_pdu_set (&pdu, AVTP_AAF_FIELD_TV, 1);
set_avtp_tstamp (avtpcrfsync, &pdu, 12345);
res = avtp_aaf_pdu_get (&pdu, AVTP_AAF_FIELD_TIMESTAMP, &tstamp);
fail_unless (res == 0);
fail_unless_equals_uint64 (tstamp, 12345);
avtp_cvf_pdu_init (&pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
avtp_cvf_pdu_set (&pdu, AVTP_CVF_FIELD_TV, 1);
set_avtp_tstamp (avtpcrfsync, &pdu, 12345);
res = avtp_cvf_pdu_get (&pdu, AVTP_CVF_FIELD_TIMESTAMP, &tstamp);
fail_unless (res == 0);
fail_unless_equals_uint64 (tstamp, 12345);
}
GST_END_TEST;
GST_START_TEST (test_set_avtp_mr_bit)
{
GstAvtpCrfSync *avtpcrfsync = g_object_new (GST_TYPE_AVTP_CRF_SYNC, NULL);
struct avtp_stream_pdu pdu;
guint64 mr_bit;
int res;
avtp_aaf_pdu_init (&pdu);
set_avtp_mr_bit (avtpcrfsync, &pdu, 1);
res = avtp_aaf_pdu_get (&pdu, AVTP_AAF_FIELD_MR, &mr_bit);
fail_unless (res == 0);
fail_unless_equals_uint64 (mr_bit, 1);
avtp_cvf_pdu_init (&pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
set_avtp_mr_bit (avtpcrfsync, &pdu, 1);
res = avtp_cvf_pdu_get (&pdu, AVTP_CVF_FIELD_MR, &mr_bit);
fail_unless (res == 0);
fail_unless_equals_uint64 (mr_bit, 1);
}
GST_END_TEST;
GST_START_TEST (test_crf_cvf_data)
{
struct buffer_tstamps orig, expected;
GstAvtpCrfBase *avtpcrfbase;
GstBuffer *buf;
GstHarness *h;
h = setup_harness ();
buf = create_input_buffer (h, AVTP_SUBTYPE_CVF);
avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfsync");
avtpcrfbase->thread_data.average_period = 3300;
avtpcrfbase->thread_data.current_ts = 110000;
orig = (struct buffer_tstamps) {
.buf_pts = 103000,.buf_dts = 100000,.avtp_ts = 110000,.h264_ts = 108000};
expected = (struct buffer_tstamps) {
.buf_pts = 104204,.buf_dts = 100000,.avtp_ts = 110000,.h264_ts = 109204};
test_crf_tstamps (h, buf, &orig, &expected);
orig = (struct buffer_tstamps) {
.buf_pts = 107000,.buf_dts = 105000,.avtp_ts = 113000,.h264_ts = 118500};
expected = (struct buffer_tstamps) {
.buf_pts = 108400,.buf_dts = 105300,.avtp_ts = 113300,.h264_ts = 119900};
test_crf_tstamps (h, buf, &orig, &expected);
/* test for invalid DTS */
orig = (struct buffer_tstamps) {
.buf_pts = 107000,.buf_dts = GST_CLOCK_TIME_NONE,.avtp_ts =
113000,.h264_ts = 118500};
expected = (struct buffer_tstamps) {
.buf_pts = 108400,.buf_dts = GST_CLOCK_TIME_NONE,.avtp_ts =
113300,.h264_ts = 119900};
test_crf_tstamps (h, buf, &orig, &expected);
gst_harness_teardown (h);
}
GST_END_TEST;
GST_START_TEST (test_crf_aaf_data)
{
struct buffer_tstamps orig, expected;
GstAvtpCrfBase *avtpcrfbase;
GstBuffer *buf;
GstHarness *h;
h = setup_harness ();
buf = create_input_buffer (h, AVTP_SUBTYPE_AAF);
avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfsync");
avtpcrfbase->thread_data.average_period = 3300;
avtpcrfbase->thread_data.current_ts = 110000;
orig = (struct buffer_tstamps) {
.buf_pts = 108000,.buf_dts = 0,.avtp_ts = 110000,.h264_ts = 0};
expected = (struct buffer_tstamps) {
.buf_pts = 108000,.buf_dts = 0,.avtp_ts = 110000,.h264_ts = 0};
test_crf_tstamps (h, buf, &orig, &expected);
orig = (struct buffer_tstamps) {
.buf_pts = 110000,.buf_dts = 0,.avtp_ts = 113000,.h264_ts = 0};
expected = (struct buffer_tstamps) {
.buf_pts = 110300,.buf_dts = 0,.avtp_ts = 113300,.h264_ts = 0};
test_crf_tstamps (h, buf, &orig, &expected);
gst_harness_teardown (h);
}
GST_END_TEST;
GST_START_TEST (test_crf_period_zero)
{
struct buffer_tstamps orig, expected;
GstAvtpCrfBase *avtpcrfbase;
GstBuffer *buf;
GstHarness *h;
h = setup_harness ();
buf = create_input_buffer (h, AVTP_SUBTYPE_CVF);
avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfsync");
avtpcrfbase->thread_data.average_period = 0.0;
avtpcrfbase->thread_data.current_ts = 110;
orig = (struct buffer_tstamps) {
.buf_pts = 100,.buf_dts = 105,.avtp_ts = 112,.h264_ts = 110};
expected = (struct buffer_tstamps) {
.buf_pts = 100,.buf_dts = 105,.avtp_ts = 112,.h264_ts = 110};
test_crf_tstamps (h, buf, &orig, &expected);
gst_harness_teardown (h);
}
GST_END_TEST;
static Suite *
avtpcrfsync_suite (void)
{
Suite *s = suite_create ("avtpcrfsync");
TCase *tc_chain = tcase_create ("general");
GST_DEBUG_CATEGORY_INIT (avtpcrfsync_debug, "avtpcrfsync", 0,
"CRF Synchronizer");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_properties);
tcase_add_test (tc_chain, test_set_avtp_tstamp);
tcase_add_test (tc_chain, test_set_avtp_mr_bit);
tcase_add_test (tc_chain, test_crf_cvf_data);
tcase_add_test (tc_chain, test_crf_aaf_data);
tcase_add_test (tc_chain, test_crf_period_zero);
return s;
}
GST_CHECK_MAIN (avtpcrfsync);