Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
230 views
in Technique[技术] by (71.8m points)

Method to Cancel/Abort GStreamer tcpclientsink Timeout

I am working on an application that uses GStreamer to send a Motion JPEG video stream through a tcpclientsink element. The application works fine, except if I disrupt the network by switching the connection from wired to wireless or wireless to wired. When that happens, it looks like the tcpclientsink element waits 15 minutes before responding to messages. That becomes a problem if I try to shut down the application during this time. Here is what I've observed:

  1. Start a Motion JPEG media stream with GStreamer using tcpclientsink as the sink. The code pushing the video runs in its own thread.
  2. While the media stream is running, disrupt the connection by switching the type of network connection.
  3. Start shutting down the application. Call gst_bus_post(bus, gst_message_new_eos(NULL)). This seems to get ignored.
  4. Call pthread_join to wait for the video thread to exit. It does not respond for up to 15 minutes.

When I look at the GST_DEBUG messages, I can see that the GStreamer tcpclientsink hit an error while writing. It apparently waits 15 minutes while retrying.

Is there a way I can abort or cancel the timeout associated with tcpclientsink? Is there a different message I could send to cause the sink to terminate immediately?

I know I can use pthread_timedjoin_np and pthread_cancel to kill the video thread if GStreamer does not respond as fast as I would like, but I would prefer to have GStreamer exit as cleanly as possible.

Update

I should have mentioned I'm using GStreamer 0.10.36. Unfortunately this might just be a bug with that version. I see the handling has changed quite a bit in 1.2.x. I'm still hoping there is a workaround for the version I'm using.

I was able to recreate this problem using gst-launch-0.10. This might be more complicated than necessary, but it worked for me:

Launch three scripts:

  • The following relays the data between the consumer and the producer:

    while [ 1 ] do gst-launch-0.10 tcpserversrc host=0 port=${PORT_IN} ! jpegdec ! jpegenc ! tcpserversink port=${PORT_OUT} done

  • The following is the script for the consumer

    gst-launch-0.10 tcpclientsrc host=${IP_ADDR} port=${PORT_OUT} ! jpegdec ! ffmpegcolorspace ! ximagesink

  • The following is the script for the producer

    gst-launch-0.10 ximagesrc ! videoscale ! video/x-raw-rgb,framerate=1/1,width=640,height=320 ! ffmpegcolorspace ! jpegenc ! tcpclientsink host=${IP_ADDR} port=${PORT_IN}

I ran the first two scripts on one machine and the third script on a second machine. When I switched the network connection on the second machine from wired to wireless, it took 15+ minutes for the tcpclientsink to report an error.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In order to fix the problem, I had to patch GStreamer. I added code to specify the send timeout in the gst_tcp_client_sink_start() function of gsttcpclientsink.c

struct timeval timeout;
timeout.tv_sec = 60;
timeout.tv_usec = 0;
...
setsockopt (this->sock_fd.fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));

Now the application is capable of shutting down within one minute (acceptable for my situation) even if the network was disrupted while streaming video.

Note: It doesn't look like this will be a problem with version 1.2.1, but I need to stay with 0.10.36.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...