3

我需要帮助来调试概率问题。我构建了一个 gstreamer 管道,将 NVENC 编码的 h264 比特流(仅限视频)流式传输到浏览器。浏览器很少正常播放。在大多数情况下,只有几帧被渲染然后图片被冻结。

NVENC 设置遵循“https://cloud.google.com/solutions/gpu-accelerated-streaming-using-webrtc”,它们是 h264 高配置和低延迟高质量和 NVENC_INFINITE_GOPLENGTH(一些设置已尝试,如 rateControlMode/enableVFR /sliceMode/repeatSPSPPS/outputAUD 但没有帮助)。在运行时,NVENC 将实时渲染的 opengl fbo 纹理编码为 h264 比特流,并通过 appsrc 将它们推送到 gstreamer。目前纹理大小为 512x512 并以 10/20/30 fps 的速度输入。

我使用gstreamer 1.18.2,管道定义为“appsrc name=nvenc_src do-timestamp=1!video/x-h264,stream-format=byte-stream,alignment=au!rtph264pay aggregate-mode=zero-latency!队列!应用程序/x-rtp,媒体=视频,编码名称=H264,有效负载=123!webrtcbin bundle-policy=max-compat name=backend_webrtc”。

gstreamer 部分代码遵循 sendrecv 示例(用 websocketpp 替换 libsoup 并删除 recv 逻辑)。

该应用程序构建为 MSVC 2019 32 位。浏览器解码器是 NVDEC。exe应用程序和js代码在同一台PC上运行(windwos 10,gtx1060,驱动版本460.89)。我在 Chrome(87.0.4280.88) 和 edge(87.0.664.66) 中尝试过。我还尝试在 android(chrome) 和 ios(safari) 中运行 js 代码并获得相同的结果。

可以得出结论,NVENC 生成了“正确的”h264 比特流。我将原始 h264 比特流转储到文件中。该文件在 VLC 中正常播放。我还尝试将转储的 h264 比特流推入 gstreamer。冻结的问题仍然存在。

图片冻结后,播放永远不会恢复。浏览器的“webrtc-internals”显示 bytes/headerBytes/packests_Received 保持增长,而 frameReceived/framesDecoded/framesDropped 保持不变。

由于按位相同的 h264 帧在不同的运行中表现不同,我猜 rtp 时间戳可能会导致问题。我尝试将appsrc 的do-timestamp 设置为0 并手动设置gstbuffer 的PTS,但它没有帮助。

4

2 回答 2

2

以下是您需要注意的几件事:

  • 无限 GOP 将不起作用 - 您必须将 NVENC 配置为每 30 - 60 帧发送一个关键帧。
  • 当然,SPS-PPS NAL 必须出现在每个关键帧之前。
  • 禁止 B 帧:WebRTC 不支持它们,因为它们会增加延迟。
  • NAL 之间的启动代码必须是 3 字节的启动代码:WebRTC 不尊重 2 字节的启动代码。我们之前遇到过这个问题,不得不手动更正启动代码。
于 2021-01-01T19:31:48.377 回答
0

感谢 user1390208 的善意提醒,我使用 h264 分析器工具检查转储的比特流并找出弊端。

浏览器确实支持无限 GOP。但它需要关键帧和 SPS-PPS 才能从错误中恢复。在发射过程中很可能需要重新发送。所以一个快速的解决方案是在 js 检测到 fps 为 0 后重新发送关键帧和 SPS-PPS 并通过 webrtc 数据通道向 gstreamer 发送重新发送请求。

我找不到答案的原因有两个:

  • 在调用 nvEncEncodePicture 之前我没有设置 encodePicFlags。无论 gopLength 和 frameIntervalP 设置为 all I 还是 I&P,NVENC 始终生成无限 GOP。有许多与 GOP 相关的参数,现在我看起来很困惑。在我当前的代码中,获得所需 GOP 控制的唯一方法是在调用 nvEncEncodePicture 之前设置 NV_ENC_PIC_PARAMS::encodePicFlags。请注意,我使用 NV_ENC_PRESET_LOW_LATENCY_HQ_GUID 和 NV_ENC_H264_PROFILE_HIGH_GUID 可能会导致始终生成无限 GOP(当未设置 encodePicFlags 时)?NVENC 在设置 gopLength & frameIntervalP & repeatSPSPPS 时没有报告错误,所以我认为当 GOP 是所有 I 帧并且 SPS-PPS 没有帮助时也会发生此问题。

  • Infinity GOP 并不总是在启动过程中导致浏览器出现上述问题。

因此,在我使用分析器工具检查 h264 比特流之前,在我看来,即使是全关键帧+SPS-PPS 比特流也存在这个概率问题。

顺便说一句,NVENC 生成 4 字节的起始码。

于 2021-01-02T04:57:43.327 回答