在FFmpeg库中,很多函数没有直接的参数可以设置超时。
那么有哪些函数可以通过设置 AVFormatContext 的 interrupt_callback 来实现超时控制?
-
avformat_open_input
: 打开输入文件或流。这个函数会阻塞,尤其是在网络流的情况下,可能会因为等待服务器响应而长时间阻塞。 -
avformat_find_stream_info
: 读取流信息。这个函数会尝试读取更多的数据来获得流的详细信息,如果数据源响应缓慢,也会阻塞。 -
av_read_frame
: 读取数据包。这个函数会读取下一帧的数据包,如果数据源响应缓慢或者网络连接不稳定,也会阻塞。 -
avio_read
: 从输入缓冲区读取数据,这个函数也会阻塞。 -
avio_open
: 打开文件或网络资源以进行读取或写入的函数。 -
av_seek_frame
或 **avformat_seek_file
**用于在媒体流中进行跳转操作 -
等等
总之在打开、关闭、读写网络流的时候都有可能遇到阻塞的问题。
以**avformat_find_stream_info函数为例,函数的调用关系如下:
**
avformat_find_stream_info
read_frame_internal
ff_read_packet
s->iformat->read_packet
read_packet(rpsp.c)
ff_sdp_demuxer.read_packet = ff_rtsp_fetch_packet
ff_rtsp_fetch_packet
read_packet
ff_rtsp_tcp_read_packet
ff_rtsp_read_reply
ffurl_read_complete
retry_transfer_wrapper
ff_check_interrupt
ff_check_interrupt函数用于检测中断回调函数是否应该触发中断操作。
调用ff_check_interrupt函数的函数包括:
async_check_interrupt in async.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
retry_transfer_wrapper in avio.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
get_current_fragment in dashdec.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
read_data in dashdec.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
reopen_demux_for_component in dashdec.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
dash_read_packet in dashdec.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
failing_write_packet in fifo_test.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
read_data in hls.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
read_data in hls.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
read_data in hls.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
hls_read in hlsproto.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
hls_read in hlsproto.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
libsrt_network_wait_fd_timeout in libsrt.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
libsrt_listen_connect in libsrt.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
ff_network_wait_fd_timeout in network.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
ff_network_sleep_interruptible in network.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
ff_poll_interrupt in network.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
ff_listen_connect in network.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
start_connect_attempt in network.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
rtp_read in rtpproto.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
udp_read_packet in rtsp.c (ffmpeg\ffmpeg-4.1.4\libavformat) :
以上函数被进一步调用的关系如下:
retry_transfer_wrapper
ffurl_read
wrapped_url_read
io_read_packet
cache_read
concat_read
crypto_read
ftp_getc
ftp_read
ftp_read_dir
gopher_read
hls_read
http_getc
http_buf_read
http_shutdown
rtmpe_read
rtmp_http_send_cmd
rtmp_http_read
rtmp_http_open
ff_rtmp_packet_read
ff_rtmp_packet_read_internal
rtmp_write
udp_read_packet
rtp_read_header
sap_read_header
sap_fetch_packet
srtp_read
subfile_read
gnutls_url_pull
tls_read_callback
mbedtls_recv
url_bio_bread
tls_client_handshake_loop
tls_read
tls_read_cb
ffurl_read_complete
get_chunk_header
read_data_packet
get_http_header_data
get_tcp_server_response
rtmp_packet_read_one_chunk
rtmp_calc_swfhash
rtmp_handshake
rtmp_receive_hs_packet
rtmp_server_handshake
ff_rtsp_skip_packet
ff_rtsp_read_reply
read_line
rtsp_read_announce
ff_rtsp_tcp_read_packet
ffurl_write
io_write_packet
crypto_write
crypto_close
ftp_send_command
ftp_write
gopher_write
http_write_reply
http_connect
http_write
ff_rtmp_packet_write
ff_rtp_check_and_send_back_rr
ff_rtp_send_punch_packets
ff_rtp_send_rtcp_feedback
ff_rtsp_read_reply
ff_rtsp_tcp_write_packet
gnutls_url_push
http_proxy_open
http_proxy_write
http_shutdown
icecast_write
ism_write
mbedtls_send
md5_close
prompeg_write_fec
rtmp_handshake
rtmp_send_hs_packet
rtmp_server_handshake
rtmpe_write
rtp_write
rtsp_send_cmd_with_content_async
rtsp_send_reply
sap_write_close
sap_write_packet
send_command_packet
srtp_write
tee_write
tls_client_handshake
tls_client_handshake_loop
tls_shutdown_client
tls_write
tls_write_callback
tls_write_cb
url_bio_bwrite
async_check_interrupt
async_buffer_task
async_open
async_read_internal
async_seek
ff_listen_connect
sctp_open
unix_open
ff_network_sleep_interruptible
http_read_stream
ff_network_wait_fd_timeout
tcp_read
tcp_write
ff_poll_interrupt
ff_listen_connect
ff_connect_parallel
get_current_fragment
read_data
libsrt_listen_connect
libsrt_setup
libsrt_network_wait_fd_timeout
libsrt_listen
libsrt_listen_connect
libsrt_read
libsrt_write
read_data
hls_read_header
pulse_read_packet
reopen_demux_for_component
tls_client_handshake_loop
reopen_demux_for_component
open_demux_for_component
recheck_discard_flags
dash_read_packet
dash_seek
start_connect_attempt
ff_connect_parallel
udp_read_packet
read_packet
dash_read_packet
AVInputFormat ff_dash_demuxer = {
.name = "dash",
.long_name = NULL_IF_CONFIG_SMALL("Dynamic Adaptive Streaming over HTTP"),
.priv_class = &dash_class,
.priv_data_size = sizeof(DASHContext),
.read_probe = dash_probe,
.read_header = dash_read_header,
.read_packet = dash_read_packet,
.read_close = dash_close,
.read_seek = dash_read_seek,
.flags = AVFMT_NO_BYTE_SEEK,
};
failing_write_packet
AVOutputFormat ff_fifo_test_muxer = {
.name = "fifo_test",
.long_name = NULL_IF_CONFIG_SMALL("Fifo test muxer"),
.priv_data_size = sizeof(FailingMuxerContext),
.write_header = failing_write_header,
.write_packet = failing_write_packet,
.write_trailer = failing_write_trailer,
.deinit = failing_deinit,
.priv_class = &failing_muxer_class,
.flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH,
};
hls_read
const URLProtocol ff_hls_protocol = {
.name = "hls",
.url_open = hls_open,
.url_read = hls_read,
.url_close = hls_close,
.flags = URL_PROTOCOL_FLAG_NESTED_SCHEME,
.priv_data_size = sizeof(HLSContext),
};
rtp_read
const URLProtocol ff_rtp_protocol = {
.name = "rtp",
.url_open = rtp_open,
.url_read = rtp_read,
.url_write = rtp_write,
.url_close = rtp_close,
.url_get_file_handle = rtp_get_file_handle,
.url_get_multi_file_handle = rtp_get_multi_file_handle,
.priv_data_size = sizeof(RTPContext),
.flags = URL_PROTOCOL_FLAG_NETWORK,
.priv_data_class = &rtp_class,
};