gpt4 book ai didi

directshow - 如何处理原始 UDP 数据包,以便它们可以被 Directshow 源过滤器中的解码器过滤器解码

转载 作者:行者123 更新时间:2023-12-03 07:13:55 27 4
gpt4 key购买 nike

长篇故事:

  • 有一个 H264/MPEG-4 源
  • 我可以用 RTSP 协议(protocol)连接这个源。
  • 我可以使用 RTP 协议(protocol)获取原始 UDP 数据包。
  • 然后将这些原始 UDP 数据包发送到解码器 [h264/mp​​eg-4] [DS 源过滤器]
  • 但是那些“原始”UDP 数据包无法被 Decoder[h264/mp​​eg-4] 过滤器解码

  • 很快:

    我如何处理这些原始 UDP 数据以便被 H264/MPEG-4 解码器过滤器解码? 任何人都可以清楚地确定我对 H264/MPEG 流的处理步骤吗?

    额外信息:

    我可以用 FFmpeg 做到这一点......但我无法真正弄清楚 FFmpeg 如何处理原始数据,以便解码器可以解码。

    最佳答案

    蛋糕的和平!

    1.获取数据

    正如我所看到的,您已经知道如何做到这一点(启动 RTSP session ,设置 RTP/AVP/UDP;unicast; 传输,并获取用户数据报)...但如果您有疑问,请询问。

    无论是传输(UDP 还是 TCP),数据格式基本相同:

  • RTP 数据:[RTP Header - 12bytes][Video data]
  • UDP: [RTP Data]
  • TCP:[$ - 1byte][Transport Channel - 1byte][RTP data length - 2bytes][RTP
    data]

  • 因此,要从 UDP 获取数据,您只需去除代表 RTP header 的前 12 个字节。但请注意,您需要它来获取视频定时信息,而对于 MPEG4 则需要打包信息!

    对于 TCP,您需要读取第一个字节,直到获得字节 $ .然后读取下一个字节,这将是以下数据所属的传输 channel (当服务器响应 SETUP 请求时,它说: Transport: RTP/AVP/TCP;unicast;interleaved=0-1 这意味着 VIDEO DATA 将具有 TRANSPORT_CHANNEL=0 并且 VIDEO RTCP DATA 将具有 TRANSPORT_CHANNEL=1)。你想得到视频数据,所以我们期望 0...然后读取一个短的(2 个字节),它代表后面的 RTP 数据的长度,所以读取那么多字节,现​​在做与 UDP 相同的操作。

    2. 数据拆包

    H264 和 MPEG4 数据通常是打包的(在 SDP 中有 packetization-mode 参数,可以有值 0、1 和 2 它们各自的含义,以及如何对其进行解包,您可以看到 HERE )因为有某个网络限制一个端点可以通过称为 MTU 的 TCP 或 UDP 发送。它通常为 1500 字节或更少。因此,如果视频帧大于(通常是),则需要将其分段(打包)为 MTU 大小的片段。这可以通过 TCP 和 UDP 传输上的编码器/流媒体来完成,或者您可以在 IP 上中继以在另一端对视频帧进行分段和重组...和 TCP。

    H264:要检查 RTP 数据(通过 UDP 到达,或通过 TCP 交错)是否包含一个较大的 H264 视频帧的片段,您必须知道该片段在打包时的外观:

    H264 碎片
    First byte:  [ 3 NAL UNIT BITS | 5 FRAGMENT TYPE BITS] 
    Second byte: [ START BIT | END BIT | RESERVED BIT | 5 NAL UNIT BITS]
    Other bytes: [... VIDEO FRAGMENT DATA...]

    现在,获取名为 Data 的字节数组中的第一个视频数据并获得以下信息:
    int fragment_type = Data[0] & 0x1F;
    int nal_type = Data[1] & 0x1F;
    int start_bit = Data[1] & 0x80;
    int end_bit = Data[1] & 0x40;

    fragment_type == 28然后它后面的视频数据代表视频帧片段。下次检查是 start_bit设置,如果是,则该片段是序列中的第一个片段。您可以使用它通过从第一个有效载荷字节 ( 3 NAL UNIT BITS ) 中取出前 3 位并将它们与第二个有效载荷字节 ( 5 NAL UNIT BITS ) 中的最后 5 位组合来重建 IDR 的 NAL 字节,因此您将得到这样的字节 [3 NAL UNIT BITS | 5 NAL UNIT BITS] .然后首先将该 NAL 字节写入一个清除缓冲区中 VIDEO FRAGMENT DATA从那个片段。

    start_bitend_bit是 0 然后只写 VIDEO FRAGMENT DATA (跳过识别片段的前两个有效载荷字节)到缓冲区。

    start_bit是 0 和 end_bit是1,这意味着它是最后一个片段,你只需写它的 VIDEO FRAGMENT DATA (跳过标识片段的前两个字节)到缓冲区,现在您的视频帧已重建!

    请记住,RTP 数据在前 12 个字节中包含 RTP header ,并且如果帧被分段,则永远不会在碎片整理缓冲区中写入前两个字节,并且您需要重建 NAL 字节并首先写入。如果你在这里搞砸了一些东西,图片将是不完整的(其中一半是灰色或黑色的,或者你会看到伪影)。

    MPEG4:
    这是个简单的。您需要检查 RTP Header 中的 MARKER_BIT。如果视频数据代表整个视频帧,则设置该字节( 1 ),并且它是 0视频数据的一部分是一个视频帧片段。因此,要对其进行解包,您需要查看 MARKER_BIT 是什么。如果是 1就是这样,只需读取视频数据字节。

    全车架:
       [MARKER = 1]

    打包框架:
       [MARKER = 0], [MARKER = 0], [MARKER = 0], [MARKER = 1]

    第一个包含 MARKER_BIT=0 的数据包是第一个视频帧片段,随后的所有其他片段包括第一个 MARKER_BIT=1是同一视频帧的片段。所以你需要做的是:
  • 直到 MARKER_BIT=0将视频数据放入解包缓冲区
  • 将下一个视频数据放在MARKER_BIT=1进入同一个缓冲区
  • 解包缓冲区现在包含一整帧 MPEG4 帧

  • 3.解码器处理数据(NAL字节流)

    当您对视频帧进行解包后,您需要制作 NAL 字节流。它具有以下格式:
  • H264:0x000001[SPS], 0x000001[PPS], 0x000001[VIDEO FRAME], 0x000001...
  • MPEG4:0x000001[Visual Object Sequence Start], 0x000001[VIDEO FRAME]

  • 规则:
  • 每个帧都必须以 0x000001 开头无论编解码器如何,都是 3 字节代码
  • 每个流都必须以 CONFIGURATION INFO 开头,对于 H264 是 SPS 和 PPS 帧的顺序(SDP 中的 sprop-parameter-sets),对于 MPEG4 是 VOS 帧(SDP 中的 config 参数)

  • 因此,您需要为 H264 和 MPEG4 构建一个配置缓冲区,并带有 3 个字节 0x000001 ,首先发送它,然后在每个解包的视频帧前面加上相同的 3 个字节并将其发送到解码器。

    如果您需要任何澄清只是评论... :)

    关于directshow - 如何处理原始 UDP 数据包,以便它们可以被 Directshow 源过滤器中的解码器过滤器解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7665217/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com