在 UDP (MPEGTS) 中流式传输时 FFMPEG 损坏的帧
FFMPEG corrupted frame when streaming in UDP (MPEGTS)
我正在开发一个屏幕流程序,到目前为止,我可以完美地捕获屏幕并将其编码为视频。
但是,每当我尝试通过 LAN 播放它并使用 Mplayer 播放时,它都能够在简单的桌面(文本文档等...)中 运行 但是当我尝试播放视频时,帧显示已损坏直到我退出视频(此视频导致帧损坏最严重https://www.youtube.com/watch?v=1La4QzGeaaQ&t=230s)
我不太确定为什么在流式传输时,youtube 视频的帧已损坏,但在将其保存到文件时(将 URL 从 udp://192.168.1.xxx:YYYY 更改为到文件名 C:\Test.ts) 根本没有损坏的帧。
我的 Mplayer 日志:
`V: 0.0 1563/1563 51% 43% 0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 23 51, bytestream -64
[h264 @ 0000000001d04940]concealing 2066 DC, 2066 AC, 2066 MV errors in I frame
V: 0.0 1564/1564 51% 43% 0.0% 0 0
[h264 @ 0000000001d04940]concealing 7598 DC, 7598 AC, 7598 MV errors in P frame
V: 0.0 1652/1652 50% 43% 0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 26 49, bytestream -55
[h264 @ 0000000001d04940]concealing 2303 DC, 2303 AC, 2303 MV errors in I frame
V: 0.0 1653/1653 50% 43% 0.0% 0 0
[h264 @ 0000000001d04940]concealing 7727 DC, 7727 AC, 7727 MV errors in P frame
V: 0.0 1741/1741 49% 43% 0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 65 62, bytestream -57
[h264 @ 0000000001d04940]concealing 704 DC, 704 AC, 704 MV errors in I frame
V: 0.0 1742/1742 49% 43% 0.0% 0 0`
流初始化代码
static void Stream_ini(const char *Url, AVFormatContext *&ofmt_ctx, AVCodec *codec, AVCodecContext *c, AVStream *&out_stream)
{
int ret;
avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", Url);
out_stream = avformat_new_stream(ofmt_ctx, codec)
out_stream->codec = c;
av_dump_format(ofmt_ctx, 0, Url, 1);
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
if (!(ofmt_ctx->flags & AVFMT_NOFILE))
{
ret = avio_open(&ofmt_ctx->pb, Url, AVIO_FLAG_WRITE);
if (ret < 0)
{
printf("Could not open output URL '%s'", Url);
return;
}
}
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0)
{
printf("Error occurred when opening output URL\n");
return;
}
}
此代码将获取捕获的屏幕并将其发送到编码器:
ScreenCap.load_screen_data(inFrame,timmer) // this will capture screen and return the time and AVFrame for encoding
sws_scale(ctx, inFrame->data, inFrame->linesize, 0,c->height, frame->data, frame->linesize);
frame->pts = (timmer - first_frame_time) / fps;
EncodeToPkT(c, frame, pkt, ofmt_ctx,out_stream);
av_frame_free(&inFrame);
然后,AVFrame 将被发送到编码器,使用 avcodec_send_frame() 获取数据包数据,并使用 av_interleaved_write_frame() 通过 LAN 流式传输它。
为简单起见,删除了所有错误检查
此外,这是我的编码器 AVCodecContex 设置:
c->bit_rate = 15000000;
c->width = 1920;
c->height = 1080;
c->time_base = AVRational{ 1, 90 };
c->framerate = AVRational{ 90, 1 };
c->gop_size = 90;
c->max_b_frames = 0;
c->pix_fmt = AV_PIX_FMT_RGB0;
我也注意到只有当我增加编码器比特率 (15 MBIT) 时才会发生这种情况,但当它降低到 (10 MBIT) 时它发生的次数就会减少。当它降低到 2 MBIT 时,损坏的帧不再发生但是质量真的很差。
我使用 PC -> 有线 -> 笔记本电脑、PC -> 无线 -> 笔记本电脑、PC -> 虚拟 PC、仅 PC(在程序和 Mplayer 中输入 PC IP 地址)测试了 LAN 中的流式传输,所有结果都相同。
我还通过输出原始图像来测试我的 DXGICap.load_screen_data 功能,并且根本没有损坏的图像
有没有人知道为什么。
谢谢南
这不仅仅是使用 UDP 的情况,即。你会收到数据包 out-of-order 然后解码会 fail/complain?尝试使用 TCP,看看会发生什么。
我正在开发一个屏幕流程序,到目前为止,我可以完美地捕获屏幕并将其编码为视频。 但是,每当我尝试通过 LAN 播放它并使用 Mplayer 播放时,它都能够在简单的桌面(文本文档等...)中 运行 但是当我尝试播放视频时,帧显示已损坏直到我退出视频(此视频导致帧损坏最严重https://www.youtube.com/watch?v=1La4QzGeaaQ&t=230s)
我不太确定为什么在流式传输时,youtube 视频的帧已损坏,但在将其保存到文件时(将 URL 从 udp://192.168.1.xxx:YYYY 更改为到文件名 C:\Test.ts) 根本没有损坏的帧。 我的 Mplayer 日志:
`V: 0.0 1563/1563 51% 43% 0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 23 51, bytestream -64
[h264 @ 0000000001d04940]concealing 2066 DC, 2066 AC, 2066 MV errors in I frame
V: 0.0 1564/1564 51% 43% 0.0% 0 0
[h264 @ 0000000001d04940]concealing 7598 DC, 7598 AC, 7598 MV errors in P frame
V: 0.0 1652/1652 50% 43% 0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 26 49, bytestream -55
[h264 @ 0000000001d04940]concealing 2303 DC, 2303 AC, 2303 MV errors in I frame
V: 0.0 1653/1653 50% 43% 0.0% 0 0
[h264 @ 0000000001d04940]concealing 7727 DC, 7727 AC, 7727 MV errors in P frame
V: 0.0 1741/1741 49% 43% 0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 65 62, bytestream -57
[h264 @ 0000000001d04940]concealing 704 DC, 704 AC, 704 MV errors in I frame
V: 0.0 1742/1742 49% 43% 0.0% 0 0`
流初始化代码
static void Stream_ini(const char *Url, AVFormatContext *&ofmt_ctx, AVCodec *codec, AVCodecContext *c, AVStream *&out_stream)
{
int ret;
avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", Url);
out_stream = avformat_new_stream(ofmt_ctx, codec)
out_stream->codec = c;
av_dump_format(ofmt_ctx, 0, Url, 1);
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
if (!(ofmt_ctx->flags & AVFMT_NOFILE))
{
ret = avio_open(&ofmt_ctx->pb, Url, AVIO_FLAG_WRITE);
if (ret < 0)
{
printf("Could not open output URL '%s'", Url);
return;
}
}
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0)
{
printf("Error occurred when opening output URL\n");
return;
}
}
此代码将获取捕获的屏幕并将其发送到编码器:
ScreenCap.load_screen_data(inFrame,timmer) // this will capture screen and return the time and AVFrame for encoding
sws_scale(ctx, inFrame->data, inFrame->linesize, 0,c->height, frame->data, frame->linesize);
frame->pts = (timmer - first_frame_time) / fps;
EncodeToPkT(c, frame, pkt, ofmt_ctx,out_stream);
av_frame_free(&inFrame);
然后,AVFrame 将被发送到编码器,使用 avcodec_send_frame() 获取数据包数据,并使用 av_interleaved_write_frame() 通过 LAN 流式传输它。
为简单起见,删除了所有错误检查
此外,这是我的编码器 AVCodecContex 设置:
c->bit_rate = 15000000;
c->width = 1920;
c->height = 1080;
c->time_base = AVRational{ 1, 90 };
c->framerate = AVRational{ 90, 1 };
c->gop_size = 90;
c->max_b_frames = 0;
c->pix_fmt = AV_PIX_FMT_RGB0;
我也注意到只有当我增加编码器比特率 (15 MBIT) 时才会发生这种情况,但当它降低到 (10 MBIT) 时它发生的次数就会减少。当它降低到 2 MBIT 时,损坏的帧不再发生但是质量真的很差。
我使用 PC -> 有线 -> 笔记本电脑、PC -> 无线 -> 笔记本电脑、PC -> 虚拟 PC、仅 PC(在程序和 Mplayer 中输入 PC IP 地址)测试了 LAN 中的流式传输,所有结果都相同。
我还通过输出原始图像来测试我的 DXGICap.load_screen_data 功能,并且根本没有损坏的图像
有没有人知道为什么。
谢谢南
这不仅仅是使用 UDP 的情况,即。你会收到数据包 out-of-order 然后解码会 fail/complain?尝试使用 TCP,看看会发生什么。