• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer AVTP Plugin
3  * Copyright (C) 2019 Intel Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later
9  * version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301 USA
20  */
21 
22 #include <avtp.h>
23 #include <avtp_crf.h>
24 #include <avtp_aaf.h>
25 #include <avtp_cvf.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gstharness.h>
28 #include "../../../ext/avtp/gstavtpcrfutil.h"
29 
30 #define STREAM_ID 0xDEADC0DEDEADC0DE
31 
32 static GstHarness *
setup_harness(void)33 setup_harness (void)
34 {
35   GstHarness *h;
36 
37   h = gst_harness_new_parse
38       ("avtpcrfcheck streamid=0xDEADC0DEDEADC0DE drop_invalid=1");
39 
40   if (!h)
41     GST_ERROR ("Cannot create harness!");
42   gst_harness_set_src_caps_str (h, "application/x-avtp");
43   return h;
44 }
45 
46 static void
fill_buffer_video_data(struct avtp_stream_pdu * pdu)47 fill_buffer_video_data (struct avtp_stream_pdu *pdu)
48 {
49   const gint DATA_LEN = sizeof (guint32) + 3;
50 
51   avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
52   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
53   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
54   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
55   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
56   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
57   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 0);
58   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
59 }
60 
61 static void
fill_buffer_audio_data(struct avtp_stream_pdu * pdu)62 fill_buffer_audio_data (struct avtp_stream_pdu *pdu)
63 {
64   const int DATA_LEN = 4;
65 
66   avtp_aaf_pdu_init (pdu);
67   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TV, 1);
68   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_ID, 0xDEADC0DEDEADC0DE);
69   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_FORMAT, AVTP_AAF_FORMAT_INT_16BIT);
70   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_NSR, AVTP_AAF_PCM_NSR_48KHZ);
71   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, 2);
72   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_BIT_DEPTH, 16);
73   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_SP, AVTP_AAF_PCM_SP_NORMAL);
74   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TIMESTAMP, 0);
75   avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, DATA_LEN);
76 }
77 
78 static GstBuffer *
create_input_buffer(GstHarness * h,guint32 subtype)79 create_input_buffer (GstHarness * h, guint32 subtype)
80 {
81   struct avtp_stream_pdu *pdu;
82   GstMapInfo info;
83   GstBuffer *buf;
84   const gint DATA_LEN = sizeof (guint32) + 3;
85 
86   buf = gst_harness_create_buffer (h, sizeof (struct avtp_stream_pdu) +
87       DATA_LEN);
88 
89   gst_buffer_map (buf, &info, GST_MAP_WRITE);
90   pdu = (struct avtp_stream_pdu *) info.data;
91 
92   if (subtype == AVTP_SUBTYPE_AAF)
93     fill_buffer_audio_data (pdu);
94   else
95     fill_buffer_video_data (pdu);
96 
97   gst_buffer_unmap (buf, &info);
98 
99   return buf;
100 }
101 
102 static void
set_buffer_tstamps(GstBuffer * buf,GstClockTime avtp_tstamp,GstClockTime h264_tstamp)103 set_buffer_tstamps (GstBuffer * buf, GstClockTime avtp_tstamp,
104     GstClockTime h264_tstamp)
105 {
106   struct avtp_stream_pdu *pdu;
107   GstMapInfo info;
108   guint32 type;
109   gint r;
110 
111   gst_buffer_map (buf, &info, GST_MAP_WRITE);
112   pdu = (struct avtp_stream_pdu *) info.data;
113 
114   r = avtp_pdu_get ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE, &type);
115   g_assert (r == 0);
116   if (type == AVTP_SUBTYPE_AAF)
117     avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TIMESTAMP, avtp_tstamp);
118   else if (type == AVTP_SUBTYPE_CVF) {
119     avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, avtp_tstamp);
120     avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, h264_tstamp);
121   }
122   gst_buffer_unmap (buf, &info);
123 }
124 
125 static void
test_crf_tstamps(GstHarness * h,GstBuffer * buf,GstClockTime avtp_tstamp,GstClockTime h264_tstamp,guint expected_buffers)126 test_crf_tstamps (GstHarness * h, GstBuffer * buf, GstClockTime avtp_tstamp,
127     GstClockTime h264_tstamp, guint expected_buffers)
128 {
129   set_buffer_tstamps (buf, avtp_tstamp, h264_tstamp);
130   gst_harness_push (h, gst_buffer_copy (buf));
131   fail_unless_equals_uint64 (gst_harness_buffers_received (h),
132       expected_buffers);
133 }
134 
GST_START_TEST(test_properties)135 GST_START_TEST (test_properties)
136 {
137   const guint64 streamid = 0xAABBCCDDEEFF0001;
138   const gchar *address = "01:AA:BB:CC:DD:EE";
139   const gchar *ifname = "enp1s0";
140   const gboolean drop_invalid = TRUE;
141   GstElement *element;
142   guint64 val64;
143   gboolean val;
144   gchar *str;
145 
146   element = gst_check_setup_element ("avtpcrfcheck");
147 
148   g_object_set (G_OBJECT (element), "ifname", ifname, NULL);
149   g_object_get (G_OBJECT (element), "ifname", &str, NULL);
150   fail_unless_equals_string (str, ifname);
151   g_free (str);
152 
153   g_object_set (G_OBJECT (element), "address", address, NULL);
154   g_object_get (G_OBJECT (element), "address", &str, NULL);
155   fail_unless_equals_string (str, address);
156   g_free (str);
157 
158   g_object_set (G_OBJECT (element), "streamid", streamid, NULL);
159   g_object_get (G_OBJECT (element), "streamid", &val64, NULL);
160   fail_unless (val64 == streamid);
161 
162   g_object_set (G_OBJECT (element), "drop-invalid", drop_invalid, NULL);
163   g_object_get (G_OBJECT (element), "drop-invalid", &val, NULL);
164   fail_unless (val == drop_invalid);
165 
166   gst_object_unref (element);
167 }
168 
169 GST_END_TEST;
170 
GST_START_TEST(test_crf_cvf_data)171 GST_START_TEST (test_crf_cvf_data)
172 {
173   GstAvtpCrfBase *avtpcrfbase;
174   GstBuffer *buf;
175   GstHarness *h;
176 
177   h = setup_harness ();
178 
179   buf = create_input_buffer (h, AVTP_SUBTYPE_CVF);
180   avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfcheck");
181   avtpcrfbase->thread_data.average_period = 3300;
182   avtpcrfbase->thread_data.current_ts = 110000;
183   gst_object_unref (avtpcrfbase);
184 
185   test_crf_tstamps (h, buf, 110000, 109204, 1);
186   test_crf_tstamps (h, buf, 113600, 119400, 2);
187   test_crf_tstamps (h, buf, 218000, 119400, 2);
188   test_crf_tstamps (h, buf, 218000, 102000, 2);
189 
190   gst_buffer_unref (buf);
191   gst_harness_teardown (h);
192 }
193 
194 GST_END_TEST;
195 
GST_START_TEST(test_crf_aaf_data)196 GST_START_TEST (test_crf_aaf_data)
197 {
198   GstAvtpCrfBase *avtpcrfbase;
199   GstBuffer *buf;
200   GstHarness *h;
201 
202   h = setup_harness ();
203 
204   buf = create_input_buffer (h, AVTP_SUBTYPE_AAF);
205   avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfcheck");
206   avtpcrfbase->thread_data.average_period = 3300;
207   avtpcrfbase->thread_data.current_ts = 110000;
208   gst_object_unref (avtpcrfbase);
209 
210   test_crf_tstamps (h, buf, 113300, 0, 1);
211   test_crf_tstamps (h, buf, 112900, 0, 2);
212   test_crf_tstamps (h, buf, 210000, 0, 2);
213 
214   gst_buffer_unref (buf);
215   gst_harness_teardown (h);
216 }
217 
218 GST_END_TEST;
219 
GST_START_TEST(test_crf_period_zero)220 GST_START_TEST (test_crf_period_zero)
221 {
222   GstAvtpCrfBase *avtpcrfbase;
223   GstBuffer *buf;
224   GstHarness *h;
225 
226   h = setup_harness ();
227 
228   buf = create_input_buffer (h, AVTP_SUBTYPE_CVF);
229   avtpcrfbase = (GstAvtpCrfBase *) gst_harness_find_element (h, "avtpcrfcheck");
230   avtpcrfbase->thread_data.average_period = 0.0;
231   avtpcrfbase->thread_data.current_ts = 110;
232   gst_object_unref (avtpcrfbase);
233 
234   test_crf_tstamps (h, buf, 112, 110, 1);
235 
236   gst_buffer_unref (buf);
237   gst_harness_teardown (h);
238 }
239 
240 GST_END_TEST;
241 
242 static Suite *
avtpcrfcheck_suite(void)243 avtpcrfcheck_suite (void)
244 {
245   Suite *s = suite_create ("avtpcrfcheck");
246   TCase *tc_chain = tcase_create ("general");
247 
248   suite_add_tcase (s, tc_chain);
249   tcase_add_test (tc_chain, test_properties);
250   tcase_add_test (tc_chain, test_crf_cvf_data);
251   tcase_add_test (tc_chain, test_crf_aaf_data);
252   tcase_add_test (tc_chain, test_crf_period_zero);
253 
254   return s;
255 }
256 
257 GST_CHECK_MAIN (avtpcrfcheck);
258