0

我正在尝试创建一个自定义 I/O 层以将原始 H.264 帧数据从 QUdpSocket 数据报传递给 FFMPEG。H.264 帧没有任何类型的容器,只是从帧抓取设备流式传输。出了点问题,因为由于某种原因,当我调用 avcodec_decode_video2() 时,FFMPEG 认为访问单元的大小为 1:

[h264 @ 0x1030dd000] missing picture in access unit with size 1
[h264 @ 0x1030dd000] no frame!

我的第一步是探测 AVInputFormat 的第一帧:

socket->readDatagram(datagram.data(), datagram.size());

AVProbeData probeData;
probeData.filename = udpUrl.toStdString().c_str();
probeData.buf_size = datagram.size() + AVPROBE_PADDING_SIZE;
probeData.buf = (unsigned char *)malloc(datagram.size() + AVPROBE_PADDING_SIZE);
memcpy(&probeData.buf[AVPROBE_PADDING_SIZE], datagram.data(), datagram.size());

inputFormat = av_probe_input_format(&probeData, 1);

接下来我分配一个AVIOContext:

buffer = (unsigned char *)malloc(bufferSize);
ioContext = avio_alloc_context(buffer, bufferSize, 0, socket, &readFrame, NULL, NULL);

之后我调用avformat_open_input_stream():

if (av_open_input_stream(&formatContext, ioContext, "", inputFormat, NULL) != 0)

这似乎成功返回。但是,视频流缺少重要信息,例如宽度、高度和像素格式,这会导致 av_find_stream_info() 失败。我可以手动设置这些参数,但它不会导致成功解码,这让我想知道我还缺少什么。

据我所知,NAL 单元完好无损:

First Frame
00:00:00:01:27:64:00:28:ad:84:09:26:6e:23:34:90:81:24:cd:c4:66:92:10:24:99:b8:8c:d2:42:04:93:37:11:9a:48:40:92:66:e2:33:49:08:12:4c:dc:46:69:21:05:5a:eb:d7:d7:e4:fe:bf:27:d7:ae:b5:50:82:ad:75:eb:eb:f2:7f:5f:93:eb:d7:5a:ab:40:50:1e:c8:
00:00:00:01:28:ee:3c:b0:
00:00:00:01:25:88:84:27:...

Second Frame
00:00:00:01:21:9a:59:15:...

我错过了 API 调用吗?谁能看到我可能做错了什么?

4

1 回答 1

0

这只是一个猜测,但问题可能是因为您使用的是 UDP,而不是 TCP。问题在于 UDP 不可靠,数据包可能会丢失、重复或乱序到达。并且数据包可能与帧不对应。所以你可能会得到零碎的帧和乱码信息。我不认为 ffmpeg 会处理得很好。

来自维基百科:

UDP 使用简单的传输模型,没有隐式的握手对话,以提供可靠性、排序或数据完整性。因此,UDP 提供了不可靠的服务,并且数据报可能会乱序到达、出现重复或在没有通知的情况下丢失。UDP 假设错误检查和纠正不是必需的或在应用程序中执行,避免了网络接口级别的此类处理的开销

所以也许你应该尝试使用 TCP,看看它是否有效。TCP 应该确保您准确地接收到您发送的内容,因此它与将输出本地传输到 ffmpeg 应该没有什么不同。

于 2012-04-19T20:24:07.350 回答