Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I don't know the time unit to use for av_dict_set to set a timeout

I am confused. I am using the av_dict_set function to set a time-out, but when I searched for information about av_dict_set, the time unit seems to be different. I don't know how to set it now. Can anyone help?

I found some code like the following:

pFormatCtx = avformat_alloc_context();

av_dict_set(&opts, "rtsp_transport", "tcp", 0);
//av_dict_set(&opts, "timeout", "5000000", 0);
if(strncmp(stream_url, "rtmp:", sizeof("rtmp:")) == 0){
    av_dict_set(&opts, "timeout", "6", 0); // in secs
}
else if(strncmp(stream_url, "http:", sizeof("http:")) == 0){
    av_dict_set(&opts, "timeout", "6000", 0); // in ms
}

if(avformat_open_input(&pFormatCtx, stream_url, NULL, &opts)!=0)
{
  return 1;
}

Maybe it should set the time unit according to the different protocols (http or rtsp).

Is the code above right ?

like image 418
ICYMYM Avatar asked Dec 02 '15 02:12

ICYMYM


1 Answers

TL;DR

  • RTMP and RTSP protocol, time base: seconds;
  • HTTP protocol, time base: microseconds (not milliseconds).

So just fix the HTTP section accordingly by multiplying your current value *1000.


FULL

I have a C++ application that uses libav to encode an H.264/AAC RTSP stream and push it to a local RTSP server that then serves it. Also I have another C++ application that uses libav to decode this RTSP stream, extract video/audio data from packets, rescale them and show pixels data from buffers using SFML.

In the decoding application I use timeout option to determine if the RTSP stream is available or not. This is an optional parameter but if the decoding process starts earlier than RTSP stream being available, the decoding process hangs if timeout is not set. This happens because the default value for RTSP and HTTP protocol is -1, that means "wait infinitely". If you instead set it to a different value and this situation happen, avformat_open_input will return an AVERROR code that you can analyze further, for example you can do new attempts to reconnect to the RTSP stream by simply starting over, thus giving you a finer control over your execution flow.

So the question is: "What is the correct time base for this value so I can use it accordingly?"

As documented here, for RTSP protocol, you can set timeout option to estabilish the maximum amount of time needed to wait to open your stream. In RTSP section, the guide explicitely says that this value is estimated in seconds:

timeout

Set maximum timeout (in seconds) to wait for incoming connections.

A value of -1 means infinite (default). This option implies the rtsp_flags set to ‘listen’.

While it doesn't specify it for RTMP protocol, I have tested it by changing my RTSP URL to RTMP URL without changing the time base and it worked as expected, so my deduction is that both protocols share the same time base.

Also, in the same page, here, for HTTP protocol, you can set timeout value for the same purpose but the time base must be in microseconds.

timeout

Set timeout in microseconds of socket I/O operations used by the underlying low level operation. By default it is set to -1, which means that the timeout is not specified.

So in your case you need to replace, as the time base you expected is not correct (I assume you meant milliseconds) and the correct one is microseconds, in order to have a 6s timeout and not 0.006s timeout:

else if(strncmp(stream_url, "http:", sizeof("http:")) == 0){
    av_dict_set(&opts, "timeout", "6000", 0); // in ms
}

with this:

else if(strncmp(stream_url, "http:", sizeof("http:")) == 0){
    av_dict_set(&opts, "timeout", "6000000", 0); // In microseconds
}

As your example shows how to do it already, you alloc a format context; then, before you open your stream, you create an AVDictionary and set the timeout value with av_dict_set. You can also set other options. All these informations are passed to avformat_open_input by passing as reference the dictionary just created and configured.

As described in line 405 in libavformat\utils.c, the dictionary info will be copied to the decoder format context priv_data and will be used in order to open the stream.

If timeout is triggered, the function will return an AVERROR code.

avformat_network_init();
AVFormatContext* muxer_receiver = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options, "timeout", "3", 0);
if(avformat_open_input(&muxer_receiver, "rtsp://:32400/live/1", NULL, &options)!=0){
    return EXIT_FAILURE;
}
if(avformat_find_stream_info(muxer_receiver, NULL)<0){
    return EXIT_FAILURE;
}
// Do stuff like retrieving video and audio streams index
av_read_play(muxer_receiver);
like image 178
Fabio Crispino Avatar answered Oct 20 '22 07:10

Fabio Crispino