| /* 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; |
| } |