RTMP使用笔记(一):解析使用wireshark抓取的RTMP协议包_wireshark rtmp(1)

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

目录

一、使用ffmpeg推送RTMP流

使用以下命令用ffmpeg推流到wowza:

ffmpeg -i "D:\var\siren\event-20181227\_113720723.mp4" -vcodec copy -acodec copy -f flv rtmp://192.168.154.202/live/rtsptest.stream

二、wireshark抓包筛选RTMP协议

推流过程中使用wireshark抓包,利用过滤器筛选出协议为RTMP的包
在这里插入图片描述

三、结合wireshark抓包数据讲解RTMP

1. 简介

RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing)和分包(packetizing)的问题。

Adobe的实时消息传递协议(RTMP)通过可靠的流传输提供双向消息多路复用服务,例如TCP [RFC0793],用于在一对通信对等体之间携带具有相关定时信息的视频,音频和数据消息的并行流。 实现通常为不同类别的消息分配不同的优先级,这可以影响在传输容量受限时消息被排队到基础流传输的顺序。

2. 定义

  • Payload(有效载荷):包中包含的数据,例如音频样本或压缩视频数据。
  • Packet(数据包):数据包由固定的头部和有效载荷数据组成。一些底层协议可能会要求对数据包定义封装。
  • Port(端口):“传输协议用于区分给定主机内多个目的地的抽象描述,TCP / IP协议使用小正整数识别端口。”OSI传输层使用的传输选择器(TSEL)等同于端口。
  • Transport address(传输地址):标识传输层端点的网络地址和端口的组合,例如IP地址和TCP端口。
  • Message stream(消息流):通信中消息流通的一个逻辑通道。
  • Message stream ID(消息流 ID):每条消息都有一个与之关联的ID,以标识它正在流动的消息流。
  • Chunk(块):消息的片段。在通过网络发送消息之前,消息被分成更小的部分并进行交错。这些块确保跨多个流的所有消息的按时间戳排序的端到端传送。
  • Chunk stream(块流):允许在特定方向上流动块的逻辑通信通道,块流可以从客户端传输到服务器并反向。
  • Chunk stream ID(块流ID):每个块都有一个与之关联的ID,以识别它正在流动的块流。
  • Multiplexing(合成):将单独的音频/视频数据制作成一个连贯的音频/视频流的过程,使得可以同时传输多个视频和音频。
  • DeMultiplexing(解复用):多路复用的逆过程,其中交织的音频和视频数据被组合以形成原始音频和视频数据。
  • Remote Procedure Call (RPC 远程方法调用):允许客户端或服务器在对等端调用子例程或过程的请求。
  • Metadata(元数据):有关数据的说明。 电影的元数据包括电影标题,持续时间,创建日期等。
  • Application Instance(应用实例):客户端通过发送连接请求连接的服务器上的应用程序实例。
  • Action Message Format (AMF 动作消息格式):一种紧凑的二进制格式,用于序列化ActionScript对象图。AMF有两个版本:AMF 0 [AMF0]和AMF 3 [AMF3]。

3. RTMP Chunk Stream

3.1. 消息格式

可以拆分为块以支持多路复用的消息格式取决于更高级别的协议。 但是,消息格式应该包含创建块所需的以下字段:

  • Timestamp:消息的时间戳。 该字段可以传输4个字节。
  • Length:消息有效负载的长度。 如果无法省略消息标题,则应将其包含在长度中。 该字段占用块头中的3个字节。
  • Type Id:类型ID的范围被保留用于协议控制消息。 这些传播信息的消息由RTMP Chunk Stream协议和更高级别的协议处理。 所有其他类型ID可供更高级别协议使用,并被RTMP Chunk Stream视为不透明值。 事实上,RTMP Chunk Stream中没有任何内容要求将这些值用作类型; 所有(非协议)消息可以是相同类型,或者应用程序可以使用此字段来区分同时跟踪而不是类型。 该字段在块头中占用1个字节。
  • Message Stream ID:消息流ID可以是任意值。 复用到同一块流上的不同消息流基于它们的消息流ID被多路分用。 除此之外,就RTMP Chunk Stream而言,这是一个不透明的值。该字段以小端格式占用块头中的4个字节。

3.2. 握手

RTMP连接以握手开始, 握手不同于协议的其余部分。它由三个静态大小的块组成,而不是由带有标题的可变大小的块组成。 客户端(已启动连接的端点)和服务器均发送相同的三个块。 对于展示,当客户端发送时,这些块将被指定为C0,C1和C2; S0,S1和S2由服务器发送。

3.2.1 握手顺序

  • 握手开始于客户端发送C0和C1块。
  • 在发送C2之前,客户端必须等待直到收到S1。
  • 在发送任何其他数据之前,客户端必须等待直到收到S2。
  • 在发送S0和S1之前,服务器必须等待直到收到C0,并且可以等到C1之后。 在发送S2之前,服务器必须等待直到收到C1。 在发送任何其他数据之前,服务器必须等待直到收到C2。

3.2.2 C0和S0格式

C0和S0数据包是单个八位字节,被视为单个8位整数字段:
在这里插入图片描述
以下是C0 / S0数据包中的字段:

版本(8位):在C0中,此字段标识客户端请求的RTMP版本。 在S0中,该字段标识服务器选择的RTMP版本。 此规范定义的版本为3。值0-2是早期专有产品使用的弃用值;4-31保留用于将来的实现;不允许使用32-255(允许区分RTMP与基于文本的协议,后者始终以可打印字符开头)。 无法识别客户端请求的版本的服务器应该响应3。客户端可以选择降级到版本3,或放弃握手。

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

cs/618679757)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的例程,它演示了如何在Qt下使用OpenCV进行RTMP推流: ```c++ #include <QCoreApplication> #include <opencv2/opencv.hpp> #include <rtmp.h> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 初始化RTMPRTMP_LibInit(); // 创建RTMP对象 RTMP *rtmp = RTMP_Alloc(); // 设置RTMP属性 RTMP_SetupURL(rtmp, "rtmp://your_rtmp_server_address"); RTMP_EnableWrite(rtmp); RTMP_Connect(rtmp, NULL); RTMP_ConnectStream(rtmp, 0); // 打开视频文件 cv::VideoCapture cap(0); // 检查视频文件是否打开成功 if (!cap.isOpened()) { qDebug() << "Failed to open video file."; return -1; } // 定义视频帧 cv::Mat frame; // 读取视频帧并推送到RTMP服务器 while (true) { // 读取视频帧 cap >> frame; // 检查视频帧是否为空 if (frame.empty()) { qDebug() << "End of video file."; break; } // 将视频帧转换为RTMP数据 RTMPPacket *packet = RTMPPacket_Alloc(1024 * 64); // 填充RTMP数据 RTMPPacket_Reset(packet); packet->m_nChannel = 0x04; packet->m_headerType = RTMP_PACKET_SIZE_LARGE; packet->m_packetType = RTMP_PACKET_TYPE_VIDEO; packet->m_nTimeStamp = RTMP_GetTime() - 500; packet->m_nInfoField2 = rtmp->m_stream_id; packet->m_nBodySize = cv::imencode(".jpg", frame).size(); memcpy(packet->m_body, cv::imencode(".jpg", frame).data(), packet->m_nBodySize); // 发送RTMP数据 RTMP_SendPacket(rtmp, packet, true); RTMPPacket_Free(packet); // 等待一段时间 cv::waitKey(30); } // 断开RTMP连接 RTMP_Close(rtmp); RTMP_Free(rtmp); // 清理RTMPRTMP_LibExit(); return a.exec(); } ``` 这个例程使用OpenCV的VideoCapture类来读取摄像头视频帧,并将每一帧转换为RTMP数据,并使用RTMP_SendPacket函数将数据发送到RTMP服务器。请注意,此示例中的推流代码仅适用于视频帧大小不超过64KB的情况,如果您的视频帧大小超过64KB,则需要修改代码以支持较大的数据

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值