1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

substitute all TAB with 4spaces.

This commit is contained in:
winlin 2014-03-18 11:32:58 +08:00
parent e5770b10b1
commit c85dde7f3f
64 changed files with 14105 additions and 14105 deletions

View file

@ -45,28 +45,28 @@ SrsBandwidth::~SrsBandwidth()
int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServer* _rtmp) int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServer* _rtmp)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
rtmp = _rtmp; rtmp = _rtmp;
req = _req; req = _req;
if (!_srs_config->get_bw_check_enabled(req->vhost)) { if (!_srs_config->get_bw_check_enabled(req->vhost)) {
return ret; return ret;
} }
// validate the bandwidth check key // validate the bandwidth check key
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost); std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
if (req->tcUrl.find(key) == std::string::npos) { if (req->tcUrl.find(key) == std::string::npos) {
ret = ERROR_SYSTEM_BANDWIDTH_KEY; ret = ERROR_SYSTEM_BANDWIDTH_KEY;
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d", srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret); req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
return ret; return ret;
} }
// shared global last check time, // shared global last check time,
// to avoid attach by bandwidth check, // to avoid attach by bandwidth check,
// if client request check in the window(specifeid by interval), // if client request check in the window(specifeid by interval),
// directly reject the request. // directly reject the request.
static int64_t last_check_time = 0; static int64_t last_check_time = 0;
int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost); int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost);
@ -75,15 +75,15 @@ int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServe
if (last_check_time > 0 && time_now - last_check_time < interval_ms) { if (last_check_time > 0 && time_now - last_check_time < interval_ms) {
ret = ERROR_SYSTEM_BANDWIDTH_DENIED; ret = ERROR_SYSTEM_BANDWIDTH_DENIED;
srs_trace("bandcheck denied, " srs_trace("bandcheck denied, "
"last_check=%"PRId64", now=%"PRId64", interval=%d", "last_check=%"PRId64", now=%"PRId64", interval=%d",
last_check_time, time_now, interval_ms); last_check_time, time_now, interval_ms);
rtmp->response_connect_reject(req, "bandcheck rejected"); rtmp->response_connect_reject(req, "bandcheck rejected");
return ret; return ret;
} }
// accept and do bandwidth check. // accept and do bandwidth check.
last_check_time = time_now; last_check_time = time_now;
char* local_ip = 0; char* local_ip = 0;
if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) { if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) {
@ -137,7 +137,7 @@ int SrsBandwidth::do_bandwidth_check()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsProtocol* protocol = rtmp->get_protocol(); SrsProtocol* protocol = rtmp->get_protocol();
int play_duration_ms = 3000; int play_duration_ms = 3000;
int play_interval_ms = 0; int play_interval_ms = 0;
@ -154,14 +154,14 @@ int SrsBandwidth::do_bandwidth_check()
int64_t start_time = srs_get_system_time_ms(); int64_t start_time = srs_get_system_time_ms();
ret = check_play(play_duration_ms, ret = check_play(play_duration_ms,
play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps); play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps);
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
srs_error("band width play check failed. ret=%d", ret); srs_error("band width play check failed. ret=%d", ret);
return ret; return ret;
} }
ret = check_publish(publish_duration_ms, ret = check_publish(publish_duration_ms,
publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps); publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps);
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
srs_error("band width publish check failed. ret=%d", ret); srs_error("band width publish check failed. ret=%d", ret);
return ret; return ret;
@ -188,29 +188,29 @@ int SrsBandwidth::do_bandwidth_check()
pkt->data->set("publish_bytes", SrsAmf0Any::number(publish_bytes)); pkt->data->set("publish_bytes", SrsAmf0Any::number(publish_bytes));
pkt->data->set("publish_time", SrsAmf0Any::number(publish_actual_duration_ms)); pkt->data->set("publish_time", SrsAmf0Any::number(publish_actual_duration_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check finish message failed. ret=%d", ret); srs_error("send bandwidth check finish message failed. ret=%d", ret);
return ret; return ret;
} }
// if flash, we notice the result, and expect a final packet. // if flash, we notice the result, and expect a final packet.
while (true) { while (true) {
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL; SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
// info level to ignore and return success. // info level to ignore and return success.
srs_info("expect final message failed. ret=%d", ret); srs_info("expect final message failed. ret=%d", ret);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
SrsAutoFree(SrsCommonMessage, msg, false); SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get final message success."); srs_info("get final message success.");
if (pkt->is_flash_final()) { if (pkt->is_flash_final()) {
srs_info("BW check recv flash final response."); srs_info("BW check recv flash final response.");
break; break;
} }
} }
srs_info("BW check finished."); srs_info("BW check finished.");
@ -218,44 +218,44 @@ int SrsBandwidth::do_bandwidth_check()
} }
int SrsBandwidth::check_play( int SrsBandwidth::check_play(
int duration_ms, int interval_ms, int& actual_duration_ms, int duration_ms, int interval_ms, int& actual_duration_ms,
int& play_bytes, int max_play_kbps) int& play_bytes, int max_play_kbps)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsProtocol* protocol = rtmp->get_protocol(); SrsProtocol* protocol = rtmp->get_protocol();
if (true) { if (true) {
// send start play command to client // send start play command to client
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play(); SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check start play message failed. ret=%d", ret); srs_error("send bandwidth check start play message failed. ret=%d", ret);
return ret; return ret;
} }
srs_info("BW check begin."); srs_info("BW check begin.");
} }
while (true) { while (true) {
// recv client's starting play response // recv client's starting play response
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL; SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret); srs_error("expect bandwidth message failed. ret=%d", ret);
return ret; return ret;
} }
SrsAutoFree(SrsCommonMessage, msg, false); SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes."); srs_info("get bandwidth message succes.");
if (pkt->is_starting_play()) { if (pkt->is_starting_play()) {
srs_info("BW check recv play begin response."); srs_info("BW check recv play begin response.");
break; break;
} }
} }
// send play data to client // send play data to client
int64_t current_time = srs_get_system_time_ms(); int64_t current_time = srs_get_system_time_ms();
@ -280,10 +280,10 @@ int SrsBandwidth::check_play(
} }
data_count += 2; data_count += 2;
// TODO: FIXME: get length from the rtmp protocol stack. // TODO: FIXME: get length from the rtmp protocol stack.
play_bytes += pkt->get_payload_length(); play_bytes += pkt->get_payload_length();
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check play messages failed. ret=%d", ret); srs_error("send bandwidth check play messages failed. ret=%d", ret);
return ret; return ret;
@ -305,81 +305,81 @@ int SrsBandwidth::check_play(
actual_duration_ms = srs_get_system_time_ms() - current_time; actual_duration_ms = srs_get_system_time_ms() - current_time;
srs_info("BW check send play bytes over."); srs_info("BW check send play bytes over.");
if (true) { if (true) {
// notify client to stop play // notify client to stop play
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play(); SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms)); pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes)); pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check stop play message failed. ret=%d", ret); srs_error("send bandwidth check stop play message failed. ret=%d", ret);
return ret; return ret;
} }
srs_info("BW check stop play bytes."); srs_info("BW check stop play bytes.");
} }
while (true) { while (true) {
// recv client's stop play response. // recv client's stop play response.
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL; SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret); srs_error("expect bandwidth message failed. ret=%d", ret);
return ret; return ret;
} }
SrsAutoFree(SrsCommonMessage, msg, false); SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes."); srs_info("get bandwidth message succes.");
if (pkt->is_stopped_play()) { if (pkt->is_stopped_play()) {
srs_info("BW check recv stop play response."); srs_info("BW check recv stop play response.");
break; break;
} }
} }
return ret; return ret;
} }
int SrsBandwidth::check_publish( int SrsBandwidth::check_publish(
int duration_ms, int interval_ms, int& actual_duration_ms, int duration_ms, int interval_ms, int& actual_duration_ms,
int& publish_bytes, int max_pub_kbps) int& publish_bytes, int max_pub_kbps)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsProtocol* protocol = rtmp->get_protocol(); SrsProtocol* protocol = rtmp->get_protocol();
if (true) { if (true) {
// notify client to start publish // notify client to start publish
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish(); SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check start publish message failed. ret=%d", ret); srs_error("send bandwidth check start publish message failed. ret=%d", ret);
return ret; return ret;
} }
srs_info("BW check publish begin."); srs_info("BW check publish begin.");
} }
while (true) { while (true) {
// read client's notification of starting publish // read client's notification of starting publish
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL; SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret); srs_error("expect bandwidth message failed. ret=%d", ret);
return ret; return ret;
} }
SrsAutoFree(SrsCommonMessage, msg, false); SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes."); srs_info("get bandwidth message succes.");
if (pkt->is_starting_publish()) { if (pkt->is_starting_publish()) {
srs_info("BW check recv publish begin response."); srs_info("BW check recv publish begin response.");
break; break;
} }
} }
// recv publish msgs until @duration_ms ms // recv publish msgs until @duration_ms ms
int64_t current_time = srs_get_system_time_ms(); int64_t current_time = srs_get_system_time_ms();
@ -393,7 +393,7 @@ int SrsBandwidth::check_publish(
} }
SrsAutoFree(SrsCommonMessage, msg, false); SrsAutoFree(SrsCommonMessage, msg, false);
// TODO: FIXME. // TODO: FIXME.
publish_bytes += msg->header.payload_length; publish_bytes += msg->header.payload_length;
int kbps = 0; int kbps = 0;
@ -411,21 +411,21 @@ int SrsBandwidth::check_publish(
actual_duration_ms = srs_get_system_time_ms() - current_time; actual_duration_ms = srs_get_system_time_ms() - current_time;
srs_info("BW check recv publish data over."); srs_info("BW check recv publish data over.");
if (true) { if (true) {
// notify client to stop publish // notify client to stop publish
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish(); SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms)); pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes)); pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes));
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send bandwidth check stop publish message failed. ret=%d", ret); srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
return ret; return ret;
} }
srs_info("BW check stop publish bytes."); srs_info("BW check stop publish bytes.");
} }
// expect client to stop publish // expect client to stop publish
// if flash client, we never expect the client stop publish bytes, // if flash client, we never expect the client stop publish bytes,
@ -433,22 +433,22 @@ int SrsBandwidth::check_publish(
// there are many many packets in the queue. // there are many many packets in the queue.
// we just ignore the packet and send the bandwidth test data. // we just ignore the packet and send the bandwidth test data.
// TODO: FIXME: check whether flash client. // TODO: FIXME: check whether flash client.
while (false) { while (false) {
// recv client's stop publish response. // recv client's stop publish response.
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
SrsBandwidthPacket* pkt = NULL; SrsBandwidthPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("expect bandwidth message failed. ret=%d", ret); srs_error("expect bandwidth message failed. ret=%d", ret);
return ret; return ret;
} }
SrsAutoFree(SrsCommonMessage, msg, false); SrsAutoFree(SrsCommonMessage, msg, false);
srs_info("get bandwidth message succes."); srs_info("get bandwidth message succes.");
if (pkt->is_stopped_publish()) { if (pkt->is_stopped_publish()) {
srs_info("BW check recv stop publish response."); srs_info("BW check recv stop publish response.");
break; break;
} }
} }
return ret; return ret;
} }

File diff suppressed because it is too large Load diff

View file

@ -53,43 +53,43 @@ class SrsBandwidth;
class SrsClient : public SrsConnection, public ISrsReloadHandler class SrsClient : public SrsConnection, public ISrsReloadHandler
{ {
private: private:
char* ip; char* ip;
SrsRequest* req; SrsRequest* req;
SrsResponse* res; SrsResponse* res;
SrsSocket* skt; SrsSocket* skt;
SrsRtmpServer* rtmp; SrsRtmpServer* rtmp;
SrsRefer* refer; SrsRefer* refer;
#ifdef SRS_HTTP_CALLBACK #ifdef SRS_HTTP_CALLBACK
SrsHttpHooks* http_hooks; SrsHttpHooks* http_hooks;
#endif #endif
SrsBandwidth* bandwidth; SrsBandwidth* bandwidth;
public: public:
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd); SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsClient(); virtual ~SrsClient();
protected: protected:
virtual int do_cycle(); virtual int do_cycle();
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual int on_reload_vhost_removed(std::string vhost); virtual int on_reload_vhost_removed(std::string vhost);
private: private:
// when valid and connected to vhost/app, service the client. // when valid and connected to vhost/app, service the client.
virtual int service_cycle(); virtual int service_cycle();
// stream(play/publish) service cycle, identify client first. // stream(play/publish) service cycle, identify client first.
virtual int stream_service_cycle(); virtual int stream_service_cycle();
virtual int check_vhost(); virtual int check_vhost();
virtual int playing(SrsSource* source); virtual int playing(SrsSource* source);
virtual int fmle_publish(SrsSource* source); virtual int fmle_publish(SrsSource* source);
virtual int flash_publish(SrsSource* source); virtual int flash_publish(SrsSource* source);
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg); virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
virtual int get_peer_ip(); virtual int get_peer_ip();
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
private: private:
virtual int on_connect(); virtual int on_connect();
virtual void on_close(); virtual void on_close();
virtual int on_publish(); virtual int on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
virtual int on_play(); virtual int on_play();
virtual void on_stop(); virtual void on_stop();
}; };
#endif #endif

View file

@ -33,29 +33,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsCodecBuffer::SrsCodecBuffer() SrsCodecBuffer::SrsCodecBuffer()
{ {
size = 0; size = 0;
bytes = NULL; bytes = NULL;
} }
void SrsCodecBuffer::append(void* data, int len) void SrsCodecBuffer::append(void* data, int len)
{ {
srs_assert(data); srs_assert(data);
srs_assert(len > 0); srs_assert(len > 0);
bytes = (char*)realloc(bytes, size + len); bytes = (char*)realloc(bytes, size + len);
memcpy(bytes + size, data, len); memcpy(bytes + size, data, len);
size += len; size += len;
} }
void SrsCodecBuffer::free() void SrsCodecBuffer::free()
{ {
size = 0; size = 0;
srs_freepa(bytes); srs_freepa(bytes);
} }
SrsCodecSample::SrsCodecSample() SrsCodecSample::SrsCodecSample()
{ {
clear(); clear();
} }
SrsCodecSample::~SrsCodecSample() SrsCodecSample::~SrsCodecSample()
@ -64,468 +64,468 @@ SrsCodecSample::~SrsCodecSample()
void SrsCodecSample::clear() void SrsCodecSample::clear()
{ {
is_video = false; is_video = false;
nb_buffers = 0; nb_buffers = 0;
cts = 0; cts = 0;
frame_type = SrsCodecVideoAVCFrameReserved; frame_type = SrsCodecVideoAVCFrameReserved;
avc_packet_type = SrsCodecVideoAVCTypeReserved; avc_packet_type = SrsCodecVideoAVCTypeReserved;
sound_rate = SrsCodecAudioSampleRateReserved; sound_rate = SrsCodecAudioSampleRateReserved;
sound_size = SrsCodecAudioSampleSizeReserved; sound_size = SrsCodecAudioSampleSizeReserved;
sound_type = SrsCodecAudioSoundTypeReserved; sound_type = SrsCodecAudioSoundTypeReserved;
aac_packet_type = SrsCodecAudioTypeReserved; aac_packet_type = SrsCodecAudioTypeReserved;
} }
int SrsCodecSample::add_sample(char* bytes, int size) int SrsCodecSample::add_sample(char* bytes, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) { if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode samples error, " srs_error("hls decode samples error, "
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret); "exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
return ret; return ret;
} }
SrsCodecBuffer* buf = &buffers[nb_buffers++]; SrsCodecBuffer* buf = &buffers[nb_buffers++];
buf->bytes = bytes; buf->bytes = bytes;
buf->size = size; buf->size = size;
return ret; return ret;
} }
SrsCodec::SrsCodec() SrsCodec::SrsCodec()
{ {
width = 0; width = 0;
height = 0; height = 0;
duration = 0; duration = 0;
NAL_unit_length = 0; NAL_unit_length = 0;
frame_rate = 0; frame_rate = 0;
video_data_rate = 0; video_data_rate = 0;
video_codec_id = 0; video_codec_id = 0;
audio_data_rate = 0; audio_data_rate = 0;
audio_codec_id = 0; audio_codec_id = 0;
avc_profile = 0; avc_profile = 0;
avc_level = 0; avc_level = 0;
aac_profile = 0; aac_profile = 0;
aac_sample_rate = 0; aac_sample_rate = 0;
aac_channels = 0; aac_channels = 0;
avc_extra_size = 0; avc_extra_size = 0;
avc_extra_data = NULL; avc_extra_data = NULL;
aac_extra_size = 0; aac_extra_size = 0;
aac_extra_data = NULL; aac_extra_data = NULL;
sequenceParameterSetLength = 0; sequenceParameterSetLength = 0;
sequenceParameterSetNALUnit = NULL; sequenceParameterSetNALUnit = NULL;
pictureParameterSetLength = 0; pictureParameterSetLength = 0;
pictureParameterSetNALUnit = NULL; pictureParameterSetNALUnit = NULL;
stream = new SrsStream(); stream = new SrsStream();
} }
SrsCodec::~SrsCodec() SrsCodec::~SrsCodec()
{ {
srs_freepa(avc_extra_data); srs_freepa(avc_extra_data);
srs_freepa(aac_extra_data); srs_freepa(aac_extra_data);
srs_freep(stream); srs_freep(stream);
srs_freepa(sequenceParameterSetNALUnit); srs_freepa(sequenceParameterSetNALUnit);
srs_freepa(pictureParameterSetNALUnit); srs_freepa(pictureParameterSetNALUnit);
} }
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
sample->is_video = false; sample->is_video = false;
if (!data || size <= 0) { if (!data || size <= 0) {
srs_trace("no audio present, hls ignore it."); srs_trace("no audio present, hls ignore it.");
return ret; return ret;
} }
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret; return ret;
} }
// audio decode // audio decode
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio sound_format failed. ret=%d", ret); srs_error("hls decode audio sound_format failed. ret=%d", ret);
return ret; return ret;
} }
int8_t sound_format = stream->read_1bytes(); int8_t sound_format = stream->read_1bytes();
int8_t sound_type = sound_format & 0x01; int8_t sound_type = sound_format & 0x01;
int8_t sound_size = (sound_format >> 1) & 0x01; int8_t sound_size = (sound_format >> 1) & 0x01;
int8_t sound_rate = (sound_format >> 2) & 0x03; int8_t sound_rate = (sound_format >> 2) & 0x03;
sound_format = (sound_format >> 4) & 0x0f; sound_format = (sound_format >> 4) & 0x0f;
audio_codec_id = sound_format; audio_codec_id = sound_format;
sample->sound_type = (SrsCodecAudioSoundType)sound_type; sample->sound_type = (SrsCodecAudioSoundType)sound_type;
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
sample->sound_size = (SrsCodecAudioSampleSize)sound_size; sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
// reset the sample rate by sequence header // reset the sample rate by sequence header
static int aac_sample_rates[] = { static int aac_sample_rates[] = {
96000, 88200, 64000, 48000, 96000, 88200, 64000, 48000,
44100, 32000, 24000, 22050, 44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000, 16000, 12000, 11025, 8000,
7350, 0, 0, 0 7350, 0, 0, 0
}; };
switch (aac_sample_rates[aac_sample_rate]) { switch (aac_sample_rates[aac_sample_rate]) {
case 11025: case 11025:
sample->sound_rate = SrsCodecAudioSampleRate11025; sample->sound_rate = SrsCodecAudioSampleRate11025;
break; break;
case 22050: case 22050:
sample->sound_rate = SrsCodecAudioSampleRate22050; sample->sound_rate = SrsCodecAudioSampleRate22050;
break; break;
case 44100: case 44100:
sample->sound_rate = SrsCodecAudioSampleRate44100; sample->sound_rate = SrsCodecAudioSampleRate44100;
break; break;
}; };
// only support aac // only support aac
if (audio_codec_id != SrsCodecAudioAAC) { if (audio_codec_id != SrsCodecAudioAAC) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support audio aac codec. ret=%d", ret); srs_error("hls only support audio aac codec. ret=%d", ret);
return ret; return ret;
} }
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret); srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
return ret; return ret;
} }
int8_t aac_packet_type = stream->read_1bytes(); int8_t aac_packet_type = stream->read_1bytes();
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type; sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) { if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
// AudioSpecificConfig // AudioSpecificConfig
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
aac_extra_size = stream->left(); aac_extra_size = stream->left();
if (aac_extra_size > 0) { if (aac_extra_size > 0) {
srs_freepa(aac_extra_data); srs_freepa(aac_extra_data);
aac_extra_data = new char[aac_extra_size]; aac_extra_data = new char[aac_extra_size];
memcpy(aac_extra_data, stream->current(), aac_extra_size); memcpy(aac_extra_data, stream->current(), aac_extra_size);
} }
// only need to decode the first 2bytes: // only need to decode the first 2bytes:
// audioObjectType, aac_profile, 5bits. // audioObjectType, aac_profile, 5bits.
// samplingFrequencyIndex, aac_sample_rate, 4bits. // samplingFrequencyIndex, aac_sample_rate, 4bits.
// channelConfiguration, aac_channels, 4bits // channelConfiguration, aac_channels, 4bits
if (!stream->require(2)) { if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed. ret=%d", ret); srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
return ret; return ret;
} }
aac_profile = stream->read_1bytes(); aac_profile = stream->read_1bytes();
aac_sample_rate = stream->read_1bytes(); aac_sample_rate = stream->read_1bytes();
aac_channels = (aac_sample_rate >> 3) & 0x0f; aac_channels = (aac_sample_rate >> 3) & 0x0f;
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
aac_profile = (aac_profile >> 3) & 0x1f; aac_profile = (aac_profile >> 3) & 0x1f;
if (aac_profile == 0 || aac_profile == 0x1f) { if (aac_profile == 0 || aac_profile == 0x1f) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed, " srs_error("hls decode audio aac sequence header failed, "
"adts object=%d invalid. ret=%d", aac_profile, ret); "adts object=%d invalid. ret=%d", aac_profile, ret);
return ret; return ret;
} }
// aac_profile = audioObjectType - 1 // aac_profile = audioObjectType - 1
aac_profile--; aac_profile--;
if (aac_profile > 3) { if (aac_profile > 3) {
// Mark all extended profiles as LC // Mark all extended profiles as LC
// to make Android as happy as possible. // to make Android as happy as possible.
// @see: ngx_rtmp_hls_parse_aac_header // @see: ngx_rtmp_hls_parse_aac_header
aac_profile = 1; aac_profile = 1;
} }
} else if (aac_packet_type == SrsCodecAudioTypeRawData) { } else if (aac_packet_type == SrsCodecAudioTypeRawData) {
// ensure the sequence header demuxed // ensure the sequence header demuxed
if (aac_extra_size <= 0 || !aac_extra_data) { if (aac_extra_size <= 0 || !aac_extra_data) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret); srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
return ret; return ret;
} }
// Raw AAC frame data in UI8 [] // Raw AAC frame data in UI8 []
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) { if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
srs_error("hls add audio sample failed. ret=%d", ret); srs_error("hls add audio sample failed. ret=%d", ret);
return ret; return ret;
} }
} else { } else {
// ignored. // ignored.
} }
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size); sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
return ret; return ret;
} }
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
sample->is_video = true; sample->is_video = true;
if (!data || size <= 0) { if (!data || size <= 0) {
srs_trace("no video present, hls ignore it."); srs_trace("no video present, hls ignore it.");
return ret; return ret;
} }
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret; return ret;
} }
// video decode // video decode
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video frame_type failed. ret=%d", ret); srs_error("hls decode video frame_type failed. ret=%d", ret);
return ret; return ret;
} }
int8_t frame_type = stream->read_1bytes(); int8_t frame_type = stream->read_1bytes();
int8_t codec_id = frame_type & 0x0f; int8_t codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f; frame_type = (frame_type >> 4) & 0x0f;
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
// only support h.264/avc // only support h.264/avc
if (codec_id != SrsCodecVideoAVC) { if (codec_id != SrsCodecVideoAVC) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support video h.264/avc codec. ret=%d", ret); srs_error("hls only support video h.264/avc codec. ret=%d", ret);
return ret; return ret;
} }
video_codec_id = codec_id; video_codec_id = codec_id;
if (!stream->require(4)) { if (!stream->require(4)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc_packet_type failed. ret=%d", ret); srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
return ret; return ret;
} }
int8_t avc_packet_type = stream->read_1bytes(); int8_t avc_packet_type = stream->read_1bytes();
int32_t composition_time = stream->read_3bytes(); int32_t composition_time = stream->read_3bytes();
// pts = dts + cts. // pts = dts + cts.
sample->cts = composition_time; sample->cts = composition_time;
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
// AVCDecoderConfigurationRecord // AVCDecoderConfigurationRecord
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
avc_extra_size = stream->left(); avc_extra_size = stream->left();
if (avc_extra_size > 0) { if (avc_extra_size > 0) {
srs_freepa(avc_extra_data); srs_freepa(avc_extra_data);
avc_extra_data = new char[avc_extra_size]; avc_extra_data = new char[avc_extra_size];
memcpy(avc_extra_data, stream->current(), avc_extra_size); memcpy(avc_extra_data, stream->current(), avc_extra_size);
} }
if (!stream->require(6)) { if (!stream->require(6)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header failed. ret=%d", ret); srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
return ret; return ret;
} }
//int8_t configurationVersion = stream->read_1bytes(); //int8_t configurationVersion = stream->read_1bytes();
//int8_t AVCProfileIndication = stream->read_1bytes(); //int8_t AVCProfileIndication = stream->read_1bytes();
//int8_t profile_compatibility = stream->read_1bytes(); //int8_t profile_compatibility = stream->read_1bytes();
//int8_t AVCLevelIndication = stream->read_1bytes(); //int8_t AVCLevelIndication = stream->read_1bytes();
stream->skip(4); stream->skip(4);
// parse the NALU size. // parse the NALU size.
int8_t lengthSizeMinusOne = stream->read_1bytes(); int8_t lengthSizeMinusOne = stream->read_1bytes();
lengthSizeMinusOne &= 0x03; lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne; NAL_unit_length = lengthSizeMinusOne;
// 1 sps // 1 sps
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret; return ret;
} }
int8_t numOfSequenceParameterSets = stream->read_1bytes(); int8_t numOfSequenceParameterSets = stream->read_1bytes();
numOfSequenceParameterSets &= 0x1f; numOfSequenceParameterSets &= 0x1f;
if (numOfSequenceParameterSets != 1) { if (numOfSequenceParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret; return ret;
} }
if (!stream->require(2)) { if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
return ret; return ret;
} }
sequenceParameterSetLength = stream->read_2bytes(); sequenceParameterSetLength = stream->read_2bytes();
if (!stream->require(sequenceParameterSetLength)) { if (!stream->require(sequenceParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
return ret; return ret;
} }
if (sequenceParameterSetLength > 0) { if (sequenceParameterSetLength > 0) {
srs_freepa(sequenceParameterSetNALUnit); srs_freepa(sequenceParameterSetNALUnit);
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength); memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
stream->skip(sequenceParameterSetLength); stream->skip(sequenceParameterSetLength);
} }
// 1 pps // 1 pps
if (!stream->require(1)) { if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret; return ret;
} }
int8_t numOfPictureParameterSets = stream->read_1bytes(); int8_t numOfPictureParameterSets = stream->read_1bytes();
numOfPictureParameterSets &= 0x1f; numOfPictureParameterSets &= 0x1f;
if (numOfPictureParameterSets != 1) { if (numOfPictureParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret; return ret;
} }
if (!stream->require(2)) { if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
return ret; return ret;
} }
pictureParameterSetLength = stream->read_2bytes(); pictureParameterSetLength = stream->read_2bytes();
if (!stream->require(pictureParameterSetLength)) { if (!stream->require(pictureParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
return ret; return ret;
} }
if (pictureParameterSetLength > 0) { if (pictureParameterSetLength > 0) {
srs_freepa(pictureParameterSetNALUnit); srs_freepa(pictureParameterSetNALUnit);
pictureParameterSetNALUnit = new char[pictureParameterSetLength]; pictureParameterSetNALUnit = new char[pictureParameterSetLength];
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength); memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
stream->skip(pictureParameterSetLength); stream->skip(pictureParameterSetLength);
} }
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
// ensure the sequence header demuxed // ensure the sequence header demuxed
if (avc_extra_size <= 0 || !avc_extra_data) { if (avc_extra_size <= 0 || !avc_extra_data) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret); srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
return ret; return ret;
} }
// One or more NALUs (Full frames are required) // One or more NALUs (Full frames are required)
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
int PictureLength = stream->left(); int PictureLength = stream->left();
for (int i = 0; i < PictureLength;) { for (int i = 0; i < PictureLength;) {
if (!stream->require(NAL_unit_length + 1)) { if (!stream->require(NAL_unit_length + 1)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU size failed. ret=%d", ret); srs_error("hls decode video avc NALU size failed. ret=%d", ret);
return ret; return ret;
} }
int32_t NALUnitLength = 0; int32_t NALUnitLength = 0;
if (NAL_unit_length == 3) { if (NAL_unit_length == 3) {
NALUnitLength = stream->read_4bytes(); NALUnitLength = stream->read_4bytes();
} else if (NALUnitLength == 2) { } else if (NALUnitLength == 2) {
NALUnitLength = stream->read_3bytes(); NALUnitLength = stream->read_3bytes();
} else if (NALUnitLength == 1) { } else if (NALUnitLength == 1) {
NALUnitLength = stream->read_2bytes(); NALUnitLength = stream->read_2bytes();
} else { } else {
NALUnitLength = stream->read_1bytes(); NALUnitLength = stream->read_1bytes();
} }
// NALUnit // NALUnit
if (!stream->require(NALUnitLength)) { if (!stream->require(NALUnitLength)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU data failed. ret=%d", ret); srs_error("hls decode video avc NALU data failed. ret=%d", ret);
return ret; return ret;
} }
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) { if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
srs_error("hls add video sample failed. ret=%d", ret); srs_error("hls add video sample failed. ret=%d", ret);
return ret; return ret;
} }
stream->skip(NALUnitLength); stream->skip(NALUnitLength);
i += NAL_unit_length + 1 + NALUnitLength; i += NAL_unit_length + 1 + NALUnitLength;
} }
} else { } else {
// ignored. // ignored.
} }
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d", srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
frame_type, video_codec_id, avc_packet_type, composition_time, size); frame_type, video_codec_id, avc_packet_type, composition_time, size);
return ret; return ret;
} }
bool SrsCodec::video_is_keyframe(int8_t* data, int size) bool SrsCodec::video_is_keyframe(int8_t* data, int size)
{ {
// 2bytes required. // 2bytes required.
if (size < 1) { if (size < 1) {
return false; return false;
} }
char frame_type = *(char*)data; char frame_type = *(char*)data;
frame_type = (frame_type >> 4) & 0x0F; frame_type = (frame_type >> 4) & 0x0F;
return frame_type == SrsCodecVideoAVCFrameKeyFrame; return frame_type == SrsCodecVideoAVCFrameKeyFrame;
} }
bool SrsCodec::video_is_sequence_header(int8_t* data, int size) bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
{ {
// sequence header only for h264 // sequence header only for h264
if (!video_is_h264(data, size)) { if (!video_is_h264(data, size)) {
return false; return false;
} }
// 2bytes required. // 2bytes required.
if (size < 2) { if (size < 2) {
return false; return false;
} }
char frame_type = *(char*)data; char frame_type = *(char*)data;
frame_type = (frame_type >> 4) & 0x0F; frame_type = (frame_type >> 4) & 0x0F;
char avc_packet_type = *(char*)(data + 1); char avc_packet_type = *(char*)(data + 1);
return frame_type == SrsCodecVideoAVCFrameKeyFrame return frame_type == SrsCodecVideoAVCFrameKeyFrame
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader; && avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
} }
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size) bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
{ {
// sequence header only for aac // sequence header only for aac
if (!audio_is_aac(data, size)) { if (!audio_is_aac(data, size)) {
return false; return false;
} }
// 2bytes required. // 2bytes required.
if (size < 2) { if (size < 2) {
return false; return false;
} }
char aac_packet_type = *(char*)(data + 1); char aac_packet_type = *(char*)(data + 1);
return aac_packet_type == SrsCodecAudioTypeSequenceHeader; return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
} }
bool SrsCodec::video_is_h264(int8_t* data, int size) bool SrsCodec::video_is_h264(int8_t* data, int size)
{ {
// 1bytes required. // 1bytes required.
if (size < 1) { if (size < 1) {
return false; return false;
} }
char codec_id = *(char*)data; char codec_id = *(char*)data;
codec_id = codec_id & 0x0F; codec_id = codec_id & 0x0F;
return codec_id == SrsCodecVideoAVC; return codec_id == SrsCodecVideoAVC;
} }
bool SrsCodec::audio_is_aac(int8_t* data, int size) bool SrsCodec::audio_is_aac(int8_t* data, int size)
{ {
// 1bytes required. // 1bytes required.
if (size < 1) { if (size < 1) {
return false; return false;
} }
char sound_format = *(char*)data; char sound_format = *(char*)data;
sound_format = (sound_format >> 4) & 0x0F; sound_format = (sound_format >> 4) & 0x0F;
return sound_format == SrsCodecAudioAAC; return sound_format == SrsCodecAudioAAC;
} }

View file

@ -37,104 +37,104 @@ class SrsStream;
// E.4.3.1 VIDEODATA // E.4.3.1 VIDEODATA
// CodecID UB [4] // CodecID UB [4]
// Codec Identifier. The following values are defined: // Codec Identifier. The following values are defined:
// 2 = Sorenson H.263 // 2 = Sorenson H.263
// 3 = Screen video // 3 = Screen video
// 4 = On2 VP6 // 4 = On2 VP6
// 5 = On2 VP6 with alpha channel // 5 = On2 VP6 with alpha channel
// 6 = Screen video version 2 // 6 = Screen video version 2
// 7 = AVC // 7 = AVC
enum SrsCodecVideo enum SrsCodecVideo
{ {
SrsCodecVideoReserved = 0, SrsCodecVideoReserved = 0,
SrsCodecVideoSorensonH263 = 2, SrsCodecVideoSorensonH263 = 2,
SrsCodecVideoScreenVideo = 3, SrsCodecVideoScreenVideo = 3,
SrsCodecVideoOn2VP6 = 4, SrsCodecVideoOn2VP6 = 4,
SrsCodecVideoOn2VP6WithAlphaChannel = 5, SrsCodecVideoOn2VP6WithAlphaChannel = 5,
SrsCodecVideoScreenVideoVersion2 = 6, SrsCodecVideoScreenVideoVersion2 = 6,
SrsCodecVideoAVC = 7, SrsCodecVideoAVC = 7,
}; };
// E.4.3.1 VIDEODATA // E.4.3.1 VIDEODATA
// Frame Type UB [4] // Frame Type UB [4]
// Type of video frame. The following values are defined: // Type of video frame. The following values are defined:
// 1 = key frame (for AVC, a seekable frame) // 1 = key frame (for AVC, a seekable frame)
// 2 = inter frame (for AVC, a non-seekable frame) // 2 = inter frame (for AVC, a non-seekable frame)
// 3 = disposable inter frame (H.263 only) // 3 = disposable inter frame (H.263 only)
// 4 = generated key frame (reserved for server use only) // 4 = generated key frame (reserved for server use only)
// 5 = video info/command frame // 5 = video info/command frame
enum SrsCodecVideoAVCFrame enum SrsCodecVideoAVCFrame
{ {
SrsCodecVideoAVCFrameReserved = 0, SrsCodecVideoAVCFrameReserved = 0,
SrsCodecVideoAVCFrameKeyFrame = 1, SrsCodecVideoAVCFrameKeyFrame = 1,
SrsCodecVideoAVCFrameInterFrame = 2, SrsCodecVideoAVCFrameInterFrame = 2,
SrsCodecVideoAVCFrameDisposableInterFrame = 3, SrsCodecVideoAVCFrameDisposableInterFrame = 3,
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4, SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
SrsCodecVideoAVCFrameVideoInfoFrame = 5, SrsCodecVideoAVCFrameVideoInfoFrame = 5,
}; };
// AVCPacketType IF CodecID == 7 UI8 // AVCPacketType IF CodecID == 7 UI8
// The following values are defined: // The following values are defined:
// 0 = AVC sequence header // 0 = AVC sequence header
// 1 = AVC NALU // 1 = AVC NALU
// 2 = AVC end of sequence (lower level NALU sequence ender is // 2 = AVC end of sequence (lower level NALU sequence ender is
// not required or supported) // not required or supported)
enum SrsCodecVideoAVCType enum SrsCodecVideoAVCType
{ {
SrsCodecVideoAVCTypeReserved = -1, SrsCodecVideoAVCTypeReserved = -1,
SrsCodecVideoAVCTypeSequenceHeader = 0, SrsCodecVideoAVCTypeSequenceHeader = 0,
SrsCodecVideoAVCTypeNALU = 1, SrsCodecVideoAVCTypeNALU = 1,
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
}; };
// SoundFormat UB [4] // SoundFormat UB [4]
// Format of SoundData. The following values are defined: // Format of SoundData. The following values are defined:
// 0 = Linear PCM, platform endian // 0 = Linear PCM, platform endian
// 1 = ADPCM // 1 = ADPCM
// 2 = MP3 // 2 = MP3
// 3 = Linear PCM, little endian // 3 = Linear PCM, little endian
// 4 = Nellymoser 16 kHz mono // 4 = Nellymoser 16 kHz mono
// 5 = Nellymoser 8 kHz mono // 5 = Nellymoser 8 kHz mono
// 6 = Nellymoser // 6 = Nellymoser
// 7 = G.711 A-law logarithmic PCM // 7 = G.711 A-law logarithmic PCM
// 8 = G.711 mu-law logarithmic PCM // 8 = G.711 mu-law logarithmic PCM
// 9 = reserved // 9 = reserved
// 10 = AAC // 10 = AAC
// 11 = Speex // 11 = Speex
// 14 = MP3 8 kHz // 14 = MP3 8 kHz
// 15 = Device-specific sound // 15 = Device-specific sound
// Formats 7, 8, 14, and 15 are reserved. // Formats 7, 8, 14, and 15 are reserved.
// AAC is supported in Flash Player 9,0,115,0 and higher. // AAC is supported in Flash Player 9,0,115,0 and higher.
// Speex is supported in Flash Player 10 and higher. // Speex is supported in Flash Player 10 and higher.
enum SrsCodecAudio enum SrsCodecAudio
{ {
SrsCodecAudioLinearPCMPlatformEndian = 0, SrsCodecAudioLinearPCMPlatformEndian = 0,
SrsCodecAudioADPCM = 1, SrsCodecAudioADPCM = 1,
SrsCodecAudioMP3 = 2, SrsCodecAudioMP3 = 2,
SrsCodecAudioLinearPCMLittleEndian = 3, SrsCodecAudioLinearPCMLittleEndian = 3,
SrsCodecAudioNellymoser16kHzMono = 4, SrsCodecAudioNellymoser16kHzMono = 4,
SrsCodecAudioNellymoser8kHzMono = 5, SrsCodecAudioNellymoser8kHzMono = 5,
SrsCodecAudioNellymoser = 6, SrsCodecAudioNellymoser = 6,
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7, SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8, SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
SrsCodecAudioReserved = 9, SrsCodecAudioReserved = 9,
SrsCodecAudioAAC = 10, SrsCodecAudioAAC = 10,
SrsCodecAudioSpeex = 11, SrsCodecAudioSpeex = 11,
SrsCodecAudioReservedMP3_8kHz = 14, SrsCodecAudioReservedMP3_8kHz = 14,
SrsCodecAudioReservedDeviceSpecificSound = 15, SrsCodecAudioReservedDeviceSpecificSound = 15,
}; };
// AACPacketType IF SoundFormat == 10 UI8 // AACPacketType IF SoundFormat == 10 UI8
// The following values are defined: // The following values are defined:
// 0 = AAC sequence header // 0 = AAC sequence header
// 1 = AAC raw // 1 = AAC raw
enum SrsCodecAudioType enum SrsCodecAudioType
{ {
SrsCodecAudioTypeReserved = -1, SrsCodecAudioTypeReserved = -1,
SrsCodecAudioTypeSequenceHeader = 0, SrsCodecAudioTypeSequenceHeader = 0,
SrsCodecAudioTypeRawData = 1, SrsCodecAudioTypeRawData = 1,
}; };
// Sampling rate. The following values are defined: // Sampling rate. The following values are defined:
@ -144,12 +144,12 @@ enum SrsCodecAudioType
// 3 = 44 kHz = 44100 Hz // 3 = 44 kHz = 44100 Hz
enum SrsCodecAudioSampleRate enum SrsCodecAudioSampleRate
{ {
SrsCodecAudioSampleRateReserved = -1, SrsCodecAudioSampleRateReserved = -1,
SrsCodecAudioSampleRate5512 = 0, SrsCodecAudioSampleRate5512 = 0,
SrsCodecAudioSampleRate11025 = 1, SrsCodecAudioSampleRate11025 = 1,
SrsCodecAudioSampleRate22050 = 2, SrsCodecAudioSampleRate22050 = 2,
SrsCodecAudioSampleRate44100 = 3, SrsCodecAudioSampleRate44100 = 3,
}; };
// Size of each audio sample. This parameter only pertains to // Size of each audio sample. This parameter only pertains to
@ -159,10 +159,10 @@ enum SrsCodecAudioSampleRate
// 1 = 16-bit samples // 1 = 16-bit samples
enum SrsCodecAudioSampleSize enum SrsCodecAudioSampleSize
{ {
SrsCodecAudioSampleSizeReserved = -1, SrsCodecAudioSampleSizeReserved = -1,
SrsCodecAudioSampleSize8bit = 0, SrsCodecAudioSampleSize8bit = 0,
SrsCodecAudioSampleSize16bit = 1, SrsCodecAudioSampleSize16bit = 1,
}; };
// Mono or stereo sound // Mono or stereo sound
@ -170,10 +170,10 @@ enum SrsCodecAudioSampleSize
// 1 = Stereo sound // 1 = Stereo sound
enum SrsCodecAudioSoundType enum SrsCodecAudioSoundType
{ {
SrsCodecAudioSoundTypeReserved = -1, SrsCodecAudioSoundTypeReserved = -1,
SrsCodecAudioSoundTypeMono = 0, SrsCodecAudioSoundTypeMono = 0,
SrsCodecAudioSoundTypeStereo = 1, SrsCodecAudioSoundTypeStereo = 1,
}; };
/** /**
@ -181,21 +181,21 @@ enum SrsCodecAudioSoundType
*/ */
struct SrsCodecBuffer struct SrsCodecBuffer
{ {
/** /**
* @remark user must manage the bytes. * @remark user must manage the bytes.
*/ */
int size; int size;
char* bytes; char* bytes;
SrsCodecBuffer(); SrsCodecBuffer();
void append(void* data, int len); void append(void* data, int len);
/** /**
* free the bytes, * free the bytes,
* user can invoke it to free the bytes, * user can invoke it to free the bytes,
* the SrsCodecBuffer never free automatically. * the SrsCodecBuffer never free automatically.
*/ */
void free(); void free();
}; };
/** /**
@ -204,26 +204,26 @@ struct SrsCodecBuffer
class SrsCodecSample class SrsCodecSample
{ {
public: public:
int nb_buffers; int nb_buffers;
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
public: public:
bool is_video; bool is_video;
// video specified // video specified
SrsCodecVideoAVCFrame frame_type; SrsCodecVideoAVCFrame frame_type;
SrsCodecVideoAVCType avc_packet_type; SrsCodecVideoAVCType avc_packet_type;
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78. // CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
// cts = pts - dts, where dts = flvheader->timestamp. // cts = pts - dts, where dts = flvheader->timestamp.
int32_t cts; int32_t cts;
// audio specified // audio specified
SrsCodecAudioSampleRate sound_rate; SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size; SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type; SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type; SrsCodecAudioType aac_packet_type;
public: public:
SrsCodecSample(); SrsCodecSample();
virtual ~SrsCodecSample(); virtual ~SrsCodecSample();
void clear(); void clear();
int add_sample(char* bytes, int size); int add_sample(char* bytes, int size);
}; };
/** /**
@ -232,81 +232,81 @@ public:
class SrsCodec class SrsCodec
{ {
private: private:
SrsStream* stream; SrsStream* stream;
public: public:
/** /**
* video specified * video specified
*/ */
// @see: SrsCodecVideo // @see: SrsCodecVideo
int video_codec_id; int video_codec_id;
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_profile; u_int8_t avc_profile;
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_level; u_int8_t avc_level;
int width; int width;
int height; int height;
int video_data_rate; // in bps int video_data_rate; // in bps
int frame_rate; int frame_rate;
int duration; int duration;
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 // lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
int8_t NAL_unit_length; int8_t NAL_unit_length;
u_int16_t sequenceParameterSetLength; u_int16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit; char* sequenceParameterSetNALUnit;
u_int16_t pictureParameterSetLength; u_int16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit; char* pictureParameterSetNALUnit;
/** /**
* audio specified * audio specified
*/ */
// @see: SrsCodecAudioType // @see: SrsCodecAudioType
int audio_codec_id; int audio_codec_id;
int audio_data_rate; // in bps int audio_data_rate; // in bps
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40. // audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
u_int8_t aac_profile; u_int8_t aac_profile;
// samplingFrequencyIndex // samplingFrequencyIndex
u_int8_t aac_sample_rate; u_int8_t aac_sample_rate;
// channelConfiguration // channelConfiguration
u_int8_t aac_channels; u_int8_t aac_channels;
// the avc extra data, the AVC sequence header, // the avc extra data, the AVC sequence header,
// without the flv codec header, // without the flv codec header,
// @see: ffmpeg, AVCodecContext::extradata // @see: ffmpeg, AVCodecContext::extradata
int avc_extra_size; int avc_extra_size;
char* avc_extra_data; char* avc_extra_data;
// the aac extra data, the AAC sequence header, // the aac extra data, the AAC sequence header,
// without the flv codec header, // without the flv codec header,
// @see: ffmpeg, AVCodecContext::extradata // @see: ffmpeg, AVCodecContext::extradata
int aac_extra_size; int aac_extra_size;
char* aac_extra_data; char* aac_extra_data;
public: public:
SrsCodec(); SrsCodec();
virtual ~SrsCodec(); virtual ~SrsCodec();
// the following function used for hls to build the codec info. // the following function used for hls to build the codec info.
public: public:
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample); virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample); virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
// the following function used to finger out the flv/rtmp packet detail. // the following function used to finger out the flv/rtmp packet detail.
public: public:
/** /**
* only check the frame_type, not check the codec type. * only check the frame_type, not check the codec type.
*/ */
static bool video_is_keyframe(int8_t* data, int size); static bool video_is_keyframe(int8_t* data, int size);
/** /**
* check codec h264, keyframe, sequence header * check codec h264, keyframe, sequence header
*/ */
static bool video_is_sequence_header(int8_t* data, int size); static bool video_is_sequence_header(int8_t* data, int size);
/** /**
* check codec aac, sequence header * check codec aac, sequence header
*/ */
static bool audio_is_sequence_header(int8_t* data, int size); static bool audio_is_sequence_header(int8_t* data, int size);
/** /**
* check codec h264. * check codec h264.
*/ */
static bool video_is_h264(int8_t* data, int size); static bool video_is_h264(int8_t* data, int size);
private: private:
/** /**
* check codec aac. * check codec aac.
*/ */
static bool audio_is_aac(int8_t* data, int size); static bool audio_is_aac(int8_t* data, int size);
}; };
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -66,25 +66,25 @@ class SrsFileBuffer;
class SrsConfDirective class SrsConfDirective
{ {
public: public:
int conf_line; int conf_line;
std::string name; std::string name;
std::vector<std::string> args; std::vector<std::string> args;
std::vector<SrsConfDirective*> directives; std::vector<SrsConfDirective*> directives;
public: public:
SrsConfDirective(); SrsConfDirective();
virtual ~SrsConfDirective(); virtual ~SrsConfDirective();
std::string arg0(); std::string arg0();
std::string arg1(); std::string arg1();
std::string arg2(); std::string arg2();
SrsConfDirective* at(int index); SrsConfDirective* at(int index);
SrsConfDirective* get(std::string _name); SrsConfDirective* get(std::string _name);
SrsConfDirective* get(std::string _name, std::string _arg0); SrsConfDirective* get(std::string _name, std::string _arg0);
public: public:
virtual int parse(const char* filename); virtual int parse(const char* filename);
public: public:
enum SrsDirectiveType{parse_file, parse_block}; enum SrsDirectiveType{parse_file, parse_block};
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type); virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args); virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
}; };
/** /**
@ -97,81 +97,81 @@ public:
class SrsConfig class SrsConfig
{ {
private: private:
bool show_help; bool show_help;
bool show_version; bool show_version;
std::string config_file; std::string config_file;
SrsConfDirective* root; SrsConfDirective* root;
std::vector<ISrsReloadHandler*> subscribes; std::vector<ISrsReloadHandler*> subscribes;
public: public:
SrsConfig(); SrsConfig();
virtual ~SrsConfig(); virtual ~SrsConfig();
public: public:
virtual int reload(); virtual int reload();
virtual void subscribe(ISrsReloadHandler* handler); virtual void subscribe(ISrsReloadHandler* handler);
virtual void unsubscribe(ISrsReloadHandler* handler); virtual void unsubscribe(ISrsReloadHandler* handler);
public: public:
virtual int parse_options(int argc, char** argv); virtual int parse_options(int argc, char** argv);
private: private:
virtual int parse_file(const char* filename); virtual int parse_file(const char* filename);
virtual int parse_argv(int& i, char** argv); virtual int parse_argv(int& i, char** argv);
virtual void print_help(char** argv); virtual void print_help(char** argv);
public: public:
virtual SrsConfDirective* get_vhost(std::string vhost); virtual SrsConfDirective* get_vhost(std::string vhost);
virtual bool get_vhost_enabled(std::string vhost); virtual bool get_vhost_enabled(std::string vhost);
virtual bool get_vhost_enabled(SrsConfDirective* vhost); virtual bool get_vhost_enabled(SrsConfDirective* vhost);
virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); virtual SrsConfDirective* get_vhost_on_connect(std::string vhost);
virtual SrsConfDirective* get_vhost_on_close(std::string vhost); virtual SrsConfDirective* get_vhost_on_close(std::string vhost);
virtual SrsConfDirective* get_vhost_on_publish(std::string vhost); virtual SrsConfDirective* get_vhost_on_publish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);
virtual SrsConfDirective* get_vhost_on_play(std::string vhost); virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
virtual bool get_transcode_enabled(SrsConfDirective* transcode); virtual bool get_transcode_enabled(SrsConfDirective* transcode);
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines); virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
virtual bool get_engine_enabled(SrsConfDirective* engine); virtual bool get_engine_enabled(SrsConfDirective* engine);
virtual std::string get_engine_vcodec(SrsConfDirective* engine); virtual std::string get_engine_vcodec(SrsConfDirective* engine);
virtual int get_engine_vbitrate(SrsConfDirective* engine); virtual int get_engine_vbitrate(SrsConfDirective* engine);
virtual double get_engine_vfps(SrsConfDirective* engine); virtual double get_engine_vfps(SrsConfDirective* engine);
virtual int get_engine_vwidth(SrsConfDirective* engine); virtual int get_engine_vwidth(SrsConfDirective* engine);
virtual int get_engine_vheight(SrsConfDirective* engine); virtual int get_engine_vheight(SrsConfDirective* engine);
virtual int get_engine_vthreads(SrsConfDirective* engine); virtual int get_engine_vthreads(SrsConfDirective* engine);
virtual std::string get_engine_vprofile(SrsConfDirective* engine); virtual std::string get_engine_vprofile(SrsConfDirective* engine);
virtual std::string get_engine_vpreset(SrsConfDirective* engine); virtual std::string get_engine_vpreset(SrsConfDirective* engine);
virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams); virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams);
virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter); virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
virtual std::string get_engine_acodec(SrsConfDirective* engine); virtual std::string get_engine_acodec(SrsConfDirective* engine);
virtual int get_engine_abitrate(SrsConfDirective* engine); virtual int get_engine_abitrate(SrsConfDirective* engine);
virtual int get_engine_asample_rate(SrsConfDirective* engine); virtual int get_engine_asample_rate(SrsConfDirective* engine);
virtual int get_engine_achannels(SrsConfDirective* engine); virtual int get_engine_achannels(SrsConfDirective* engine);
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams); virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
virtual std::string get_engine_output(SrsConfDirective* engine); virtual std::string get_engine_output(SrsConfDirective* engine);
virtual std::string get_log_dir(); virtual std::string get_log_dir();
virtual int get_max_connections(); virtual int get_max_connections();
virtual bool get_gop_cache(std::string vhost); virtual bool get_gop_cache(std::string vhost);
virtual double get_queue_length(std::string vhost); virtual double get_queue_length(std::string vhost);
virtual SrsConfDirective* get_forward(std::string vhost); virtual SrsConfDirective* get_forward(std::string vhost);
private: private:
virtual SrsConfDirective* get_hls(std::string vhost); virtual SrsConfDirective* get_hls(std::string vhost);
public: public:
virtual bool get_hls_enabled(std::string vhost); virtual bool get_hls_enabled(std::string vhost);
virtual std::string get_hls_path(std::string vhost); virtual std::string get_hls_path(std::string vhost);
virtual double get_hls_fragment(std::string vhost); virtual double get_hls_fragment(std::string vhost);
virtual double get_hls_window(std::string vhost); virtual double get_hls_window(std::string vhost);
virtual SrsConfDirective* get_refer(std::string vhost); virtual SrsConfDirective* get_refer(std::string vhost);
virtual SrsConfDirective* get_refer_play(std::string vhost); virtual SrsConfDirective* get_refer_play(std::string vhost);
virtual SrsConfDirective* get_refer_publish(std::string vhost); virtual SrsConfDirective* get_refer_publish(std::string vhost);
virtual SrsConfDirective* get_listen(); virtual SrsConfDirective* get_listen();
virtual int get_chunk_size(const std::string& vhost); virtual int get_chunk_size(const std::string& vhost);
virtual int get_pithy_print_publish(); virtual int get_pithy_print_publish();
virtual int get_pithy_print_forwarder(); virtual int get_pithy_print_forwarder();
virtual int get_pithy_print_encoder(); virtual int get_pithy_print_encoder();
virtual int get_pithy_print_hls(); virtual int get_pithy_print_hls();
virtual int get_pithy_print_play(); virtual int get_pithy_print_play();
virtual bool get_bw_check_enabled(const std::string& vhost); virtual bool get_bw_check_enabled(const std::string& vhost);
virtual std::string get_bw_check_key(const std::string& vhost); virtual std::string get_bw_check_key(const std::string& vhost);
virtual int get_bw_check_interval_ms(const std::string& vhost); virtual int get_bw_check_interval_ms(const std::string& vhost);
virtual int get_bw_check_limit_kbps(const std::string& vhost); virtual int get_bw_check_limit_kbps(const std::string& vhost);
}; };
/** /**

View file

@ -29,19 +29,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd)
{ {
server = srs_server; server = srs_server;
stfd = client_stfd; stfd = client_stfd;
connection_id = 0; connection_id = 0;
} }
SrsConnection::~SrsConnection() SrsConnection::~SrsConnection()
{ {
srs_close_stfd(stfd); srs_close_stfd(stfd);
} }
int SrsConnection::start() int SrsConnection::start()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (st_thread_create(cycle_thread, this, 0, 0) == NULL) { if (st_thread_create(cycle_thread, this, 0, 0) == NULL) {
ret = ERROR_ST_CREATE_CYCLE_THREAD; ret = ERROR_ST_CREATE_CYCLE_THREAD;
@ -50,43 +50,43 @@ int SrsConnection::start()
} }
srs_verbose("create st conn cycle thread success."); srs_verbose("create st conn cycle thread success.");
return ret; return ret;
} }
void SrsConnection::cycle() void SrsConnection::cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
_srs_context->generate_id(); _srs_context->generate_id();
connection_id = _srs_context->get_id(); connection_id = _srs_context->get_id();
ret = do_cycle(); ret = do_cycle();
// if socket io error, set to closed. // if socket io error, set to closed.
if (srs_is_client_gracefully_close(ret)) { if (srs_is_client_gracefully_close(ret)) {
ret = ERROR_SOCKET_CLOSED; ret = ERROR_SOCKET_CLOSED;
} }
// success. // success.
if (ret == ERROR_SUCCESS) { if (ret == ERROR_SUCCESS) {
srs_trace("client process normally finished. ret=%d", ret); srs_trace("client process normally finished. ret=%d", ret);
} }
// client close peer. // client close peer.
if (ret == ERROR_SOCKET_CLOSED) { if (ret == ERROR_SOCKET_CLOSED) {
srs_warn("client disconnect peer. ret=%d", ret); srs_warn("client disconnect peer. ret=%d", ret);
} }
server->remove(this); server->remove(this);
} }
void* SrsConnection::cycle_thread(void* arg) void* SrsConnection::cycle_thread(void* arg)
{ {
SrsConnection* conn = (SrsConnection*)arg; SrsConnection* conn = (SrsConnection*)arg;
srs_assert(conn != NULL); srs_assert(conn != NULL);
conn->cycle(); conn->cycle();
return NULL; return NULL;
} }

View file

@ -36,19 +36,19 @@ class SrsServer;
class SrsConnection class SrsConnection
{ {
protected: protected:
SrsServer* server; SrsServer* server;
st_netfd_t stfd; st_netfd_t stfd;
int connection_id; int connection_id;
public: public:
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd); SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsConnection(); virtual ~SrsConnection();
public: public:
virtual int start(); virtual int start();
protected: protected:
virtual int do_cycle() = 0; virtual int do_cycle() = 0;
private: private:
virtual void cycle(); virtual void cycle();
static void* cycle_thread(void* arg); static void* cycle_thread(void* arg);
}; };
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -47,38 +47,38 @@ class SrsPithyPrint;
class SrsFFMPEG class SrsFFMPEG
{ {
private: private:
bool started; bool started;
pid_t pid; pid_t pid;
private: private:
std::string log_file; std::string log_file;
int log_fd; int log_fd;
private: private:
std::string ffmpeg; std::string ffmpeg;
std::vector<std::string> vfilter; std::vector<std::string> vfilter;
std::string vcodec; std::string vcodec;
int vbitrate; int vbitrate;
double vfps; double vfps;
int vwidth; int vwidth;
int vheight; int vheight;
int vthreads; int vthreads;
std::string vprofile; std::string vprofile;
std::string vpreset; std::string vpreset;
std::vector<std::string> vparams; std::vector<std::string> vparams;
std::string acodec; std::string acodec;
int abitrate; int abitrate;
int asample_rate; int asample_rate;
int achannels; int achannels;
std::vector<std::string> aparams; std::vector<std::string> aparams;
std::string output; std::string output;
std::string input; std::string input;
public: public:
SrsFFMPEG(std::string ffmpeg_bin); SrsFFMPEG(std::string ffmpeg_bin);
virtual ~SrsFFMPEG(); virtual ~SrsFFMPEG();
public: public:
virtual int initialize(SrsRequest* req, SrsConfDirective* engine); virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
virtual int start(); virtual int start();
virtual int cycle(); virtual int cycle();
virtual void stop(); virtual void stop();
}; };
/** /**
@ -88,26 +88,26 @@ public:
class SrsEncoder : public ISrsThreadHandler class SrsEncoder : public ISrsThreadHandler
{ {
private: private:
std::vector<SrsFFMPEG*> ffmpegs; std::vector<SrsFFMPEG*> ffmpegs;
private: private:
SrsThread* pthread; SrsThread* pthread;
SrsPithyPrint* pithy_print; SrsPithyPrint* pithy_print;
public: public:
SrsEncoder(); SrsEncoder();
virtual ~SrsEncoder(); virtual ~SrsEncoder();
public: public:
virtual int on_publish(SrsRequest* req); virtual int on_publish(SrsRequest* req);
virtual void on_unpublish(); virtual void on_unpublish();
// interface ISrsThreadHandler. // interface ISrsThreadHandler.
public: public:
virtual int cycle(); virtual int cycle();
virtual void on_leave_loop(); virtual void on_leave_loop();
private: private:
virtual void clear_engines(); virtual void clear_engines();
virtual SrsFFMPEG* at(int index); virtual SrsFFMPEG* at(int index);
virtual int parse_scope_engines(SrsRequest* req); virtual int parse_scope_engines(SrsRequest* req);
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
virtual void encoder(); virtual void encoder();
}; };
#endif #endif

View file

@ -42,203 +42,203 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsForwarder::SrsForwarder(SrsSource* _source) SrsForwarder::SrsForwarder(SrsSource* _source)
{ {
source = _source; source = _source;
io = NULL; io = NULL;
client = NULL; client = NULL;
stfd = NULL; stfd = NULL;
stream_id = 0; stream_id = 0;
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US); pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
queue = new SrsMessageQueue(); queue = new SrsMessageQueue();
jitter = new SrsRtmpJitter(); jitter = new SrsRtmpJitter();
} }
SrsForwarder::~SrsForwarder() SrsForwarder::~SrsForwarder()
{ {
on_unpublish(); on_unpublish();
srs_freep(pthread); srs_freep(pthread);
srs_freep(queue); srs_freep(queue);
srs_freep(jitter); srs_freep(jitter);
} }
void SrsForwarder::set_queue_size(double queue_size) void SrsForwarder::set_queue_size(double queue_size)
{ {
queue->set_queue_size(queue_size); queue->set_queue_size(queue_size);
} }
int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// forward app // forward app
app = req->app; app = req->app;
stream_name = req->stream; stream_name = req->stream;
server = forward_server; server = forward_server;
std::string s_port = RTMP_DEFAULT_PORT; std::string s_port = RTMP_DEFAULT_PORT;
port = ::atoi(RTMP_DEFAULT_PORT); port = ::atoi(RTMP_DEFAULT_PORT);
size_t pos = forward_server.find(":"); size_t pos = forward_server.find(":");
if (pos != std::string::npos) { if (pos != std::string::npos) {
s_port = forward_server.substr(pos + 1); s_port = forward_server.substr(pos + 1);
server = forward_server.substr(0, pos); server = forward_server.substr(0, pos);
} }
// discovery vhost // discovery vhost
std::string vhost = req->vhost; std::string vhost = req->vhost;
srs_vhost_resolve(vhost, s_port); srs_vhost_resolve(vhost, s_port);
port = ::atoi(s_port.c_str()); port = ::atoi(s_port.c_str());
// generate tcUrl // generate tcUrl
tc_url = "rtmp://"; tc_url = "rtmp://";
tc_url += vhost; tc_url += vhost;
tc_url += "/"; tc_url += "/";
tc_url += req->app; tc_url += req->app;
// dead loop check // dead loop check
std::string source_ep = req->vhost; std::string source_ep = req->vhost;
source_ep += ":"; source_ep += ":";
source_ep += req->port; source_ep += req->port;
std::string dest_ep = vhost; std::string dest_ep = vhost;
dest_ep += ":"; dest_ep += ":";
dest_ep += s_port; dest_ep += s_port;
if (source_ep == dest_ep) { if (source_ep == dest_ep) {
ret = ERROR_SYSTEM_FORWARD_LOOP; ret = ERROR_SYSTEM_FORWARD_LOOP;
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d", srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
source_ep.c_str(), dest_ep.c_str(), ret); source_ep.c_str(), dest_ep.c_str(), ret);
return ret; return ret;
} }
srs_trace("start forward %s to %s, stream: %s/%s", srs_trace("start forward %s to %s, stream: %s/%s",
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
stream_name.c_str()); stream_name.c_str());
if ((ret = pthread->start()) != ERROR_SUCCESS) { if ((ret = pthread->start()) != ERROR_SUCCESS) {
srs_error("start srs thread failed. ret=%d", ret); srs_error("start srs thread failed. ret=%d", ret);
return ret; return ret;
} }
return ret; return ret;
} }
void SrsForwarder::on_unpublish() void SrsForwarder::on_unpublish()
{ {
pthread->stop(); pthread->stop();
close_underlayer_socket(); close_underlayer_socket();
srs_freep(client); srs_freep(client);
srs_freep(io); srs_freep(io);
} }
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) { if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
srs_freep(metadata); srs_freep(metadata);
return ret; return ret;
} }
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) { if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
srs_freep(msg); srs_freep(msg);
return ret; return ret;
} }
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int SrsForwarder::on_video(SrsSharedPtrMessage* msg) int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
srs_freep(msg); srs_freep(msg);
return ret; return ret;
} }
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int SrsForwarder::cycle() int SrsForwarder::cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = connect_server()) != ERROR_SUCCESS) { if ((ret = connect_server()) != ERROR_SUCCESS) {
return ret; return ret;
} }
srs_assert(client); srs_assert(client);
client->set_recv_timeout(SRS_RECV_TIMEOUT_US); client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
client->set_send_timeout(SRS_SEND_TIMEOUT_US); client->set_send_timeout(SRS_SEND_TIMEOUT_US);
if ((ret = client->handshake()) != ERROR_SUCCESS) { if ((ret = client->handshake()) != ERROR_SUCCESS) {
srs_error("handshake with server failed. ret=%d", ret); srs_error("handshake with server failed. ret=%d", ret);
return ret; return ret;
} }
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
return ret; return ret;
} }
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
return ret; return ret;
} }
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
stream_name.c_str(), stream_id, ret); stream_name.c_str(), stream_id, ret);
return ret; return ret;
} }
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) { if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
srs_error("callback the source to feed the sequence header failed. ret=%d", ret); srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
return ret; return ret;
} }
if ((ret = forward()) != ERROR_SUCCESS) { if ((ret = forward()) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
void SrsForwarder::close_underlayer_socket() void SrsForwarder::close_underlayer_socket()
{ {
srs_close_stfd(stfd); srs_close_stfd(stfd);
} }
int SrsForwarder::connect_server() int SrsForwarder::connect_server()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// reopen // reopen
close_underlayer_socket(); close_underlayer_socket();
// open socket. // open socket.
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
stream_name.c_str(), tc_url.c_str(), server.c_str(), port); stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
int sock = socket(AF_INET, SOCK_STREAM, 0); int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){ if(sock == -1){
@ -255,19 +255,19 @@ int SrsForwarder::connect_server()
return ret; return ret;
} }
srs_freep(client); srs_freep(client);
srs_freep(io); srs_freep(io);
io = new SrsSocket(stfd); io = new SrsSocket(stfd);
client = new SrsRtmpClient(io); client = new SrsRtmpClient(io);
// connect to server. // connect to server.
std::string ip = srs_dns_resolve(server); std::string ip = srs_dns_resolve(server);
if (ip.empty()) { if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID; ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret); srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret; return ret;
} }
sockaddr_in addr; sockaddr_in addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
@ -281,69 +281,69 @@ int SrsForwarder::connect_server()
} }
srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port); srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
return ret; return ret;
} }
int SrsForwarder::forward() int SrsForwarder::forward()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US); client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
while (pthread->can_loop()) { while (pthread->can_loop()) {
// switch to other st-threads. // switch to other st-threads.
st_usleep(0); st_usleep(0);
// read from client. // read from client.
if (true) { if (true) {
SrsCommonMessage* msg = NULL; SrsCommonMessage* msg = NULL;
ret = client->recv_message(&msg); ret = client->recv_message(&msg);
srs_verbose("play loop recv message. ret=%d", ret); srs_verbose("play loop recv message. ret=%d", ret);
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
srs_error("recv server control message failed. ret=%d", ret); srs_error("recv server control message failed. ret=%d", ret);
return ret; return ret;
} }
} }
// forward all messages. // forward all messages.
int count = 0; int count = 0;
SrsSharedPtrMessage** msgs = NULL; SrsSharedPtrMessage** msgs = NULL;
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) { if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
srs_error("get message to forward failed. ret=%d", ret); srs_error("get message to forward failed. ret=%d", ret);
return ret; return ret;
} }
// ignore when no messages. // ignore when no messages.
if (count <= 0) { if (count <= 0) {
srs_verbose("no packets to forward."); srs_verbose("no packets to forward.");
continue; continue;
} }
SrsAutoFree(SrsSharedPtrMessage*, msgs, true); SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
// pithy print // pithy print
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
if (pithy_print.can_print()) { if (pithy_print.can_print()) {
srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
} }
// all msgs to forward. // all msgs to forward.
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
SrsSharedPtrMessage* msg = msgs[i]; SrsSharedPtrMessage* msg = msgs[i];
srs_assert(msg); srs_assert(msg);
msgs[i] = NULL; msgs[i] = NULL;
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) { if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
srs_error("forwarder send message to server failed. ret=%d", ret); srs_error("forwarder send message to server failed. ret=%d", ret);
return ret; return ret;
} }
} }
} }
return ret; return ret;
} }

View file

@ -49,39 +49,39 @@ class SrsSource;
class SrsForwarder : public ISrsThreadHandler class SrsForwarder : public ISrsThreadHandler
{ {
private: private:
std::string app; std::string app;
std::string tc_url; std::string tc_url;
std::string stream_name; std::string stream_name;
int stream_id; int stream_id;
std::string server; std::string server;
int port; int port;
private: private:
st_netfd_t stfd; st_netfd_t stfd;
SrsThread* pthread; SrsThread* pthread;
private: private:
SrsSource* source; SrsSource* source;
ISrsProtocolReaderWriter* io; ISrsProtocolReaderWriter* io;
SrsRtmpClient* client; SrsRtmpClient* client;
SrsRtmpJitter* jitter; SrsRtmpJitter* jitter;
SrsMessageQueue* queue; SrsMessageQueue* queue;
public: public:
SrsForwarder(SrsSource* _source); SrsForwarder(SrsSource* _source);
virtual ~SrsForwarder(); virtual ~SrsForwarder();
public: public:
virtual void set_queue_size(double queue_size); virtual void set_queue_size(double queue_size);
public: public:
virtual int on_publish(SrsRequest* req, std::string forward_server); virtual int on_publish(SrsRequest* req, std::string forward_server);
virtual void on_unpublish(); virtual void on_unpublish();
virtual int on_meta_data(SrsSharedPtrMessage* metadata); virtual int on_meta_data(SrsSharedPtrMessage* metadata);
virtual int on_audio(SrsSharedPtrMessage* msg); virtual int on_audio(SrsSharedPtrMessage* msg);
virtual int on_video(SrsSharedPtrMessage* msg); virtual int on_video(SrsSharedPtrMessage* msg);
// interface ISrsThreadHandler. // interface ISrsThreadHandler.
public: public:
virtual int cycle(); virtual int cycle();
private: private:
virtual void close_underlayer_socket(); virtual void close_underlayer_socket();
virtual int connect_server(); virtual int connect_server();
virtual int forward(); virtual int forward();
}; };
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -56,40 +56,40 @@ class SrsSource;
class SrsHlsAacJitter class SrsHlsAacJitter
{ {
private: private:
int64_t base_pts; int64_t base_pts;
int64_t nb_samples; int64_t nb_samples;
int sync_ms; int sync_ms;
public: public:
SrsHlsAacJitter(); SrsHlsAacJitter();
virtual ~SrsHlsAacJitter(); virtual ~SrsHlsAacJitter();
/** /**
* when buffer start, calc the "correct" pts for ts, * when buffer start, calc the "correct" pts for ts,
* @param flv_pts, the flv pts calc from flv header timestamp, * @param flv_pts, the flv pts calc from flv header timestamp,
* @return the calc correct pts. * @return the calc correct pts.
*/ */
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate); virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
/** /**
* when buffer continue, muxer donot write to file, * when buffer continue, muxer donot write to file,
* the audio buffer continue grow and donot need a pts, * the audio buffer continue grow and donot need a pts,
* for the ts audio PES packet only has one pts at the first time. * for the ts audio PES packet only has one pts at the first time.
*/ */
virtual void on_buffer_continue(); virtual void on_buffer_continue();
}; };
//TODO: refine the ts muxer, do more jobs. //TODO: refine the ts muxer, do more jobs.
class SrsTSMuxer class SrsTSMuxer
{ {
private: private:
int fd; int fd;
std::string path; std::string path;
public: public:
SrsTSMuxer(); SrsTSMuxer();
virtual ~SrsTSMuxer(); virtual ~SrsTSMuxer();
public: public:
virtual int open(std::string _path); virtual int open(std::string _path);
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb); virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
virtual void close(); virtual void close();
}; };
/** /**
@ -98,26 +98,26 @@ public:
*/ */
struct SrsM3u8Segment struct SrsM3u8Segment
{ {
// duration in seconds in m3u8. // duration in seconds in m3u8.
double duration; double duration;
// sequence number in m3u8. // sequence number in m3u8.
int sequence_no; int sequence_no;
// ts uri in m3u8. // ts uri in m3u8.
std::string uri; std::string uri;
// ts full file to write. // ts full file to write.
std::string full_path; std::string full_path;
// the muxer to write ts. // the muxer to write ts.
SrsTSMuxer* muxer; SrsTSMuxer* muxer;
// current segment start dts for m3u8 // current segment start dts for m3u8
int64_t segment_start_dts; int64_t segment_start_dts;
SrsM3u8Segment(); SrsM3u8Segment();
virtual ~SrsM3u8Segment(); virtual ~SrsM3u8Segment();
/** /**
* update the segment duration. * update the segment duration.
*/ */
virtual double update_duration(int64_t video_stream_dts); virtual double update_duration(int64_t video_stream_dts);
}; };
/** /**
@ -126,39 +126,39 @@ struct SrsM3u8Segment
class SrsM3u8Muxer class SrsM3u8Muxer
{ {
private: private:
std::string app; std::string app;
std::string stream; std::string stream;
private: private:
std::string hls_path; std::string hls_path;
int hls_fragment; int hls_fragment;
int hls_window; int hls_window;
private: private:
int file_index; int file_index;
std::string m3u8; std::string m3u8;
private: private:
/** /**
* m3u8 segments. * m3u8 segments.
*/ */
std::vector<SrsM3u8Segment*> segments; std::vector<SrsM3u8Segment*> segments;
/** /**
* current writing segment. * current writing segment.
*/ */
SrsM3u8Segment* current; SrsM3u8Segment* current;
// last known dts // last known dts
int64_t video_stream_dts; int64_t video_stream_dts;
public: public:
SrsM3u8Muxer(); SrsM3u8Muxer();
virtual ~SrsM3u8Muxer(); virtual ~SrsM3u8Muxer();
public: public:
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window); virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
virtual int segment_open(); virtual int segment_open();
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb); virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
virtual int segment_close(); virtual int segment_close();
private: private:
virtual int refresh_m3u8(); virtual int refresh_m3u8();
virtual int _refresh_m3u8(int& fd, std::string m3u8_file); virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
virtual int create_dir(); virtual int create_dir();
}; };
/** /**
@ -167,35 +167,35 @@ private:
class SrsTSCache class SrsTSCache
{ {
private: private:
// current frame and buffer // current frame and buffer
SrsMpegtsFrame* af; SrsMpegtsFrame* af;
SrsCodecBuffer* ab; SrsCodecBuffer* ab;
SrsMpegtsFrame* vf; SrsMpegtsFrame* vf;
SrsCodecBuffer* vb; SrsCodecBuffer* vb;
private: private:
// the audio cache buffer start pts, to flush audio if full. // the audio cache buffer start pts, to flush audio if full.
int64_t audio_buffer_start_pts; int64_t audio_buffer_start_pts;
// time jitter for aac // time jitter for aac
SrsHlsAacJitter* aac_jitter; SrsHlsAacJitter* aac_jitter;
public: public:
SrsTSCache(); SrsTSCache();
virtual ~SrsTSCache(); virtual ~SrsTSCache();
public: public:
/** /**
* write audio to cache, if need to flush, flush to muxer. * write audio to cache, if need to flush, flush to muxer.
*/ */
virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample); virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample);
/** /**
* write video to muxer. * write video to muxer.
*/ */
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample); virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
/** /**
* flush audio in cache to muxer. * flush audio in cache to muxer.
*/ */
virtual int flush_audio(SrsM3u8Muxer* muxer); virtual int flush_audio(SrsM3u8Muxer* muxer);
private: private:
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample); virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample); virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
}; };
/** /**
@ -204,43 +204,43 @@ private:
class SrsHls class SrsHls
{ {
private: private:
SrsM3u8Muxer* muxer; SrsM3u8Muxer* muxer;
SrsTSCache* ts_cache; SrsTSCache* ts_cache;
private: private:
bool hls_enabled; bool hls_enabled;
SrsSource* source; SrsSource* source;
SrsCodec* codec; SrsCodec* codec;
SrsCodecSample* sample; SrsCodecSample* sample;
SrsRtmpJitter* jitter; SrsRtmpJitter* jitter;
SrsPithyPrint* pithy_print; SrsPithyPrint* pithy_print;
public: public:
SrsHls(SrsSource* _source); SrsHls(SrsSource* _source);
virtual ~SrsHls(); virtual ~SrsHls();
public: public:
/** /**
* publish stream event, continue to write the m3u8, * publish stream event, continue to write the m3u8,
* for the muxer object not destroyed. * for the muxer object not destroyed.
*/ */
virtual int on_publish(SrsRequest* req); virtual int on_publish(SrsRequest* req);
/** /**
* the unpublish event, only close the muxer, donot destroy the * the unpublish event, only close the muxer, donot destroy the
* muxer, for when we continue to publish, the m3u8 will continue. * muxer, for when we continue to publish, the m3u8 will continue.
*/ */
virtual void on_unpublish(); virtual void on_unpublish();
/** /**
* get some information from metadata, it's optinal. * get some information from metadata, it's optinal.
*/ */
virtual int on_meta_data(SrsAmf0Object* metadata); virtual int on_meta_data(SrsAmf0Object* metadata);
/** /**
* mux the audio packets to ts. * mux the audio packets to ts.
*/ */
virtual int on_audio(SrsSharedPtrMessage* audio); virtual int on_audio(SrsSharedPtrMessage* audio);
/** /**
* mux the video packets to ts. * mux the video packets to ts.
*/ */
virtual int on_video(SrsSharedPtrMessage* video); virtual int on_video(SrsSharedPtrMessage* video);
private: private:
virtual void hls_mux(); virtual void hls_mux();
}; };
#endif #endif

View file

@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsHttpUri::SrsHttpUri() SrsHttpUri::SrsHttpUri()
{ {
port = SRS_DEFAULT_HTTP_PORT; port = SRS_DEFAULT_HTTP_PORT;
} }
SrsHttpUri::~SrsHttpUri() SrsHttpUri::~SrsHttpUri()
@ -51,7 +51,7 @@ SrsHttpUri::~SrsHttpUri()
int SrsHttpUri::initialize(std::string _url) int SrsHttpUri::initialize(std::string _url)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
url = _url; url = _url;
const char* purl = url.c_str(); const char* purl = url.c_str();
@ -65,7 +65,7 @@ int SrsHttpUri::initialize(std::string _url)
return ret; return ret;
} }
std::string field = get_uri_field(url, &hp_u, UF_SCHEMA); std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
if(!field.empty()){ if(!field.empty()){
schema = field; schema = field;
} }
@ -80,7 +80,7 @@ int SrsHttpUri::initialize(std::string _url)
path = get_uri_field(url, &hp_u, UF_PATH); path = get_uri_field(url, &hp_u, UF_PATH);
srs_info("parse url %s success", purl); srs_info("parse url %s success", purl);
return ret; return ret;
} }
const char* SrsHttpUri::get_url() const char* SrsHttpUri::get_url()
@ -128,23 +128,23 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht
SrsHttpClient::SrsHttpClient() SrsHttpClient::SrsHttpClient()
{ {
connected = false; connected = false;
stfd = NULL; stfd = NULL;
} }
SrsHttpClient::~SrsHttpClient() SrsHttpClient::~SrsHttpClient()
{ {
disconnect(); disconnect();
} }
int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res) int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = connect(uri)) != ERROR_SUCCESS) { if ((ret = connect(uri)) != ERROR_SUCCESS) {
srs_error("http connect server failed. ret=%d", ret); srs_error("http connect server failed. ret=%d", ret);
return ret; return ret;
} }
// send POST request to uri // send POST request to uri
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
@ -177,32 +177,32 @@ int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
} }
srs_info("parse http post response success."); srs_info("parse http post response success.");
return ret; return ret;
} }
void SrsHttpClient::disconnect() void SrsHttpClient::disconnect()
{ {
connected = false; connected = false;
srs_close_stfd(stfd); srs_close_stfd(stfd);
} }
int SrsHttpClient::connect(SrsHttpUri* uri) int SrsHttpClient::connect(SrsHttpUri* uri)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (connected) { if (connected) {
return ret; return ret;
} }
disconnect(); disconnect();
std::string ip = srs_dns_resolve(uri->get_host()); std::string ip = srs_dns_resolve(uri->get_host());
if (ip.empty()) { if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID; ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret); srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret; return ret;
} }
int sock = socket(AF_INET, SOCK_STREAM, 0); int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){ if(sock == -1){
@ -226,16 +226,16 @@ int SrsHttpClient::connect(SrsHttpUri* uri)
if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){ if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
ret = ERROR_ST_CONNECT; ret = ERROR_ST_CONNECT;
srs_error("connect to server error. " srs_error("connect to server error. "
"ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret); "ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);
return ret; return ret;
} }
srs_info("connect to server success. " srs_info("connect to server success. "
"http url=%s, server=%s, ip=%s, port=%d", "http url=%s, server=%s, ip=%s, port=%d",
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port()); uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
connected = true; connected = true;
return ret; return ret;
} }
int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response) int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response)
@ -327,17 +327,17 @@ int SrsHttpClient::parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::str
char buf[SRS_HTTP_BODY_BUFFER]; char buf[SRS_HTTP_BODY_BUFFER];
return parse_response_body_data( return parse_response_body_data(
uri, skt, response, (size_t)body_left, uri, skt, response, (size_t)body_left,
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
); );
} else { } else {
// if ignore response, use shared fast memory. // if ignore response, use shared fast memory.
static char buf[SRS_HTTP_BODY_BUFFER]; static char buf[SRS_HTTP_BODY_BUFFER];
return parse_response_body_data( return parse_response_body_data(
uri, skt, response, (size_t)body_left, uri, skt, response, (size_t)body_left,
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
); );
} }
return ret; return ret;
@ -351,7 +351,7 @@ int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std
while (body_left > 0) { while (body_left > 0) {
ssize_t nread; ssize_t nread;
int size_to_read = srs_min(size, body_left); int size_to_read = srs_min(size, body_left);
if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) { if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) {
srs_error("read header from server failed. ret=%d", ret); srs_error("read header from server failed. ret=%d", ret);
return ret; return ret;
@ -394,424 +394,424 @@ SrsHttpHooks::~SrsHttpHooks()
int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req) int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_connect url failed. " srs_error("http uri parse on_connect url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret; return ret;
} }
/** /**
{ {
"action": "on_connect", "action": "on_connect",
"client_id": 1985, "client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"pageUrl": "http://www.test.com/live.html" "pageUrl": "http://www.test.com/live.html"
} }
*/ */
std::stringstream ss; std::stringstream ss;
ss << "{" ss << "{"
// action // action
<< '"' << "action" << '"' << ':' << '"' << "action" << '"' << ':'
<< '"' << "on_connect" << '"' << '"' << "on_connect" << '"'
<< ',' << ','
// client_id // client_id
<< '"' << "client_id" << '"' << ':' << '"' << "client_id" << '"' << ':'
<< std::dec << client_id << std::dec << client_id
<< ',' << ','
// ip // ip
<< '"' << "ip" << '"' << ':' << '"' << "ip" << '"' << ':'
<< '"' << ip << '"' << '"' << ip << '"'
<< ',' << ','
// vhost // vhost
<< '"' << "vhost" << '"' << ':' << '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"' << '"' << req->vhost << '"'
<< ',' << ','
// app // app
<< '"' << "app" << '"' << ':' << '"' << "app" << '"' << ':'
<< '"' << req->app << '"' << '"' << req->app << '"'
<< ',' << ','
// pageUrl // pageUrl
<< '"' << "pageUrl" << '"' << ':' << '"' << "pageUrl" << '"' << ':'
<< '"' << req->pageUrl << '"' << '"' << req->pageUrl << '"'
//<< ',' //<< ','
<< "}"; << "}";
std::string data = ss.str(); std::string data = ss.str();
std::string res; std::string res;
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_connect uri failed. " srs_error("http post on_connect uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret; return ret;
} }
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_connect validate failed. " srs_error("http hook on_connect validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret; return ret;
} }
srs_trace("http hook on_connect success. " srs_trace("http hook on_connect success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret; return ret;
} }
void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req) void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_close url failed, ignored. " srs_warn("http uri parse on_close url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return; return;
} }
/** /**
{ {
"action": "on_close", "action": "on_close",
"client_id": 1985, "client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream" "stream": "livestream"
} }
*/ */
std::stringstream ss; std::stringstream ss;
ss << "{" ss << "{"
// action // action
<< '"' << "action" << '"' << ':' << '"' << "action" << '"' << ':'
<< '"' << "on_close" << '"' << '"' << "on_close" << '"'
<< ',' << ','
// client_id // client_id
<< '"' << "client_id" << '"' << ':' << '"' << "client_id" << '"' << ':'
<< std::dec << client_id << std::dec << client_id
<< ',' << ','
// ip // ip
<< '"' << "ip" << '"' << ':' << '"' << "ip" << '"' << ':'
<< '"' << ip << '"' << '"' << ip << '"'
<< ',' << ','
// vhost // vhost
<< '"' << "vhost" << '"' << ':' << '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"' << '"' << req->vhost << '"'
<< ',' << ','
// app // app
<< '"' << "app" << '"' << ':' << '"' << "app" << '"' << ':'
<< '"' << req->app << '"' << '"' << req->app << '"'
//<< ',' //<< ','
<< "}"; << "}";
std::string data = ss.str(); std::string data = ss.str();
std::string res; std::string res;
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_close uri failed, ignored. " srs_warn("http post on_close uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
} }
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_close validate failed, ignored. " srs_warn("http hook on_close validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return; return;
} }
srs_trace("http hook on_close success. " srs_trace("http hook on_close success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
} }
int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req) int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_publish url failed. " srs_error("http uri parse on_publish url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret; return ret;
} }
/** /**
{ {
"action": "on_publish", "action": "on_publish",
"client_id": 1985, "client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream" "stream": "livestream"
} }
*/ */
std::stringstream ss; std::stringstream ss;
ss << "{" ss << "{"
// action // action
<< '"' << "action" << '"' << ':' << '"' << "action" << '"' << ':'
<< '"' << "on_publish" << '"' << '"' << "on_publish" << '"'
<< ',' << ','
// client_id // client_id
<< '"' << "client_id" << '"' << ':' << '"' << "client_id" << '"' << ':'
<< std::dec << client_id << std::dec << client_id
<< ',' << ','
// ip // ip
<< '"' << "ip" << '"' << ':' << '"' << "ip" << '"' << ':'
<< '"' << ip << '"' << '"' << ip << '"'
<< ',' << ','
// vhost // vhost
<< '"' << "vhost" << '"' << ':' << '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"' << '"' << req->vhost << '"'
<< ',' << ','
// app // app
<< '"' << "app" << '"' << ':' << '"' << "app" << '"' << ':'
<< '"' << req->app << '"' << '"' << req->app << '"'
<< ',' << ','
// stream // stream
<< '"' << "stream" << '"' << ':' << '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"' << '"' << req->stream << '"'
//<< ',' //<< ','
<< "}"; << "}";
std::string data = ss.str(); std::string data = ss.str();
std::string res; std::string res;
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_publish uri failed. " srs_error("http post on_publish uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret; return ret;
} }
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_publish validate failed. " srs_error("http hook on_publish validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret; return ret;
} }
srs_trace("http hook on_publish success. " srs_trace("http hook on_publish success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret; return ret;
} }
void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req) void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_unpublish url failed, ignored. " srs_warn("http uri parse on_unpublish url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return; return;
} }
/** /**
{ {
"action": "on_unpublish", "action": "on_unpublish",
"client_id": 1985, "client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream" "stream": "livestream"
} }
*/ */
std::stringstream ss; std::stringstream ss;
ss << "{" ss << "{"
// action // action
<< '"' << "action" << '"' << ':' << '"' << "action" << '"' << ':'
<< '"' << "on_unpublish" << '"' << '"' << "on_unpublish" << '"'
<< ',' << ','
// client_id // client_id
<< '"' << "client_id" << '"' << ':' << '"' << "client_id" << '"' << ':'
<< std::dec << client_id << std::dec << client_id
<< ',' << ','
// ip // ip
<< '"' << "ip" << '"' << ':' << '"' << "ip" << '"' << ':'
<< '"' << ip << '"' << '"' << ip << '"'
<< ',' << ','
// vhost // vhost
<< '"' << "vhost" << '"' << ':' << '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"' << '"' << req->vhost << '"'
<< ',' << ','
// app // app
<< '"' << "app" << '"' << ':' << '"' << "app" << '"' << ':'
<< '"' << req->app << '"' << '"' << req->app << '"'
<< ',' << ','
// stream // stream
<< '"' << "stream" << '"' << ':' << '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"' << '"' << req->stream << '"'
//<< ',' //<< ','
<< "}"; << "}";
std::string data = ss.str(); std::string data = ss.str();
std::string res; std::string res;
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_unpublish uri failed, ignored. " srs_warn("http post on_unpublish uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
} }
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_unpublish validate failed, ignored. " srs_warn("http hook on_unpublish validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return; return;
} }
srs_trace("http hook on_unpublish success. " srs_trace("http hook on_unpublish success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
} }
int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req) int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_error("http uri parse on_play url failed. " srs_error("http uri parse on_play url failed. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return ret; return ret;
} }
/** /**
{ {
"action": "on_play", "action": "on_play",
"client_id": 1985, "client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream" "stream": "livestream"
} }
*/ */
std::stringstream ss; std::stringstream ss;
ss << "{" ss << "{"
// action // action
<< '"' << "action" << '"' << ':' << '"' << "action" << '"' << ':'
<< '"' << "on_play" << '"' << '"' << "on_play" << '"'
<< ',' << ','
// client_id // client_id
<< '"' << "client_id" << '"' << ':' << '"' << "client_id" << '"' << ':'
<< std::dec << client_id << std::dec << client_id
<< ',' << ','
// ip // ip
<< '"' << "ip" << '"' << ':' << '"' << "ip" << '"' << ':'
<< '"' << ip << '"' << '"' << ip << '"'
<< ',' << ','
// vhost // vhost
<< '"' << "vhost" << '"' << ':' << '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"' << '"' << req->vhost << '"'
<< ',' << ','
// app // app
<< '"' << "app" << '"' << ':' << '"' << "app" << '"' << ':'
<< '"' << req->app << '"' << '"' << req->app << '"'
<< ',' << ','
// stream // stream
<< '"' << "stream" << '"' << ':' << '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"' << '"' << req->stream << '"'
//<< ',' //<< ','
<< "}"; << "}";
std::string data = ss.str(); std::string data = ss.str();
std::string res; std::string res;
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_error("http post on_play uri failed. " srs_error("http post on_play uri failed. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret; return ret;
} }
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_error("http hook on_play validate failed. " srs_error("http hook on_play validate failed. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return ret; return ret;
} }
srs_trace("http hook on_play success. " srs_trace("http hook on_play success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return ret; return ret;
} }
void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req) void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsHttpUri uri; SrsHttpUri uri;
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
srs_warn("http uri parse on_stop url failed, ignored. " srs_warn("http uri parse on_stop url failed, ignored. "
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
return; return;
} }
/** /**
{ {
"action": "on_stop", "action": "on_stop",
"client_id": 1985, "client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream" "stream": "livestream"
} }
*/ */
std::stringstream ss; std::stringstream ss;
ss << "{" ss << "{"
// action // action
<< '"' << "action" << '"' << ':' << '"' << "action" << '"' << ':'
<< '"' << "on_stop" << '"' << '"' << "on_stop" << '"'
<< ',' << ','
// client_id // client_id
<< '"' << "client_id" << '"' << ':' << '"' << "client_id" << '"' << ':'
<< std::dec << client_id << std::dec << client_id
<< ',' << ','
// ip // ip
<< '"' << "ip" << '"' << ':' << '"' << "ip" << '"' << ':'
<< '"' << ip << '"' << '"' << ip << '"'
<< ',' << ','
// vhost // vhost
<< '"' << "vhost" << '"' << ':' << '"' << "vhost" << '"' << ':'
<< '"' << req->vhost << '"' << '"' << req->vhost << '"'
<< ',' << ','
// app // app
<< '"' << "app" << '"' << ':' << '"' << "app" << '"' << ':'
<< '"' << req->app << '"' << '"' << req->app << '"'
<< ',' << ','
// stream // stream
<< '"' << "stream" << '"' << ':' << '"' << "stream" << '"' << ':'
<< '"' << req->stream << '"' << '"' << req->stream << '"'
//<< ',' //<< ','
<< "}"; << "}";
std::string data = ss.str(); std::string data = ss.str();
std::string res; std::string res;
SrsHttpClient http; SrsHttpClient http;
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
srs_warn("http post on_stop uri failed, ignored. " srs_warn("http post on_stop uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
} }
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
ret = ERROR_HTTP_DATA_INVLIAD; ret = ERROR_HTTP_DATA_INVLIAD;
srs_warn("http hook on_stop validate failed, ignored. " srs_warn("http hook on_stop validate failed, ignored. "
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
return; return;
} }
srs_trace("http hook on_stop success. " srs_trace("http hook on_stop success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d", "client_id=%d, url=%s, request=%s, response=%s, ret=%d",
client_id, url.c_str(), data.c_str(), res.c_str(), ret); client_id, url.c_str(), data.c_str(), res.c_str(), ret);
return; return;
} }
#endif #endif

View file

@ -40,8 +40,8 @@ class SrsSocket;
#include <http_parser.h> #include <http_parser.h>
#define SRS_HTTP_HEADER_BUFFER 1024 #define SRS_HTTP_HEADER_BUFFER 1024
#define SRS_HTTP_BODY_BUFFER 32 * 1024 #define SRS_HTTP_BODY_BUFFER 32 * 1024
/** /**
* used to resolve the http uri. * used to resolve the http uri.
@ -55,13 +55,13 @@ private:
int port; int port;
std::string path; std::string path;
public: public:
SrsHttpUri(); SrsHttpUri();
virtual ~SrsHttpUri(); virtual ~SrsHttpUri();
public: public:
/** /**
* initialize the http uri. * initialize the http uri.
*/ */
virtual int initialize(std::string _url); virtual int initialize(std::string _url);
public: public:
virtual const char* get_url(); virtual const char* get_url();
virtual const char* get_schema(); virtual const char* get_schema();
@ -82,23 +82,23 @@ private:
class SrsHttpClient class SrsHttpClient
{ {
private: private:
bool connected; bool connected;
st_netfd_t stfd; st_netfd_t stfd;
private: private:
http_parser http_header; http_parser http_header;
public: public:
SrsHttpClient(); SrsHttpClient();
virtual ~SrsHttpClient(); virtual ~SrsHttpClient();
public: public:
/** /**
* to post data to the uri. * to post data to the uri.
* @param req the data post to uri. * @param req the data post to uri.
* @param res the response data from server. * @param res the response data from server.
*/ */
virtual int post(SrsHttpUri* uri, std::string req, std::string& res); virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
private: private:
virtual void disconnect(); virtual void disconnect();
virtual int connect(SrsHttpUri* uri); virtual int connect(SrsHttpUri* uri);
private: private:
virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response); virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);
virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received); virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);
@ -117,54 +117,54 @@ private:
class SrsHttpHooks class SrsHttpHooks
{ {
public: public:
SrsHttpHooks(); SrsHttpHooks();
virtual ~SrsHttpHooks(); virtual ~SrsHttpHooks();
public: public:
/** /**
* on_connect hook, when client connect to srs. * on_connect hook, when client connect to srs.
* @param client_id the id of client on server. * @param client_id the id of client on server.
* @param url the api server url, to valid the client. * @param url the api server url, to valid the client.
* ignore if empty. * ignore if empty.
* @return valid failed or connect to the url failed. * @return valid failed or connect to the url failed.
*/ */
virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req); virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
/** /**
* on_close hook, when client disconnect to srs, where client is valid by on_connect. * on_close hook, when client disconnect to srs, where client is valid by on_connect.
* @param client_id the id of client on server. * @param client_id the id of client on server.
* @param url the api server url, to process the event. * @param url the api server url, to process the event.
* ignore if empty. * ignore if empty.
*/ */
virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req); virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);
/** /**
* on_publish hook, when client(encoder) start to publish stream * on_publish hook, when client(encoder) start to publish stream
* @param client_id the id of client on server. * @param client_id the id of client on server.
* @param url the api server url, to valid the client. * @param url the api server url, to valid the client.
* ignore if empty. * ignore if empty.
* @return valid failed or connect to the url failed. * @return valid failed or connect to the url failed.
*/ */
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req); virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
/** /**
* on_unpublish hook, when client(encoder) stop publish stream. * on_unpublish hook, when client(encoder) stop publish stream.
* @param client_id the id of client on server. * @param client_id the id of client on server.
* @param url the api server url, to process the event. * @param url the api server url, to process the event.
* ignore if empty. * ignore if empty.
*/ */
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req); virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
/** /**
* on_play hook, when client start to play stream. * on_play hook, when client start to play stream.
* @param client_id the id of client on server. * @param client_id the id of client on server.
* @param url the api server url, to valid the client. * @param url the api server url, to valid the client.
* ignore if empty. * ignore if empty.
* @return valid failed or connect to the url failed. * @return valid failed or connect to the url failed.
*/ */
virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req); virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
/** /**
* on_stop hook, when client stop to play the stream. * on_stop hook, when client stop to play the stream.
* @param client_id the id of client on server. * @param client_id the id of client on server.
* @param url the api server url, to process the event. * @param url the api server url, to process the event.
* ignore if empty. * ignore if empty.
*/ */
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req); virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
}; };
#endif #endif

View file

@ -36,7 +36,7 @@ SrsThreadContext::~SrsThreadContext()
void SrsThreadContext::generate_id() void SrsThreadContext::generate_id()
{ {
static int id = 1; static int id = 1;
cache[st_thread_self()] = id++; cache[st_thread_self()] = id++;
} }
@ -55,7 +55,7 @@ int SrsThreadContext::get_id()
SrsFastLog::SrsFastLog() SrsFastLog::SrsFastLog()
{ {
level = SrsLogLevel::Trace; level = SrsLogLevel::Trace;
log_data = new char[LOG_MAX_SIZE]; log_data = new char[LOG_MAX_SIZE];
} }
@ -185,15 +185,15 @@ bool SrsFastLog::generate_header(const char* tag, int context_id, const char* le
int log_header_size = -1; int log_header_size = -1;
if (tag) { if (tag) {
log_header_size = snprintf(log_data, LOG_MAX_SIZE, log_header_size = snprintf(log_data, LOG_MAX_SIZE,
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ", "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ",
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000),
level_name, tag, context_id, errno); level_name, tag, context_id, errno);
} else { } else {
log_header_size = snprintf(log_data, LOG_MAX_SIZE, log_header_size = snprintf(log_data, LOG_MAX_SIZE,
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ", "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ",
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000),
level_name, context_id, errno); level_name, context_id, errno);
} }
if (log_header_size == -1) { if (log_header_size == -1) {

View file

@ -35,132 +35,132 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
struct SrsStageInfo : public ISrsReloadHandler struct SrsStageInfo : public ISrsReloadHandler
{ {
int stage_id; int stage_id;
int pithy_print_time_ms; int pithy_print_time_ms;
int nb_clients; int nb_clients;
SrsStageInfo(int _stage_id) SrsStageInfo(int _stage_id)
{ {
stage_id = _stage_id; stage_id = _stage_id;
nb_clients = 0; nb_clients = 0;
update_print_time(); update_print_time();
_srs_config->subscribe(this); _srs_config->subscribe(this);
} }
virtual ~SrsStageInfo() virtual ~SrsStageInfo()
{ {
_srs_config->unsubscribe(this); _srs_config->unsubscribe(this);
} }
void update_print_time() void update_print_time()
{ {
switch (stage_id) { switch (stage_id) {
case SRS_STAGE_PLAY_USER: { case SRS_STAGE_PLAY_USER: {
pithy_print_time_ms = _srs_config->get_pithy_print_play(); pithy_print_time_ms = _srs_config->get_pithy_print_play();
break; break;
} }
case SRS_STAGE_PUBLISH_USER: { case SRS_STAGE_PUBLISH_USER: {
pithy_print_time_ms = _srs_config->get_pithy_print_publish(); pithy_print_time_ms = _srs_config->get_pithy_print_publish();
break; break;
} }
case SRS_STAGE_FORWARDER: { case SRS_STAGE_FORWARDER: {
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder(); pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
break; break;
} }
case SRS_STAGE_ENCODER: { case SRS_STAGE_ENCODER: {
pithy_print_time_ms = _srs_config->get_pithy_print_encoder(); pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
break; break;
} }
case SRS_STAGE_HLS: { case SRS_STAGE_HLS: {
pithy_print_time_ms = _srs_config->get_pithy_print_hls(); pithy_print_time_ms = _srs_config->get_pithy_print_hls();
break; break;
} }
default: { default: {
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS; pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
break; break;
} }
} }
} }
public: public:
virtual int on_reload_pithy_print() virtual int on_reload_pithy_print()
{ {
update_print_time(); update_print_time();
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
}; };
static std::map<int, SrsStageInfo*> _srs_stages; static std::map<int, SrsStageInfo*> _srs_stages;
SrsPithyPrint::SrsPithyPrint(int _stage_id) SrsPithyPrint::SrsPithyPrint(int _stage_id)
{ {
stage_id = _stage_id; stage_id = _stage_id;
client_id = enter_stage(); client_id = enter_stage();
printed_age = age = 0; printed_age = age = 0;
} }
SrsPithyPrint::~SrsPithyPrint() SrsPithyPrint::~SrsPithyPrint()
{ {
leave_stage(); leave_stage();
} }
int SrsPithyPrint::enter_stage() int SrsPithyPrint::enter_stage()
{ {
SrsStageInfo* stage = NULL; SrsStageInfo* stage = NULL;
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id); std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
if (it == _srs_stages.end()) { if (it == _srs_stages.end()) {
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id); stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
} else { } else {
stage = it->second; stage = it->second;
} }
srs_assert(stage != NULL); srs_assert(stage != NULL);
client_id = stage->nb_clients++; client_id = stage->nb_clients++;
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms); stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
return client_id; return client_id;
} }
void SrsPithyPrint::leave_stage() void SrsPithyPrint::leave_stage()
{ {
SrsStageInfo* stage = _srs_stages[stage_id]; SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL); srs_assert(stage != NULL);
stage->nb_clients--; stage->nb_clients--;
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms); stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
} }
void SrsPithyPrint::elapse(int64_t time_ms) void SrsPithyPrint::elapse(int64_t time_ms)
{ {
age += time_ms; age += time_ms;
} }
bool SrsPithyPrint::can_print() bool SrsPithyPrint::can_print()
{ {
SrsStageInfo* stage = _srs_stages[stage_id]; SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL); srs_assert(stage != NULL);
int64_t alive_age = age - printed_age; int64_t alive_age = age - printed_age;
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms; int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
bool can_print = alive_age >= can_print_age; bool can_print = alive_age >= can_print_age;
if (can_print) { if (can_print) {
printed_age = age; printed_age = age;
} }
return can_print; return can_print;
} }
int64_t SrsPithyPrint::get_age() int64_t SrsPithyPrint::get_age()
{ {
return age; return age;
} }
void SrsPithyPrint::set_age(int64_t _age) void SrsPithyPrint::set_age(int64_t _age)
{ {
age = _age; age = _age;
} }

View file

@ -50,39 +50,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsPithyPrint class SrsPithyPrint
{ {
private: private:
int client_id; int client_id;
int stage_id; int stage_id;
int64_t age; int64_t age;
int64_t printed_age; int64_t printed_age;
public: public:
/** /**
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER. * @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
*/ */
SrsPithyPrint(int _stage_id); SrsPithyPrint(int _stage_id);
virtual ~SrsPithyPrint(); virtual ~SrsPithyPrint();
private: private:
/** /**
* enter the specified stage, return the client id. * enter the specified stage, return the client id.
*/ */
virtual int enter_stage(); virtual int enter_stage();
/** /**
* leave the specified stage, release the client id. * leave the specified stage, release the client id.
*/ */
virtual void leave_stage(); virtual void leave_stage();
public: public:
/** /**
* specified client elapse some time. * specified client elapse some time.
*/ */
virtual void elapse(int64_t time_ms); virtual void elapse(int64_t time_ms);
/** /**
* whether current client can print. * whether current client can print.
*/ */
virtual bool can_print(); virtual bool can_print();
/** /**
* get the elapsed time in ms. * get the elapsed time in ms.
*/ */
virtual int64_t get_age(); virtual int64_t get_age();
virtual void set_age(int64_t _age); virtual void set_age(int64_t _age);
}; };
#endif #endif

View file

@ -29,60 +29,60 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
int SrsRefer::check(std::string page_url, SrsConfDirective* refer) int SrsRefer::check(std::string page_url, SrsConfDirective* refer)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (!refer) { if (!refer) {
srs_verbose("ignore refer check for page_url=%s", page_url.c_str()); srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
return ret; return ret;
} }
for (int i = 0; i < (int)refer->args.size(); i++) { for (int i = 0; i < (int)refer->args.size(); i++) {
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) { if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
srs_verbose("check refer success. page_url=%s, refer=%s", srs_verbose("check refer success. page_url=%s, refer=%s",
page_url.c_str(), refer->args.at(i).c_str()); page_url.c_str(), refer->args.at(i).c_str());
return ret; return ret;
} }
} }
ret = ERROR_RTMP_ACCESS_DENIED; ret = ERROR_RTMP_ACCESS_DENIED;
srs_error("check refer failed. ret=%d", ret); srs_error("check refer failed. ret=%d", ret);
return ret; return ret;
} }
int SrsRefer::check_single_refer(std::string page_url, std::string refer) int SrsRefer::check_single_refer(std::string page_url, std::string refer)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
size_t pos = std::string::npos; size_t pos = std::string::npos;
std::string domain_name = page_url; std::string domain_name = page_url;
if ((pos = domain_name.find("://")) != std::string::npos) { if ((pos = domain_name.find("://")) != std::string::npos) {
domain_name = domain_name.substr(pos + 3); domain_name = domain_name.substr(pos + 3);
} }
if ((pos = domain_name.find("/")) != std::string::npos) { if ((pos = domain_name.find("/")) != std::string::npos) {
domain_name = domain_name.substr(0, pos); domain_name = domain_name.substr(0, pos);
} }
if ((pos = domain_name.find(":")) != std::string::npos) { if ((pos = domain_name.find(":")) != std::string::npos) {
domain_name = domain_name.substr(0, pos); domain_name = domain_name.substr(0, pos);
} }
pos = domain_name.find(refer); pos = domain_name.find(refer);
if (pos == std::string::npos) { if (pos == std::string::npos) {
ret = ERROR_RTMP_ACCESS_DENIED; ret = ERROR_RTMP_ACCESS_DENIED;
} }
// match primary domain. // match primary domain.
if (pos != domain_name.length() - refer.length()) { if (pos != domain_name.length() - refer.length()) {
ret = ERROR_RTMP_ACCESS_DENIED; ret = ERROR_RTMP_ACCESS_DENIED;
} }
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d", srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d",
page_url.c_str(), domain_name.c_str(), refer.c_str(), ret); page_url.c_str(), domain_name.c_str(), refer.c_str(), ret);
} }
return ret; return ret;
} }

View file

@ -36,14 +36,14 @@ class SrsConfDirective;
class SrsRefer class SrsRefer
{ {
public: public:
/** /**
* to check the refer. * to check the refer.
* @param page_url the client page url. * @param page_url the client page url.
* @param refer the refer in config. * @param refer the refer in config.
*/ */
virtual int check(std::string page_url, SrsConfDirective* refer); virtual int check(std::string page_url, SrsConfDirective* refer);
private: private:
virtual int check_single_refer(std::string page_url, std::string refer); virtual int check_single_refer(std::string page_url, std::string refer);
}; };
#endif #endif

View file

@ -37,41 +37,41 @@ ISrsReloadHandler::~ISrsReloadHandler()
int ISrsReloadHandler::on_reload_listen() int ISrsReloadHandler::on_reload_listen()
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_pithy_print() int ISrsReloadHandler::on_reload_pithy_print()
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/) int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/) int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/) int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_forward(string /*vhost*/) int ISrsReloadHandler::on_reload_forward(string /*vhost*/)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_hls(string /*vhost*/) int ISrsReloadHandler::on_reload_hls(string /*vhost*/)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int ISrsReloadHandler::on_reload_transcode(string /*vhost*/) int ISrsReloadHandler::on_reload_transcode(string /*vhost*/)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View file

@ -37,17 +37,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsReloadHandler class ISrsReloadHandler
{ {
public: public:
ISrsReloadHandler(); ISrsReloadHandler();
virtual ~ISrsReloadHandler(); virtual ~ISrsReloadHandler();
public: public:
virtual int on_reload_listen(); virtual int on_reload_listen();
virtual int on_reload_pithy_print(); virtual int on_reload_pithy_print();
virtual int on_reload_vhost_removed(std::string vhost); virtual int on_reload_vhost_removed(std::string vhost);
virtual int on_reload_gop_cache(std::string vhost); virtual int on_reload_gop_cache(std::string vhost);
virtual int on_reload_queue_length(std::string vhost); virtual int on_reload_queue_length(std::string vhost);
virtual int on_reload_forward(std::string vhost); virtual int on_reload_forward(std::string vhost);
virtual int on_reload_hls(std::string vhost); virtual int on_reload_hls(std::string vhost);
virtual int on_reload_transcode(std::string vhost); virtual int on_reload_transcode(std::string vhost);
}; };
#endif #endif

View file

@ -40,40 +40,40 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
{ {
fd = -1; fd = -1;
stfd = NULL; stfd = NULL;
port = 0; port = 0;
server = _server; server = _server;
type = _type; type = _type;
pthread = new SrsThread(this, 0); pthread = new SrsThread(this, 0);
} }
SrsListener::~SrsListener() SrsListener::~SrsListener()
{ {
srs_close_stfd(stfd); srs_close_stfd(stfd);
pthread->stop(); pthread->stop();
srs_freep(pthread); srs_freep(pthread);
// st does not close it sometimes, // st does not close it sometimes,
// close it manually. // close it manually.
close(fd); close(fd);
} }
int SrsListener::listen(int _port) int SrsListener::listen(int _port)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
port = _port; port = _port;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
ret = ERROR_SOCKET_CREATE; ret = ERROR_SOCKET_CREATE;
srs_error("create linux socket error. ret=%d", ret); srs_error("create linux socket error. ret=%d", ret);
return ret; return ret;
} }
srs_verbose("create linux socket success. fd=%d", fd); srs_verbose("create linux socket success. fd=%d", fd);
int reuse_socket = 1; int reuse_socket = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) { if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
@ -116,17 +116,17 @@ int SrsListener::listen(int _port)
srs_trace("server started, listen at port=%d, fd=%d", port, fd); srs_trace("server started, listen at port=%d, fd=%d", port, fd);
return ret; return ret;
} }
void SrsListener::on_enter_loop() void SrsListener::on_enter_loop()
{ {
srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd);
} }
int SrsListener::cycle() int SrsListener::cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
@ -137,44 +137,44 @@ int SrsListener::cycle()
} }
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
srs_warn("accept client error. ret=%d", ret); srs_warn("accept client error. ret=%d", ret);
return ret; return ret;
} }
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
return ret; return ret;
} }
SrsServer::SrsServer() SrsServer::SrsServer()
{ {
signal_reload = false; signal_reload = false;
signal_gmc_stop = false; signal_gmc_stop = false;
srs_assert(_srs_config); srs_assert(_srs_config);
_srs_config->subscribe(this); _srs_config->subscribe(this);
} }
SrsServer::~SrsServer() SrsServer::~SrsServer()
{ {
_srs_config->unsubscribe(this); _srs_config->unsubscribe(this);
if (true) { if (true) {
std::vector<SrsConnection*>::iterator it; std::vector<SrsConnection*>::iterator it;
for (it = conns.begin(); it != conns.end(); ++it) { for (it = conns.begin(); it != conns.end(); ++it) {
SrsConnection* conn = *it; SrsConnection* conn = *it;
srs_freep(conn); srs_freep(conn);
} }
conns.clear(); conns.clear();
} }
close_listeners(); close_listeners();
} }
int SrsServer::initialize() int SrsServer::initialize()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// use linux epoll. // use linux epoll.
if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) { if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
@ -191,47 +191,47 @@ int SrsServer::initialize()
} }
srs_verbose("st_init success"); srs_verbose("st_init success");
// set current log id. // set current log id.
_srs_context->generate_id(); _srs_context->generate_id();
srs_info("log set id success"); srs_info("log set id success");
return ret; return ret;
} }
int SrsServer::listen() int SrsServer::listen()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
SrsConfDirective* conf = NULL; SrsConfDirective* conf = NULL;
// stream service port. // stream service port.
conf = _srs_config->get_listen(); conf = _srs_config->get_listen();
srs_assert(conf); srs_assert(conf);
close_listeners(); close_listeners();
for (int i = 0; i < (int)conf->args.size(); i++) { for (int i = 0; i < (int)conf->args.size(); i++) {
SrsListener* listener = new SrsListener(this, SrsListenerStream); SrsListener* listener = new SrsListener(this, SrsListenerStream);
listeners.push_back(listener); listeners.push_back(listener);
int port = ::atoi(conf->args.at(i).c_str()); int port = ::atoi(conf->args.at(i).c_str());
if ((ret = listener->listen(port)) != ERROR_SUCCESS) { if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
srs_error("listen at port %d failed. ret=%d", port, ret); srs_error("listen at port %d failed. ret=%d", port, ret);
return ret; return ret;
} }
} }
return ret; return ret;
} }
int SrsServer::cycle() int SrsServer::cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// the deamon thread, update the time cache // the deamon thread, update the time cache
while (true) { while (true) {
st_usleep(SRS_TIME_RESOLUTION_MS * 1000); st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
srs_update_system_time_ms(); srs_update_system_time_ms();
// for gperf heap checker, // for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc // @see: research/gperftools/heap-checker/heap_checker.cc
@ -239,110 +239,110 @@ int SrsServer::cycle()
// but, if gperf, use reload to ensure main return normally, // but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump. // because directly exit will cause core-dump.
#ifdef SRS_GPERF_MC #ifdef SRS_GPERF_MC
if (signal_gmc_stop) { if (signal_gmc_stop) {
break; break;
} }
#endif #endif
if (signal_reload) { if (signal_reload) {
signal_reload = false; signal_reload = false;
srs_info("get signal reload, to reload the config."); srs_info("get signal reload, to reload the config.");
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) { if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
srs_error("reload config failed. ret=%d", ret); srs_error("reload config failed. ret=%d", ret);
return ret; return ret;
} }
srs_trace("reload config success."); srs_trace("reload config success.");
} }
} }
return ret; return ret;
} }
void SrsServer::remove(SrsConnection* conn) void SrsServer::remove(SrsConnection* conn)
{ {
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn); std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
if (it != conns.end()) { if (it != conns.end()) {
conns.erase(it); conns.erase(it);
} }
srs_info("conn removed. conns=%d", (int)conns.size()); srs_info("conn removed. conns=%d", (int)conns.size());
// all connections are created by server, // all connections are created by server,
// so we free it here. // so we free it here.
srs_freep(conn); srs_freep(conn);
} }
void SrsServer::on_signal(int signo) void SrsServer::on_signal(int signo)
{ {
if (signo == SIGNAL_RELOAD) { if (signo == SIGNAL_RELOAD) {
signal_reload = true; signal_reload = true;
return; return;
} }
if (signo == SIGINT) { if (signo == SIGINT) {
#ifdef SRS_GPERF_MC #ifdef SRS_GPERF_MC
srs_trace("gmc is on, main cycle will terminate normally."); srs_trace("gmc is on, main cycle will terminate normally.");
signal_gmc_stop = true; signal_gmc_stop = true;
#else #else
srs_trace("user terminate program"); srs_trace("user terminate program");
exit(0); exit(0);
#endif #endif
return; return;
} }
// TODO: handle the SIGINT, SIGTERM. // TODO: handle the SIGINT, SIGTERM.
} }
void SrsServer::close_listeners() void SrsServer::close_listeners()
{ {
std::vector<SrsListener*>::iterator it; std::vector<SrsListener*>::iterator it;
for (it = listeners.begin(); it != listeners.end(); ++it) { for (it = listeners.begin(); it != listeners.end(); ++it) {
SrsListener* listener = *it; SrsListener* listener = *it;
srs_freep(listener); srs_freep(listener);
} }
listeners.clear(); listeners.clear();
} }
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
int max_connections = _srs_config->get_max_connections(); int max_connections = _srs_config->get_max_connections();
if ((int)conns.size() >= max_connections) { if ((int)conns.size() >= max_connections) {
int fd = st_netfd_fileno(client_stfd); int fd = st_netfd_fileno(client_stfd);
srs_error("exceed the max connections, drop client: " srs_error("exceed the max connections, drop client: "
"clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
srs_close_stfd(client_stfd); srs_close_stfd(client_stfd);
return ret; return ret;
} }
SrsConnection* conn = NULL; SrsConnection* conn = NULL;
if (type == SrsListenerStream) { if (type == SrsListenerStream) {
conn = new SrsClient(this, client_stfd); conn = new SrsClient(this, client_stfd);
} else { } else {
// handler others // handler others
} }
srs_assert(conn); srs_assert(conn);
// directly enqueue, the cycle thread will remove the client. // directly enqueue, the cycle thread will remove the client.
conns.push_back(conn); conns.push_back(conn);
srs_verbose("add conn from port %d to vector. conns=%d", port, (int)conns.size()); srs_verbose("add conn from port %d to vector. conns=%d", port, (int)conns.size());
// cycle will start process thread and when finished remove the client. // cycle will start process thread and when finished remove the client.
if ((ret = conn->start()) != ERROR_SUCCESS) { if ((ret = conn->start()) != ERROR_SUCCESS) {
return ret; return ret;
} }
srs_verbose("conn start finished. ret=%d", ret); srs_verbose("conn start finished. ret=%d", ret);
return ret; return ret;
} }
int SrsServer::on_reload_listen() int SrsServer::on_reload_listen()
{ {
return listen(); return listen();
} }

View file

@ -41,53 +41,53 @@ class SrsConnection;
enum SrsListenerType enum SrsListenerType
{ {
SrsListenerStream = 0, SrsListenerStream = 0,
SrsListenerApi SrsListenerApi
}; };
class SrsListener : public ISrsThreadHandler class SrsListener : public ISrsThreadHandler
{ {
public: public:
SrsListenerType type; SrsListenerType type;
private: private:
int fd; int fd;
st_netfd_t stfd; st_netfd_t stfd;
int port; int port;
SrsServer* server; SrsServer* server;
SrsThread* pthread; SrsThread* pthread;
public: public:
SrsListener(SrsServer* _server, SrsListenerType _type); SrsListener(SrsServer* _server, SrsListenerType _type);
virtual ~SrsListener(); virtual ~SrsListener();
public: public:
virtual int listen(int port); virtual int listen(int port);
// interface ISrsThreadHandler. // interface ISrsThreadHandler.
public: public:
virtual void on_enter_loop(); virtual void on_enter_loop();
virtual int cycle(); virtual int cycle();
}; };
class SrsServer : public ISrsReloadHandler class SrsServer : public ISrsReloadHandler
{ {
friend class SrsListener; friend class SrsListener;
private: private:
std::vector<SrsConnection*> conns; std::vector<SrsConnection*> conns;
std::vector<SrsListener*> listeners; std::vector<SrsListener*> listeners;
bool signal_reload; bool signal_reload;
bool signal_gmc_stop; bool signal_gmc_stop;
public: public:
SrsServer(); SrsServer();
virtual ~SrsServer(); virtual ~SrsServer();
public: public:
virtual int initialize(); virtual int initialize();
virtual int listen(); virtual int listen();
virtual int cycle(); virtual int cycle();
virtual void remove(SrsConnection* conn); virtual void remove(SrsConnection* conn);
virtual void on_signal(int signo); virtual void on_signal(int signo);
private: private:
virtual void close_listeners(); virtual void close_listeners();
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
public: public:
virtual int on_reload_listen(); virtual int on_reload_listen();
}; };
#endif #endif

View file

@ -28,9 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsSocket::SrsSocket(st_netfd_t client_stfd) SrsSocket::SrsSocket(st_netfd_t client_stfd)
{ {
stfd = client_stfd; stfd = client_stfd;
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
recv_bytes = send_bytes = 0; recv_bytes = send_bytes = 0;
start_time_ms = srs_get_system_time_ms(); start_time_ms = srs_get_system_time_ms();
} }
SrsSocket::~SrsSocket() SrsSocket::~SrsSocket()
@ -39,59 +39,59 @@ SrsSocket::~SrsSocket()
bool SrsSocket::is_never_timeout(int64_t timeout_us) bool SrsSocket::is_never_timeout(int64_t timeout_us)
{ {
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
} }
void SrsSocket::set_recv_timeout(int64_t timeout_us) void SrsSocket::set_recv_timeout(int64_t timeout_us)
{ {
recv_timeout = timeout_us; recv_timeout = timeout_us;
} }
int64_t SrsSocket::get_recv_timeout() int64_t SrsSocket::get_recv_timeout()
{ {
return recv_timeout; return recv_timeout;
} }
void SrsSocket::set_send_timeout(int64_t timeout_us) void SrsSocket::set_send_timeout(int64_t timeout_us)
{ {
send_timeout = timeout_us; send_timeout = timeout_us;
} }
int64_t SrsSocket::get_send_timeout() int64_t SrsSocket::get_send_timeout()
{ {
return send_timeout; return send_timeout;
} }
int64_t SrsSocket::get_recv_bytes() int64_t SrsSocket::get_recv_bytes()
{ {
return recv_bytes; return recv_bytes;
} }
int64_t SrsSocket::get_send_bytes() int64_t SrsSocket::get_send_bytes()
{ {
return send_bytes; return send_bytes;
} }
int SrsSocket::get_recv_kbps() int SrsSocket::get_recv_kbps()
{ {
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) { if (diff_ms <= 0) {
return 0; return 0;
} }
return recv_bytes * 8 / diff_ms; return recv_bytes * 8 / diff_ms;
} }
int SrsSocket::get_send_kbps() int SrsSocket::get_send_kbps()
{ {
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) { if (diff_ms <= 0) {
return 0; return 0;
} }
return send_bytes * 8 / diff_ms; return send_bytes * 8 / diff_ms;
} }
int SrsSocket::read(const void* buf, size_t size, ssize_t* nread) int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
@ -103,9 +103,9 @@ int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
// On success a non-negative integer indicating the number of bytes actually read is returned // On success a non-negative integer indicating the number of bytes actually read is returned
// (a value of 0 means the network connection is closed or end of file is reached). // (a value of 0 means the network connection is closed or end of file is reached).
if (*nread <= 0) { if (*nread <= 0) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
if (*nread == 0) { if (*nread == 0) {
errno = ECONNRESET; errno = ECONNRESET;
@ -128,9 +128,9 @@ int SrsSocket::read_fully(const void* buf, size_t size, ssize_t* nread)
// On success a non-negative integer indicating the number of bytes actually read is returned // On success a non-negative integer indicating the number of bytes actually read is returned
// (a value less than nbyte means the network connection is closed or end of file is reached) // (a value less than nbyte means the network connection is closed or end of file is reached)
if (*nread != (ssize_t)size) { if (*nread != (ssize_t)size) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
if (*nread >= 0) { if (*nread >= 0) {
errno = ECONNRESET; errno = ECONNRESET;
@ -151,9 +151,9 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite)
*nwrite = st_write(stfd, (void*)buf, size, send_timeout); *nwrite = st_write(stfd, (void*)buf, size, send_timeout);
if (*nwrite <= 0) { if (*nwrite <= 0) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
return ERROR_SOCKET_WRITE; return ERROR_SOCKET_WRITE;
} }
@ -170,9 +170,9 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
*nwrite = st_writev(stfd, iov, iov_size, send_timeout); *nwrite = st_writev(stfd, iov, iov_size, send_timeout);
if (*nwrite <= 0) { if (*nwrite <= 0) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
return ERROR_SOCKET_WRITE; return ERROR_SOCKET_WRITE;
} }

View file

@ -40,25 +40,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsSocket : public ISrsProtocolReaderWriter class SrsSocket : public ISrsProtocolReaderWriter
{ {
private: private:
int64_t recv_timeout; int64_t recv_timeout;
int64_t send_timeout; int64_t send_timeout;
int64_t recv_bytes; int64_t recv_bytes;
int64_t send_bytes; int64_t send_bytes;
int64_t start_time_ms; int64_t start_time_ms;
st_netfd_t stfd; st_netfd_t stfd;
public: public:
SrsSocket(st_netfd_t client_stfd); SrsSocket(st_netfd_t client_stfd);
virtual ~SrsSocket(); virtual ~SrsSocket();
public: public:
virtual bool is_never_timeout(int64_t timeout_us); virtual bool is_never_timeout(int64_t timeout_us);
virtual void set_recv_timeout(int64_t timeout_us); virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout(); virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us); virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout(); virtual int64_t get_send_timeout();
virtual int64_t get_recv_bytes(); virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes(); virtual int64_t get_send_bytes();
virtual int get_recv_kbps(); virtual int get_recv_kbps();
virtual int get_send_kbps(); virtual int get_send_kbps();
public: public:
virtual int read(const void* buf, size_t size, ssize_t* nread); virtual int read(const void* buf, size_t size, ssize_t* nread);
virtual int read_fully(const void* buf, size_t size, ssize_t* nread); virtual int read_fully(const void* buf, size_t size, ssize_t* nread);

File diff suppressed because it is too large Load diff

View file

@ -57,20 +57,20 @@ class SrsEncoder;
class SrsRtmpJitter class SrsRtmpJitter
{ {
private: private:
int64_t last_pkt_time; int64_t last_pkt_time;
int64_t last_pkt_correct_time; int64_t last_pkt_correct_time;
public: public:
SrsRtmpJitter(); SrsRtmpJitter();
virtual ~SrsRtmpJitter(); virtual ~SrsRtmpJitter();
public: public:
/** /**
* detect the time jitter and correct it. * detect the time jitter and correct it.
*/ */
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
/** /**
* get current client time, the last packet time. * get current client time, the last packet time.
*/ */
virtual int get_time(); virtual int get_time();
}; };
/** /**
@ -80,39 +80,39 @@ public:
class SrsMessageQueue class SrsMessageQueue
{ {
private: private:
int64_t av_start_time; int64_t av_start_time;
int64_t av_end_time; int64_t av_end_time;
int queue_size_ms; int queue_size_ms;
std::vector<SrsSharedPtrMessage*> msgs; std::vector<SrsSharedPtrMessage*> msgs;
public: public:
SrsMessageQueue(); SrsMessageQueue();
virtual ~SrsMessageQueue(); virtual ~SrsMessageQueue();
public: public:
/** /**
* set the queue size * set the queue size
* @param queue_size the queue size in seconds. * @param queue_size the queue size in seconds.
*/ */
virtual void set_queue_size(double queue_size); virtual void set_queue_size(double queue_size);
public: public:
/** /**
* enqueue the message, the timestamp always monotonically. * enqueue the message, the timestamp always monotonically.
* @param msg, the msg to enqueue, user never free it whatever the return code. * @param msg, the msg to enqueue, user never free it whatever the return code.
*/ */
virtual int enqueue(SrsSharedPtrMessage* msg); virtual int enqueue(SrsSharedPtrMessage* msg);
/** /**
* get packets in consumer queue. * get packets in consumer queue.
* @pmsgs SrsMessages*[], output the prt array. * @pmsgs SrsMessages*[], output the prt array.
* @count the count in array. * @count the count in array.
* @max_count the max count to dequeue, 0 to dequeue all. * @max_count the max count to dequeue, 0 to dequeue all.
*/ */
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
private: private:
/** /**
* remove a gop from the front. * remove a gop from the front.
* if no iframe found, clear it. * if no iframe found, clear it.
*/ */
virtual void shrink(); virtual void shrink();
virtual void clear(); virtual void clear();
}; };
/** /**
@ -121,39 +121,39 @@ private:
class SrsConsumer class SrsConsumer
{ {
private: private:
SrsRtmpJitter* jitter; SrsRtmpJitter* jitter;
SrsSource* source; SrsSource* source;
SrsMessageQueue* queue; SrsMessageQueue* queue;
bool paused; bool paused;
public: public:
SrsConsumer(SrsSource* _source); SrsConsumer(SrsSource* _source);
virtual ~SrsConsumer(); virtual ~SrsConsumer();
public: public:
virtual void set_queue_size(double queue_size); virtual void set_queue_size(double queue_size);
public: public:
/** /**
* get current client time, the last packet time. * get current client time, the last packet time.
*/ */
virtual int get_time(); virtual int get_time();
/** /**
* enqueue an shared ptr message. * enqueue an shared ptr message.
* @param tba timebase of audio. * @param tba timebase of audio.
* used to calc the audio time delta if time-jitter detected. * used to calc the audio time delta if time-jitter detected.
* @param tbv timebase of video. * @param tbv timebase of video.
* used to calc the video time delta if time-jitter detected. * used to calc the video time delta if time-jitter detected.
*/ */
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv); virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
/** /**
* get packets in consumer queue. * get packets in consumer queue.
* @pmsgs SrsMessages*[], output the prt array. * @pmsgs SrsMessages*[], output the prt array.
* @count the count in array. * @count the count in array.
* @max_count the max count to dequeue, 0 to dequeue all. * @max_count the max count to dequeue, 0 to dequeue all.
*/ */
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
/** /**
* when client send the pause message. * when client send the pause message.
*/ */
virtual int on_play_client_pause(bool is_pause); virtual int on_play_client_pause(bool is_pause);
}; };
/** /**
@ -164,33 +164,33 @@ public:
class SrsGopCache class SrsGopCache
{ {
private: private:
/** /**
* if disabled the gop cache, * if disabled the gop cache,
* the client will wait for the next keyframe for h264, * the client will wait for the next keyframe for h264,
* and will be black-screen. * and will be black-screen.
*/ */
bool enable_gop_cache; bool enable_gop_cache;
/** /**
* the video frame count, avoid cache for pure audio stream. * the video frame count, avoid cache for pure audio stream.
*/ */
int cached_video_count; int cached_video_count;
/** /**
* cached gop. * cached gop.
*/ */
std::vector<SrsSharedPtrMessage*> gop_cache; std::vector<SrsSharedPtrMessage*> gop_cache;
public: public:
SrsGopCache(); SrsGopCache();
virtual ~SrsGopCache(); virtual ~SrsGopCache();
public: public:
virtual void set(bool enabled); virtual void set(bool enabled);
/** /**
* only for h264 codec * only for h264 codec
* 1. cache the gop when got h264 video packet. * 1. cache the gop when got h264 video packet.
* 2. clear gop when got keyframe. * 2. clear gop when got keyframe.
*/ */
virtual int cache(SrsSharedPtrMessage* msg); virtual int cache(SrsSharedPtrMessage* msg);
virtual void clear(); virtual void clear();
virtual int dump(SrsConsumer* consumer, int tba, int tbv); virtual int dump(SrsConsumer* consumer, int tba, int tbv);
}; };
/** /**
@ -199,89 +199,89 @@ public:
class SrsSource : public ISrsReloadHandler class SrsSource : public ISrsReloadHandler
{ {
private: private:
static std::map<std::string, SrsSource*> pool; static std::map<std::string, SrsSource*> pool;
public: public:
/** /**
* find stream by vhost/app/stream. * find stream by vhost/app/stream.
* @param req the client request. * @param req the client request.
* @return the matched source, never be NULL. * @return the matched source, never be NULL.
* @remark stream_url should without port and schema. * @remark stream_url should without port and schema.
*/ */
static SrsSource* find(SrsRequest* req); static SrsSource* find(SrsRequest* req);
private: private:
// deep copy of client request. // deep copy of client request.
SrsRequest* req; SrsRequest* req;
// to delivery stream to clients. // to delivery stream to clients.
std::vector<SrsConsumer*> consumers; std::vector<SrsConsumer*> consumers;
// hls handler. // hls handler.
#ifdef SRS_HLS #ifdef SRS_HLS
SrsHls* hls; SrsHls* hls;
#endif #endif
// transcoding handler. // transcoding handler.
#ifdef SRS_FFMPEG #ifdef SRS_FFMPEG
SrsEncoder* encoder; SrsEncoder* encoder;
#endif #endif
// gop cache for client fast startup. // gop cache for client fast startup.
SrsGopCache* gop_cache; SrsGopCache* gop_cache;
// to forward stream to other servers // to forward stream to other servers
std::vector<SrsForwarder*> forwarders; std::vector<SrsForwarder*> forwarders;
private: private:
/** /**
* the sample rate of audio in metadata. * the sample rate of audio in metadata.
*/ */
int sample_rate; int sample_rate;
/** /**
* the video frame rate in metadata. * the video frame rate in metadata.
*/ */
int frame_rate; int frame_rate;
/** /**
* can publish, true when is not streaming * can publish, true when is not streaming
*/ */
bool _can_publish; bool _can_publish;
private: private:
SrsSharedPtrMessage* cache_metadata; SrsSharedPtrMessage* cache_metadata;
// the cached video sequence header. // the cached video sequence header.
SrsSharedPtrMessage* cache_sh_video; SrsSharedPtrMessage* cache_sh_video;
// the cached audio sequence header. // the cached audio sequence header.
SrsSharedPtrMessage* cache_sh_audio; SrsSharedPtrMessage* cache_sh_audio;
public: public:
/** /**
* @param _req the client request object, * @param _req the client request object,
* this object will deep copy it for reload. * this object will deep copy it for reload.
*/ */
SrsSource(SrsRequest* _req); SrsSource(SrsRequest* _req);
virtual ~SrsSource(); virtual ~SrsSource();
// interface ISrsReloadHandler // interface ISrsReloadHandler
public: public:
virtual int on_reload_gop_cache(std::string vhost); virtual int on_reload_gop_cache(std::string vhost);
virtual int on_reload_queue_length(std::string vhost); virtual int on_reload_queue_length(std::string vhost);
virtual int on_reload_forward(std::string vhost); virtual int on_reload_forward(std::string vhost);
virtual int on_reload_hls(std::string vhost); virtual int on_reload_hls(std::string vhost);
virtual int on_reload_transcode(std::string vhost); virtual int on_reload_transcode(std::string vhost);
public: public:
// for the SrsForwarder to callback to request the sequence headers. // for the SrsForwarder to callback to request the sequence headers.
virtual int on_forwarder_start(SrsForwarder* forwarder); virtual int on_forwarder_start(SrsForwarder* forwarder);
// for the SrsHls to callback to request the sequence headers. // for the SrsHls to callback to request the sequence headers.
virtual int on_hls_start(); virtual int on_hls_start();
public: public:
virtual bool can_publish(); virtual bool can_publish();
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
virtual int on_audio(SrsCommonMessage* audio); virtual int on_audio(SrsCommonMessage* audio);
virtual int on_video(SrsCommonMessage* video); virtual int on_video(SrsCommonMessage* video);
/** /**
* publish stream event notify. * publish stream event notify.
* @param _req the request from client, the source will deep copy it, * @param _req the request from client, the source will deep copy it,
* for when reload the request of client maybe invalid. * for when reload the request of client maybe invalid.
*/ */
virtual int on_publish(SrsRequest* _req); virtual int on_publish(SrsRequest* _req);
virtual void on_unpublish(); virtual void on_unpublish();
public: public:
virtual int create_consumer(SrsConsumer*& consumer); virtual int create_consumer(SrsConsumer*& consumer);
virtual void on_consumer_destroy(SrsConsumer* consumer); virtual void on_consumer_destroy(SrsConsumer* consumer);
virtual void set_cache(bool enabled); virtual void set_cache(bool enabled);
private: private:
virtual int create_forwarders(); virtual int create_forwarders();
virtual void destroy_forwarders(); virtual void destroy_forwarders();
}; };
#endif #endif

View file

@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
void srs_close_stfd(st_netfd_t& stfd) void srs_close_stfd(st_netfd_t& stfd)
{ {
if (stfd) { if (stfd) {
int fd = st_netfd_fileno(stfd); int fd = st_netfd_fileno(stfd);
st_netfd_close(stfd); st_netfd_close(stfd);
stfd = NULL; stfd = NULL;
// st does not close it sometimes, // st does not close it sometimes,
// close it manually. // close it manually.
close(fd); close(fd);
} }
} }

View file

@ -40,14 +40,14 @@ void ISrsThreadHandler::on_enter_loop()
int ISrsThreadHandler::on_before_cycle() int ISrsThreadHandler::on_before_cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
return ret; return ret;
} }
int ISrsThreadHandler::on_end_cycle() int ISrsThreadHandler::on_end_cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
return ret; return ret;
} }
void ISrsThreadHandler::on_leave_loop() void ISrsThreadHandler::on_leave_loop()
@ -56,21 +56,21 @@ void ISrsThreadHandler::on_leave_loop()
SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us) SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us)
{ {
handler = thread_handler; handler = thread_handler;
cycle_interval_us = interval_us; cycle_interval_us = interval_us;
tid = NULL; tid = NULL;
loop = false; loop = false;
} }
SrsThread::~SrsThread() SrsThread::~SrsThread()
{ {
stop(); stop();
} }
int SrsThread::start() int SrsThread::start()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if(tid) { if(tid) {
srs_info("thread already running."); srs_info("thread already running.");
@ -78,7 +78,7 @@ int SrsThread::start()
} }
if((tid = st_thread_create(thread_fun, this, 1, 0)) == NULL){ if((tid = st_thread_create(thread_fun, this, 1, 0)) == NULL){
ret = ERROR_ST_CREATE_CYCLE_THREAD; ret = ERROR_ST_CREATE_CYCLE_THREAD;
srs_error("st_thread_create failed. ret=%d", ret); srs_error("st_thread_create failed. ret=%d", ret);
return ret; return ret;
} }
@ -88,74 +88,74 @@ int SrsThread::start()
void SrsThread::stop() void SrsThread::stop()
{ {
if (tid) { if (tid) {
loop = false; loop = false;
// the interrupt will cause the socket to read/write error, // the interrupt will cause the socket to read/write error,
// which will terminate the cycle thread. // which will terminate the cycle thread.
st_thread_interrupt(tid); st_thread_interrupt(tid);
// wait the thread to exit. // wait the thread to exit.
st_thread_join(tid, NULL); st_thread_join(tid, NULL);
tid = NULL; tid = NULL;
} }
} }
bool SrsThread::can_loop() bool SrsThread::can_loop()
{ {
return loop; return loop;
} }
void SrsThread::thread_cycle() void SrsThread::thread_cycle()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(handler); srs_assert(handler);
_srs_context->generate_id(); _srs_context->generate_id();
srs_trace("thread cycle start"); srs_trace("thread cycle start");
handler->on_end_cycle(); handler->on_end_cycle();
loop = true; loop = true;
while (loop) { while (loop) {
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) { if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret); srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
goto failed; goto failed;
} }
srs_info("thread on before cycle success"); srs_info("thread on before cycle success");
if ((ret = handler->cycle()) != ERROR_SUCCESS) { if ((ret = handler->cycle()) != ERROR_SUCCESS) {
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret); srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
goto failed; goto failed;
} }
srs_info("thread cycle success"); srs_info("thread cycle success");
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) { if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret); srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
goto failed; goto failed;
} }
srs_info("thread on end cycle success"); srs_info("thread on end cycle success");
failed: failed:
if (!loop) { if (!loop) {
break; break;
} }
st_usleep(cycle_interval_us); st_usleep(cycle_interval_us);
} }
handler->on_leave_loop(); handler->on_leave_loop();
srs_trace("thread cycle finished"); srs_trace("thread cycle finished");
} }
void* SrsThread::thread_fun(void* arg) void* SrsThread::thread_fun(void* arg)
{ {
SrsThread* obj = (SrsThread*)arg; SrsThread* obj = (SrsThread*)arg;
srs_assert(obj); srs_assert(obj);
obj->thread_cycle(); obj->thread_cycle();
return NULL; return NULL;
} }

View file

@ -34,14 +34,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/** /**
* the handler for the thread, callback interface. * the handler for the thread, callback interface.
* the thread model defines as: * the thread model defines as:
* handler->on_enter_loop() * handler->on_enter_loop()
* while loop: * while loop:
* handler->on_before_cycle() * handler->on_before_cycle()
* handler->cycle() * handler->cycle()
* handler->on_end_cycle() * handler->on_end_cycle()
* if !loop then break for user stop thread. * if !loop then break for user stop thread.
* sleep(CycleIntervalMilliseconds) * sleep(CycleIntervalMilliseconds)
* handler->on_leave_loop() * handler->on_leave_loop()
* when stop, the thread will interrupt the st_thread, * when stop, the thread will interrupt the st_thread,
* which will cause the socket to return error and * which will cause the socket to return error and
* terminate the cycle thread. * terminate the cycle thread.
@ -49,31 +49,31 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* when thread interrupt, the socket maybe not got EINT, * when thread interrupt, the socket maybe not got EINT,
* espectially on st_usleep(), so the cycle must check the loop, * espectially on st_usleep(), so the cycle must check the loop,
* when handler->cycle() has loop itself, for example: * when handler->cycle() has loop itself, for example:
* handler->cycle() is: * handler->cycle() is:
* while (true): * while (true):
* st_usleep(0); * st_usleep(0);
* if (read_from_socket(skt) < 0) break; * if (read_from_socket(skt) < 0) break;
* if thread stop when read_from_socket, it's ok, the loop will break, * if thread stop when read_from_socket, it's ok, the loop will break,
* but when thread stop interrupt the s_usleep(0), then the loop is * but when thread stop interrupt the s_usleep(0), then the loop is
* death loop. * death loop.
* in a word, the handler->cycle() must: * in a word, the handler->cycle() must:
* handler->cycle() is: * handler->cycle() is:
* while (pthread->can_loop()): * while (pthread->can_loop()):
* st_usleep(0); * st_usleep(0);
* if (read_from_socket(skt) < 0) break; * if (read_from_socket(skt) < 0) break;
* check the loop, then it works. * check the loop, then it works.
*/ */
class ISrsThreadHandler class ISrsThreadHandler
{ {
public: public:
ISrsThreadHandler(); ISrsThreadHandler();
virtual ~ISrsThreadHandler(); virtual ~ISrsThreadHandler();
public: public:
virtual void on_enter_loop(); virtual void on_enter_loop();
virtual int on_before_cycle(); virtual int on_before_cycle();
virtual int cycle() = 0; virtual int cycle() = 0;
virtual int on_end_cycle(); virtual int on_end_cycle();
virtual void on_leave_loop(); virtual void on_leave_loop();
}; };
/** /**
@ -83,41 +83,41 @@ public:
class SrsThread class SrsThread
{ {
private: private:
st_thread_t tid; st_thread_t tid;
bool loop; bool loop;
private: private:
ISrsThreadHandler* handler; ISrsThreadHandler* handler;
int64_t cycle_interval_us; int64_t cycle_interval_us;
public: public:
/** /**
* initialize the thread. * initialize the thread.
* @param thread_handler, the cycle handler for the thread. * @param thread_handler, the cycle handler for the thread.
* @param interval_us, the sleep interval when cycle finished. * @param interval_us, the sleep interval when cycle finished.
*/ */
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us); SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
virtual ~SrsThread(); virtual ~SrsThread();
public: public:
/** /**
* start the thread, invoke the cycle of handler util * start the thread, invoke the cycle of handler util
* user stop the thread. * user stop the thread.
* @remark ignore any error of cycle of handler. * @remark ignore any error of cycle of handler.
* @remark user can start multiple times, ignore if already started. * @remark user can start multiple times, ignore if already started.
*/ */
virtual int start(); virtual int start();
/** /**
* stop the thread, wait for the thread to terminate. * stop the thread, wait for the thread to terminate.
* @remark user can stop multiple times, ignore if already stopped. * @remark user can stop multiple times, ignore if already stopped.
*/ */
virtual void stop(); virtual void stop();
/** /**
* whether the thread should loop, * whether the thread should loop,
* used for handler->cycle() which has a loop method, * used for handler->cycle() which has a loop method,
* to check this method, break if false. * to check this method, break if false.
*/ */
virtual bool can_loop(); virtual bool can_loop();
private: private:
virtual void thread_cycle(); virtual void thread_cycle();
static void* thread_fun(void* arg); static void* thread_fun(void* arg);
}; };
#endif #endif

View file

@ -32,7 +32,7 @@ static int64_t _srs_system_time_us_cache = 0;
int64_t srs_get_system_time_ms() int64_t srs_get_system_time_ms()
{ {
return _srs_system_time_us_cache / 1000; return _srs_system_time_us_cache / 1000;
} }
void srs_update_system_time_ms() void srs_update_system_time_ms()
@ -49,19 +49,19 @@ void srs_update_system_time_ms()
std::string srs_replace(std::string str, std::string old_str, std::string new_str) std::string srs_replace(std::string str, std::string old_str, std::string new_str)
{ {
std::string ret = str; std::string ret = str;
if (old_str == new_str) { if (old_str == new_str) {
return ret; return ret;
} }
size_t pos = 0; size_t pos = 0;
while ((pos = ret.find(old_str, pos)) != std::string::npos) { while ((pos = ret.find(old_str, pos)) != std::string::npos) {
ret = ret.replace(pos, old_str.length(), new_str); ret = ret.replace(pos, old_str.length(), new_str);
pos += new_str.length(); pos += new_str.length();
} }
return ret; return ret;
} }
std::string srs_dns_resolve(std::string host) std::string srs_dns_resolve(std::string host)

View file

@ -69,18 +69,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// free the p and set to NULL. // free the p and set to NULL.
// p must be a T*. // p must be a T*.
#define srs_freep(p) \ #define srs_freep(p) \
if (p) { \ if (p) { \
delete p; \ delete p; \
p = NULL; \ p = NULL; \
} \ } \
(void)0 (void)0
// free the p which represents a array // free the p which represents a array
#define srs_freepa(p) \ #define srs_freepa(p) \
if (p) { \ if (p) { \
delete[] p; \ delete[] p; \
p = NULL; \ p = NULL; \
} \ } \
(void)0 (void)0
// compare // compare
#define srs_min(a, b) (((a) < (b))? (a) : (b)) #define srs_min(a, b) (((a) < (b))? (a) : (b))

View file

@ -34,7 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* auto free the instance in the current scope. * auto free the instance in the current scope.
*/ */
#define SrsAutoFree(className, instance, is_array) \ #define SrsAutoFree(className, instance, is_array) \
__SrsAutoFree<className> _auto_free_##instance(&instance, is_array) __SrsAutoFree<className> _auto_free_##instance(&instance, is_array)
template<class T> template<class T>
class __SrsAutoFree class __SrsAutoFree

View file

@ -46,46 +46,46 @@ SrsBuffer::~SrsBuffer()
int SrsBuffer::size() int SrsBuffer::size()
{ {
return (int)data.size(); return (int)data.size();
} }
char* SrsBuffer::bytes() char* SrsBuffer::bytes()
{ {
return &data.at(0); return &data.at(0);
} }
void SrsBuffer::erase(int size) void SrsBuffer::erase(int size)
{ {
data.erase(data.begin(), data.begin() + size); data.erase(data.begin(), data.begin() + size);
} }
void SrsBuffer::append(char* bytes, int size) void SrsBuffer::append(char* bytes, int size)
{ {
data.insert(data.end(), bytes, bytes + size); data.insert(data.end(), bytes, bytes + size);
} }
int SrsBuffer::ensure_buffer_bytes(ISrsBufferReader* skt, int required_size) int SrsBuffer::ensure_buffer_bytes(ISrsBufferReader* skt, int required_size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (required_size < 0) { if (required_size < 0) {
ret = ERROR_SYSTEM_SIZE_NEGATIVE; ret = ERROR_SYSTEM_SIZE_NEGATIVE;
srs_error("size is negative. size=%d, ret=%d", required_size, ret); srs_error("size is negative. size=%d, ret=%d", required_size, ret);
return ret; return ret;
} }
while (size() < required_size) { while (size() < required_size) {
char buffer[SOCKET_READ_SIZE]; char buffer[SOCKET_READ_SIZE];
ssize_t nread; ssize_t nread;
if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) { if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) {
return ret; return ret;
} }
srs_assert((int)nread > 0); srs_assert((int)nread > 0);
append(buffer, (int)nread); append(buffer, (int)nread);
} }
return ret; return ret;
} }

View file

@ -38,8 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsBufferReader class ISrsBufferReader
{ {
public: public:
ISrsBufferReader(); ISrsBufferReader();
virtual ~ISrsBufferReader(); virtual ~ISrsBufferReader();
// for protocol/amf0/msg-codec // for protocol/amf0/msg-codec
public: public:
virtual int read(const void* buf, size_t size, ssize_t* nread) = 0; virtual int read(const void* buf, size_t size, ssize_t* nread) = 0;
@ -53,18 +53,18 @@ public:
class SrsBuffer class SrsBuffer
{ {
private: private:
std::vector<char> data; std::vector<char> data;
public: public:
SrsBuffer(); SrsBuffer();
virtual ~SrsBuffer(); virtual ~SrsBuffer();
public: public:
virtual int size(); virtual int size();
virtual char* bytes(); virtual char* bytes();
virtual void erase(int size); virtual void erase(int size);
private: private:
virtual void append(char* bytes, int size); virtual void append(char* bytes, int size);
public: public:
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size); virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
}; };
#endif #endif

View file

@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bool srs_is_system_control_error(int error_code) bool srs_is_system_control_error(int error_code)
{ {
return error_code == ERROR_CONTROL_RTMP_CLOSE return error_code == ERROR_CONTROL_RTMP_CLOSE
|| error_code == ERROR_CONTROL_REPUBLISH; || error_code == ERROR_CONTROL_REPUBLISH;
} }
bool srs_is_client_gracefully_close(int error_code) bool srs_is_client_gracefully_close(int error_code)
{ {
return error_code == ERROR_SOCKET_READ return error_code == ERROR_SOCKET_READ
|| error_code == ERROR_SOCKET_READ_FULLY || error_code == ERROR_SOCKET_READ_FULLY
|| error_code == ERROR_SOCKET_WRITE; || error_code == ERROR_SOCKET_WRITE;
} }

View file

@ -30,133 +30,133 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp> #include <srs_core.hpp>
#define ERROR_SUCCESS 0 #define ERROR_SUCCESS 0
#define ERROR_ST_SET_EPOLL 100 #define ERROR_ST_SET_EPOLL 100
#define ERROR_ST_INITIALIZE 101 #define ERROR_ST_INITIALIZE 101
#define ERROR_ST_OPEN_SOCKET 102 #define ERROR_ST_OPEN_SOCKET 102
#define ERROR_ST_CREATE_LISTEN_THREAD 103 #define ERROR_ST_CREATE_LISTEN_THREAD 103
#define ERROR_ST_CREATE_CYCLE_THREAD 104 #define ERROR_ST_CREATE_CYCLE_THREAD 104
#define ERROR_ST_CONNECT 105 #define ERROR_ST_CONNECT 105
#define ERROR_SOCKET_CREATE 200 #define ERROR_SOCKET_CREATE 200
#define ERROR_SOCKET_SETREUSE 201 #define ERROR_SOCKET_SETREUSE 201
#define ERROR_SOCKET_BIND 202 #define ERROR_SOCKET_BIND 202
#define ERROR_SOCKET_LISTEN 203 #define ERROR_SOCKET_LISTEN 203
#define ERROR_SOCKET_CLOSED 204 #define ERROR_SOCKET_CLOSED 204
#define ERROR_SOCKET_GET_PEER_NAME 205 #define ERROR_SOCKET_GET_PEER_NAME 205
#define ERROR_SOCKET_GET_PEER_IP 206 #define ERROR_SOCKET_GET_PEER_IP 206
#define ERROR_SOCKET_READ 207 #define ERROR_SOCKET_READ 207
#define ERROR_SOCKET_READ_FULLY 208 #define ERROR_SOCKET_READ_FULLY 208
#define ERROR_SOCKET_WRITE 209 #define ERROR_SOCKET_WRITE 209
#define ERROR_SOCKET_WAIT 210 #define ERROR_SOCKET_WAIT 210
#define ERROR_SOCKET_TIMEOUT 211 #define ERROR_SOCKET_TIMEOUT 211
#define ERROR_SOCKET_GET_LOCAL_IP 212 #define ERROR_SOCKET_GET_LOCAL_IP 212
#define ERROR_RTMP_PLAIN_REQUIRED 300 #define ERROR_RTMP_PLAIN_REQUIRED 300
#define ERROR_RTMP_CHUNK_START 301 #define ERROR_RTMP_CHUNK_START 301
#define ERROR_RTMP_MSG_INVLIAD_SIZE 302 #define ERROR_RTMP_MSG_INVLIAD_SIZE 302
#define ERROR_RTMP_AMF0_DECODE 303 #define ERROR_RTMP_AMF0_DECODE 303
#define ERROR_RTMP_AMF0_INVALID 304 #define ERROR_RTMP_AMF0_INVALID 304
#define ERROR_RTMP_REQ_CONNECT 305 #define ERROR_RTMP_REQ_CONNECT 305
#define ERROR_RTMP_REQ_TCURL 306 #define ERROR_RTMP_REQ_TCURL 306
#define ERROR_RTMP_MESSAGE_DECODE 307 #define ERROR_RTMP_MESSAGE_DECODE 307
#define ERROR_RTMP_MESSAGE_ENCODE 308 #define ERROR_RTMP_MESSAGE_ENCODE 308
#define ERROR_RTMP_AMF0_ENCODE 309 #define ERROR_RTMP_AMF0_ENCODE 309
#define ERROR_RTMP_CHUNK_SIZE 310 #define ERROR_RTMP_CHUNK_SIZE 310
#define ERROR_RTMP_TRY_SIMPLE_HS 311 #define ERROR_RTMP_TRY_SIMPLE_HS 311
#define ERROR_RTMP_CH_SCHEMA 312 #define ERROR_RTMP_CH_SCHEMA 312
#define ERROR_RTMP_PACKET_SIZE 313 #define ERROR_RTMP_PACKET_SIZE 313
#define ERROR_RTMP_VHOST_NOT_FOUND 314 #define ERROR_RTMP_VHOST_NOT_FOUND 314
#define ERROR_RTMP_ACCESS_DENIED 315 #define ERROR_RTMP_ACCESS_DENIED 315
#define ERROR_RTMP_HANDSHAKE 316 #define ERROR_RTMP_HANDSHAKE 316
#define ERROR_RTMP_NO_REQUEST 317 #define ERROR_RTMP_NO_REQUEST 317
// if user use complex handshake, but without ssl, // if user use complex handshake, but without ssl,
// 1. srs is ok, ignore and turn to simple handshake. // 1. srs is ok, ignore and turn to simple handshake.
// 2. srs-librtmp return error, to terminate the program. // 2. srs-librtmp return error, to terminate the program.
#define ERROR_RTMP_HS_SSL_REQUIRE 318 #define ERROR_RTMP_HS_SSL_REQUIRE 318
#define ERROR_SYSTEM_STREAM_INIT 400 #define ERROR_SYSTEM_STREAM_INIT 400
#define ERROR_SYSTEM_PACKET_INVALID 401 #define ERROR_SYSTEM_PACKET_INVALID 401
#define ERROR_SYSTEM_CLIENT_INVALID 402 #define ERROR_SYSTEM_CLIENT_INVALID 402
#define ERROR_SYSTEM_ASSERT_FAILED 403 #define ERROR_SYSTEM_ASSERT_FAILED 403
#define ERROR_SYSTEM_SIZE_NEGATIVE 404 #define ERROR_SYSTEM_SIZE_NEGATIVE 404
#define ERROR_SYSTEM_CONFIG_INVALID 405 #define ERROR_SYSTEM_CONFIG_INVALID 405
#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406 #define ERROR_SYSTEM_CONFIG_DIRECTIVE 406
#define ERROR_SYSTEM_CONFIG_BLOCK_START 407 #define ERROR_SYSTEM_CONFIG_BLOCK_START 407
#define ERROR_SYSTEM_CONFIG_BLOCK_END 408 #define ERROR_SYSTEM_CONFIG_BLOCK_END 408
#define ERROR_SYSTEM_CONFIG_EOF 409 #define ERROR_SYSTEM_CONFIG_EOF 409
#define ERROR_SYSTEM_STREAM_BUSY 410 #define ERROR_SYSTEM_STREAM_BUSY 410
#define ERROR_SYSTEM_IP_INVALID 411 #define ERROR_SYSTEM_IP_INVALID 411
#define ERROR_SYSTEM_FORWARD_LOOP 412 #define ERROR_SYSTEM_FORWARD_LOOP 412
#define ERROR_SYSTEM_WAITPID 413 #define ERROR_SYSTEM_WAITPID 413
#define ERROR_SYSTEM_BANDWIDTH_KEY 414 #define ERROR_SYSTEM_BANDWIDTH_KEY 414
#define ERROR_SYSTEM_BANDWIDTH_DENIED 415 #define ERROR_SYSTEM_BANDWIDTH_DENIED 415
// see librtmp. // see librtmp.
// failed when open ssl create the dh // failed when open ssl create the dh
#define ERROR_OpenSslCreateDH 500 #define ERROR_OpenSslCreateDH 500
// failed when open ssl create the Private key. // failed when open ssl create the Private key.
#define ERROR_OpenSslCreateP 501 #define ERROR_OpenSslCreateP 501
// when open ssl create G. // when open ssl create G.
#define ERROR_OpenSslCreateG 502 #define ERROR_OpenSslCreateG 502
// when open ssl parse P1024 // when open ssl parse P1024
#define ERROR_OpenSslParseP1024 503 #define ERROR_OpenSslParseP1024 503
// when open ssl set G // when open ssl set G
#define ERROR_OpenSslSetG 504 #define ERROR_OpenSslSetG 504
// when open ssl generate DHKeys // when open ssl generate DHKeys
#define ERROR_OpenSslGenerateDHKeys 505 #define ERROR_OpenSslGenerateDHKeys 505
// when open ssl share key already computed. // when open ssl share key already computed.
#define ERROR_OpenSslShareKeyComputed 506 #define ERROR_OpenSslShareKeyComputed 506
// when open ssl get shared key size. // when open ssl get shared key size.
#define ERROR_OpenSslGetSharedKeySize 507 #define ERROR_OpenSslGetSharedKeySize 507
// when open ssl get peer public key. // when open ssl get peer public key.
#define ERROR_OpenSslGetPeerPublicKey 508 #define ERROR_OpenSslGetPeerPublicKey 508
// when open ssl compute shared key. // when open ssl compute shared key.
#define ERROR_OpenSslComputeSharedKey 509 #define ERROR_OpenSslComputeSharedKey 509
// when open ssl is invalid DH state. // when open ssl is invalid DH state.
#define ERROR_OpenSslInvalidDHState 510 #define ERROR_OpenSslInvalidDHState 510
// when open ssl copy key // when open ssl copy key
#define ERROR_OpenSslCopyKey 511 #define ERROR_OpenSslCopyKey 511
// when open ssl sha256 digest key invalid size. // when open ssl sha256 digest key invalid size.
#define ERROR_OpenSslSha256DigestSize 512 #define ERROR_OpenSslSha256DigestSize 512
#define ERROR_HLS_METADATA 600 #define ERROR_HLS_METADATA 600
#define ERROR_HLS_DECODE_ERROR 601 #define ERROR_HLS_DECODE_ERROR 601
#define ERROR_HLS_CREATE_DIR 602 #define ERROR_HLS_CREATE_DIR 602
#define ERROR_HLS_OPEN_FAILED 603 #define ERROR_HLS_OPEN_FAILED 603
#define ERROR_HLS_WRITE_FAILED 604 #define ERROR_HLS_WRITE_FAILED 604
#define ERROR_HLS_AAC_FRAME_LENGTH 605 #define ERROR_HLS_AAC_FRAME_LENGTH 605
#define ERROR_HLS_AVC_SAMPLE_SIZE 606 #define ERROR_HLS_AVC_SAMPLE_SIZE 606
#define ERROR_ENCODER_VCODEC 700 #define ERROR_ENCODER_VCODEC 700
#define ERROR_ENCODER_OUTPUT 701 #define ERROR_ENCODER_OUTPUT 701
#define ERROR_ENCODER_ACHANNELS 702 #define ERROR_ENCODER_ACHANNELS 702
#define ERROR_ENCODER_ASAMPLE_RATE 703 #define ERROR_ENCODER_ASAMPLE_RATE 703
#define ERROR_ENCODER_ABITRATE 704 #define ERROR_ENCODER_ABITRATE 704
#define ERROR_ENCODER_ACODEC 705 #define ERROR_ENCODER_ACODEC 705
#define ERROR_ENCODER_VPRESET 706 #define ERROR_ENCODER_VPRESET 706
#define ERROR_ENCODER_VPROFILE 707 #define ERROR_ENCODER_VPROFILE 707
#define ERROR_ENCODER_VTHREADS 708 #define ERROR_ENCODER_VTHREADS 708
#define ERROR_ENCODER_VHEIGHT 709 #define ERROR_ENCODER_VHEIGHT 709
#define ERROR_ENCODER_VWIDTH 710 #define ERROR_ENCODER_VWIDTH 710
#define ERROR_ENCODER_VFPS 711 #define ERROR_ENCODER_VFPS 711
#define ERROR_ENCODER_VBITRATE 712 #define ERROR_ENCODER_VBITRATE 712
#define ERROR_ENCODER_FORK 713 #define ERROR_ENCODER_FORK 713
#define ERROR_ENCODER_LOOP 714 #define ERROR_ENCODER_LOOP 714
#define ERROR_ENCODER_OPEN 715 #define ERROR_ENCODER_OPEN 715
#define ERROR_ENCODER_DUP2 716 #define ERROR_ENCODER_DUP2 716
#define ERROR_HTTP_PARSE_URI 800 #define ERROR_HTTP_PARSE_URI 800
#define ERROR_HTTP_DATA_INVLIAD 801 #define ERROR_HTTP_DATA_INVLIAD 801
#define ERROR_HTTP_PARSE_HEADER 802 #define ERROR_HTTP_PARSE_HEADER 802
// system control message, // system control message,
// not an error, but special control logic. // not an error, but special control logic.
// sys ctl: rtmp close stream, support replay. // sys ctl: rtmp close stream, support replay.
#define ERROR_CONTROL_RTMP_CLOSE 900 #define ERROR_CONTROL_RTMP_CLOSE 900
// FMLE stop publish and republish. // FMLE stop publish and republish.
#define ERROR_CONTROL_REPUBLISH 901 #define ERROR_CONTROL_REPUBLISH 901
/** /**
* whether the error code is an system control error. * whether the error code is an system control error.

View file

@ -65,6 +65,6 @@ void ISrsThreadContext::generate_id()
int ISrsThreadContext::get_id() int ISrsThreadContext::get_id()
{ {
return 0; return 0;
} }

View file

@ -110,16 +110,16 @@ extern ISrsThreadContext* _srs_context;
#endif #endif
#if 1 #if 1
#undef srs_verbose #undef srs_verbose
#define srs_verbose(msg, ...) (void)0 #define srs_verbose(msg, ...) (void)0
#endif #endif
#if 1 #if 1
#undef srs_info #undef srs_info
#define srs_info(msg, ...) (void)0 #define srs_info(msg, ...) (void)0
#endif #endif
#if 0 #if 0
#undef srs_trace #undef srs_trace
#define srs_trace(msg, ...) (void)0 #define srs_trace(msg, ...) (void)0
#endif #endif
#endif #endif

View file

@ -28,8 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsStream::SrsStream() SrsStream::SrsStream()
{ {
p = bytes = NULL; p = bytes = NULL;
size = 0; size = 0;
} }
SrsStream::~SrsStream() SrsStream::~SrsStream()
@ -38,113 +38,113 @@ SrsStream::~SrsStream()
int SrsStream::initialize(char* _bytes, int _size) int SrsStream::initialize(char* _bytes, int _size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (!_bytes) { if (!_bytes) {
ret = ERROR_SYSTEM_STREAM_INIT; ret = ERROR_SYSTEM_STREAM_INIT;
srs_error("stream param bytes must not be NULL. ret=%d", ret); srs_error("stream param bytes must not be NULL. ret=%d", ret);
return ret; return ret;
} }
if (_size <= 0) { if (_size <= 0) {
ret = ERROR_SYSTEM_STREAM_INIT; ret = ERROR_SYSTEM_STREAM_INIT;
srs_error("stream param size must be positive. ret=%d", ret); srs_error("stream param size must be positive. ret=%d", ret);
return ret; return ret;
} }
size = _size; size = _size;
p = bytes = _bytes; p = bytes = _bytes;
return ret; return ret;
} }
void SrsStream::reset() void SrsStream::reset()
{ {
p = bytes; p = bytes;
} }
bool SrsStream::empty() bool SrsStream::empty()
{ {
return !p || !bytes || (p >= bytes + size); return !p || !bytes || (p >= bytes + size);
} }
bool SrsStream::require(int required_size) bool SrsStream::require(int required_size)
{ {
return !empty() && (required_size <= bytes + size - p); return !empty() && (required_size <= bytes + size - p);
} }
void SrsStream::skip(int size) void SrsStream::skip(int size)
{ {
p += size; p += size;
} }
int SrsStream::pos() int SrsStream::pos()
{ {
return p - bytes; return p - bytes;
} }
int SrsStream::left() int SrsStream::left()
{ {
return size - pos(); return size - pos();
} }
char* SrsStream::current() char* SrsStream::current()
{ {
return p; return p;
} }
int8_t SrsStream::read_1bytes() int8_t SrsStream::read_1bytes()
{ {
srs_assert(require(1)); srs_assert(require(1));
return (int8_t)*p++; return (int8_t)*p++;
} }
int16_t SrsStream::read_2bytes() int16_t SrsStream::read_2bytes()
{ {
srs_assert(require(2)); srs_assert(require(2));
int16_t value; int16_t value;
pp = (char*)&value; pp = (char*)&value;
pp[1] = *p++; pp[1] = *p++;
pp[0] = *p++; pp[0] = *p++;
return value; return value;
} }
int32_t SrsStream::read_3bytes() int32_t SrsStream::read_3bytes()
{ {
srs_assert(require(3)); srs_assert(require(3));
int32_t value = 0x00; int32_t value = 0x00;
pp = (char*)&value; pp = (char*)&value;
pp[2] = *p++; pp[2] = *p++;
pp[1] = *p++; pp[1] = *p++;
pp[0] = *p++; pp[0] = *p++;
return value; return value;
} }
int32_t SrsStream::read_4bytes() int32_t SrsStream::read_4bytes()
{ {
srs_assert(require(4)); srs_assert(require(4));
int32_t value; int32_t value;
pp = (char*)&value; pp = (char*)&value;
pp[3] = *p++; pp[3] = *p++;
pp[2] = *p++; pp[2] = *p++;
pp[1] = *p++; pp[1] = *p++;
pp[0] = *p++; pp[0] = *p++;
return value; return value;
} }
int64_t SrsStream::read_8bytes() int64_t SrsStream::read_8bytes()
{ {
srs_assert(require(8)); srs_assert(require(8));
int64_t value; int64_t value;
pp = (char*)&value; pp = (char*)&value;
pp[7] = *p++; pp[7] = *p++;
pp[6] = *p++; pp[6] = *p++;
pp[5] = *p++; pp[5] = *p++;
@ -154,68 +154,68 @@ int64_t SrsStream::read_8bytes()
pp[1] = *p++; pp[1] = *p++;
pp[0] = *p++; pp[0] = *p++;
return value; return value;
} }
std::string SrsStream::read_string(int len) std::string SrsStream::read_string(int len)
{ {
srs_assert(require(len)); srs_assert(require(len));
std::string value; std::string value;
value.append(p, len); value.append(p, len);
p += len; p += len;
return value; return value;
} }
void SrsStream::write_1bytes(int8_t value) void SrsStream::write_1bytes(int8_t value)
{ {
srs_assert(require(1)); srs_assert(require(1));
*p++ = value; *p++ = value;
} }
void SrsStream::write_2bytes(int16_t value) void SrsStream::write_2bytes(int16_t value)
{ {
srs_assert(require(2)); srs_assert(require(2));
pp = (char*)&value; pp = (char*)&value;
*p++ = pp[1]; *p++ = pp[1];
*p++ = pp[0]; *p++ = pp[0];
} }
void SrsStream::write_4bytes(int32_t value) void SrsStream::write_4bytes(int32_t value)
{ {
srs_assert(require(4)); srs_assert(require(4));
pp = (char*)&value; pp = (char*)&value;
*p++ = pp[3]; *p++ = pp[3];
*p++ = pp[2]; *p++ = pp[2];
*p++ = pp[1]; *p++ = pp[1];
*p++ = pp[0]; *p++ = pp[0];
} }
void SrsStream::write_8bytes(int64_t value) void SrsStream::write_8bytes(int64_t value)
{ {
srs_assert(require(8)); srs_assert(require(8));
pp = (char*)&value; pp = (char*)&value;
*p++ = pp[7]; *p++ = pp[7];
*p++ = pp[6]; *p++ = pp[6];
*p++ = pp[5]; *p++ = pp[5];
*p++ = pp[4]; *p++ = pp[4];
*p++ = pp[3]; *p++ = pp[3];
*p++ = pp[2]; *p++ = pp[2];
*p++ = pp[1]; *p++ = pp[1];
*p++ = pp[0]; *p++ = pp[0];
} }
void SrsStream::write_string(std::string value) void SrsStream::write_string(std::string value)
{ {
srs_assert(require(value.length())); srs_assert(require(value.length()));
memcpy(p, value.data(), value.length()); memcpy(p, value.data(), value.length());
p += value.length(); p += value.length();
} }

View file

@ -36,95 +36,95 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsStream class SrsStream
{ {
private: private:
char* p; char* p;
char* pp; char* pp;
char* bytes; char* bytes;
int size; int size;
public: public:
SrsStream(); SrsStream();
virtual ~SrsStream(); virtual ~SrsStream();
public: public:
/** /**
* initialize the stream from bytes. * initialize the stream from bytes.
* @_bytes, must not be NULL, or return error. * @_bytes, must not be NULL, or return error.
* @_size, must be positive, or return error. * @_size, must be positive, or return error.
* @remark, stream never free the _bytes, user must free it. * @remark, stream never free the _bytes, user must free it.
*/ */
virtual int initialize(char* _bytes, int _size); virtual int initialize(char* _bytes, int _size);
/** /**
* reset the position to beginning. * reset the position to beginning.
*/ */
virtual void reset(); virtual void reset();
/** /**
* whether stream is empty. * whether stream is empty.
* if empty, never read or write. * if empty, never read or write.
*/ */
virtual bool empty(); virtual bool empty();
/** /**
* whether required size is ok. * whether required size is ok.
* @return true if stream can read/write specified required_size bytes. * @return true if stream can read/write specified required_size bytes.
*/ */
virtual bool require(int required_size); virtual bool require(int required_size);
/** /**
* to skip some size. * to skip some size.
* @size can be any value. positive to forward; nagetive to backward. * @size can be any value. positive to forward; nagetive to backward.
*/ */
virtual void skip(int size); virtual void skip(int size);
/** /**
* tell the current pos. * tell the current pos.
*/ */
virtual int pos(); virtual int pos();
/** /**
* left size of bytes. * left size of bytes.
*/ */
virtual int left(); virtual int left();
virtual char* current(); virtual char* current();
public: public:
/** /**
* get 1bytes char from stream. * get 1bytes char from stream.
*/ */
virtual int8_t read_1bytes(); virtual int8_t read_1bytes();
/** /**
* get 2bytes int from stream. * get 2bytes int from stream.
*/ */
virtual int16_t read_2bytes(); virtual int16_t read_2bytes();
/** /**
* get 3bytes int from stream. * get 3bytes int from stream.
*/ */
virtual int32_t read_3bytes(); virtual int32_t read_3bytes();
/** /**
* get 4bytes int from stream. * get 4bytes int from stream.
*/ */
virtual int32_t read_4bytes(); virtual int32_t read_4bytes();
/** /**
* get 8bytes int from stream. * get 8bytes int from stream.
*/ */
virtual int64_t read_8bytes(); virtual int64_t read_8bytes();
/** /**
* get string from stream, length specifies by param len. * get string from stream, length specifies by param len.
*/ */
virtual std::string read_string(int len); virtual std::string read_string(int len);
public: public:
/** /**
* write 1bytes char to stream. * write 1bytes char to stream.
*/ */
virtual void write_1bytes(int8_t value); virtual void write_1bytes(int8_t value);
/** /**
* write 2bytes int to stream. * write 2bytes int to stream.
*/ */
virtual void write_2bytes(int16_t value); virtual void write_2bytes(int16_t value);
/** /**
* write 4bytes int to stream. * write 4bytes int to stream.
*/ */
virtual void write_4bytes(int32_t value); virtual void write_4bytes(int32_t value);
/** /**
* write 8bytes int to stream. * write 8bytes int to stream.
*/ */
virtual void write_8bytes(int64_t value); virtual void write_8bytes(int64_t value);
/** /**
* write string to stream * write string to stream
*/ */
virtual void write_string(std::string value); virtual void write_string(std::string value);
}; };
#endif #endif

View file

@ -34,25 +34,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <sys/uio.h> #include <sys/uio.h>
#ifndef ST_UTIME_NO_TIMEOUT #ifndef ST_UTIME_NO_TIMEOUT
#define ST_UTIME_NO_TIMEOUT -1 #define ST_UTIME_NO_TIMEOUT -1
#endif #endif
SimpleSocketStream::SimpleSocketStream() SimpleSocketStream::SimpleSocketStream()
{ {
fd = -1; fd = -1;
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
recv_bytes = send_bytes = 0; recv_bytes = send_bytes = 0;
srs_update_system_time_ms(); srs_update_system_time_ms();
start_time_ms = srs_get_system_time_ms(); start_time_ms = srs_get_system_time_ms();
} }
SimpleSocketStream::~SimpleSocketStream() SimpleSocketStream::~SimpleSocketStream()
{ {
if (fd != -1) { if (fd != -1) {
::close(fd); ::close(fd);
fd = -1; fd = -1;
} }
} }
int SimpleSocketStream::create_socket() int SimpleSocketStream::create_socket()
@ -61,7 +61,7 @@ int SimpleSocketStream::create_socket()
return -1; return -1;
} }
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
int SimpleSocketStream::connect(const char* server_ip, int port) int SimpleSocketStream::connect(const char* server_ip, int port)
@ -75,22 +75,22 @@ int SimpleSocketStream::connect(const char* server_ip, int port)
return -1; return -1;
} }
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
// ISrsBufferReader // ISrsBufferReader
int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread) int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
*nread = ::recv(fd, (void*)buf, size, 0); *nread = ::recv(fd, (void*)buf, size, 0);
// On success a non-negative integer indicating the number of bytes actually read is returned // On success a non-negative integer indicating the number of bytes actually read is returned
// (a value of 0 means the network connection is closed or end of file is reached). // (a value of 0 means the network connection is closed or end of file is reached).
if (*nread <= 0) { if (*nread <= 0) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
if (*nread == 0) { if (*nread == 0) {
errno = ECONNRESET; errno = ECONNRESET;
@ -101,130 +101,130 @@ int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
recv_bytes += *nread; recv_bytes += *nread;
return ret; return ret;
} }
// ISrsProtocolReader // ISrsProtocolReader
void SimpleSocketStream::set_recv_timeout(int64_t timeout_us) void SimpleSocketStream::set_recv_timeout(int64_t timeout_us)
{ {
recv_timeout = timeout_us; recv_timeout = timeout_us;
} }
int64_t SimpleSocketStream::get_recv_timeout() int64_t SimpleSocketStream::get_recv_timeout()
{ {
return recv_timeout; return recv_timeout;
} }
int64_t SimpleSocketStream::get_recv_bytes() int64_t SimpleSocketStream::get_recv_bytes()
{ {
return recv_bytes; return recv_bytes;
} }
int SimpleSocketStream::get_recv_kbps() int SimpleSocketStream::get_recv_kbps()
{ {
srs_update_system_time_ms(); srs_update_system_time_ms();
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) { if (diff_ms <= 0) {
return 0; return 0;
} }
return recv_bytes * 8 / diff_ms; return recv_bytes * 8 / diff_ms;
} }
// ISrsProtocolWriter // ISrsProtocolWriter
void SimpleSocketStream::set_send_timeout(int64_t timeout_us) void SimpleSocketStream::set_send_timeout(int64_t timeout_us)
{ {
send_timeout = timeout_us; send_timeout = timeout_us;
} }
int64_t SimpleSocketStream::get_send_timeout() int64_t SimpleSocketStream::get_send_timeout()
{ {
return send_timeout; return send_timeout;
} }
int64_t SimpleSocketStream::get_send_bytes() int64_t SimpleSocketStream::get_send_bytes()
{ {
return send_bytes; return send_bytes;
} }
int SimpleSocketStream::get_send_kbps() int SimpleSocketStream::get_send_kbps()
{ {
srs_update_system_time_ms(); srs_update_system_time_ms();
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
if (diff_ms <= 0) { if (diff_ms <= 0) {
return 0; return 0;
} }
return send_bytes * 8 / diff_ms; return send_bytes * 8 / diff_ms;
} }
int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite) int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
*nwrite = ::writev(fd, iov, iov_size); *nwrite = ::writev(fd, iov, iov_size);
if (*nwrite <= 0) { if (*nwrite <= 0) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
return ERROR_SOCKET_WRITE; return ERROR_SOCKET_WRITE;
} }
send_bytes += *nwrite; send_bytes += *nwrite;
return ret; return ret;
} }
// ISrsProtocolReaderWriter // ISrsProtocolReaderWriter
bool SimpleSocketStream::is_never_timeout(int64_t timeout_us) bool SimpleSocketStream::is_never_timeout(int64_t timeout_us)
{ {
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
} }
int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread) int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
size_t left = size; size_t left = size;
*nread = 0; *nread = 0;
while (left > 0) { while (left > 0) {
char* this_buf = (char*)buf + *nread; char* this_buf = (char*)buf + *nread;
ssize_t this_nread; ssize_t this_nread;
if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) { if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) {
return ret; return ret;
} }
*nread += this_nread; *nread += this_nread;
left -= this_nread; left -= this_nread;
} }
recv_bytes += *nread; recv_bytes += *nread;
return ret; return ret;
} }
int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite) int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
*nwrite = ::send(fd, (void*)buf, size, 0); *nwrite = ::send(fd, (void*)buf, size, 0);
if (*nwrite <= 0) { if (*nwrite <= 0) {
if (errno == ETIME) { if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT; return ERROR_SOCKET_TIMEOUT;
} }
return ERROR_SOCKET_WRITE; return ERROR_SOCKET_WRITE;
} }
send_bytes += *nwrite; send_bytes += *nwrite;
return ret; return ret;
} }

View file

@ -39,37 +39,37 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SimpleSocketStream : public ISrsProtocolReaderWriter class SimpleSocketStream : public ISrsProtocolReaderWriter
{ {
private: private:
int64_t start_time_ms; int64_t start_time_ms;
int64_t recv_timeout; int64_t recv_timeout;
int64_t send_timeout; int64_t send_timeout;
int64_t recv_bytes; int64_t recv_bytes;
int64_t send_bytes; int64_t send_bytes;
int fd; int fd;
public: public:
SimpleSocketStream(); SimpleSocketStream();
virtual ~SimpleSocketStream(); virtual ~SimpleSocketStream();
public: public:
virtual int create_socket(); virtual int create_socket();
virtual int connect(const char* server, int port); virtual int connect(const char* server, int port);
// ISrsBufferReader // ISrsBufferReader
public: public:
virtual int read(const void* buf, size_t size, ssize_t* nread); virtual int read(const void* buf, size_t size, ssize_t* nread);
// ISrsProtocolReader // ISrsProtocolReader
public: public:
virtual void set_recv_timeout(int64_t timeout_us); virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout(); virtual int64_t get_recv_timeout();
virtual int64_t get_recv_bytes(); virtual int64_t get_recv_bytes();
virtual int get_recv_kbps(); virtual int get_recv_kbps();
// ISrsProtocolWriter // ISrsProtocolWriter
public: public:
virtual void set_send_timeout(int64_t timeout_us); virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout(); virtual int64_t get_send_timeout();
virtual int64_t get_send_bytes(); virtual int64_t get_send_bytes();
virtual int get_send_kbps(); virtual int get_send_kbps();
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite); virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
// ISrsProtocolReaderWriter // ISrsProtocolReaderWriter
public: public:
virtual bool is_never_timeout(int64_t timeout_us); virtual bool is_never_timeout(int64_t timeout_us);
virtual int read_fully(const void* buf, size_t size, ssize_t* nread); virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
virtual int write(const void* buf, size_t size, ssize_t* nwrite); virtual int write(const void* buf, size_t size, ssize_t* nwrite);
}; };

View file

@ -38,9 +38,9 @@ using namespace std;
// if user want to define log, define the folowing macro. // if user want to define log, define the folowing macro.
#ifndef SRS_RTMP_USER_DEFINED_LOG #ifndef SRS_RTMP_USER_DEFINED_LOG
// kernel module. // kernel module.
ISrsLog* _srs_log = new ISrsLog(); ISrsLog* _srs_log = new ISrsLog();
ISrsThreadContext* _srs_context = new ISrsThreadContext(); ISrsThreadContext* _srs_context = new ISrsThreadContext();
#endif #endif
/** /**
@ -48,13 +48,13 @@ using namespace std;
*/ */
struct Context struct Context
{ {
std::string url; std::string url;
std::string tcUrl; std::string tcUrl;
std::string host; std::string host;
std::string port; std::string port;
std::string vhost; std::string vhost;
std::string app; std::string app;
std::string stream; std::string stream;
SrsRtmpClient* rtmp; SrsRtmpClient* rtmp;
SimpleSocketStream* skt; SimpleSocketStream* skt;
@ -73,68 +73,68 @@ struct Context
int srs_librtmp_context_connect(Context* context) int srs_librtmp_context_connect(Context* context)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// parse uri // parse uri
size_t pos = string::npos; size_t pos = string::npos;
string uri = context->url; string uri = context->url;
// tcUrl, stream // tcUrl, stream
if ((pos = uri.rfind("/")) != string::npos) { if ((pos = uri.rfind("/")) != string::npos) {
context->stream = uri.substr(pos + 1); context->stream = uri.substr(pos + 1);
context->tcUrl = uri = uri.substr(0, pos); context->tcUrl = uri = uri.substr(0, pos);
} }
// schema // schema
if ((pos = uri.find("rtmp://")) != string::npos) { if ((pos = uri.find("rtmp://")) != string::npos) {
uri = uri.substr(pos + 7); uri = uri.substr(pos + 7);
} }
// host/vhost/port // host/vhost/port
if ((pos = uri.find(":")) != string::npos) { if ((pos = uri.find(":")) != string::npos) {
context->vhost = context->host = uri.substr(0, pos); context->vhost = context->host = uri.substr(0, pos);
uri = uri.substr(pos + 1); uri = uri.substr(pos + 1);
if ((pos = uri.find("/")) != string::npos) { if ((pos = uri.find("/")) != string::npos) {
context->port = uri.substr(0, pos); context->port = uri.substr(0, pos);
uri = uri.substr(pos + 1); uri = uri.substr(pos + 1);
} }
} else { } else {
if ((pos = uri.find("/")) != string::npos) { if ((pos = uri.find("/")) != string::npos) {
context->vhost = context->host = uri.substr(0, pos); context->vhost = context->host = uri.substr(0, pos);
uri = uri.substr(pos + 1); uri = uri.substr(pos + 1);
} }
context->port = RTMP_DEFAULT_PORT; context->port = RTMP_DEFAULT_PORT;
} }
// app // app
context->app = uri; context->app = uri;
// query of app // query of app
if ((pos = uri.find("?")) != string::npos) { if ((pos = uri.find("?")) != string::npos) {
context->app = uri.substr(0, pos); context->app = uri.substr(0, pos);
string query = uri.substr(pos + 1); string query = uri.substr(pos + 1);
if ((pos = query.find("vhost=")) != string::npos) { if ((pos = query.find("vhost=")) != string::npos) {
context->vhost = query.substr(pos + 6); context->vhost = query.substr(pos + 6);
if ((pos = context->vhost.find("&")) != string::npos) { if ((pos = context->vhost.find("&")) != string::npos) {
context->vhost = context->vhost.substr(pos); context->vhost = context->vhost.substr(pos);
} }
} }
} }
// create socket // create socket
srs_freep(context->skt); srs_freep(context->skt);
context->skt = new SimpleSocketStream(); context->skt = new SimpleSocketStream();
if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) { if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
return ret; return ret;
} }
// connect to server:port // connect to server:port
string server = srs_dns_resolve(context->host); string server = srs_dns_resolve(context->host);
if (server.empty()) { if (server.empty()) {
return -1; return -1;
} }
if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) { if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
#ifdef __cplusplus #ifdef __cplusplus
@ -144,7 +144,7 @@ extern "C"{
srs_rtmp_t srs_rtmp_create(const char* url) srs_rtmp_t srs_rtmp_create(const char* url)
{ {
Context* context = new Context(); Context* context = new Context();
context->url = url; context->url = url;
return context; return context;
} }
@ -158,7 +158,7 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp)
int srs_simple_handshake(srs_rtmp_t rtmp) int srs_simple_handshake(srs_rtmp_t rtmp)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
@ -168,24 +168,24 @@ int srs_simple_handshake(srs_rtmp_t rtmp)
return ret; return ret;
} }
// simple handshake // simple handshake
srs_freep(context->rtmp); srs_freep(context->rtmp);
context->rtmp = new SrsRtmpClient(context->skt); context->rtmp = new SrsRtmpClient(context->skt);
if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) { if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int srs_complex_handshake(srs_rtmp_t rtmp) int srs_complex_handshake(srs_rtmp_t rtmp)
{ {
#ifndef SRS_SSL #ifndef SRS_SSL
return ERROR_RTMP_HS_SSL_REQUIRE; return ERROR_RTMP_HS_SSL_REQUIRE;
#endif #endif
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
@ -195,41 +195,41 @@ int srs_complex_handshake(srs_rtmp_t rtmp)
return ret; return ret;
} }
// complex handshake // complex handshake
srs_freep(context->rtmp); srs_freep(context->rtmp);
context->rtmp = new SrsRtmpClient(context->skt); context->rtmp = new SrsRtmpClient(context->skt);
if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) { if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int srs_connect_app(srs_rtmp_t rtmp) int srs_connect_app(srs_rtmp_t rtmp)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
string tcUrl = "rtmp://"; string tcUrl = "rtmp://";
tcUrl += context->vhost; tcUrl += context->vhost;
tcUrl += ":"; tcUrl += ":";
tcUrl += context->port; tcUrl += context->port;
tcUrl += "/"; tcUrl += "/";
tcUrl += context->app; tcUrl += context->app;
if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) { if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {
return ret; return ret;
} }
return ret; return ret;
} }
int srs_play_stream(srs_rtmp_t rtmp) int srs_play_stream(srs_rtmp_t rtmp)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
@ -241,12 +241,12 @@ int srs_play_stream(srs_rtmp_t rtmp)
return ret; return ret;
} }
return ret; return ret;
} }
int srs_publish_stream(srs_rtmp_t rtmp) int srs_publish_stream(srs_rtmp_t rtmp)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
@ -255,29 +255,29 @@ int srs_publish_stream(srs_rtmp_t rtmp)
return ret; return ret;
} }
return ret; return ret;
} }
const char* srs_type2string(int type) const char* srs_type2string(int type)
{ {
switch (type) { switch (type) {
case SRS_RTMP_TYPE_AUDIO: return "Audio"; case SRS_RTMP_TYPE_AUDIO: return "Audio";
case SRS_RTMP_TYPE_VIDEO: return "Video"; case SRS_RTMP_TYPE_VIDEO: return "Video";
case SRS_RTMP_TYPE_SCRIPT: return "Data"; case SRS_RTMP_TYPE_SCRIPT: return "Data";
default: return "Unknown"; default: return "Unknown";
} }
return "Unknown"; return "Unknown";
} }
int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size) int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size)
{ {
*type = 0; *type = 0;
*timestamp = 0; *timestamp = 0;
*data = NULL; *data = NULL;
*size = 0; *size = 0;
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
@ -322,81 +322,81 @@ int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** dat
break; break;
} }
return ret; return ret;
} }
int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size) int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_assert(rtmp != NULL); srs_assert(rtmp != NULL);
Context* context = (Context*)rtmp; Context* context = (Context*)rtmp;
SrsSharedPtrMessage* msg = NULL; SrsSharedPtrMessage* msg = NULL;
if (type == SRS_RTMP_TYPE_AUDIO) { if (type == SRS_RTMP_TYPE_AUDIO) {
SrsMessageHeader header; SrsMessageHeader header;
header.initialize_audio(size, timestamp, context->stream_id); header.initialize_audio(size, timestamp, context->stream_id);
msg = new SrsSharedPtrMessage(); msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data); srs_freepa(data);
return ret; return ret;
} }
} else if (type == SRS_RTMP_TYPE_VIDEO) { } else if (type == SRS_RTMP_TYPE_VIDEO) {
SrsMessageHeader header; SrsMessageHeader header;
header.initialize_video(size, timestamp, context->stream_id); header.initialize_video(size, timestamp, context->stream_id);
msg = new SrsSharedPtrMessage(); msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data); srs_freepa(data);
return ret; return ret;
} }
} else if (type == SRS_RTMP_TYPE_SCRIPT) { } else if (type == SRS_RTMP_TYPE_SCRIPT) {
SrsMessageHeader header; SrsMessageHeader header;
header.initialize_amf0_script(size, context->stream_id); header.initialize_amf0_script(size, context->stream_id);
msg = new SrsSharedPtrMessage(); msg = new SrsSharedPtrMessage();
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
srs_freepa(data); srs_freepa(data);
return ret; return ret;
} }
} }
if (msg) { if (msg) {
// send out encoded msg. // send out encoded msg.
if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) { if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) {
return ret; return ret;
} }
} else { } else {
// directly free data if not sent out. // directly free data if not sent out.
srs_freepa(data); srs_freepa(data);
} }
return ret; return ret;
} }
int srs_ssl_enabled() int srs_ssl_enabled()
{ {
#ifndef SRS_SSL #ifndef SRS_SSL
return false; return false;
#endif #endif
return true; return true;
} }
int srs_version_major() int srs_version_major()
{ {
return ::atoi(VERSION_MAJOR); return ::atoi(VERSION_MAJOR);
} }
int srs_version_minor() int srs_version_minor()
{ {
return ::atoi(VERSION_MINOR); return ::atoi(VERSION_MINOR);
} }
int srs_version_revision() int srs_version_revision()
{ {
return ::atoi(VERSION_REVISION); return ::atoi(VERSION_REVISION);
} }
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -48,7 +48,7 @@ typedef void* srs_rtmp_t;
/** /**
* create/destroy a rtmp protocol stack. * create/destroy a rtmp protocol stack.
* @url rtmp url, for example: * @url rtmp url, for example:
* rtmp://127.0.0.1/live/livestream * rtmp://127.0.0.1/live/livestream
* @return a rtmp handler, or NULL if error occured. * @return a rtmp handler, or NULL if error occured.
*/ */
srs_rtmp_t srs_rtmp_create(const char* url); srs_rtmp_t srs_rtmp_create(const char* url);
@ -113,23 +113,23 @@ int srs_publish_stream(srs_rtmp_t rtmp);
#define SRS_RTMP_TYPE_SCRIPT 18 #define SRS_RTMP_TYPE_SCRIPT 18
/** /**
* convert the flv tag type to string. * convert the flv tag type to string.
* SRS_RTMP_TYPE_AUDIO to "Audio" * SRS_RTMP_TYPE_AUDIO to "Audio"
* SRS_RTMP_TYPE_VIDEO to "Video" * SRS_RTMP_TYPE_VIDEO to "Video"
* SRS_RTMP_TYPE_SCRIPT to "Data" * SRS_RTMP_TYPE_SCRIPT to "Data"
* otherwise, "Unknown" * otherwise, "Unknown"
*/ */
const char* srs_type2string(int type); const char* srs_type2string(int type);
/** /**
* read a audio/video/script-data packet from rtmp stream. * read a audio/video/script-data packet from rtmp stream.
* @param type, output the packet type, macros: * @param type, output the packet type, macros:
* SRS_RTMP_TYPE_AUDIO, FlvTagAudio * SRS_RTMP_TYPE_AUDIO, FlvTagAudio
* SRS_RTMP_TYPE_VIDEO, FlvTagVideo * SRS_RTMP_TYPE_VIDEO, FlvTagVideo
* SRS_RTMP_TYPE_SCRIPT, FlvTagScript * SRS_RTMP_TYPE_SCRIPT, FlvTagScript
* @param timestamp, in ms, overflow in 50days * @param timestamp, in ms, overflow in 50days
* @param data, the packet data, according to type: * @param data, the packet data, according to type:
* FlvTagAudio, @see "E.4.2.1 AUDIODATA" * FlvTagAudio, @see "E.4.2.1 AUDIODATA"
* FlvTagVideo, @see "E.4.3.1 VIDEODATA" * FlvTagVideo, @see "E.4.3.1 VIDEODATA"
* FlvTagScript, @see "E.4.4.1 SCRIPTDATA" * FlvTagScript, @see "E.4.4.1 SCRIPTDATA"
* @param size, size of packet. * @param size, size of packet.
* @return the error code. 0 for success; otherwise, error. * @return the error code. 0 for success; otherwise, error.
* *

View file

@ -158,8 +158,8 @@ public:
private: private:
int connect_server(); int connect_server();
private: private:
st_netfd_t stfd; st_netfd_t stfd;
ISrsProtocolReaderWriter* skt; ISrsProtocolReaderWriter* skt;
SrsBandCheckClient* bandCheck_Client; SrsBandCheckClient* bandCheck_Client;
std::string server_address; std::string server_address;
int server_port; int server_port;
@ -493,8 +493,8 @@ int SrsBandCheckClient::expect_stop_pub()
this->set_recv_timeout(1000 * 1000); this->set_recv_timeout(1000 * 1000);
this->set_send_timeout(1000 * 1000); this->set_send_timeout(1000 * 1000);
SrsCommonMessage* msg; SrsCommonMessage* msg;
SrsBandwidthPacket* pkt; SrsBandwidthPacket* pkt;
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(this->protocol, &msg, &pkt)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(this->protocol, &msg, &pkt)) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -641,16 +641,16 @@ int SrsBandCheckClient::send_final()
SrsBandCheck::SrsBandCheck() SrsBandCheck::SrsBandCheck()
{ {
skt = NULL; skt = NULL;
bandCheck_Client = NULL; bandCheck_Client = NULL;
stfd = NULL; stfd = NULL;
} }
SrsBandCheck::~SrsBandCheck() SrsBandCheck::~SrsBandCheck()
{ {
srs_freep(bandCheck_Client); srs_freep(bandCheck_Client);
srs_freep(skt); srs_freep(skt);
srs_close_stfd(stfd); srs_close_stfd(stfd);
} }
int SrsBandCheck::check(const std::string &app, const std::string &tcUrl) int SrsBandCheck::check(const std::string &app, const std::string &tcUrl)
@ -709,7 +709,7 @@ int SrsBandCheck::connect_server()
return ret; return ret;
} }
skt = new SrsSocket(stfd); skt = new SrsSocket(stfd);
bandCheck_Client = new SrsBandCheckClient(skt); bandCheck_Client = new SrsBandCheckClient(skt);
// connect to server. // connect to server.
@ -757,7 +757,7 @@ int init_st()
void print_help(char** argv) void print_help(char** argv)
{ {
printf( printf(
"Usage: %s [OPTION]...\n" "Usage: %s [OPTION]...\n"
"test band width from client to rtmp server.\n" "test band width from client to rtmp server.\n"
"Mandatory arguments to long options are mandatory for short options too.\n" "Mandatory arguments to long options are mandatory for short options too.\n"
" -i, --ip the ip or domain that to test\n" " -i, --ip the ip or domain that to test\n"
@ -767,8 +767,8 @@ void print_help(char** argv)
" -V, --version output version information and exit \n" " -V, --version output version information and exit \n"
" -h, --help display this help and exit \n" " -h, --help display this help and exit \n"
"\n" "\n"
"For example:\n" "For example:\n"
" %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e" " %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e"
"\n\n" "\n\n"
"Exit status:\n" "Exit status:\n"
"0 if OK,\n" "0 if OK,\n"

View file

@ -38,21 +38,21 @@ SrsServer* _srs_server = new SrsServer();
#include <signal.h> #include <signal.h>
#ifdef SRS_GPERF_MP #ifdef SRS_GPERF_MP
#include <gperftools/heap-profiler.h> #include <gperftools/heap-profiler.h>
#endif #endif
#ifdef SRS_GPERF_CP #ifdef SRS_GPERF_CP
#include <gperftools/profiler.h> #include <gperftools/profiler.h>
#endif #endif
void handler(int signo) void handler(int signo)
{ {
srs_trace("get a signal, signo=%d", signo); srs_trace("get a signal, signo=%d", signo);
_srs_server->on_signal(signo); _srs_server->on_signal(signo);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
#ifdef SRS_GPERF_MP #ifdef SRS_GPERF_MP
HeapProfilerStart("gperf.srs.gmp"); HeapProfilerStart("gperf.srs.gmp");
@ -61,36 +61,36 @@ int main(int argc, char** argv)
ProfilerStart("gperf.srs.gcp"); ProfilerStart("gperf.srs.gcp");
#endif #endif
signal(SIGNAL_RELOAD, handler); signal(SIGNAL_RELOAD, handler);
signal(SIGINT, handler); signal(SIGINT, handler);
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) { if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
return ret; return ret;
} }
#ifdef SRS_GPERF_MC #ifdef SRS_GPERF_MC
#ifdef SRS_GPERF_MP #ifdef SRS_GPERF_MP
srs_error("option --with-gmc confict with --with-gmp, " srs_error("option --with-gmc confict with --with-gmp, "
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n" "@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
"Note that since the heap-checker uses the heap-profiling framework internally, " "Note that since the heap-checker uses the heap-profiling framework internally, "
"it is not possible to run both the heap-checker and heap profiler at the same time"); "it is not possible to run both the heap-checker and heap profiler at the same time");
return -1; return -1;
#endif #endif
#endif #endif
if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) { if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) {
return ret; return ret;
} }
// TODO: create log dir in _srs_config->get_log_dir() // TODO: create log dir in _srs_config->get_log_dir()
if ((ret = _srs_server->listen()) != ERROR_SUCCESS) { if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
return ret; return ret;
} }
if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) { if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) {
return ret; return ret;
} }
return 0; return 0;
} }

File diff suppressed because it is too large Load diff

View file

@ -43,29 +43,29 @@ class __SrsAmf0ObjectEOF;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// amf0 codec // amf0 codec
// 1. SrsAmf0Any: read any from stream // 1. SrsAmf0Any: read any from stream
// SrsAmf0Any* pany = NULL; // SrsAmf0Any* pany = NULL;
// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) { // if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) {
// return ret; // return ret;
// } // }
// srs_assert(pany); // if success, always valid object. // srs_assert(pany); // if success, always valid object.
// 2. SrsAmf0Any: convert to specifid type, for instance, string // 2. SrsAmf0Any: convert to specifid type, for instance, string
// SrsAmf0Any* pany = ... // SrsAmf0Any* pany = ...
// if (pany->is_string()) { // if (pany->is_string()) {
// string v = pany->to_str(); // string v = pany->to_str();
// } // }
// 3. SrsAmf0Any: parse specified type to any, for instance, string // 3. SrsAmf0Any: parse specified type to any, for instance, string
// SrsAmf0Any* pany = SrsAmf0Any::str("winlin"); // SrsAmf0Any* pany = SrsAmf0Any::str("winlin");
// 4. SrsAmf0Size: get amf0 instance size // 4. SrsAmf0Size: get amf0 instance size
// int size = SrsAmf0Size::str("winlin"); // int size = SrsAmf0Size::str("winlin");
// 5. SrsAmf0Object: create the amf0 object. // 5. SrsAmf0Object: create the amf0 object.
// SrsAmf0Object* obj = SrsAmf0Any::object(); // SrsAmf0Object* obj = SrsAmf0Any::object();
// 5. SrsAmf0EcmaArray: create the amf0 ecma array. // 5. SrsAmf0EcmaArray: create the amf0 ecma array.
// SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array(); // SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
// //
// please carefully the size and count of amf0 any: // please carefully the size and count of amf0 any:
// 1. total_size(): the total memory size the object wrote to buffer. // 1. total_size(): the total memory size the object wrote to buffer.
// 2. count(): the total element count of object, for instance, the properties // 2. count(): the total element count of object, for instance, the properties
// of amf0 object, used for key_at/value_at loop. // of amf0 object, used for key_at/value_at loop.
// //
// for detail usage, see interfaces of each object. // for detail usage, see interfaces of each object.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -76,73 +76,73 @@ class __SrsAmf0ObjectEOF;
* any amf0 value. * any amf0 value.
* 2.1 Types Overview * 2.1 Types Overview
* value-type = number-type | boolean-type | string-type | object-type * value-type = number-type | boolean-type | string-type | object-type
* | null-marker | undefined-marker | reference-type | ecma-array-type * | null-marker | undefined-marker | reference-type | ecma-array-type
* | strict-array-type | date-type | long-string-type | xml-document-type * | strict-array-type | date-type | long-string-type | xml-document-type
* | typed-object-type * | typed-object-type
*/ */
class SrsAmf0Any class SrsAmf0Any
{ {
public: public:
char marker; char marker;
public: public:
SrsAmf0Any(); SrsAmf0Any();
virtual ~SrsAmf0Any(); virtual ~SrsAmf0Any();
public: public:
virtual bool is_string(); virtual bool is_string();
virtual bool is_boolean(); virtual bool is_boolean();
virtual bool is_number(); virtual bool is_number();
virtual bool is_null(); virtual bool is_null();
virtual bool is_undefined(); virtual bool is_undefined();
virtual bool is_object(); virtual bool is_object();
virtual bool is_object_eof(); virtual bool is_object_eof();
virtual bool is_ecma_array(); virtual bool is_ecma_array();
public: public:
/** /**
* get the string of any when is_string() indicates true. * get the string of any when is_string() indicates true.
* user must ensure the type is a string, or assert failed. * user must ensure the type is a string, or assert failed.
*/ */
virtual std::string to_str(); virtual std::string to_str();
/** /**
* get the boolean of any when is_boolean() indicates true. * get the boolean of any when is_boolean() indicates true.
* user must ensure the type is a boolean, or assert failed. * user must ensure the type is a boolean, or assert failed.
*/ */
virtual bool to_boolean(); virtual bool to_boolean();
/** /**
* get the number of any when is_number() indicates true. * get the number of any when is_number() indicates true.
* user must ensure the type is a number, or assert failed. * user must ensure the type is a number, or assert failed.
*/ */
virtual double to_number(); virtual double to_number();
/** /**
* get the object of any when is_object() indicates true. * get the object of any when is_object() indicates true.
* user must ensure the type is a object, or assert failed. * user must ensure the type is a object, or assert failed.
*/ */
virtual SrsAmf0Object* to_object(); virtual SrsAmf0Object* to_object();
/** /**
* get the ecma array of any when is_ecma_array() indicates true. * get the ecma array of any when is_ecma_array() indicates true.
* user must ensure the type is a ecma array, or assert failed. * user must ensure the type is a ecma array, or assert failed.
*/ */
virtual SrsAmf0EcmaArray* to_ecma_array(); virtual SrsAmf0EcmaArray* to_ecma_array();
public: public:
/** /**
* get the size of amf0 any, including the marker size. * get the size of amf0 any, including the marker size.
*/ */
virtual int total_size() = 0; virtual int total_size() = 0;
/** /**
* read elem from stream * read elem from stream
*/ */
virtual int read(SrsStream* stream) = 0; virtual int read(SrsStream* stream) = 0;
virtual int write(SrsStream* stream) = 0; virtual int write(SrsStream* stream) = 0;
public: public:
static SrsAmf0Any* str(const char* value = NULL); static SrsAmf0Any* str(const char* value = NULL);
static SrsAmf0Any* boolean(bool value = false); static SrsAmf0Any* boolean(bool value = false);
static SrsAmf0Any* number(double value = 0.0); static SrsAmf0Any* number(double value = 0.0);
static SrsAmf0Any* null(); static SrsAmf0Any* null();
static SrsAmf0Any* undefined(); static SrsAmf0Any* undefined();
static SrsAmf0Object* object(); static SrsAmf0Object* object();
static SrsAmf0Any* object_eof(); static SrsAmf0Any* object_eof();
static SrsAmf0EcmaArray* ecma_array(); static SrsAmf0EcmaArray* ecma_array();
public: public:
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue); static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
}; };
/** /**
@ -153,33 +153,33 @@ public:
class SrsAmf0Object : public SrsAmf0Any class SrsAmf0Object : public SrsAmf0Any
{ {
private: private:
__SrsUnSortedHashtable* properties; __SrsUnSortedHashtable* properties;
__SrsAmf0ObjectEOF* eof; __SrsAmf0ObjectEOF* eof;
private: private:
// use SrsAmf0Any::object() to create it. // use SrsAmf0Any::object() to create it.
friend class SrsAmf0Any; friend class SrsAmf0Any;
SrsAmf0Object(); SrsAmf0Object();
public: public:
virtual ~SrsAmf0Object(); virtual ~SrsAmf0Object();
public: public:
virtual int total_size(); virtual int total_size();
virtual int read(SrsStream* stream); virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream); virtual int write(SrsStream* stream);
public: public:
virtual int count(); virtual int count();
// @remark: max index is count(). // @remark: max index is count().
virtual std::string key_at(int index); virtual std::string key_at(int index);
// @remark: max index is count(). // @remark: max index is count().
virtual SrsAmf0Any* value_at(int index); virtual SrsAmf0Any* value_at(int index);
public: public:
virtual void set(std::string key, SrsAmf0Any* value); virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name); virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name); virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name); virtual SrsAmf0Any* ensure_property_number(std::string name);
}; };
/** /**
@ -191,35 +191,35 @@ public:
class SrsAmf0EcmaArray : public SrsAmf0Any class SrsAmf0EcmaArray : public SrsAmf0Any
{ {
private: private:
__SrsUnSortedHashtable* properties; __SrsUnSortedHashtable* properties;
__SrsAmf0ObjectEOF* eof; __SrsAmf0ObjectEOF* eof;
int32_t _count; int32_t _count;
private: private:
// use SrsAmf0Any::ecma_array() to create it. // use SrsAmf0Any::ecma_array() to create it.
friend class SrsAmf0Any; friend class SrsAmf0Any;
SrsAmf0EcmaArray(); SrsAmf0EcmaArray();
public: public:
virtual ~SrsAmf0EcmaArray(); virtual ~SrsAmf0EcmaArray();
public: public:
virtual int total_size(); virtual int total_size();
virtual int read(SrsStream* stream); virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream); virtual int write(SrsStream* stream);
public: public:
virtual void clear(); virtual void clear();
virtual int count(); virtual int count();
// @remark: max index is count(). // @remark: max index is count().
virtual std::string key_at(int index); virtual std::string key_at(int index);
// @remark: max index is count(). // @remark: max index is count().
virtual SrsAmf0Any* value_at(int index); virtual SrsAmf0Any* value_at(int index);
public: public:
virtual void set(std::string key, SrsAmf0Any* value); virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name); virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name); virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name); virtual SrsAmf0Any* ensure_property_number(std::string name);
}; };
/** /**
@ -228,22 +228,22 @@ public:
class SrsAmf0Size class SrsAmf0Size
{ {
public: public:
static int utf8(std::string value); static int utf8(std::string value);
static int str(std::string value); static int str(std::string value);
static int number(); static int number();
static int null(); static int null();
static int undefined(); static int undefined();
static int boolean(); static int boolean();
static int object(SrsAmf0Object* obj); static int object(SrsAmf0Object* obj);
static int object_eof(); static int object_eof();
static int ecma_array(SrsAmf0EcmaArray* arr); static int ecma_array(SrsAmf0EcmaArray* arr);
static int any(SrsAmf0Any* o); static int any(SrsAmf0Any* o);
}; };
/** /**
* read anything from stream. * read anything from stream.
* @param ppvalue, the output amf0 any elem. * @param ppvalue, the output amf0 any elem.
* NULL if error; otherwise, never NULL and user must free it. * NULL if error; otherwise, never NULL and user must free it.
*/ */
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue); extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);
@ -259,7 +259,7 @@ extern int srs_amf0_write_string(SrsStream* stream, std::string value);
* read amf0 boolean from stream. * read amf0 boolean from stream.
* 2.4 String Type * 2.4 String Type
* boolean-type = boolean-marker U8 * boolean-type = boolean-marker U8
* 0 is false, <> 0 is true * 0 is false, <> 0 is true
*/ */
extern int srs_amf0_read_boolean(SrsStream* stream, bool& value); extern int srs_amf0_read_boolean(SrsStream* stream, bool& value);
extern int srs_amf0_write_boolean(SrsStream* stream, bool value); extern int srs_amf0_write_boolean(SrsStream* stream, bool value);

File diff suppressed because it is too large Load diff

View file

@ -39,17 +39,17 @@ class SrsComplexHandshake;
class SrsSimpleHandshake class SrsSimpleHandshake
{ {
public: public:
SrsSimpleHandshake(); SrsSimpleHandshake();
virtual ~SrsSimpleHandshake(); virtual ~SrsSimpleHandshake();
public: public:
/** /**
* simple handshake. * simple handshake.
* @param complex_hs, try complex handshake first, * @param complex_hs, try complex handshake first,
* if NULL, use simple handshake. * if NULL, use simple handshake.
* if failed, rollback to simple handshake. * if failed, rollback to simple handshake.
*/ */
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
}; };
/** /**
@ -60,20 +60,20 @@ public:
class SrsComplexHandshake class SrsComplexHandshake
{ {
public: public:
SrsComplexHandshake(); SrsComplexHandshake();
virtual ~SrsComplexHandshake(); virtual ~SrsComplexHandshake();
public: public:
/** /**
* complex hanshake. * complex hanshake.
* @_c1, size of c1 must be 1536. * @_c1, size of c1 must be 1536.
* @remark, user must free the c1. * @remark, user must free the c1.
* @return user must: * @return user must:
* continue connect app if success, * continue connect app if success,
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
* otherwise, disconnect * otherwise, disconnect
*/ */
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1); virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1);
virtual int handshake_with_server(ISrsProtocolReaderWriter* io); virtual int handshake_with_server(ISrsProtocolReaderWriter* io);
}; };
#endif #endif

View file

@ -40,14 +40,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class ISrsProtocolReader : public ISrsBufferReader class ISrsProtocolReader : public ISrsBufferReader
{ {
public: public:
ISrsProtocolReader(); ISrsProtocolReader();
virtual ~ISrsProtocolReader(); virtual ~ISrsProtocolReader();
// for protocol // for protocol
public: public:
virtual void set_recv_timeout(int64_t timeout_us) = 0; virtual void set_recv_timeout(int64_t timeout_us) = 0;
virtual int64_t get_recv_timeout() = 0; virtual int64_t get_recv_timeout() = 0;
virtual int64_t get_recv_bytes() = 0; virtual int64_t get_recv_bytes() = 0;
virtual int get_recv_kbps() = 0; virtual int get_recv_kbps() = 0;
}; };
/** /**
@ -56,28 +56,28 @@ public:
class ISrsProtocolWriter class ISrsProtocolWriter
{ {
public: public:
ISrsProtocolWriter(); ISrsProtocolWriter();
virtual ~ISrsProtocolWriter(); virtual ~ISrsProtocolWriter();
// for protocol // for protocol
public: public:
virtual void set_send_timeout(int64_t timeout_us) = 0; virtual void set_send_timeout(int64_t timeout_us) = 0;
virtual int64_t get_send_timeout() = 0; virtual int64_t get_send_timeout() = 0;
virtual int64_t get_send_bytes() = 0; virtual int64_t get_send_bytes() = 0;
virtual int get_send_kbps() = 0; virtual int get_send_kbps() = 0;
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite) = 0; virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite) = 0;
}; };
class ISrsProtocolReaderWriter : public ISrsProtocolReader, public ISrsProtocolWriter class ISrsProtocolReaderWriter : public ISrsProtocolReader, public ISrsProtocolWriter
{ {
public: public:
ISrsProtocolReaderWriter(); ISrsProtocolReaderWriter();
virtual ~ISrsProtocolReaderWriter(); virtual ~ISrsProtocolReaderWriter();
// for protocol // for protocol
public: public:
/** /**
* whether the specified timeout_us is never timeout. * whether the specified timeout_us is never timeout.
*/ */
virtual bool is_never_timeout(int64_t timeout_us) = 0; virtual bool is_never_timeout(int64_t timeout_us) = 0;
// for handshake. // for handshake.
public: public:
virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0; virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0;

File diff suppressed because it is too large Load diff

View file

@ -48,41 +48,41 @@ class SrsPlayPacket;
*/ */
struct SrsRequest struct SrsRequest
{ {
/** /**
* tcUrl: rtmp://request_vhost:port/app/stream * tcUrl: rtmp://request_vhost:port/app/stream
* support pass vhost in query string, such as: * support pass vhost in query string, such as:
* rtmp://ip:port/app?vhost=request_vhost/stream * rtmp://ip:port/app?vhost=request_vhost/stream
* rtmp://ip:port/app...vhost...request_vhost/stream * rtmp://ip:port/app...vhost...request_vhost/stream
*/ */
std::string tcUrl; std::string tcUrl;
std::string pageUrl; std::string pageUrl;
std::string swfUrl; std::string swfUrl;
double objectEncoding; double objectEncoding;
std::string schema; std::string schema;
std::string vhost; std::string vhost;
std::string port; std::string port;
std::string app; std::string app;
std::string stream; std::string stream;
SrsRequest(); SrsRequest();
virtual ~SrsRequest(); virtual ~SrsRequest();
/** /**
* deep copy the request, for source to use it to support reload, * deep copy the request, for source to use it to support reload,
* for when initialize the source, the request is valid, * for when initialize the source, the request is valid,
* when reload it, the request maybe invalid, so need to copy it. * when reload it, the request maybe invalid, so need to copy it.
*/ */
virtual SrsRequest* copy(); virtual SrsRequest* copy();
/** /**
* disconvery vhost/app from tcUrl. * disconvery vhost/app from tcUrl.
*/ */
virtual int discovery_app(); virtual int discovery_app();
virtual std::string get_stream_url(); virtual std::string get_stream_url();
virtual void strip(); virtual void strip();
private: private:
std::string& trim(std::string& str, std::string chs); std::string& trim(std::string& str, std::string chs);
}; };
/** /**
@ -90,10 +90,10 @@ private:
*/ */
struct SrsResponse struct SrsResponse
{ {
int stream_id; int stream_id;
SrsResponse(); SrsResponse();
virtual ~SrsResponse(); virtual ~SrsResponse();
}; };
/** /**
@ -101,10 +101,10 @@ struct SrsResponse
*/ */
enum SrsClientType enum SrsClientType
{ {
SrsClientUnknown, SrsClientUnknown,
SrsClientPlay, SrsClientPlay,
SrsClientFMLEPublish, SrsClientFMLEPublish,
SrsClientFlashPublish, SrsClientFlashPublish,
}; };
std::string srs_client_type_string(SrsClientType type); std::string srs_client_type_string(SrsClientType type);
@ -114,36 +114,36 @@ std::string srs_client_type_string(SrsClientType type);
class SrsRtmpClient class SrsRtmpClient
{ {
protected: protected:
SrsProtocol* protocol; SrsProtocol* protocol;
ISrsProtocolReaderWriter* io; ISrsProtocolReaderWriter* io;
public: public:
SrsRtmpClient(ISrsProtocolReaderWriter* skt); SrsRtmpClient(ISrsProtocolReaderWriter* skt);
virtual ~SrsRtmpClient(); virtual ~SrsRtmpClient();
public: public:
virtual void set_recv_timeout(int64_t timeout_us); virtual void set_recv_timeout(int64_t timeout_us);
virtual void set_send_timeout(int64_t timeout_us); virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes(); virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes(); virtual int64_t get_send_bytes();
virtual int get_recv_kbps(); virtual int get_recv_kbps();
virtual int get_send_kbps(); virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg); virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg); virtual int send_message(ISrsMessage* msg);
public: public:
// try complex, then simple handshake. // try complex, then simple handshake.
virtual int handshake(); virtual int handshake();
// only use simple handshake // only use simple handshake
virtual int simple_handshake(); virtual int simple_handshake();
// only use complex handshake // only use complex handshake
virtual int complex_handshake(); virtual int complex_handshake();
virtual int connect_app(std::string app, std::string tc_url); virtual int connect_app(std::string app, std::string tc_url);
virtual int create_stream(int& stream_id); virtual int create_stream(int& stream_id);
virtual int play(std::string stream, int stream_id); virtual int play(std::string stream, int stream_id);
// flash publish schema: // flash publish schema:
// connect-app => create-stream => flash-publish // connect-app => create-stream => flash-publish
virtual int publish(std::string stream, int stream_id); virtual int publish(std::string stream, int stream_id);
// FMLE publish schema: // FMLE publish schema:
// connect-app => FMLE publish // connect-app => FMLE publish
virtual int fmle_publish(std::string stream, int& stream_id); virtual int fmle_publish(std::string stream, int& stream_id);
}; };
/** /**
@ -155,93 +155,93 @@ public:
class SrsRtmpServer class SrsRtmpServer
{ {
private: private:
SrsProtocol* protocol; SrsProtocol* protocol;
ISrsProtocolReaderWriter* io; ISrsProtocolReaderWriter* io;
public: public:
SrsRtmpServer(ISrsProtocolReaderWriter* skt); SrsRtmpServer(ISrsProtocolReaderWriter* skt);
virtual ~SrsRtmpServer(); virtual ~SrsRtmpServer();
public: public:
virtual SrsProtocol* get_protocol(); virtual SrsProtocol* get_protocol();
virtual void set_recv_timeout(int64_t timeout_us); virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout(); virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us); virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_send_timeout(); virtual int64_t get_send_timeout();
virtual int64_t get_recv_bytes(); virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes(); virtual int64_t get_send_bytes();
virtual int get_recv_kbps(); virtual int get_recv_kbps();
virtual int get_send_kbps(); virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg); virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg); virtual int send_message(ISrsMessage* msg);
public: public:
virtual int handshake(); virtual int handshake();
virtual int connect_app(SrsRequest* req); virtual int connect_app(SrsRequest* req);
virtual int set_window_ack_size(int ack_size); virtual int set_window_ack_size(int ack_size);
/** /**
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2) * @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
* using the Limit type field. * using the Limit type field.
*/ */
virtual int set_peer_bandwidth(int bandwidth, int type); virtual int set_peer_bandwidth(int bandwidth, int type);
/** /**
* @param server_ip the ip of server. * @param server_ip the ip of server.
*/ */
virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL); virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL);
virtual void response_connect_reject(SrsRequest* req, const char* desc); virtual void response_connect_reject(SrsRequest* req, const char* desc);
virtual int on_bw_done(); virtual int on_bw_done();
/** /**
* recv some message to identify the client. * recv some message to identify the client.
* @stream_id, client will createStream to play or publish by flash, * @stream_id, client will createStream to play or publish by flash,
* the stream_id used to response the createStream request. * the stream_id used to response the createStream request.
* @type, output the client type. * @type, output the client type.
*/ */
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name); virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
/** /**
* set the chunk size when client type identified. * set the chunk size when client type identified.
*/ */
virtual int set_chunk_size(int chunk_size); virtual int set_chunk_size(int chunk_size);
/** /**
* when client type is play, response with packets: * when client type is play, response with packets:
* StreamBegin, * StreamBegin,
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start)., * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
* |RtmpSampleAccess(false, false), * |RtmpSampleAccess(false, false),
* onStatus(NetStream.Data.Start). * onStatus(NetStream.Data.Start).
*/ */
virtual int start_play(int stream_id); virtual int start_play(int stream_id);
/** /**
* when client(type is play) send pause message, * when client(type is play) send pause message,
* if is_pause, response the following packets: * if is_pause, response the following packets:
* onStatus(NetStream.Pause.Notify) * onStatus(NetStream.Pause.Notify)
* StreamEOF * StreamEOF
* if not is_pause, response the following packets: * if not is_pause, response the following packets:
* onStatus(NetStream.Unpause.Notify) * onStatus(NetStream.Unpause.Notify)
* StreamBegin * StreamBegin
*/ */
virtual int on_play_client_pause(int stream_id, bool is_pause); virtual int on_play_client_pause(int stream_id, bool is_pause);
/** /**
* when client type is publish, response with packets: * when client type is publish, response with packets:
* releaseStream response * releaseStream response
* FCPublish * FCPublish
* FCPublish response * FCPublish response
* createStream response * createStream response
* onFCPublish(NetStream.Publish.Start) * onFCPublish(NetStream.Publish.Start)
* onStatus(NetStream.Publish.Start) * onStatus(NetStream.Publish.Start)
*/ */
virtual int start_fmle_publish(int stream_id); virtual int start_fmle_publish(int stream_id);
/** /**
* process the FMLE unpublish event. * process the FMLE unpublish event.
* @unpublish_tid the unpublish request transaction id. * @unpublish_tid the unpublish request transaction id.
*/ */
virtual int fmle_unpublish(int stream_id, double unpublish_tid); virtual int fmle_unpublish(int stream_id, double unpublish_tid);
/** /**
* when client type is publish, response with packets: * when client type is publish, response with packets:
* onStatus(NetStream.Publish.Start) * onStatus(NetStream.Publish.Start)
*/ */
virtual int start_flash_publish(int stream_id); virtual int start_flash_publish(int stream_id);
private: private:
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name); virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name); virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
private: private:
virtual int identify_play_client(SrsPlayPacket* req, SrsClientType& type, std::string& stream_name); virtual int identify_play_client(SrsPlayPacket* req, SrsClientType& type, std::string& stream_name);
}; };
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -25,24 +25,24 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
void srs_vhost_resolve(std::string& vhost, std::string& app) void srs_vhost_resolve(std::string& vhost, std::string& app)
{ {
app = srs_replace(app, "...", "?"); app = srs_replace(app, "...", "?");
size_t pos = 0; size_t pos = 0;
if ((pos = app.find("?")) == std::string::npos) { if ((pos = app.find("?")) == std::string::npos) {
return; return;
} }
std::string query = app.substr(pos + 1); std::string query = app.substr(pos + 1);
app = app.substr(0, pos); app = app.substr(0, pos);
if ((pos = query.find("vhost?")) != std::string::npos if ((pos = query.find("vhost?")) != std::string::npos
|| (pos = query.find("vhost=")) != std::string::npos || (pos = query.find("vhost=")) != std::string::npos
|| (pos = query.find("Vhost?")) != std::string::npos || (pos = query.find("Vhost?")) != std::string::npos
|| (pos = query.find("Vhost=")) != std::string::npos || (pos = query.find("Vhost=")) != std::string::npos
) { ) {
query = query.substr(pos + 6); query = query.substr(pos + 6);
if (!query.empty()) { if (!query.empty()) {
vhost = query; vhost = query;
} }
} }
} }

View file

@ -36,8 +36,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// resolve the vhost in query string // resolve the vhost in query string
// @param app, may contains the vhost in query string format: // @param app, may contains the vhost in query string format:
// app?vhost=request_vhost // app?vhost=request_vhost
// app...vhost...request_vhost // app...vhost...request_vhost
extern void srs_vhost_resolve(std::string& vhost, std::string& app); extern void srs_vhost_resolve(std::string& vhost, std::string& app);
#endif #endif

View file

@ -1,88 +1,88 @@
file file
main readonly separator, main readonly separator,
..\main\srs_main_server.cpp, ..\main\srs_main_server.cpp,
..\main\srs_main_bandcheck.cpp, ..\main\srs_main_bandcheck.cpp,
auto readonly separator, auto readonly separator,
..\..\objs\srs_auto_headers.hpp, ..\..\objs\srs_auto_headers.hpp,
libs readonly separator, libs readonly separator,
..\libs\srs_librtmp.hpp, ..\libs\srs_librtmp.hpp,
..\libs\srs_librtmp.cpp, ..\libs\srs_librtmp.cpp,
..\libs\srs_lib_simple_socket.hpp, ..\libs\srs_lib_simple_socket.hpp,
..\libs\srs_lib_simple_socket.cpp, ..\libs\srs_lib_simple_socket.cpp,
core readonly separator, core readonly separator,
..\core\srs_core.hpp, ..\core\srs_core.hpp,
..\core\srs_core.cpp, ..\core\srs_core.cpp,
..\core\srs_core_autofree.hpp, ..\core\srs_core_autofree.hpp,
..\core\srs_core_autofree.cpp, ..\core\srs_core_autofree.cpp,
kernel readonly separator, kernel readonly separator,
..\kernel\srs_kernel_buffer.hpp, ..\kernel\srs_kernel_buffer.hpp,
..\kernel\srs_kernel_buffer.cpp, ..\kernel\srs_kernel_buffer.cpp,
..\kernel\srs_kernel_error.hpp, ..\kernel\srs_kernel_error.hpp,
..\kernel\srs_kernel_error.cpp, ..\kernel\srs_kernel_error.cpp,
..\kernel\srs_kernel_log.hpp, ..\kernel\srs_kernel_log.hpp,
..\kernel\srs_kernel_log.cpp, ..\kernel\srs_kernel_log.cpp,
..\kernel\srs_kernel_stream.hpp, ..\kernel\srs_kernel_stream.hpp,
..\kernel\srs_kernel_stream.cpp, ..\kernel\srs_kernel_stream.cpp,
rtmp-protocol readonly separator, rtmp-protocol readonly separator,
..\rtmp\srs_protocol_amf0.hpp, ..\rtmp\srs_protocol_amf0.hpp,
..\rtmp\srs_protocol_amf0.cpp, ..\rtmp\srs_protocol_amf0.cpp,
..\rtmp\srs_protocol_handshake.hpp, ..\rtmp\srs_protocol_handshake.hpp,
..\rtmp\srs_protocol_handshake.cpp, ..\rtmp\srs_protocol_handshake.cpp,
..\rtmp\srs_protocol_io.hpp, ..\rtmp\srs_protocol_io.hpp,
..\rtmp\srs_protocol_io.cpp, ..\rtmp\srs_protocol_io.cpp,
..\rtmp\srs_protocol_rtmp.hpp, ..\rtmp\srs_protocol_rtmp.hpp,
..\rtmp\srs_protocol_rtmp.cpp, ..\rtmp\srs_protocol_rtmp.cpp,
..\rtmp\srs_protocol_rtmp_stack.hpp, ..\rtmp\srs_protocol_rtmp_stack.hpp,
..\rtmp\srs_protocol_rtmp_stack.cpp, ..\rtmp\srs_protocol_rtmp_stack.cpp,
..\rtmp\srs_protocol_utility.hpp, ..\rtmp\srs_protocol_utility.hpp,
..\rtmp\srs_protocol_utility.cpp, ..\rtmp\srs_protocol_utility.cpp,
app readonly separator, app readonly separator,
..\app\srs_app_bandwidth.hpp, ..\app\srs_app_bandwidth.hpp,
..\app\srs_app_bandwidth.cpp, ..\app\srs_app_bandwidth.cpp,
..\app\srs_app_client.hpp, ..\app\srs_app_client.hpp,
..\app\srs_app_client.cpp, ..\app\srs_app_client.cpp,
..\app\srs_app_codec.hpp, ..\app\srs_app_codec.hpp,
..\app\srs_app_codec.cpp, ..\app\srs_app_codec.cpp,
..\app\srs_app_conn.hpp, ..\app\srs_app_conn.hpp,
..\app\srs_app_conn.cpp, ..\app\srs_app_conn.cpp,
..\app\srs_app_config.hpp, ..\app\srs_app_config.hpp,
..\app\srs_app_config.cpp, ..\app\srs_app_config.cpp,
..\app\srs_app_encoder.hpp, ..\app\srs_app_encoder.hpp,
..\app\srs_app_encoder.cpp, ..\app\srs_app_encoder.cpp,
..\app\srs_app_forward.hpp, ..\app\srs_app_forward.hpp,
..\app\srs_app_forward.cpp, ..\app\srs_app_forward.cpp,
..\app\srs_app_hls.hpp, ..\app\srs_app_hls.hpp,
..\app\srs_app_hls.cpp, ..\app\srs_app_hls.cpp,
..\app\srs_app_http.hpp, ..\app\srs_app_http.hpp,
..\app\srs_app_http.cpp, ..\app\srs_app_http.cpp,
..\app\srs_app_log.hpp, ..\app\srs_app_log.hpp,
..\app\srs_app_log.cpp, ..\app\srs_app_log.cpp,
..\app\srs_app_refer.hpp, ..\app\srs_app_refer.hpp,
..\app\srs_app_refer.cpp, ..\app\srs_app_refer.cpp,
..\app\srs_app_reload.hpp, ..\app\srs_app_reload.hpp,
..\app\srs_app_reload.cpp, ..\app\srs_app_reload.cpp,
..\app\srs_app_pithy_print.hpp, ..\app\srs_app_pithy_print.hpp,
..\app\srs_app_pithy_print.cpp, ..\app\srs_app_pithy_print.cpp,
..\app\srs_app_thread.hpp, ..\app\srs_app_thread.hpp,
..\app\srs_app_thread.cpp, ..\app\srs_app_thread.cpp,
..\app\srs_app_server.hpp, ..\app\srs_app_server.hpp,
..\app\srs_app_server.cpp, ..\app\srs_app_server.cpp,
..\app\srs_app_st.hpp, ..\app\srs_app_st.hpp,
..\app\srs_app_st.cpp, ..\app\srs_app_st.cpp,
..\app\srs_app_socket.hpp, ..\app\srs_app_socket.hpp,
..\app\srs_app_socket.cpp, ..\app\srs_app_socket.cpp,
..\app\srs_app_source.hpp, ..\app\srs_app_source.hpp,
..\app\srs_app_source.cpp, ..\app\srs_app_source.cpp,
utest readonly separator, utest readonly separator,
..\utest\srs_utest.hpp, ..\utest\srs_utest.hpp,
..\utest\srs_utest.cpp, ..\utest\srs_utest.cpp,
..\utest\srs_utest_amf0.hpp, ..\utest\srs_utest_amf0.hpp,
..\utest\srs_utest_amf0.cpp, ..\utest\srs_utest_amf0.cpp,
research readonly separator, research readonly separator,
..\..\research\librtmp\srs_play.c, ..\..\research\librtmp\srs_play.c,
..\..\research\librtmp\srs_publish.c, ..\..\research\librtmp\srs_publish.c,
..\..\research\hls\ts_info.cc; ..\..\research\hls\ts_info.cc;
mainconfig mainconfig
"" = "MAIN"; "" = "MAIN";

View file

@ -39,30 +39,30 @@ SrsServer* _srs_server = NULL;
// basic test and samples. // basic test and samples.
VOID TEST(SampleTest, FastSampleInt64Test) VOID TEST(SampleTest, FastSampleInt64Test)
{ {
EXPECT_EQ(1, (int)sizeof(int8_t)); EXPECT_EQ(1, (int)sizeof(int8_t));
EXPECT_EQ(2, (int)sizeof(int16_t)); EXPECT_EQ(2, (int)sizeof(int16_t));
EXPECT_EQ(4, (int)sizeof(int32_t)); EXPECT_EQ(4, (int)sizeof(int32_t));
EXPECT_EQ(8, (int)sizeof(int64_t)); EXPECT_EQ(8, (int)sizeof(int64_t));
} }
VOID TEST(SampleTest, FastSampleMacrosTest) VOID TEST(SampleTest, FastSampleMacrosTest)
{ {
EXPECT_TRUE(1); EXPECT_TRUE(1);
EXPECT_FALSE(0); EXPECT_FALSE(0);
EXPECT_EQ(1, 1); // == EXPECT_EQ(1, 1); // ==
EXPECT_NE(1, 2); // != EXPECT_NE(1, 2); // !=
EXPECT_LE(1, 2); // <= EXPECT_LE(1, 2); // <=
EXPECT_LT(1, 2); // < EXPECT_LT(1, 2); // <
EXPECT_GE(2, 1); // >= EXPECT_GE(2, 1); // >=
EXPECT_GT(2, 1); // > EXPECT_GT(2, 1); // >
EXPECT_STREQ("winlin", "winlin"); EXPECT_STREQ("winlin", "winlin");
EXPECT_STRNE("winlin", "srs"); EXPECT_STRNE("winlin", "srs");
EXPECT_STRCASEEQ("winlin", "Winlin"); EXPECT_STRCASEEQ("winlin", "Winlin");
EXPECT_STRCASENE("winlin", "srs"); EXPECT_STRCASENE("winlin", "srs");
EXPECT_FLOAT_EQ(1.0, 1.000000000000001); EXPECT_FLOAT_EQ(1.0, 1.000000000000001);
EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001); EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001);
EXPECT_NEAR(10, 15, 5); EXPECT_NEAR(10, 15, 5);
} }

File diff suppressed because it is too large Load diff