在使用FFmpeg进行推流时,单独推视频和单独推音频都没有延迟,但是音视频一起推时,不发音频流数据会延迟10秒。经查问题原因为AVFormatContext的max_interleave_delta参数默认为10秒,在ff_interleave_packet_per_dts方法中会检查所有流是否都有数据,如果没有数据会默认等待10秒,因此造成推流延迟。
附上ff_interleave_packet_per_dts 方法 源码在libavformat/mux.c 中
int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
AVPacket *pkt, int flush)
{
AVPacketList *pktl;
int stream_count = 0;
int noninterleaved_count = 0;
int i, ret;
int eof = flush;
if (pkt) {
if ((ret = ff_interleave_add_packet(s, pkt, interleave_compare_dts)) < 0)
return ret;
}
for (i = 0; i < s->nb_streams; i++) {
if (s->streams[i]->last_in_packet_buffer) {
++stream_count;
} else if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT &&
s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP8 &&
s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP9) {
++noninterleaved_count;
}
}
if (s->internal->nb_interleaved_streams == stream_count)
flush = 1;
if (s->max_interleave_delta > 0 &&
s->internal->packet_buffer &&
!flush &&
s->internal->nb_interleaved_streams == stream_count+noninterleaved_count
) {
AVPacket *top_pkt = &s->internal->packet_buffer->pkt;
int64_t delta_dts = INT64_MIN;
int64_t top_dts = av_rescale_q(top_pkt->dts,
s->streams[top_pkt->stream_index]->time_base,
AV_TIME_BASE_Q);
for (i = 0; i < s->nb_streams; i++) {
int64_t last_dts;
const AVPacketList *last = s->streams[i]->last_in_packet_buffer;
if (!last)
continue;
last_dts = av_rescale_q(last->pkt.dts,
s->streams[i]->time_base,
AV_TIME_BASE_Q);
delta_dts = FFMAX(delta_dts, last_dts - top_dts);
}
if (delta_dts > s->max_interleave_delta) {
av_log(s, AV_LOG_DEBUG,
"Delay between the first packet and last packet in the "
"muxing queue is %"PRId64" > %"PRId64": forcing output\n",
delta_dts, s->max_interleave_delta);
flush = 1;
}
}
if (s->internal->packet_buffer &&
eof &&
(s->flags & AVFMT_FLAG_SHORTEST) &&
s->internal->shortest_end == AV_NOPTS_VALUE) {
AVPacket *top_pkt = &s->internal->packet_buffer->pkt;
s->internal->shortest_end = av_rescale_q(top_pkt->dts,
s->streams[top_pkt->stream_index]->time_base,
AV_TIME_BASE_Q);
}
if (s->internal->shortest_end != AV_NOPTS_VALUE) {
while (s->internal->packet_buffer) {
AVPacket *top_pkt = &s->internal->packet_buffer->pkt;
AVStream *st;
int64_t top_dts = av_rescale_q(top_pkt->dts,
s->streams[top_pkt->stream_index]->time_base,
AV_TIME_BASE_Q);
if (s->internal->shortest_end + 1 >= top_dts)
break;
pktl = s->internal->packet_buffer;
st = s->streams[pktl->pkt.stream_index];
s->internal->packet_buffer = pktl->next;
if (!s->internal->packet_buffer)
s->internal->packet_buffer_end = NULL;
if (st->last_in_packet_buffer == pktl)
st->last_in_packet_buffer = NULL;
av_packet_unref(&pktl->pkt);
av_freep(&pktl);
flush = 0;
}
}
if (stream_count && flush) {
AVStream *st;
pktl = s->internal->packet_buffer;
*out = pktl->pkt;
st = s->streams[out->stream_index];
s->internal->packet_buffer = pktl->next;
if (!s->internal->packet_buffer)
s->internal->packet_buffer_end = NULL;
if (st->last_in_packet_buffer == pktl)
st->last_in_packet_buffer = NULL;
av_freep(&pktl);
return 1;
} else {
av_init_packet(out);
return 0;
}
}
关键代码
if (delta_dts > s->max_interleave_delta) {
av_log(s, AV_LOG_DEBUG,
"Delay between the first packet and last packet in the "
"muxing queue is %"PRId64" > %"PRId64": forcing output\n",
delta_dts, s->max_interleave_delta);
flush = 1;
}