在cpp中使用libpcap打印rtp头信息

发布于 2024-12-11 20:36:40 字数 1111 浏览 3 评论 0原文

我正在使用 libpcap 解析 pcap 文件。

我想打印 rtp&rtcp 负载类型(H264 为 96/PCMU 为 0)(还有时间戳),以便我可以区分它是否是音频/视频。

我可以正确打印这些 rtp/rtcp 数据包序列号,但不能正确打印负载类型。

typedef struct {

   unsigned int version:2;   /* protocol version */
   unsigned int p:1;         /* padding flag */
   unsigned int x:1;         /* header extension flag */
   unsigned int cc:4;        /* CSRC count */
   unsigned int m:1;         /* marker bit */
   unsigned int pt:7;        /* payload type */

       u_int16 seq;              /* sequence number */
       u_int32 ts;               /* timestamp */
       u_int32 ssrc;             /* synchronization source */
       u_int32 csrc[1];          /* optional CSRC list */
   } rtp_hdr_t;

rtp_hdr_t *rtphdr=(rtp_hdr_t *)(packet + sizeof(struct ether_header) +sizeof(struct ip_header) + sizeof(struct udp_header));

cout<< ntohs(rtphdr->pt) << endl;

例如:获取有效负载类型是 12288 和 0。但我必须获取 96 和 0(如在wireshark中)。

cout << ntohs(rtphdr->ts) << endl;

例如:获取时间戳信息类似于 49892(5 位十进制数) 但我必须获得像 3269770717 这样的值。

I am parsing the pcap file using libpcap.

I want to print rtp&rtcp payload type(96 for H264/0 for PCMU) (and timestamp also) so that I can distinguish whether it is audio/video.

I can able to print those rtp/rtcp packet sequence numbers correctly but not palyload type.

typedef struct {

   unsigned int version:2;   /* protocol version */
   unsigned int p:1;         /* padding flag */
   unsigned int x:1;         /* header extension flag */
   unsigned int cc:4;        /* CSRC count */
   unsigned int m:1;         /* marker bit */
   unsigned int pt:7;        /* payload type */

       u_int16 seq;              /* sequence number */
       u_int32 ts;               /* timestamp */
       u_int32 ssrc;             /* synchronization source */
       u_int32 csrc[1];          /* optional CSRC list */
   } rtp_hdr_t;

rtp_hdr_t *rtphdr=(rtp_hdr_t *)(packet + sizeof(struct ether_header) +sizeof(struct ip_header) + sizeof(struct udp_header));

cout<< ntohs(rtphdr->pt) << endl;

Ex:getting payload type is 12288 and 0. But I have to get 96 and 0(as in wireshark).

cout << ntohs(rtphdr->ts) << endl;

Ex:getting timestamp information is like 49892(5 digit decimal number)
but I have to get values like 3269770717.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜巴黎 2024-12-18 20:36:40

ntohs() 函数将无符号短整数从网络字节顺序转换为主机字节顺序。请注意,它是字节顺序,因此,对于一字节有效负载,您不需要此转换。

对于时间戳,您应该使用 ntohl() 代替,因为您正在使用 32 位值。

更新
我认为这比使用字段更自然:

typedef struct {
   u_int8 version_p_x_cc;
   u_int8 m_pt;
   u_int16 seq; 
   ....
}

// payload type:
cout<< rtphdr->m_pt & 0x7f << endl;
// marker bit
cout<< (rtphdr->m_pt >> 7) & 0x01  << endl;

The ntohs() function converts the unsigned short integer from network byte order to host byte order. Note that it's byte order, so, for one-byte payload you don't need this conversion.

For timestamp you should use ntohl() instead, since you are working with 32-bit value.

Update
I think this will be more natural than using fields:

typedef struct {
   u_int8 version_p_x_cc;
   u_int8 m_pt;
   u_int16 seq; 
   ....
}

// payload type:
cout<< rtphdr->m_pt & 0x7f << endl;
// marker bit
cout<< (rtphdr->m_pt >> 7) & 0x01  << endl;
仅冇旳回忆 2024-12-18 20:36:40

好吧,您以大端顺序编写了位字段,但我猜您使用的是小端机器(英特尔)。你应该使用 uint16_t 代替你的 unsigned int 。毕竟你只有 16 位。

Well, you wrote the bitfield in big endian order, but I guess you use a little endian machine (Intel). And you should use uint16_t instaed of your unsigned int. You have only 16 bits, after all.

蘑菇王子 2024-12-18 20:36:40

这一切都与字节序有关。所以你的结构应该根据字节顺序。

    struct rtpHeader {
#if __BYTE_ORDER == __BIG_ENDIAN
        //For big endian
        unsigned char version:2;       // Version, currently 2
        unsigned char padding:1;       // Padding bit
        unsigned char extension:1;     // Extension bit
        unsigned char cc:4;            // CSRC count
        unsigned char marker:1;        // Marker bit
        unsigned char payload:7;       // Payload type
#else
        //For little endian
        unsigned char cc:4;            // CSRC count
        unsigned char extension:1;     // Extension bit
        unsigned char padding:1;       // Padding bit
        unsigned char version:2;       // Version, currently 2
        unsigned char payload:7;       // Payload type
        unsigned char marker:1;        // Marker bit
#endif
        u_int16_t sequence;        // sequence number
        u_int32_t timestamp;       //  timestamp
        u_int32_t sources[1];      // contributing sources
};

Its all about endianness. So your struct should be according to endianness.

    struct rtpHeader {
#if __BYTE_ORDER == __BIG_ENDIAN
        //For big endian
        unsigned char version:2;       // Version, currently 2
        unsigned char padding:1;       // Padding bit
        unsigned char extension:1;     // Extension bit
        unsigned char cc:4;            // CSRC count
        unsigned char marker:1;        // Marker bit
        unsigned char payload:7;       // Payload type
#else
        //For little endian
        unsigned char cc:4;            // CSRC count
        unsigned char extension:1;     // Extension bit
        unsigned char padding:1;       // Padding bit
        unsigned char version:2;       // Version, currently 2
        unsigned char payload:7;       // Payload type
        unsigned char marker:1;        // Marker bit
#endif
        u_int16_t sequence;        // sequence number
        u_int32_t timestamp;       //  timestamp
        u_int32_t sources[1];      // contributing sources
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文