mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
fix #405, improve the HTTP FLV performance to 6k. 2.0.171
This commit is contained in:
parent
4df19ba99a
commit
d12fc7fcc5
13 changed files with 1193 additions and 922 deletions
|
@ -120,318 +120,6 @@ using namespace std;
|
|||
/****************************************************************************
|
||||
*****************************************************************************
|
||||
****************************************************************************/
|
||||
/**
|
||||
* the chunk stream id used for some under-layer message,
|
||||
* for example, the PC(protocol control) message.
|
||||
*/
|
||||
#define RTMP_CID_ProtocolControl 0x02
|
||||
/**
|
||||
* the AMF0/AMF3 command message, invoke method and return the result, over NetConnection.
|
||||
* generally use 0x03.
|
||||
*/
|
||||
#define RTMP_CID_OverConnection 0x03
|
||||
/**
|
||||
* the AMF0/AMF3 command message, invoke method and return the result, over NetConnection,
|
||||
* the midst state(we guess).
|
||||
* rarely used, e.g. onStatus(NetStream.Play.Reset).
|
||||
*/
|
||||
#define RTMP_CID_OverConnection2 0x04
|
||||
/**
|
||||
* the stream message(amf0/amf3), over NetStream.
|
||||
* generally use 0x05.
|
||||
*/
|
||||
#define RTMP_CID_OverStream 0x05
|
||||
/**
|
||||
* the stream message(amf0/amf3), over NetStream, the midst state(we guess).
|
||||
* rarely used, e.g. play("mp4:mystram.f4v")
|
||||
*/
|
||||
#define RTMP_CID_OverStream2 0x08
|
||||
/**
|
||||
* the stream message(video), over NetStream
|
||||
* generally use 0x06.
|
||||
*/
|
||||
#define RTMP_CID_Video 0x06
|
||||
/**
|
||||
* the stream message(audio), over NetStream.
|
||||
* generally use 0x07.
|
||||
*/
|
||||
#define RTMP_CID_Audio 0x07
|
||||
|
||||
/****************************************************************************
|
||||
*****************************************************************************
|
||||
****************************************************************************/
|
||||
|
||||
SrsMessageHeader::SrsMessageHeader()
|
||||
{
|
||||
message_type = 0;
|
||||
payload_length = 0;
|
||||
timestamp_delta = 0;
|
||||
stream_id = 0;
|
||||
|
||||
timestamp = 0;
|
||||
// we always use the connection chunk-id
|
||||
perfer_cid = RTMP_CID_OverConnection;
|
||||
}
|
||||
|
||||
SrsMessageHeader::~SrsMessageHeader()
|
||||
{
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_audio()
|
||||
{
|
||||
return message_type == RTMP_MSG_AudioMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_video()
|
||||
{
|
||||
return message_type == RTMP_MSG_VideoMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_amf0_command()
|
||||
{
|
||||
return message_type == RTMP_MSG_AMF0CommandMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_amf0_data()
|
||||
{
|
||||
return message_type == RTMP_MSG_AMF0DataMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_amf3_command()
|
||||
{
|
||||
return message_type == RTMP_MSG_AMF3CommandMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_amf3_data()
|
||||
{
|
||||
return message_type == RTMP_MSG_AMF3DataMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_window_ackledgement_size()
|
||||
{
|
||||
return message_type == RTMP_MSG_WindowAcknowledgementSize;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_ackledgement()
|
||||
{
|
||||
return message_type == RTMP_MSG_Acknowledgement;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_set_chunk_size()
|
||||
{
|
||||
return message_type == RTMP_MSG_SetChunkSize;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_user_control_message()
|
||||
{
|
||||
return message_type == RTMP_MSG_UserControlMessage;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_set_peer_bandwidth()
|
||||
{
|
||||
return message_type == RTMP_MSG_SetPeerBandwidth;
|
||||
}
|
||||
|
||||
bool SrsMessageHeader::is_aggregate()
|
||||
{
|
||||
return message_type == RTMP_MSG_AggregateMessage;
|
||||
}
|
||||
|
||||
void SrsMessageHeader::initialize_amf0_script(int size, int stream)
|
||||
{
|
||||
message_type = RTMP_MSG_AMF0DataMessage;
|
||||
payload_length = (int32_t)size;
|
||||
timestamp_delta = (int32_t)0;
|
||||
timestamp = (int64_t)0;
|
||||
stream_id = (int32_t)stream;
|
||||
|
||||
// amf0 script use connection2 chunk-id
|
||||
perfer_cid = RTMP_CID_OverConnection2;
|
||||
}
|
||||
|
||||
void SrsMessageHeader::initialize_audio(int size, u_int32_t time, int stream)
|
||||
{
|
||||
message_type = RTMP_MSG_AudioMessage;
|
||||
payload_length = (int32_t)size;
|
||||
timestamp_delta = (int32_t)time;
|
||||
timestamp = (int64_t)time;
|
||||
stream_id = (int32_t)stream;
|
||||
|
||||
// audio chunk-id
|
||||
perfer_cid = RTMP_CID_Audio;
|
||||
}
|
||||
|
||||
void SrsMessageHeader::initialize_video(int size, u_int32_t time, int stream)
|
||||
{
|
||||
message_type = RTMP_MSG_VideoMessage;
|
||||
payload_length = (int32_t)size;
|
||||
timestamp_delta = (int32_t)time;
|
||||
timestamp = (int64_t)time;
|
||||
stream_id = (int32_t)stream;
|
||||
|
||||
// video chunk-id
|
||||
perfer_cid = RTMP_CID_Video;
|
||||
}
|
||||
|
||||
SrsCommonMessage::SrsCommonMessage()
|
||||
{
|
||||
payload = NULL;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
SrsCommonMessage::~SrsCommonMessage()
|
||||
{
|
||||
srs_freep(payload);
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload()
|
||||
{
|
||||
payload = NULL;
|
||||
size = 0;
|
||||
shared_count = 0;
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload()
|
||||
{
|
||||
srs_freep(payload);
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage::SrsSharedPtrMessage()
|
||||
{
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage::~SrsSharedPtrMessage()
|
||||
{
|
||||
if (ptr) {
|
||||
if (ptr->shared_count == 0) {
|
||||
srs_freep(ptr);
|
||||
} else {
|
||||
ptr->shared_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SrsSharedPtrMessage::create(SrsCommonMessage* msg)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = create(&msg->header, msg->payload, msg->size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// to prevent double free of payload:
|
||||
// initialize already attach the payload of msg,
|
||||
// detach the payload to transfer the owner to shared ptr.
|
||||
msg->payload = NULL;
|
||||
msg->size = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsSharedPtrMessage::create(SrsMessageHeader* pheader, char* payload, int size)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (ptr) {
|
||||
ret = ERROR_SYSTEM_ASSERT_FAILED;
|
||||
srs_error("should not set the payload twice. ret=%d", ret);
|
||||
srs_assert(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ptr = new SrsSharedPtrPayload();
|
||||
|
||||
// direct attach the data.
|
||||
if (pheader) {
|
||||
ptr->header.message_type = pheader->message_type;
|
||||
ptr->header.payload_length = size;
|
||||
ptr->header.perfer_cid = pheader->perfer_cid;
|
||||
this->timestamp = pheader->timestamp;
|
||||
this->stream_id = pheader->stream_id;
|
||||
}
|
||||
ptr->payload = payload;
|
||||
ptr->size = size;
|
||||
|
||||
// message can access it.
|
||||
this->payload = ptr->payload;
|
||||
this->size = ptr->size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsSharedPtrMessage::count()
|
||||
{
|
||||
srs_assert(ptr);
|
||||
return ptr->shared_count;
|
||||
}
|
||||
|
||||
bool SrsSharedPtrMessage::check(int stream_id)
|
||||
{
|
||||
// we donot use the complex basic header,
|
||||
// ensure the basic header is 1bytes.
|
||||
if (ptr->header.perfer_cid < 2) {
|
||||
srs_info("change the chunk_id=%d to default=%d",
|
||||
ptr->header.perfer_cid, RTMP_CID_ProtocolControl);
|
||||
ptr->header.perfer_cid = RTMP_CID_ProtocolControl;
|
||||
}
|
||||
|
||||
// we assume that the stream_id in a group must be the same.
|
||||
if (this->stream_id == stream_id) {
|
||||
return true;
|
||||
}
|
||||
this->stream_id = stream_id;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SrsSharedPtrMessage::is_av()
|
||||
{
|
||||
return ptr->header.message_type == RTMP_MSG_AudioMessage
|
||||
|| ptr->header.message_type == RTMP_MSG_VideoMessage;
|
||||
}
|
||||
|
||||
bool SrsSharedPtrMessage::is_audio()
|
||||
{
|
||||
return ptr->header.message_type == RTMP_MSG_AudioMessage;
|
||||
}
|
||||
|
||||
bool SrsSharedPtrMessage::is_video()
|
||||
{
|
||||
return ptr->header.message_type == RTMP_MSG_VideoMessage;
|
||||
}
|
||||
|
||||
int SrsSharedPtrMessage::chunk_header(char* cache, int nb_cache, bool c0)
|
||||
{
|
||||
if (c0) {
|
||||
return srs_chunk_header_c0(
|
||||
ptr->header.perfer_cid, timestamp, ptr->header.payload_length,
|
||||
ptr->header.message_type, stream_id,
|
||||
cache, nb_cache);
|
||||
} else {
|
||||
return srs_chunk_header_c3(
|
||||
ptr->header.perfer_cid, timestamp,
|
||||
cache, nb_cache);
|
||||
}
|
||||
}
|
||||
|
||||
SrsSharedPtrMessage* SrsSharedPtrMessage::copy()
|
||||
{
|
||||
srs_assert(ptr);
|
||||
|
||||
SrsSharedPtrMessage* copy = new SrsSharedPtrMessage();
|
||||
|
||||
copy->ptr = ptr;
|
||||
ptr->shared_count++;
|
||||
|
||||
copy->timestamp = timestamp;
|
||||
copy->stream_id = stream_id;
|
||||
copy->payload = ptr->payload;
|
||||
copy->size = ptr->size;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
SrsPacket::SrsPacket()
|
||||
{
|
||||
|
@ -904,41 +592,7 @@ int SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msgs)
|
|||
|
||||
int SrsProtocol::do_iovs_send(iovec* iovs, int size)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// the limits of writev iovs.
|
||||
// for srs-librtmp, @see https://github.com/simple-rtmp-server/srs/issues/213
|
||||
#ifndef _WIN32
|
||||
static int limits = sysconf(_SC_IOV_MAX);
|
||||
#else
|
||||
static int limits = 1024;
|
||||
#endif
|
||||
|
||||
// send in a time.
|
||||
if (size < limits) {
|
||||
if ((ret = skt->writev(iovs, size, NULL)) != ERROR_SUCCESS) {
|
||||
if (!srs_is_client_gracefully_close(ret)) {
|
||||
srs_error("send with writev failed. ret=%d", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// send in multiple times.
|
||||
int cur_iov = 0;
|
||||
while (cur_iov < size) {
|
||||
int cur_count = srs_min(limits, size - cur_iov);
|
||||
if ((ret = skt->writev(iovs + cur_iov, cur_count, NULL)) != ERROR_SUCCESS) {
|
||||
if (!srs_is_client_gracefully_close(ret)) {
|
||||
srs_error("send with writev failed. ret=%d", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
cur_iov += cur_count;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return srs_write_large_iovs(skt, iovs, size);
|
||||
}
|
||||
|
||||
int SrsProtocol::do_send_and_free_packet(SrsPacket* packet, int stream_id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue