我在使用libav库的视频聊天应用程序中遇到一些问题。我正在通过UDP发送以VP8编码为WebM容器的1080p视频,并且效果很好。在大多数情况下,两侧的解码器都会从传输造成的数据包丢失中恢复过来。
但是,在某个时间点,它只是冻结而不再恢复。最终,双方都会发生这种情况。我正在搜索VP8编解码器参数,以设置在有损传输通道上发送时提高的鲁棒性。并且我结合了我发现的一些内容,以提高鲁棒性。但是,经过一段时间的视频聊天后,它仍然冻结。
这是我当前正在使用的参数。
pVidCodecCtx->codec_id = AV_CODEC_ID_VP8;
pVidCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pVidCodecCtx->width = frmQ->pCodecCtx->width; //1920
pVidCodecCtx->height = frmQ->pCodecCtx->height; //1080
pVidCodecCtx->time_base = frmQ->pCodecCtx->time_base;
pVidCodecCtx->pix_fmt = PIX_FMT_YUV420P;
pVidCodecCtx->qmin = 4;
pVidCodecCtx->qmax = 56;
pVidCodecCtx->bit_rate = pVidCodecCtx->width * pVidCodecCtx->height * 6;
pVidCodecCtx->slices = 8;
pVidCodecCtx->profile = 3;
pVidCodecCtx->thread_count = 3;
pVidCodecCtx->keyint_min = 5;
av_dict_set(&pDictCodecOpts, "rc_lookahead", "0", 0);
av_dict_set(&pDictCodecOpts, "quality", "realtime", 0);
av_dict_set(&pDictCodecOpts, "deadline", "realtime", 0);
av_dict_set(&pDictCodecOpts, "max-intra-rate", "0", 0);
av_dict_set(&pDictCodecOpts, "qcomp", "0", 0);
av_dict_set(&pDictCodecOpts, "default", "er", 0);
av_dict_set(&pDictCodecOpts, "error_resilient", "er", 0);
av_dict_set(&pDictCodecOpts, "partitions", "er", 0);
我还必须为解码器设置参数以提高错误恢复能力吗?还是我在编码器中缺少某些参数或设置不正确。任何帮助或提示,我们将不胜感激。
我会回答自己的问题,因为我最终设法使视频聊天正常运行。
事实证明,这些参数实际上对于提高错误恢复能力很有用。
问题是某些函数调用例如
av_read_frame()
avformat_open_input()
程序包损坏时,解码器线程中的线程被阻止,从而导致视频冻结。
因此,我最终要做的是编写一个计时器类,并让计时器测量所述函数的执行时间。我编写了一个中断回调函数,并将其传递给解码器的格式上下文,如下所示:
static int interrupt_cb (void *p)
{
unsigned int expTime = 1000;
Uint32 elapsedTime = pVidConfTimer.elapsedTimeInMs();
if (elapsedTime > expTime)
{
return 1;
}
return 0;
}
static const AVIOInterruptCB cb = {interrupt_cb, &dummy};
frmQ.pFormatCtx->interrupt_callback = cb;
如果执行时间超过expTime,则将从函数返回。您也可以将自定义参数通过void *p
传递给回调函数
在我的解码/显示线程中,我只是调用类似
timer.tic();
ret = av_read_frame(...);
timer.reset();
if (ret<0)
{
//received corrupted frame
//reinitialize format context
//open input
//find decoder and open codec
...
}
希望这可以帮助任何有类似问题的人。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句