- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 ffmpeg 实现一个(非常)低延迟的视频流 C++ 应用程序。客户端收到使用 x264 零延迟预设编码的视频,因此无需缓冲。如所述here ,如果您使用 av_read_frame() 读取编码视频流的数据包,由于 ffmpeg 中的内部缓冲,您将始终至少有一帧延迟。因此,当我在第 n+1 帧发送到客户端后调用 av_read_frame() 时,该函数将返回第 n 帧。
通过设置 AVFormatContext 标志 AVFMT_FLAG_NOPARSE 摆脱这种缓冲 | source 中建议的 AVFMT_FLAG_NOFILLIN禁用数据包解析并因此中断解码,如 source 中所述.
因此,我正在编写自己的数据包接收器和解析器。首先,这里是使用 av_read_frame() 的工作解决方案(包括一帧延迟)的相关步骤:
AVFormatContext *fctx;
AVCodecContext *cctx;
AVPacket *pkt;
AVFrame *frm;
//Initialization of AV structures
//…
//Main Loop
while(true){
//Receive packet
av_read_frame(fctx, pkt);
//Decode:
avcodec_send_packet(cctx, pkt);
avcodec_receive_frame(cctx, frm);
//Display frame
//…
}
下面是我的解决方案,它模仿了 av_read_frame() 的行为,尽我所能重现它。我能够追踪 av_read_frame 的源代码() 下降到 ff_read_packet (), 但我找不到 AVInputformat.read_packet 的来源().
int tcpsocket;
AVCodecContext *cctx;
AVPacket *pkt;
AVFrame *frm;
uint8_t recvbuf[(int)10e5];
memset(recvbuf,0,10e5);
int pos = 0;
AVCodecParserContext * parser = av_parser_init(AV_CODEC_ID_H264);
parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
parser->flags |= PARSER_FLAG_USE_CODEC_TS;
//Initialization of AV structures and the tcpsocket
//…
//Main Loop
while(true){
//Receive packet
int length = read(tcpsocket, recvbuf, 10e5);
if (length >= 0) {
//Creating temporary packet
AVPacket * tempPacket = new AVPacket;
av_init_packet(tempPacket);
av_new_packet(tempPacket, length);
memcpy(tempPacket->data, recvbuf, length);
tempPacket->pos = pos;
pos += length;
memset(recvbuf,0,length);
//Parsing temporary packet into pkt
av_init_packet(pkt);
av_parser_parse2(parser, cctx,
&(pkt->data), &(pkt->size),
tempPacket->data, tempPacket->size,
tempPacket->pts, tempPacket->dts, tempPacket->pos
);
pkt->pts = parser->pts;
pkt->dts = parser->dts;
pkt->pos = parser->pos;
//Set keyframe flag
if (parser->key_frame == 1 ||
(parser->key_frame == -1 &&
parser->pict_type == AV_PICTURE_TYPE_I))
pkt->flags |= AV_PKT_FLAG_KEY;
if (parser->key_frame == -1 && parser->pict_type == AV_PICTURE_TYPE_NONE && (pkt->flags & AV_PKT_FLAG_KEY))
pkt->flags |= AV_PKT_FLAG_KEY;
pkt->duration = 96000; //Same result as in av_read_frame()
//Decode:
avcodec_send_packet(cctx, pkt);
avcodec_receive_frame(cctx, frm);
//Display frame
//…
}
}
我检查了 fields在两种解决方案中,生成的数据包 (pkt) 就在 avcodec_send_packet() 之前。据我所知,它们是相同的。唯一的区别可能是 pkt->data 的实际内容。我的解决方案可以很好地解码 I 帧,但 P 帧中的引用似乎被破坏,导致严重的伪像和错误消息,例如“无效级别前缀”、“解码 MB xx 时出错”等。
如有任何提示,我将不胜感激。
编辑 1: 我暂时开发了一个解决方法:在视频服务器中,在发送包含帧编码数据的数据包后,我发送一个仅包含分隔符的虚拟数据包标记数据包的开始和结束。这样,我通过 av_read_frame() 推送实际的视频数据帧。我在 av_frame_read() 之后立即丢弃了虚拟数据包。
编辑 2: 已解决 here由 rom1v,如他对这个问题的评论中所写。
最佳答案
av_parser_parse2() 不一定一次性消耗您的 tempPacket。你必须在另一个循环中调用它并检查它的返回值,就像在 API docs 中一样.
关于c++ - 替换 av_read_frame() 以减少延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50682518/
我想在不解码的情况下在编码域中读取和打开视频。到目前为止,我已经编写了代码,并且它可以正常工作。但是方法 av_read_frame() 的输出只是给出了零的数量,并且相同的负整数值正在重复。 我不确
我使用 ffmpeg 解码 RTSP 视频。它喜欢这样: 当它在文件末尾时,它在 av_read_frame() 中阻塞了很长时间,为什么? 最佳答案 各种原因都可能导致长时间阻塞。但是您可以控制 I
我使用ffmpeg的dll读取USB摄像头,在控件上显示图片,并将图片保存到文件中。起初,读数正常。可以保存声音和图像。但是读了几分钟后,无法读取数据,av_read_frame返回错误码为-5,相机
我正在使用 FFMPEG解码 H264从 IP 摄像机流。有时函数 av_read_frame()返回错误 AVERROR_EXIT . 我用两台相机进行了测试。在这里,LAN network 中的摄
我是 FFMPEG 的新手,正在尝试使用 FFMPEG 进行 HLS 流式传输。当我尝试使用函数“av_read_frame”时,只要数据不可用,它就会返回一个负值。有什么方法可以让这个函数等到收到一
StackOverflow 上发布了一个问题,询问是否有任何模式可以等待 av_read_frame 提供有效数据。 : link . 我的问题是相反的: 我可以确定此方法将始终返回 -1、0 或 1
好的,所以我下载了一些 .yuv 格式的原始 UHD 序列,并在 .mp4 容器中使用 ffmpeg 对它们进行编码(h264 4:4:4,100% 质量,25fps)。当我使用 ffprobe 找出
我正在使用 libav 读取 MPEG 流。 我正在使用函数 av_read_frame() 将一些帧读入数据包: av_read_frame(pFormatCtx, &packet) 然后我使用函数
我目前正在尝试学习 FFmpeg API,关注 this tutorial .但是,我已经对视频解码的第一课产生了疑问。除了我使用的是 C++ 之外,我的代码与教程中的代码基本相同。我的问题是视频流与
是否有可能检测到 av_read_frame() 可以读取的最大数据包 (AVpacket) 大小? 最佳答案 我最近也在找同样的东西。似乎 av_read_frame 在内部为每个编解码器/格式调用
我已经编写了一些 C 代码来访问 ffmpeg 并将其包装在 C++/CLI(.NET 管理)类中。该程序获取实时视频流并提取帧并将它们转换为 PNG 文件。 不幸的是,保存到磁盘的图像总是黑色的(在
我正在使用 ffmpeg 实现一个(非常)低延迟的视频流 C++ 应用程序。客户端收到使用 x264 零延迟预设编码的视频,因此无需缓冲。如所述here ,如果您使用 av_read_frame()
我对ffmpeg有以下疑问。请澄清。 1.我正在使用 ffmpeg 并在执行 av_read_frame 之后读取 mp4 文件 我正在获取视频(stream_index = 0),音频(stream
我希望将 FFMpeg 合并到 PHP 脚本中。我的理解是,两个最好的解决方案是通过 exec() 使用命令行并提取结果或使用 PHP-FFMpeg ( https://github.com/PHP-
我一直在尝试在 android 中编写一个 rtsp 播放器。我是新手。并想知道如何存储从 av_read_frame 检索到的数据包以供进一步使用。 [例如。 不同的线程来解码它 ]。 while
我正在使用 rtmp 和 ffmpeg/libav。我有一个 fps 为 60 fps 的剪辑,由 2 个连续视频帧和 1 个音频帧组成。 2 个连续帧对应于来自 2 个摄像机的左右图像(已同步)。我
我正在尝试使用 opengl 逐帧处理视频。我使用 ffmpeg 从视频文件中读取帧。 在开始处理帧之前,我想先读取一些帧并将它们存储在内存中。所以我尝试在 while 循环中使用 av_read_f
我有一个 3500 帧的 HEVC 序列,我正在编写一个解码器来读取它(逐帧读取并转储到 yuv)。在我的 main() 中,我有一个调用 decoder() 3500 次的 for 循环(我假设在这
过去两周我一直在试验 FFMpeg,但遇到了一些麻烦...... 首先,我一直在使用 Galaxy S3,它工作得非常好,给了我有史以来最好的照片,但我最近换了 Galaxy NEXUS,这给了我很多
我正在使用 KxMovie:https://github.com/kolyvan/kxmovie 它似乎停止了一个流并关闭了应该使用的 View Controller [暂停]; 但是,如果流未正确关
我是一名优秀的程序员,十分优秀!