Skip to content

Instantly share code, notes, and snippets.

@underdoeg
Last active December 26, 2015 05:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save underdoeg/7104290 to your computer and use it in GitHub Desktop.
Save underdoeg/7104290 to your computer and use it in GitHub Desktop.
gstreamer network sync client
#include <gst/gst.h>
#include <gst/net/gstnet.h>
#include <glib.h>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <inetclientstream.hpp>
#include <exception.hpp>
using namespace std;
guint64 toInt(string s) {
guint64 res; //number which will contain the result
istringstream convert(s); // stringstream used for the conversion constructed with the contents of 'Text'
if ( !(convert >> res) ) //give the value to 'Result' using the characters in the stream
res = 0; //if that fails set 'Result' to 0
return res;
}
GstElement* playbin;
GstClockTime basetime = 0;
GstClockTime lastBasetime = 0;
gint64 duration = 0;
GstClock* originalClock;
GstClock* serverClock;
bool isPlaying = false;
GstClockTime getServerTime() {
using std::string;
using libsocket::inet_stream;
string host = "127.0.0.1";
string port = "1235";
string answer;
answer.resize(32);
try {
libsocket::inet_stream sock(host, port, LIBSOCKET_IPv4);
sock >> answer;
sock.destroy();
return toInt(answer);
} catch (libsocket::socket_exception exc) {
return GST_CLOCK_TIME_NONE;
}
return GST_CLOCK_TIME_NONE;
}
void updateServerTime() {
GstClockTime basetimeNew = basetime;
while(basetimeNew == basetime) {
basetimeNew = getServerTime();
}
basetime = basetimeNew;
if(basetime != GST_CLOCK_TIME_NONE) {
gst_element_set_start_time(playbin, GST_CLOCK_TIME_NONE);
serverClock = gst_net_client_clock_new(NULL, "127.0.0.1", 1234, basetime);
if(serverClock) {
gst_pipeline_use_clock(GST_PIPELINE(playbin), serverClock);
//gst_element_set_start_time(playbin, basetime);
gst_element_set_base_time(playbin, basetime);
}
} else {
gst_pipeline_use_clock(GST_PIPELINE(playbin), originalClock);
GstClockTime curTime = gst_clock_get_internal_time(gst_pipeline_get_clock(GST_PIPELINE(playbin)));
gst_element_set_base_time(playbin, curTime);
}
}
static gboolean handleMessage (GstBus *bus, GstMessage *msg, void* data) {
GError *err;
gchar *debug_info;
GstClockTime curTime;
GstClockTime timeDiff;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug_info);
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error (&err);
g_free (debug_info);
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
/*
gint64 len;
if (gst_element_query_duration (playbin, GST_FORMAT_BYTES , &len)) {
duration = len;
cout << duration << endl;
} else {
cout << "no duration" <<endl;
}
curTime = gst_clock_get_internal_time(serverClock);
timeDiff = curTime - basetime;
timeDiff = timeDiff % duration;
gst_element_set_base_time(playbin, curTime-timeDiff);
*/
//cout << timeDiff << endl;
isPlaying = false;
gst_element_set_state (playbin, GST_STATE_READY);
updateServerTime();
//curTime = gst_clock_get_time(serverClock);
//gst_element_set_base_time(playbin, curTime);
gst_element_set_state (playbin, GST_STATE_PLAYING);
break;
case GST_MESSAGE_STATE_CHANGED:
GstState old, newState, pending;
gst_message_parse_state_changed (msg, &old, &newState, &pending);
if (newState == GST_STATE_PLAYING) {
if(!isPlaying) {
gint64 len;
if (gst_element_query_duration (playbin, GST_FORMAT_BYTES , &len)) {
duration = len;
}
isPlaying = true;
}
}
break;
default:
break;
}
/* We want to keep receiving messages */
return true;
}
int main (int argc, char *argv[]) {
gst_init (&argc, &argv);
playbin = gst_element_factory_make ("playbin", "playbin");
gst_element_set_state (playbin, GST_STATE_READY);
g_object_set (playbin, "uri", "file:///home/phwhitfield/videonodesMedia/syncTest/SD1V06H0.MOV.mp4", NULL);
GstElement* videosink = gst_element_factory_make("cluttersink", "videosink");
if(videosink)
g_object_set(playbin,"video-sink", videosink);
else
cout << "could not set video sink" << endl;
GstBus *bus = gst_element_get_bus (playbin);
gst_bus_add_watch (bus, handleMessage, NULL);
gst_element_set_state (playbin, GST_STATE_READY);
originalClock = gst_pipeline_get_clock(GST_PIPELINE(playbin));
updateServerTime();
//gst_element_set_base_time(playbin, basetime);
//gst_element_set_start_time(pipeline, basetime);
gst_element_set_state (playbin, GST_STATE_PLAYING);
GMainLoop* loop = g_main_loop_new(NULL,FALSE);
g_main_loop_run(loop);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment