gstreamer/tests/misc/netclock-replay.c
Arun Raghavan 77b4bc44ba tests: Add some code to replay and analyse netclientclock
This takes readings in the form of ...

<local_1> <remote_1> <remote_2> <local_2>

... with one observation per line, and then replays it using the
netclientclock code.

The output is the statistics structure emitted by the netclientclock,
which can then be analysed and tuned once we get those readings for
potential edge-cases.

It should be possible to find some inputs with "bad" data and convert
this into a unit test for future tweaks to run against.
2016-03-25 12:58:57 +05:30

134 lines
3.9 KiB
C

/* GStreamer
* Copyright (C) 2016 Centricular Ltd.
* Author: Arun Raghavan <arun@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
/* We need the internal netclock estimation function to (re)run the code on
* captured samples, plus its dependencies for the build to succeed. */
#include "../../libs/gst/net/gstntppacket.c"
#include "../../libs/gst/net/gstnetclientclock.c"
static gchar *input = NULL;
static gboolean debug = FALSE;
static gint rtt_limit = 0;
static GOptionEntry entries[] = {
{"input", 'i', 0, G_OPTION_ARG_FILENAME, &input,
"Clock reading file containing one local and remote time readings, one "
"per line",
"FILE"},
{"rtt-limit", 'r', 0, G_OPTION_ARG_INT64, &rtt_limit,
"Round trip time limit on packets (in ms)", "MSEC"},
{"debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Verbose debug output", NULL},
{NULL,}
};
int
main (int argc, char *argv[])
{
GstNetClientInternalClock *clock;
GstBus *bus;
GIOChannel *channel;
GIOStatus status;
GError *error = NULL;
GOptionContext *context;
gchar *line;
int ret = 1;
context = g_option_context_new (NULL);
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_add_group (context, gst_init_get_option_group ());
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_print ("Failed to parse options: %s\n\n", error->message);
g_error_free (error);
return 1;
}
if (input) {
if (!(channel = g_io_channel_new_file (input, "r", NULL))) {
g_print ("Could not read input file: %s\n", input);
return 1;
}
} else {
if (!(channel = g_io_channel_unix_new (0))) {
g_print ("Could not read stdin");
return 1;
}
}
clock = g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, NULL);
bus = gst_bus_new ();
/* FIXME: Find a way to do this without touching the structure internals */
if (rtt_limit)
clock->roundtrip_limit = rtt_limit * GST_MSECOND;
clock->busses = g_list_prepend (clock->busses, bus);
while ((status = g_io_channel_read_line (channel, &line, NULL, NULL,
&error)) == G_IO_STATUS_NORMAL) {
GstClockTime local_1, local_2, remote_1, remote_2;
GstMessage *message;
if (sscanf (line, "%" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %"
G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, &local_1, &remote_1,
&remote_2, &local_2) != 4) {
g_print ("Failed to get local/remote time values from: %s\n", line);
goto done;
}
if (debug)
g_print ("%s", line);
gst_net_client_internal_clock_observe_times (clock, local_1, remote_1,
remote_2, local_2);
g_free (line);
if ((message = gst_bus_pop_filtered (bus, GST_MESSAGE_ELEMENT))) {
const GstStructure *st;
gchar *str;
st = gst_message_get_structure (message);
str = gst_structure_to_string (st);
g_print ("%s\n", str);
g_free (str);
gst_message_unref (message);
}
}
if (status == G_IO_CHANNEL_ERROR) {
g_print ("Error reading file: %s\n", error->message);
g_error_free (error);
goto done;
}
g_io_channel_unref (channel);
g_free (input);
gst_object_unref (bus);
ret = 0;
done:
return ret;
}