1. librttmp源码之相关结构体
分析RTMP_Connect
之前,有必要了解下一下定义。
1.1. Ip Protocol
/* Standard well-defined IP protocols. */
enum {
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
IPPROTO_TCP = 6, /* Transmission Control Protocol. */
IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */
IPPROTO_PUP = 12, /* PUP protocol. */
IPPROTO_UDP = 17, /* User Datagram Protocol. */
IPPROTO_IDP = 22, /* XNS IDP protocol. */
IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
IPPROTO_IPV6 = 41, /* IPv6 header. */
IPPROTO_RSVP = 46, /* Reservation Protocol. */
IPPROTO_GRE = 47, /* General Routing Encapsulation. */
IPPROTO_ESP = 50, /* encapsulating security payload. */
IPPROTO_AH = 51, /* authentication header. */
IPPROTO_MTP = 92, /* Multicast Transport Protocol. */
IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET. */
IPPROTO_ENCAP = 98, /* Encapsulation Header. */
IPPROTO_PIM = 103, /* Protocol Independent Multicast. */
IPPROTO_COMP = 108, /* Compression Header Protocol. */
IPPROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
IPPROTO_UDPLITE = 136, /* UDP-Lite protocol. */
IPPROTO_RAW = 255, /* Raw IP packets. */
IPPROTO_MAX
};
1.2. struct sockaddr
内容来源于:https://www.cnblogs.com/cyx-b/p/12450811.html
struct sockaddr
{
unsigned short sa_family;// 2字节,地址族,AF_xxx
char sa_data[14]; // 14字节,包含套接字中的目标地址和端口信息
};
1.3. struct addrinfo
内容来源于:https://www.cnblogs.com/LubinLew/p/POSIX-DataStructure.html
The <netdb.h>
header shall define the addrinfo
structure, which shall include at least the following members:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
/* ======================Types of sockets====================== */
enum __socket_type {
SOCK_STREAM = 1, /* Sequenced, reliable, connection-based byte streams. */
SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams of fixed maximum length. */
SOCK_RAW = 3, /* Raw protocol interface. */
SOCK_RDM = 4, /* Reliably-delivered messages. */
SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based,datagrams of fixed maximum length. */
SOCK_DCCP = 6, /* Datagram Congestion Control Protocol. */
SOCK_PACKET = 10, /* Linux specific way of getting packets at the dev level. For writing rarp and other similar things on the user level. */
/* Flags to be ORed into the type parameter of socket and socketpair and used for the flags parameter of paccept. */
SOCK_CLOEXEC = 02000000, /* Atomically set close-on-exec flag for the new descriptor(s). */
SOCK_NONBLOCK = 00004000 /* Atomically mark descriptor(s) as non-blocking. */
};
/* ============Protocol families(只列出常用几个)================= */
#define PF_UNSPEC 0 /* Unspecified. */
#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */
#define PF_INET 2 /* IP protocol family. */
#define PF_IPX 4 /* Novell Internet Protocol. */
#define PF_APPLETALK 5 /* Appletalk DDP. */
#define PF_INET6 10 /* IP version 6. */
#define PF_TIPC 30 /* TIPC sockets. */
#define PF_BLUETOOTH 31 /* Bluetooth sockets. */
/* ==============Address families(只列出常用几个)================= */
#define AF_UNSPEC PF_UNSPEC
#define AF_LOCAL PF_LOCAL
#define AF_UNIX PF_UNIX
#define AF_FILE PF_FILE
#define AF_INET PF_INET
#define AF_IPX PF_IPX
#define AF_APPLETALK PF_APPLETALK
#define AF_INET6 PF_INET6
#define AF_ROSE PF_ROSE
#define AF_NETLINK PF_NETLINK
#define AF_TIPC PF_TIPC
#define AF_BLUETOOTH PF_BLUETOOTH
/* ====Possible values for `ai_flags' field in `addrinfo' structure.===== */
#define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */
#define AI_CANONNAME 0x0002 /* Request for canonical name. */
#define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */
#define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
#define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */
#define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose returned address type. */
#ifdef __USE_GNU
#define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded
in the current locale's character set) before looking it up. */
#define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */
#define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode code points. */
#define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to STD3 rules. */
#endif
#define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */
/* =======================struct addrinfo======================= */
struct addrinfo {
int ai_flags; /* 附加选项,多个选项可以使用或操作结合 */
int ai_family; /* 指定返回地址的协议簇,取值范围:AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNSPEC(IPv4 and IPv6) */
int ai_socktype; /* enum __socket_type 类型,设置为0表示任意类型 */
int ai_protocol; /* 协议类型,设置为0表示任意类型,具体见上一节的 Ip Protocol */
socklen_t ai_addrlen; /* socket address 的长度 */
struct sockaddr *ai_addr; /* socket address 的地址 */
char *ai_canonname; /* Canonical name of service location. */
struct addrinfo *ai_next; /* 指向下一条信息,因为可能返回多个地址 */
};
1.4. RTMP
内容来源于:https://www.jianshu.com/p/05b1e5d70c06
RTMP定义在rtmp.h
。
/*
** 远程调用方法
*/
typedef struct RTMP_METHOD
{
AVal name;
int num;
} RTMP_METHOD;
typedef struct RTMPSockBuf
{
int sb_socket; // 套接字
int sb_size; // 缓冲区可读大小
char *sb_start; // 缓冲区读取位置
char sb_buf[RTMP_BUFFER_CACHE_SIZE]; // 套接字读取缓冲区
int sb_timedout; // 超时标志
void *sb_ssl; // TLS上下文
} RTMPSockBuf;
typedef struct RTMP
{
int m_inChunkSize; // 最大接收块大小
int m_outChunkSize; // 最大发送块大小
int m_nBWCheckCounter; // 带宽检测计数器
int m_nBytesIn; // 接收数据计数器
int m_nBytesInSent; // 当前数据已回应计数器
int m_nBufferMS; // 当前缓冲的时间长度,以MS为单位
int m_stream_id; // 当前连接的流ID
int m_mediaChannel; // 当前连接媒体使用的块流ID
uint32_t m_mediaStamp; // 当前连接媒体最新的时间戳
uint32_t m_pauseStamp; // 当前连接媒体暂停时的时间戳
int m_pausing; // 是否暂停状态
int m_nServerBW; // 服务器带宽
int m_nClientBW; // 客户端带宽
uint8_t m_nClientBW2; // 客户端带宽调节方式
uint8_t m_bPlaying; // 当前是否推流或连接中
uint8_t m_bSendEncoding; // 连接服务器时发送编码
uint8_t m_bSendCounter; // 设置是否向服务器发送接收字节应答
int m_numInvokes; // 0x14命令远程过程调用计数
int m_numCalls; // 0x14命令远程过程请求队列数量
RTMP_METHOD *m_methodCalls; // 远程过程调用请求队列
RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS]; // 对应块流ID上一次接收的报文
RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS]; // 对应块流ID上一次发送的报文
int m_channelTimestamp[RTMP_CHANNELS]; // 对应块流ID媒体的最新时间戳
double m_fAudioCodecs; // 音频编码器代码
double m_fVideoCodecs; // 视频编码器代码
double m_fEncoding; /* AMF0 or AMF3 */
double m_fDuration; // 当前媒体的时长
int m_msgCounter; // 使用HTTP协议发送请求的计数器
int m_polling; // 使用HTTP协议接收消息主体时的位置
int m_resplen; // 使用HTTP协议接收消息主体时的未读消息计数
int m_unackd; // 使用HTTP协议处理时无响应的计数
AVal m_clientID; // 使用HTTP协议处理时的身份ID
RTMP_READ m_read; // RTMP_Read()操作的上下文
RTMPPacket m_write; // RTMP_Write()操作使用的可复用报文对象
RTMPSockBuf m_sb; // RTMP_ReadPacket()读包操作的上下文
RTMP_LNK Link; // RTMP连接上下文
} RTMP;
1.5. RTMP_LINK
内容来源于:https://www.jianshu.com/p/05b1e5d70c06
typedef struct RTMP_LNK
{
AVal hostname; // 目标主机地址
AVal sockshost; // socks代理地址
// 连接和推拉流涉及的一些参数信息
AVal playpath0; /* parsed from URL */
AVal playpath; /* passed in explicitly */
AVal tcUrl;
AVal swfUrl;
AVal pageUrl;
AVal app;
AVal auth;
AVal flashVer;
AVal subscribepath;
AVal token;
AMFObject extras;
int edepth;
int seekTime; // 播放流的开始时间
int stopTime; // 播放流的停止时间
#define RTMP_LF_AUTH 0x0001 /* using auth param */
#define RTMP_LF_LIVE 0x0002 /* stream is live */
#define RTMP_LF_SWFV 0x0004 /* do SWF verification */
#define RTMP_LF_PLST 0x0008 /* send playlist before play */
#define RTMP_LF_BUFX 0x0010 /* toggle stream on BufferEmpty msg */
#define RTMP_LF_FTCU 0x0020 /* free tcUrl on close */
int lFlags;
int swfAge;
int protocol; // 连接使用的协议
int timeout; // 连接超时时间
unsigned short socksport; // socks代理端口
unsigned short port; // 目标主机端口
#ifdef CRYPTO
#define RTMP_SWF_HASHLEN 32
void *dh; /* for encryption */
void *rc4keyIn;
void *rc4keyOut;
uint32_t SWFSize;
uint8_t SWFHash[RTMP_SWF_HASHLEN];
char SWFVerificationResponse[RTMP_SWF_HASHLEN+10];
#endif
} RTMP_LNK;
1.6. RTMPPacket
内容来源于:https://blog.csdn.net/NB_vol_1/article/details/58660181
https://blog.csdn.net/bwangk/article/details/112802823
// 原始的rtmp消息块
typedef struct RTMPChunk
{
int c_headerSize; // 头部的长度
int c_chunkSize; // chunk的大小
char *c_chunk; // 数据
char c_header[RTMP_MAX_HEADER_SIZE]; // chunk头部
} RTMPChunk;
// rtmp消息块
typedef struct RTMPPacket
{
// chunk basic header(大部分情况是一个字节)
// #define RTMP_PACKET_SIZE_LARGE 0 onMetaData流开始的绝对时间戳控制消息(如connect)
// #define RTMP_PACKET_SIZE_MEDIUM 1 大部分的rtmp header都是8字节的
// #define RTMP_PACKET_SIZE_SMALL 2 比较少见
// #define RTMP_PACKET_SIZE_MINIMUM 3 偶尔出现,低于8字节频率
// chunk type id (2bit)fmt 对应message head {0,3,7,11} + (6bit)chunk stream id
// 块类型ID,消息头的第1个字节的前2位,决定消息头长度
uint8_t m_headerType;
// Message type ID(1-7协议控制;8,9音视频;10以后为AMF编码消息)
uint8_t m_packetType;
// 是否含有Extend timeStamp字段
uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */
// channel 即 stream id字段
// 第一个字节的低6位,命名为Chunk Stream ID,Chunk Stream ID用来表示消息的级别:
// chunk stream id 级别
// 2 low level
// 3 high level(像connect, create_stream一类消息)
// 4 control stream
// 5 video
// 6 audio
// 8 control stream
int m_nChannel;
// 时间戳
uint32_t m_nTimeStamp; /* timestamp */
// message stream id
int32_t m_nInfoField2; /* last 4 bytes in a long header */
// chunk体的长度
uint32_t m_nBodySize;
uint32_t m_nBytesRead;
RTMPChunk *m_chunk; // 原始rtmp消息块
char *m_body;
} RTMPPacket;
typedef struct RTMPPacket
{
uint8_t m_headerType; //basic header 中的type头字节,值为(0,1,2,3)表示ChunkMsgHeader的类型(4种)
uint8_t m_packetType; //Chunk Msg Header中msg type 1字节:消息类型id(8: audio;9:video;18:AMF0编码的元数据)
uint8_t m_hasAbsTimestamp; //bool值,是否是绝对时间戳(类型1时为true)
int m_nChannel; //块流ID ,通过设置ChannelID来设置Basic stream id的长度和值
uint32_t m_nTimeStamp; //时间戳,消息头前三字节
int32_t m_nInfoField2; //Chunk Msg Header中msg StreamID 4字节:消息流id
uint32_t m_nBodySize; //Chunk Msg Header中msg length 4字节:消息长度
uint32_t m_nBytesRead; //已读取的数据
RTMPChunk *m_chunk; //raw chunk结构体指针,把RTMPPacket的真实头部和数据段拷贝进来
char *m_body; //数据段指针
} RTMPPacket;
1.7. RTMP_READ
内容来源于:https://blog.csdn.net/NB_vol_1/article/details/58660181
/*
** AVal表示一个字符串
*/
typedef struct AVal
{
char *av_val;
int av_len;
} AVal;
/* state for read() wrapper */
// read函数的包装器,包括状态等等
typedef struct RTMP_READ
{
char *buf;
char *bufpos;
unsigned int buflen;
uint32_t timestamp;
uint8_t dataType;
uint8_t flags;
#define RTMP_READ_HEADER 0x01
#define RTMP_READ_RESUME 0x02
#define RTMP_READ_NO_IGNORE 0x04
#define RTMP_READ_GOTKF 0x08
#define RTMP_READ_GOTFLVK 0x10
#define RTMP_READ_SEEKING 0x20
int8_t status;
#define RTMP_READ_COMPLETE -3
#define RTMP_READ_ERROR -2
#define RTMP_READ_EOF -1
#define RTMP_READ_IGNORE 0
/* if bResume == TRUE */
uint8_t initialFrameType;
uint32_t nResumeTS;
char *metaHeader;
char *initialFrame;
uint32_t nMetaHeaderSize;
uint32_t nInitialFrameSize;
uint32_t nIgnoredFrameCounter;
uint32_t nIgnoredFlvFrameCounter;
} RTMP_READ;