tests: Add tests for CRF Synchronizer element
authorVedang Patel <vedang.patel@intel.com>
Mon, 14 Oct 2019 20:56:36 +0000 (13:56 -0700)
committervedangpatel1 <vedang.patel@intel.com>
Thu, 30 Apr 2020 23:31:25 +0000 (23:31 +0000)
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.

tests/check/elements/avtpcrfsync.c [new file with mode: 0644]
tests/check/meson.build

diff --git a/tests/check/elements/avtpcrfsync.c b/tests/check/elements/avtpcrfsync.c
new file mode 100644 (file)
index 0000000..6990d6c
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * 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);
index 1502350..8640a57 100644 (file)
@@ -81,6 +81,7 @@ if host_machine.system() != 'windows'
     [['elements/assrender.c'], not ass_dep.found(), [ass_dep]],
     [['elements/avtpaafpay.c'], not avtp_dep.found(), [avtp_dep]],
     [['elements/avtpaafdepay.c'], not avtp_dep.found(), [avtp_dep]],
+    [['elements/avtpcrfsync.c'], not avtp_dep.found(), [avtp_dep], ['../../ext/avtp/gstavtpcrfutil.c', '../../ext/avtp/gstavtpcrfbase.c']],
     [['elements/avtpcvfpay.c'], not avtp_dep.found(), [avtp_dep]],
     [['elements/avtpcvfdepay.c'], not avtp_dep.found(), [avtp_dep]],
     [['elements/avtpsink.c'], not avtp_dep.found(), [avtp_dep]],
@@ -158,8 +159,10 @@ foreach t : base_tests
     skip_test = t.get(1)
   endif
 
+  extra_sources = t.get(3, [ ])
+
   if not skip_test
-    exe = executable(test_name, fnames,
+    exe = executable(test_name, fnames, extra_sources,
       include_directories : [configinc],
       c_args : gst_plugins_bad_args + test_defines,
       cpp_args : gst_plugins_bad_args + test_defines,