rtmp服务器性能要求,简洁rtmp源站服务器

本文详细介绍了SRSProtocol类中的recv_message和recv_interlaced_message函数,展示了如何处理RTMP消息的接收、基本头和消息头解析,以及缓存chunk流以提高效率。核心内容涉及数据包结构、错误处理和消息完整性检查。
摘要由CSDN通过智能技术生成

intSrsProtocol::recv_message(SrsMessage** pmsg)

{

*pmsg = NULL;

intret = ERROR_SUCCESS;

while(true) {

SrsMessage* msg = NULL;

if((ret = recv_interlaced_message(&msg)) != ERROR_SUCCESS) {

srs_error("recv interlaced message failed. ret=%d", ret);

returnret;

}

srs_verbose("entire msg received");

if(!msg) {

continue;

}

if(msg->size <= 0 || msg->header.payload_length <= 0) {

srs_trace("ignore empty message(type=%d, size=%d, time=%d, sid=%d).",

msg->header.message_type, msg->header.payload_length,

msg->header.timestamp, msg->header.stream_id);

deletemsg;

continue;

}

srs_verbose("get a msg with raw/undecoded payload");

*pmsg = msg;

break;

}

returnret;

}

intSrsProtocol::recv_interlaced_message(SrsMessage** pmsg)

{

intret = ERROR_SUCCESS;

// chunk stream basic header.

charfmt = 0;

intcid = 0;

intbh_size = 0;

if((ret = read_basic_header(fmt, cid, bh_size)) != ERROR_SUCCESS) {

srs_error("read basic header failed. ret=%d", ret);

returnret;

}

srs_info("read basic header success. fmt=%d, cid=%d, bh_size=%d", fmt, cid, bh_size);

// get the cached chunk stream.

SrsChunkStream* chunk = NULL;

if(chunk_streams.find(cid) == chunk_streams.end()) {

chunk = chunk_streams[cid] = newSrsChunkStream(cid);

srs_info("cache new chunk stream: fmt=%d, cid=%d", fmt, cid);

} else{

chunk = chunk_streams[cid];

srs_info("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",

chunk->fmt, chunk->cid, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, chunk->header.payload_length,

chunk->header.timestamp, chunk->header.stream_id);

}

// chunk stream message header

intmh_size = 0;

if((ret = read_message_header(chunk, fmt, bh_size, mh_size)) != ERROR_SUCCESS) {

srs_error("read message header failed. ret=%d", ret);

returnret;

}

srs_info("read message header success. "

"fmt=%d, mh_size=%d, ext_time=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",

fmt, mh_size, chunk->extended_timestamp, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type,

chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id);

// read msg payload from chunk stream.

SrsMessage* msg = NULL;

intpayload_size = 0;

if((ret = read_message_payload(chunk, bh_size, mh_size, payload_size, &msg)) != ERROR_SUCCESS) {

srs_error("read message payload failed. ret=%d", ret);

returnret;

}

// not got an entire RTMP message, try next chunk.

if(!msg) {

srs_info("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",

payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length,

chunk->header.timestamp, chunk->header.stream_id);

returnret;

}

*pmsg = msg;

srs_info("get entire message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%d, sid=%d)",

payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length,

chunk->header.timestamp, chunk->header.stream_id);

returnret;

}

intSrsProtocol::read_basic_header(char& fmt,int& cid,int& bh_size)

{

intret = ERROR_SUCCESS;

intrequired_size = 1;

if((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) {

srs_error("read 1bytes basic header failed. required_size=%d, ret=%d", required_size, ret);

returnret;

}

char* p = buffer->bytes();

fmt = (*p >> 6) & 0x03;

cid = *p & 0x3f;

bh_size = 1;

if(cid > 1) {

srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid);

returnret;

}

if(cid == 0) {

required_size = 2;

if((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) {

srs_error("read 2bytes basic header failed. required_size=%d, ret=%d", required_size, ret);

returnret;

}

cid = 64;

cid += *(++p);

bh_size = 2;

srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid);

} elseif(cid == 1) {

required_size = 3;

if((ret = buffer->ensure_buffer_bytes(skt, 3)) != ERROR_SUCCESS) {

srs_error("read 3bytes basic header failed. required_size=%d, ret=%d", required_size, ret);

returnret;

}

cid = 64;

cid += *(++p);

cid += *(++p) * 256;

bh_size = 3;

srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid);

} else{

srs_error("invalid path, impossible basic header.");

srs_assert(false);

}

returnret;

}

intSrsProtocol::read_message_header(SrsChunkStream* chunk,charfmt,intbh_size,int& mh_size)

{

intret = ERROR_SUCCESS;

// when not exists cached msg, means get an new message,

// the fmt must be type0 which means new message.

if(!chunk->msg && fmt != RTMP_FMT_TYPE0) {

ret = ERROR_RTMP_CHUNK_START;

srs_error("chunk stream start, "

"fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret);

returnret;

}

// when exists cache msg, means got an partial message,

// the fmt must not be type0 which means new message.

if(chunk->msg && fmt == RTMP_FMT_TYPE0) {

ret = ERROR_RTMP_CHUNK_START;

srs_error("chunk stream exists, "

"fmt must not be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret);

returnret;

}

// create msg when new chunk stream start

if(!chunk->msg) {

srs_assert(fmt == RTMP_FMT_TYPE0);

chunk->msg = newSrsMessage();

srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid);

}

// read message header from socket to buffer.

staticcharmh_sizes[] = {11, 7, 1, 0};

mh_size = mh_sizes[(int)fmt];

srs_verbose("calc chunk message header size. fmt=%d, mh_size=%d", fmt, mh_size);

intrequired_size = bh_size + mh_size;

if((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) {

srs_error("read %dbytes message header failed. required_size=%d, ret=%d", mh_size, required_size, ret);

returnret;

}

char* p = buffer->bytes() + bh_size;

// parse the message header.

// see also: ngx_rtmp_recv

if(fmt <= RTMP_FMT_TYPE2) {

int32_t timestamp_delta;

char* pp = (char*)×tamp_delta;

pp[2] = *p++;

pp[1] = *p++;

pp[0] = *p++;

pp[3] = 0;

if(fmt == RTMP_FMT_TYPE0) {

// 6.1.2.1. Type 0

// For a type-0 chunk, the absolute timestamp of the message is sent

// here.

chunk->header.timestamp = timestamp_delta;

} else{

// 6.1.2.2. Type 1

// 6.1.2.3. Type 2

// For a type-1 or type-2 chunk, the difference between the previous

// chunk's timestamp and the current chunk's timestamp is sent here.

chunk->header.timestamp += timestamp_delta;

}

// fmt: 0

// timestamp: 3 bytes

// If the timestamp is greater than or equal to 16777215

// (hexadecimal 0x00ffffff), this value MUST be 16777215, and the

// ‘extended timestamp header’ MUST be present. Otherwise, this value

// SHOULD be the entire timestamp.

//

// fmt: 1 or 2

// timestamp delta: 3 bytes

// If the delta is greater than or equal to 16777215 (hexadecimal

// 0x00ffffff), this value MUST be 16777215, and the ‘extended

// timestamp header’ MUST be present. Otherwise, this value SHOULD be

// the entire delta.

chunk->extended_timestamp = (timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);

if(chunk->extended_timestamp) {

chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP;

}

if(fmt <= RTMP_FMT_TYPE1) {

pp = (char*)&chunk->header.payload_length;

pp[2] = *p++;

pp[1] = *p++;

pp[0] = *p++;

pp[3] = 0;

chunk->header.message_type = *p++;

if(fmt == 0) {

pp = (char*)&chunk->header.stream_id;

pp[0] = *p++;

pp[1] = *p++;

pp[2] = *p++;

pp[3] = *p++;

srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%d, payload=%d, type=%d, sid=%d",

fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length,

chunk->header.message_type, chunk->header.stream_id);

} else{

srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%d, payload=%d, type=%d",

fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length,

chunk->header.message_type);

}

} else{

srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%d",

fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp);

}

} else{

srs_verbose("header read completed. fmt=%d, size=%d, ext_time=%d",

fmt, mh_size, chunk->extended_timestamp);

}

if(chunk->extended_timestamp) {

mh_size += 4;

required_size = bh_size + mh_size;

srs_verbose("read header ext time. fmt=%d, ext_time=%d, mh_size=%d", fmt, chunk->extended_timestamp, mh_size);

if((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) {

srs_error("read %dbytes message header failed. required_size=%d, ret=%d", mh_size, required_size, ret);

returnret;

}

char* pp = (char*)&chunk->header.timestamp;

pp[3] = *p++;

pp[2] = *p++;

pp[1] = *p++;

pp[0] = *p++;

srs_verbose("header read ext_time completed. time=%d", chunk->header.timestamp);

}

// valid message

if(chunk->header.payload_length 

ret = ERROR_RTMP_MSG_INVLIAD_SIZE;

srs_error("RTMP message size must not be negative. size=%d, ret=%d",

chunk->header.payload_length, ret);

returnret;

}

// copy header to msg

chunk->msg->header = chunk->header;

returnret;

}

intSrsProtocol::read_message_payload(SrsChunkStream* chunk,intbh_size,intmh_size,int& payload_size, SrsMessage** pmsg)

{

intret = ERROR_SUCCESS;

// empty message

if(chunk->header.payload_length == 0) {

// need erase the header in buffer.

buffer->erase(bh_size + mh_size);

srs_trace("get an empty RTMP "

"message(type=%d, size=%d, time=%d, sid=%d)", chunk->header.message_type,

chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id);

*pmsg = chunk->msg;

chunk->msg = NULL;

returnret;

}

srs_assert(chunk->header.payload_length > 0);

// the chunk payload size.

payload_size = chunk->header.payload_length - chunk->msg->size;

if(payload_size > in_chunk_size) {

payload_size = in_chunk_size;

}

srs_verbose("chunk payload size is %d, message_size=%d, received_size=%d, in_chunk_size=%d",

payload_size, chunk->header.payload_length, chunk->msg->size, in_chunk_size);

// create msg payload if not initialized

if(!chunk->msg->payload) {

chunk->msg->payload = newint8_t[chunk->header.payload_length];

memset(chunk->msg->payload, 0, chunk->header.payload_length);

srs_verbose("create empty payload for RTMP message. size=%d", chunk->header.payload_length);

}

// read payload to buffer

intrequired_size = bh_size + mh_size + payload_size;

if((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) {

srs_error("read payload failed. required_size=%d, ret=%d", required_size, ret);

returnret;

}

memcpy(chunk->msg->payload + chunk->msg->size, buffer->bytes() + bh_size + mh_size, payload_size);

buffer->erase(bh_size + mh_size + payload_size);

chunk->msg->size += payload_size;

srs_verbose("chunk payload read complted. bh_size=%d, mh_size=%d, payload_size=%d", bh_size, mh_size, payload_size);

// got entire RTMP message?

if(chunk->header.payload_length == chunk->msg->size) {

*pmsg = chunk->msg;

chunk->msg = NULL;

srs_verbose("get entire RTMP message(type=%d, size=%d, time=%d, sid=%d)",

chunk->header.message_type, chunk->header.payload_length,

chunk->header.timestamp, chunk->header.stream_id);

returnret;

}

srs_verbose("get partial RTMP message(type=%d, size=%d, time=%d, sid=%d), partial size=%d",

chunk->header.message_type, chunk->header.payload_length,

chunk->header.timestamp, chunk->header.stream_id,

chunk->msg->size);

returnret;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值