从rtp数据包中解析MPEG4帧

时间:2010-11-02 21:03:57

标签: ffmpeg rtp mpeg-4

我正在尝试从来自轴摄像头的rtp流中解析不同的mpeg4帧,并使用avcodec_decode_video函数将数据包提供给ffmpeg库。这是我正在做的步骤 1. rtsp流已初始化 2. rtp流开始流入 3.我得到的第一个数据包以000001b0开始......配置数据跟随,然后该帧以000001b6开始。 第二个rtp有效载荷将不同,直到我得到一个rtp数据包,其中标记位被设置。之后我再次收到以000001b6开头的数据包并继续使用5-10 rtp数据包..此模式重复

我正在做的是 如果我检测到000001b0 / b6 - 在正确初始化解码器上下文之后,我将累积所有后来的数据包,并将更大的缓冲区提供给libavcodec的avcodec_decode_video函数。

但是我在这里得到了一张糟糕的照片,其中最顶部的部分是水平条纹 - 水晶般清晰的照片,剩下的就是蹩脚的。我不确定为什么它会像这样。请帮帮我

我在rtp数据包中获得的数据是动态-96。

要注意的是:当我传递iframes和p帧时,它们全神贯注于其他制造商的propreitary协议,ffmpeg能够解析并提供非常好的pcitures。

感谢任何帮助

1 个答案:

答案 0 :(得分:9)

尝试在AXIS IP摄像机上摆弄您的MPEG4流设置。注意Video&图像/高级部分,您应该设置它:

  1. 视频对象类型:SIMPLE
  2. [x]符合ISMA
  3. GOV结构:IP
  4. 此外,尝试更改“优先级”或“优化视频流”设置(您应该具有帧速率,图像质量,带宽,无)。

    如果这些都不起作用,请阅读更多内容......

    我希望您了解MPEG4流是如何通过RTP传输的。简而言之(如果你不确定如何):

    1. “配置框架”(Visual Object Sequence Start)以整数000001B0(十六进制)开头。它包含要解码的视频所需的数据。只有在第一次尝试解码流时,才需要将其发送到解码器,并且它用于解码后面的所有VOP。请注意,AXIS在SDP中发送此数据包(对RTSP中的DESCRIBE的响应),例如: a=fmtp:96 profile-level-id=245; config=000001B0F5000001B5891300000100000001200086C40FA28A021E0A21。因此,如果流不会改变,并且你在SDP中得到这个,你就不需要将VOS传递给解码器......但如果你这样做,那就没有坏处。

    2. 视频对象平面(I-VOP,P-VOP,B-VOP)以整数000001B6开头。如果将GOV长度设置为10,并将流的结构设置为“IP”,则将获得1个I帧(I-VOP)和9个P-VOP-s,但所有都将具有000001B6个起始码。区分它们的技巧是检查第五个字节中的下两个BITS。检查表格以确定您获得的VOP类型:

      VOP_CODING_TYPE (binary)  Coding method
                            00  intra-coded (I)
                            01  predictive-coded (P)
                            10  bidirectionally-predictive-coded (B)
                            11  sprite (S)
      
    3. 现在,要解码视频,您必须将VOS发送到解码器,然后立即进行I-VOP。但是,你从RTP流中提取这些帧的方式很难......如果I-VOP的大小是10000B,而你的网络MTU是1400B,你就不能按原样发送它而没有网络拥塞。因此,AXIS摄像机将I-VOP和所有其他BIG帧分成FRAGMENTS,它通过RTP发送为RTP数据包,其大小不超过MTU。主要思想是这个(例子):

      1. 将10000B拆分为MTU大小的片段(对于1400B MTU,您将获得大约8x [1400B]和1x [200B]片段)
      2. 将每个RTP MARKER BIT设置为0
      3. 发送
      4. 发送最后一个片段并将RTP MARKER BIT设置为1以标记最后一个片段
      5. 现在,当你收到这个时,你有点了解,但你需要恢复原来的10KB FRAME,以便解码器解码它。你正在做的方式是,只解码大得多的帧的第一个MTU字节,并且丢弃你发送给解码器的所有其他片段。这就是为什么你可以得到糟糕的图片......

        要恢复原始帧:

        1. 接收包含起始码000001B6000001B0且RTP MARKER位设置为0的数据包。如果MARKER设置为1,那就是整个帧,您可以将其解码为是!如果是0,则更多部分跟随......
        2. 将第一个片段的所有片段放入缓冲区,直到你得到一个MARKER BIT设置为1.当你得到最后一个片段时,将它放入缓冲区。
        3. 您的缓冲区现在包含一个可以发送给解码器的整个帧!
        4. 在那里,希望我帮助......:)