implementing seek over the network

amitchawla amit at wowvision.in
Tue Jul 19 06:08:29 UTC 2016


Hi,

I have been trying to implement seek over the network, by connecting two
gstreamer pipelines using tcpclientsink (sender) and tcpserversrc (receiver)
at either ends. I am using Ubuntu Linux at receiver and Windows at the
sender.

At the sender side, I just have a filesrc and tcpclientsink (so no time seek
is possible at the sender)
and at the receiver I have tcpserversrc followed by decodebin connected to
audio and video sinks.

sender pipeline:
filesrc blocksize=4194304 location=C:/Users/Downloads/bbc-japan_1080p.mov !
tcpclientsink blocksize=4194304 async=false host=192.168.100.58 port=3000

receiver pipeline:
tcpserversrc host=192.168.100.58 port=3000 blocksize=4194304 ! decodebin
name=demux ! autoaudiosink demux. ! imxeglvivsink

After some suggestions I got on this forum, I got to know that the way to
implement a seek over the network would be to first extract the BYTE offset
from the demuxer at the receiver based on a TIME value and then send across
the BYTE offset to the sender to do a BYTES seek on the sender pipeline.

However, I am not able to ascertain the steps I need to do at the receiver
to synchronize the sender and the receiver. After getting a byte location
from the receiver (qtdemux in this case), when I do a BYTES seek at the
sender I see that either video decoder or the audio decoder exits with
decode error at the receiver. I figured that might be due to the demuxer
(qtdemux) state machine not being synchronized for start of a segment (KEY
frame). I tried to do a pipeline flush start and stop at the receiver before
doing a BYTES seek at the sender, but that does not work. It looks like that
at the receiver doing a flush stop issues a newsegment event and I also see
a end of stream being signaled after that. After the doing the flush_stop
the tcpserversrc seems to get stuck and doesn't accept any data from the
network. I also tried doing a newsegment myself after the flush_stop, but
that does not help. 

I am pasting below the code for the seek procedure that I perform at the
receiver.

	g_print ("\n Init SEEK \n");

       PlayerConnectionWrite(data->playerconn, (gint64) value); // This
pauses the sender pipeline
       if (ifTCPClientReadytoGo(data->playerconn))	// check if sender is
ready to start again - do not play sender yet
{
	g_print ("\n Setting receiver pipeline to PAUSE\n");
	gst_element_set_state (data->gstpipeline->pipeline, GST_STATE_PAUSED);
	bus = gst_element_get_bus (data->gstpipeline->pipeline);
	while (flag == 0)
	{
		msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_STATE_CHANGED);
			if (GST_MESSAGE_SRC (msg) == GST_OBJECT(data->gstpipeline->pipeline))
			{
				gst_message_parse_state_changed(msg, &old_state, &new_state,
&pending_state);
				if ((old_state == GST_STATE_PLAYING) && (new_state == GST_STATE_PAUSED))
				{
					g_print ("\n Pipeline paused\n");
					flag = 1;
				}
				else
					g_print ("\n Pipeline state is %s \n",
gst_element_state_get_name(new_state));
			}
		}

		GstEvent * flush_start = gst_event_new_flush_start();
		gboolean ret = FALSE;
		ret = gst_element_send_event(GST_ELEMENT(data->gstpipeline->pipeline),
flush_start);
		if (!ret)
		{
			g_print ("\n failed flush_start\n");
			exit(1);
		}
		GstEvent* flush_stop = gst_event_new_flush_stop(FALSE);
		ret = gst_element_send_event(GST_ELEMENT(data->gstpipeline->pipeline),
flush_stop);
		if (!ret)
		{
			g_print ("\n failed flush_stop\n");
			exit(1);
		}

/**
		GstSegment *gstsegment = gst_segment_new();
		gst_segment_init (gstsegment, GST_FORMAT_TIME);
		gstsegment->rate = 1.0;
		gstsegment->start = GST_SECOND * 40; //43667446;
		gstsegment->stop = -1;

		GstEvent *eventseg = gst_event_new_segment(gstsegment);

		g_print ("\n Sending segment event\n");
		if (!gst_element_send_event(GST_ELEMENT(data->gstpipeline->pipeline),
eventseg))
		{
			g_print ("\n Segment Event Error \n");
			//exit(1);
		}
		else
			g_print ("\n Segment event success \n");
**/

		g_print ("\n Setting pipeline to Playing\n");
		gst_element_set_state (data->gstpipeline->pipeline, GST_STATE_PLAYING);
		flag = 0;
		bus = gst_element_get_bus (data->gstpipeline->pipeline);
		while (flag == 0)
		{
			msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_STATE_CHANGED);
			if (GST_MESSAGE_SRC (msg) == GST_OBJECT(data->gstpipeline->pipeline))
			{
				gst_message_parse_state_changed(msg, &old_state, &new_state,
&pending_state);
				if ((old_state == GST_STATE_PAUSED) && (new_state == GST_STATE_PLAYING))
				{
					g_print ("\n Pipeline playing\n");
					flag = 1;
				}
				else
					g_print ("\n Pipeline state is %s \n",
gst_element_state_get_name(new_state));
			}
		}

		tcp_server_goahead(data->playerconn); // restart sender pipeline after
BYTES seek - set to PLAYING 
	}

I would be really thankful if anyone could point to the mistake I am doing,
or provide some guidance to implementing seek over the network using TCP.

Regards
Amit
  






--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/implementing-seek-over-the-network-tp4678741.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.


More information about the gstreamer-devel mailing list