如何通过 WebRTC 发送 ffmpeg AVPacket(使用 libdatachannel)

How to send ffmpeg AVPacket through WebRTC (using libdatachannel)

我正在使用 ffmpeg 库对视频帧进行编码,生成具有压缩数据的 AVPacket

感谢最近关于 S/O 的一些建议,我正在尝试使用 WebRTClibdatachannel 通过网络发送该帧,特别是通过调整此处的示例:

https://github.com/paullouisageneau/libdatachannel/tree/master/examples/streamer

我在 h264rtppacketizer.cpp(库的一部分,而不是示例)中看到问题,这几乎可以肯定与我提供样本数据的方式有关。 (我不认为这与 libdatachannel 有任何关系,这与我发送的内容有关)

示例代码从文件中读取每个编码帧,并通过将文件内容设置为文件内容来填充 sample

sample = *reinterpret_cast<vector<byte> *>(&fileContents);

sample 只是一个 std::vector<byte>;

我天真地将 AVPacket->data 指针的内容复制到 sample 向量中:

sample.resize(pkt->size);
memcpy(sample.data(), pkt->data, pkt->size * sizeof(std::byte));    

但是当试图从该数据中获取长度值时,分包器失败了。 具体来说,在下面的代码中,第一次迭代的长度为 1,但第二次迭代查找索引 5,得到 1119887324。这对我的数据来说太大了,它只有 3526 字节(整个帧是一种颜色编码后可能很小):

while (index < message->size()) {
assert(index + 4 < message->size());
auto lengthPtr = (uint32_t *)(message->data() + index);
uint32_t length = ntohl(*lengthPtr);
auto naluStartIndex = index + 4;
auto naluEndIndex = naluStartIndex + length;
assert(naluEndIndex <= message->size());    
        
auto begin = message->begin() + naluStartIndex;
auto end = message->begin() + naluEndIndex;
nalus->push_back(std::make_shared<NalUnit>(begin, end));
index = naluEndIndex;
}

这是

的转储
uint32_t length = ntohl(*lengthPtr);

对于消息的前几个元素(括号中的*lengthPtr):

[2022-03-29 15:12:01.182] [info] index 0: 1  (16777216)
[2022-03-29 15:12:01.183] [info] index 1: 359  (1728118784)
[2022-03-29 15:12:01.184] [info] index 2: 91970  (1114046720)
[2022-03-29 15:12:01.186] [info] index 3: 23544512  (3225577217)
[2022-03-29 15:12:01.186] [info] index 4: 1732427807  (532693607)
[2022-03-29 15:12:01.187] [info] index 5: 1119887324  (3693068354)
[2022-03-29 15:12:01.188] [info] index 6: 3223313413  (98312128)
[2022-03-29 15:12:01.188] [info] index 7: 534512896  (384031)
[2022-03-29 15:12:01.188] [info] index 8: 3691315291  (1526728156)
[2022-03-29 15:12:01.189] [info] index 9: 83909537  (2707095557)
[2022-03-29 15:12:01.189] [info] index 10: 6004992  (10574592)
[2022-03-29 15:12:01.190] [info] index 11: 1537277952  (41307)
[2022-03-29 15:12:01.190] [info] index 12: 2701131779  (50331809)
[2022-03-29 15:12:01.192] [info] index 13: 768  (196608)

(我知道我应该 post 一个完整的样本,我正在努力)

Input #0, h264, from 'encodedOut.h264':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 1280x720, 30 tbr, 1200k tbn

更新:通过将 H264RtpPacketizer 分隔符设置从 H264RtpPacketizer::Separator::Length 更改为 H264RtpPacketizer::Separator::LongStartSequence 解决了这个问题,非常感谢 libdatachannel paullouisageneau 的作者(见下面的回答)

我有与 libx264 编码器设置相关的问题,但可以愉快地使用 h264_nvench264_mf

进行编码

streamer example for libdatachannel 的输入文件使用 32 位长度作为 NAL 单元分隔符。因此,H264RtpPacketizer 实例是使用 H264RtpPacketizer::Separator::Length.

创建的

如果我没记错的话,ffmpeg 输出将有 4 字节的起始序列作为 NAL 单元前缀(这实际上更常见),所以如果你将 packetizer 设置更改为 H264RtpPacketizer::Separator::LongStartSequence 它应该接受你的样本。