implementing seek over the network

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

implementing seek over the network

amitchawla
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
 


Reply | Threaded
Open this post in threaded view
|

Re: implementing seek over the network

amitchawla
Hi,

Could anyone please provide some guidance on this issue.

Regards
Amit
Reply | Threaded
Open this post in threaded view
|

Re: implementing seek over the network

amitchawla
Hi,

Still waiting..

Regards
Amit