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