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:
parent
e5770b10b1
commit
c85dde7f3f
64 changed files with 14105 additions and 14105 deletions
|
@ -45,28 +45,28 @@ SrsBandwidth::~SrsBandwidth()
|
|||
|
||||
int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServer* _rtmp)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
rtmp = _rtmp;
|
||||
req = _req;
|
||||
|
||||
if (!_srs_config->get_bw_check_enabled(req->vhost)) {
|
||||
return ret;
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
rtmp = _rtmp;
|
||||
req = _req;
|
||||
|
||||
if (!_srs_config->get_bw_check_enabled(req->vhost)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// validate the bandwidth check key
|
||||
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
|
||||
if (req->tcUrl.find(key) == std::string::npos) {
|
||||
ret = ERROR_SYSTEM_BANDWIDTH_KEY;
|
||||
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
|
||||
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// shared global last check time,
|
||||
// to avoid attach by bandwidth check,
|
||||
// if client request check in the window(specifeid by interval),
|
||||
// directly reject the request.
|
||||
// validate the bandwidth check key
|
||||
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
|
||||
if (req->tcUrl.find(key) == std::string::npos) {
|
||||
ret = ERROR_SYSTEM_BANDWIDTH_KEY;
|
||||
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
|
||||
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// shared global last check time,
|
||||
// to avoid attach by bandwidth check,
|
||||
// if client request check in the window(specifeid by interval),
|
||||
// directly reject the request.
|
||||
static int64_t last_check_time = 0;
|
||||
int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost);
|
||||
|
||||
|
@ -75,16 +75,16 @@ int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServe
|
|||
if (last_check_time > 0 && time_now - last_check_time < interval_ms) {
|
||||
ret = ERROR_SYSTEM_BANDWIDTH_DENIED;
|
||||
srs_trace("bandcheck denied, "
|
||||
"last_check=%"PRId64", now=%"PRId64", interval=%d",
|
||||
last_check_time, time_now, interval_ms);
|
||||
|
||||
"last_check=%"PRId64", now=%"PRId64", interval=%d",
|
||||
last_check_time, time_now, interval_ms);
|
||||
|
||||
rtmp->response_connect_reject(req, "bandcheck rejected");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// accept and do bandwidth check.
|
||||
last_check_time = time_now;
|
||||
|
||||
last_check_time = time_now;
|
||||
|
||||
char* local_ip = 0;
|
||||
if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) {
|
||||
srs_error("get local ip failed. ret = %d", ret);
|
||||
|
@ -137,7 +137,7 @@ int SrsBandwidth::do_bandwidth_check()
|
|||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsProtocol* protocol = rtmp->get_protocol();
|
||||
SrsProtocol* protocol = rtmp->get_protocol();
|
||||
|
||||
int play_duration_ms = 3000;
|
||||
int play_interval_ms = 0;
|
||||
|
@ -154,14 +154,14 @@ int SrsBandwidth::do_bandwidth_check()
|
|||
int64_t start_time = srs_get_system_time_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) {
|
||||
srs_error("band width play check failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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) {
|
||||
srs_error("band width publish check failed. ret=%d", 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_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) {
|
||||
srs_error("send bandwidth check finish message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if flash, we notice the result, and expect a final packet.
|
||||
while (true) {
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
// info level to ignore and return success.
|
||||
srs_info("expect final message failed. ret=%d", ret);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get final message success.");
|
||||
|
||||
if (pkt->is_flash_final()) {
|
||||
srs_info("BW check recv flash final response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
// info level to ignore and return success.
|
||||
srs_info("expect final message failed. ret=%d", ret);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get final message success.");
|
||||
|
||||
if (pkt->is_flash_final()) {
|
||||
srs_info("BW check recv flash final response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
srs_info("BW check finished.");
|
||||
|
||||
|
@ -218,44 +218,44 @@ int SrsBandwidth::do_bandwidth_check()
|
|||
}
|
||||
|
||||
int SrsBandwidth::check_play(
|
||||
int duration_ms, int interval_ms, int& actual_duration_ms,
|
||||
int& play_bytes, int max_play_kbps)
|
||||
int duration_ms, int interval_ms, int& actual_duration_ms,
|
||||
int& play_bytes, int max_play_kbps)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsProtocol* protocol = rtmp->get_protocol();
|
||||
SrsProtocol* protocol = rtmp->get_protocol();
|
||||
|
||||
if (true) {
|
||||
// send start play command to client
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
|
||||
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
|
||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("send bandwidth check start play message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check begin.");
|
||||
}
|
||||
if (true) {
|
||||
// send start play command to client
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
|
||||
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
|
||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("send bandwidth check start play message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check begin.");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// recv client's starting play response
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_starting_play()) {
|
||||
srs_info("BW check recv play begin response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
// recv client's starting play response
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_starting_play()) {
|
||||
srs_info("BW check recv play begin response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send play data to client
|
||||
int64_t current_time = srs_get_system_time_ms();
|
||||
|
@ -280,10 +280,10 @@ int SrsBandwidth::check_play(
|
|||
}
|
||||
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();
|
||||
|
||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("send bandwidth check play messages failed. ret=%d", ret);
|
||||
return ret;
|
||||
|
@ -305,81 +305,81 @@ int SrsBandwidth::check_play(
|
|||
actual_duration_ms = srs_get_system_time_ms() - current_time;
|
||||
srs_info("BW check send play bytes over.");
|
||||
|
||||
if (true) {
|
||||
// notify client to stop play
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
||||
pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes));
|
||||
if (true) {
|
||||
// notify client to stop play
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
||||
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) {
|
||||
srs_error("send bandwidth check stop play message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check stop play bytes.");
|
||||
}
|
||||
srs_error("send bandwidth check stop play message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check stop play bytes.");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// recv client's stop play response.
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_stopped_play()) {
|
||||
srs_info("BW check recv stop play response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
// recv client's stop play response.
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_stopped_play()) {
|
||||
srs_info("BW check recv stop play response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsBandwidth::check_publish(
|
||||
int duration_ms, int interval_ms, int& actual_duration_ms,
|
||||
int& publish_bytes, int max_pub_kbps)
|
||||
int duration_ms, int interval_ms, int& actual_duration_ms,
|
||||
int& publish_bytes, int max_pub_kbps)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsProtocol* protocol = rtmp->get_protocol();
|
||||
SrsProtocol* protocol = rtmp->get_protocol();
|
||||
|
||||
if (true) {
|
||||
// notify client to start publish
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
|
||||
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
|
||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("send bandwidth check start publish message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check publish begin.");
|
||||
}
|
||||
if (true) {
|
||||
// notify client to start publish
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
|
||||
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
|
||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("send bandwidth check start publish message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check publish begin.");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// read client's notification of starting publish
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_starting_publish()) {
|
||||
srs_info("BW check recv publish begin response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
// read client's notification of starting publish
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_starting_publish()) {
|
||||
srs_info("BW check recv publish begin response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// recv publish msgs until @duration_ms ms
|
||||
int64_t current_time = srs_get_system_time_ms();
|
||||
|
@ -393,7 +393,7 @@ int SrsBandwidth::check_publish(
|
|||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
|
||||
// TODO: FIXME.
|
||||
// TODO: FIXME.
|
||||
publish_bytes += msg->header.payload_length;
|
||||
|
||||
int kbps = 0;
|
||||
|
@ -411,21 +411,21 @@ int SrsBandwidth::check_publish(
|
|||
actual_duration_ms = srs_get_system_time_ms() - current_time;
|
||||
srs_info("BW check recv publish data over.");
|
||||
|
||||
if (true) {
|
||||
// notify client to stop publish
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
||||
pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes));
|
||||
if (true) {
|
||||
// notify client to stop publish
|
||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
|
||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
||||
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) {
|
||||
srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check stop publish bytes.");
|
||||
}
|
||||
srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("BW check stop publish bytes.");
|
||||
}
|
||||
|
||||
// expect client to stop publish
|
||||
// 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.
|
||||
// we just ignore the packet and send the bandwidth test data.
|
||||
// TODO: FIXME: check whether flash client.
|
||||
while (false) {
|
||||
// recv client's stop publish response.
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_stopped_publish()) {
|
||||
srs_info("BW check recv stop publish response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (false) {
|
||||
// recv client's stop publish response.
|
||||
SrsCommonMessage* msg = NULL;
|
||||
SrsBandwidthPacket* pkt = NULL;
|
||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||
srs_info("get bandwidth message succes.");
|
||||
|
||||
if (pkt->is_stopped_publish()) {
|
||||
srs_info("BW check recv stop publish response.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,7 +42,7 @@ class SrsRefer;
|
|||
class SrsConsumer;
|
||||
class SrsCommonMessage;
|
||||
class SrsSocket;
|
||||
#ifdef SRS_HTTP_CALLBACK
|
||||
#ifdef SRS_HTTP_CALLBACK
|
||||
class SrsHttpHooks;
|
||||
#endif
|
||||
class SrsBandwidth;
|
||||
|
@ -53,43 +53,43 @@ class SrsBandwidth;
|
|||
class SrsClient : public SrsConnection, public ISrsReloadHandler
|
||||
{
|
||||
private:
|
||||
char* ip;
|
||||
SrsRequest* req;
|
||||
SrsResponse* res;
|
||||
SrsSocket* skt;
|
||||
SrsRtmpServer* rtmp;
|
||||
SrsRefer* refer;
|
||||
#ifdef SRS_HTTP_CALLBACK
|
||||
SrsHttpHooks* http_hooks;
|
||||
char* ip;
|
||||
SrsRequest* req;
|
||||
SrsResponse* res;
|
||||
SrsSocket* skt;
|
||||
SrsRtmpServer* rtmp;
|
||||
SrsRefer* refer;
|
||||
#ifdef SRS_HTTP_CALLBACK
|
||||
SrsHttpHooks* http_hooks;
|
||||
#endif
|
||||
SrsBandwidth* bandwidth;
|
||||
SrsBandwidth* bandwidth;
|
||||
public:
|
||||
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||
virtual ~SrsClient();
|
||||
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||
virtual ~SrsClient();
|
||||
protected:
|
||||
virtual int do_cycle();
|
||||
virtual int do_cycle();
|
||||
// interface ISrsReloadHandler
|
||||
public:
|
||||
virtual int on_reload_vhost_removed(std::string vhost);
|
||||
virtual int on_reload_vhost_removed(std::string vhost);
|
||||
private:
|
||||
// when valid and connected to vhost/app, service the client.
|
||||
virtual int service_cycle();
|
||||
// stream(play/publish) service cycle, identify client first.
|
||||
virtual int stream_service_cycle();
|
||||
virtual int check_vhost();
|
||||
virtual int playing(SrsSource* source);
|
||||
virtual int fmle_publish(SrsSource* source);
|
||||
virtual int flash_publish(SrsSource* source);
|
||||
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
|
||||
virtual int get_peer_ip();
|
||||
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
|
||||
// when valid and connected to vhost/app, service the client.
|
||||
virtual int service_cycle();
|
||||
// stream(play/publish) service cycle, identify client first.
|
||||
virtual int stream_service_cycle();
|
||||
virtual int check_vhost();
|
||||
virtual int playing(SrsSource* source);
|
||||
virtual int fmle_publish(SrsSource* source);
|
||||
virtual int flash_publish(SrsSource* source);
|
||||
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
|
||||
virtual int get_peer_ip();
|
||||
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
|
||||
private:
|
||||
virtual int on_connect();
|
||||
virtual void on_close();
|
||||
virtual int on_publish();
|
||||
virtual void on_unpublish();
|
||||
virtual int on_play();
|
||||
virtual void on_stop();
|
||||
virtual int on_connect();
|
||||
virtual void on_close();
|
||||
virtual int on_publish();
|
||||
virtual void on_unpublish();
|
||||
virtual int on_play();
|
||||
virtual void on_stop();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,29 +33,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
SrsCodecBuffer::SrsCodecBuffer()
|
||||
{
|
||||
size = 0;
|
||||
bytes = NULL;
|
||||
size = 0;
|
||||
bytes = NULL;
|
||||
}
|
||||
|
||||
void SrsCodecBuffer::append(void* data, int len)
|
||||
{
|
||||
srs_assert(data);
|
||||
srs_assert(len > 0);
|
||||
srs_assert(data);
|
||||
srs_assert(len > 0);
|
||||
|
||||
bytes = (char*)realloc(bytes, size + len);
|
||||
memcpy(bytes + size, data, len);
|
||||
size += len;
|
||||
bytes = (char*)realloc(bytes, size + len);
|
||||
memcpy(bytes + size, data, len);
|
||||
size += len;
|
||||
}
|
||||
|
||||
void SrsCodecBuffer::free()
|
||||
{
|
||||
size = 0;
|
||||
srs_freepa(bytes);
|
||||
size = 0;
|
||||
srs_freepa(bytes);
|
||||
}
|
||||
|
||||
SrsCodecSample::SrsCodecSample()
|
||||
{
|
||||
clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
SrsCodecSample::~SrsCodecSample()
|
||||
|
@ -64,468 +64,468 @@ SrsCodecSample::~SrsCodecSample()
|
|||
|
||||
void SrsCodecSample::clear()
|
||||
{
|
||||
is_video = false;
|
||||
nb_buffers = 0;
|
||||
is_video = false;
|
||||
nb_buffers = 0;
|
||||
|
||||
cts = 0;
|
||||
frame_type = SrsCodecVideoAVCFrameReserved;
|
||||
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
||||
|
||||
sound_rate = SrsCodecAudioSampleRateReserved;
|
||||
sound_size = SrsCodecAudioSampleSizeReserved;
|
||||
sound_type = SrsCodecAudioSoundTypeReserved;
|
||||
aac_packet_type = SrsCodecAudioTypeReserved;
|
||||
cts = 0;
|
||||
frame_type = SrsCodecVideoAVCFrameReserved;
|
||||
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
||||
|
||||
sound_rate = SrsCodecAudioSampleRateReserved;
|
||||
sound_size = SrsCodecAudioSampleSizeReserved;
|
||||
sound_type = SrsCodecAudioSoundTypeReserved;
|
||||
aac_packet_type = SrsCodecAudioTypeReserved;
|
||||
}
|
||||
|
||||
int SrsCodecSample::add_sample(char* bytes, int size)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode samples error, "
|
||||
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsCodecBuffer* buf = &buffers[nb_buffers++];
|
||||
buf->bytes = bytes;
|
||||
buf->size = size;
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode samples error, "
|
||||
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsCodecBuffer* buf = &buffers[nb_buffers++];
|
||||
buf->bytes = bytes;
|
||||
buf->size = size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsCodec::SrsCodec()
|
||||
{
|
||||
width = 0;
|
||||
height = 0;
|
||||
duration = 0;
|
||||
NAL_unit_length = 0;
|
||||
frame_rate = 0;
|
||||
video_data_rate = 0;
|
||||
video_codec_id = 0;
|
||||
audio_data_rate = 0;
|
||||
audio_codec_id = 0;
|
||||
avc_profile = 0;
|
||||
avc_level = 0;
|
||||
aac_profile = 0;
|
||||
aac_sample_rate = 0;
|
||||
aac_channels = 0;
|
||||
avc_extra_size = 0;
|
||||
avc_extra_data = NULL;
|
||||
aac_extra_size = 0;
|
||||
aac_extra_data = NULL;
|
||||
sequenceParameterSetLength = 0;
|
||||
sequenceParameterSetNALUnit = NULL;
|
||||
pictureParameterSetLength = 0;
|
||||
pictureParameterSetNALUnit = NULL;
|
||||
width = 0;
|
||||
height = 0;
|
||||
duration = 0;
|
||||
NAL_unit_length = 0;
|
||||
frame_rate = 0;
|
||||
video_data_rate = 0;
|
||||
video_codec_id = 0;
|
||||
audio_data_rate = 0;
|
||||
audio_codec_id = 0;
|
||||
avc_profile = 0;
|
||||
avc_level = 0;
|
||||
aac_profile = 0;
|
||||
aac_sample_rate = 0;
|
||||
aac_channels = 0;
|
||||
avc_extra_size = 0;
|
||||
avc_extra_data = NULL;
|
||||
aac_extra_size = 0;
|
||||
aac_extra_data = NULL;
|
||||
sequenceParameterSetLength = 0;
|
||||
sequenceParameterSetNALUnit = NULL;
|
||||
pictureParameterSetLength = 0;
|
||||
pictureParameterSetNALUnit = NULL;
|
||||
|
||||
stream = new SrsStream();
|
||||
stream = new SrsStream();
|
||||
}
|
||||
|
||||
SrsCodec::~SrsCodec()
|
||||
{
|
||||
srs_freepa(avc_extra_data);
|
||||
srs_freepa(aac_extra_data);
|
||||
srs_freepa(avc_extra_data);
|
||||
srs_freepa(aac_extra_data);
|
||||
|
||||
srs_freep(stream);
|
||||
srs_freepa(sequenceParameterSetNALUnit);
|
||||
srs_freepa(pictureParameterSetNALUnit);
|
||||
srs_freep(stream);
|
||||
srs_freepa(sequenceParameterSetNALUnit);
|
||||
srs_freepa(pictureParameterSetNALUnit);
|
||||
}
|
||||
|
||||
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
sample->is_video = false;
|
||||
|
||||
if (!data || size <= 0) {
|
||||
srs_trace("no audio present, hls ignore it.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
sample->is_video = false;
|
||||
|
||||
if (!data || size <= 0) {
|
||||
srs_trace("no audio present, hls ignore it.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// audio decode
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio sound_format failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t sound_format = stream->read_1bytes();
|
||||
|
||||
int8_t sound_type = sound_format & 0x01;
|
||||
int8_t sound_size = (sound_format >> 1) & 0x01;
|
||||
int8_t sound_rate = (sound_format >> 2) & 0x03;
|
||||
sound_format = (sound_format >> 4) & 0x0f;
|
||||
|
||||
audio_codec_id = sound_format;
|
||||
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
|
||||
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
|
||||
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
|
||||
|
||||
// reset the sample rate by sequence header
|
||||
// audio decode
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio sound_format failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t sound_format = stream->read_1bytes();
|
||||
|
||||
int8_t sound_type = sound_format & 0x01;
|
||||
int8_t sound_size = (sound_format >> 1) & 0x01;
|
||||
int8_t sound_rate = (sound_format >> 2) & 0x03;
|
||||
sound_format = (sound_format >> 4) & 0x0f;
|
||||
|
||||
audio_codec_id = sound_format;
|
||||
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
|
||||
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
|
||||
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
|
||||
|
||||
// reset the sample rate by sequence header
|
||||
static int aac_sample_rates[] = {
|
||||
96000, 88200, 64000, 48000,
|
||||
44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000,
|
||||
7350, 0, 0, 0
|
||||
96000, 88200, 64000, 48000,
|
||||
44100, 32000, 24000, 22050,
|
||||
16000, 12000, 11025, 8000,
|
||||
7350, 0, 0, 0
|
||||
};
|
||||
switch (aac_sample_rates[aac_sample_rate]) {
|
||||
case 11025:
|
||||
sample->sound_rate = SrsCodecAudioSampleRate11025;
|
||||
break;
|
||||
sample->sound_rate = SrsCodecAudioSampleRate11025;
|
||||
break;
|
||||
case 22050:
|
||||
sample->sound_rate = SrsCodecAudioSampleRate22050;
|
||||
break;
|
||||
sample->sound_rate = SrsCodecAudioSampleRate22050;
|
||||
break;
|
||||
case 44100:
|
||||
sample->sound_rate = SrsCodecAudioSampleRate44100;
|
||||
break;
|
||||
sample->sound_rate = SrsCodecAudioSampleRate44100;
|
||||
break;
|
||||
};
|
||||
|
||||
// only support aac
|
||||
if (audio_codec_id != SrsCodecAudioAAC) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls only support audio aac codec. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
// only support aac
|
||||
if (audio_codec_id != SrsCodecAudioAAC) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls only support audio aac codec. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t aac_packet_type = stream->read_1bytes();
|
||||
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
|
||||
|
||||
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
||||
// AudioSpecificConfig
|
||||
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
||||
aac_extra_size = stream->left();
|
||||
if (aac_extra_size > 0) {
|
||||
srs_freepa(aac_extra_data);
|
||||
aac_extra_data = new char[aac_extra_size];
|
||||
memcpy(aac_extra_data, stream->current(), aac_extra_size);
|
||||
}
|
||||
|
||||
// only need to decode the first 2bytes:
|
||||
// audioObjectType, aac_profile, 5bits.
|
||||
// samplingFrequencyIndex, aac_sample_rate, 4bits.
|
||||
// channelConfiguration, aac_channels, 4bits
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
aac_profile = stream->read_1bytes();
|
||||
aac_sample_rate = stream->read_1bytes();
|
||||
|
||||
aac_channels = (aac_sample_rate >> 3) & 0x0f;
|
||||
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
|
||||
aac_profile = (aac_profile >> 3) & 0x1f;
|
||||
|
||||
if (aac_profile == 0 || aac_profile == 0x1f) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac sequence header failed, "
|
||||
"adts object=%d invalid. ret=%d", aac_profile, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// aac_profile = audioObjectType - 1
|
||||
aac_profile--;
|
||||
|
||||
if (aac_profile > 3) {
|
||||
// Mark all extended profiles as LC
|
||||
// to make Android as happy as possible.
|
||||
// @see: ngx_rtmp_hls_parse_aac_header
|
||||
aac_profile = 1;
|
||||
}
|
||||
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
|
||||
// ensure the sequence header demuxed
|
||||
if (aac_extra_size <= 0 || !aac_extra_data) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Raw AAC frame data in UI8 []
|
||||
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
|
||||
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
|
||||
srs_error("hls add audio sample failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
// ignored.
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t aac_packet_type = stream->read_1bytes();
|
||||
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
|
||||
|
||||
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
||||
// AudioSpecificConfig
|
||||
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
||||
aac_extra_size = stream->left();
|
||||
if (aac_extra_size > 0) {
|
||||
srs_freepa(aac_extra_data);
|
||||
aac_extra_data = new char[aac_extra_size];
|
||||
memcpy(aac_extra_data, stream->current(), aac_extra_size);
|
||||
}
|
||||
|
||||
// only need to decode the first 2bytes:
|
||||
// audioObjectType, aac_profile, 5bits.
|
||||
// samplingFrequencyIndex, aac_sample_rate, 4bits.
|
||||
// channelConfiguration, aac_channels, 4bits
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
aac_profile = stream->read_1bytes();
|
||||
aac_sample_rate = stream->read_1bytes();
|
||||
|
||||
aac_channels = (aac_sample_rate >> 3) & 0x0f;
|
||||
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
|
||||
aac_profile = (aac_profile >> 3) & 0x1f;
|
||||
|
||||
if (aac_profile == 0 || aac_profile == 0x1f) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac sequence header failed, "
|
||||
"adts object=%d invalid. ret=%d", aac_profile, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// aac_profile = audioObjectType - 1
|
||||
aac_profile--;
|
||||
|
||||
if (aac_profile > 3) {
|
||||
// Mark all extended profiles as LC
|
||||
// to make Android as happy as possible.
|
||||
// @see: ngx_rtmp_hls_parse_aac_header
|
||||
aac_profile = 1;
|
||||
}
|
||||
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
|
||||
// ensure the sequence header demuxed
|
||||
if (aac_extra_size <= 0 || !aac_extra_data) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Raw AAC frame data in UI8 []
|
||||
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
|
||||
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
|
||||
srs_error("hls add audio sample failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
// ignored.
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
sample->is_video = true;
|
||||
|
||||
if (!data || size <= 0) {
|
||||
srs_trace("no video present, hls ignore it.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
sample->is_video = true;
|
||||
|
||||
if (!data || size <= 0) {
|
||||
srs_trace("no video present, hls ignore it.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// video decode
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video frame_type failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t frame_type = stream->read_1bytes();
|
||||
int8_t codec_id = frame_type & 0x0f;
|
||||
frame_type = (frame_type >> 4) & 0x0f;
|
||||
|
||||
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
|
||||
|
||||
// only support h.264/avc
|
||||
if (codec_id != SrsCodecVideoAVC) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
video_codec_id = codec_id;
|
||||
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int8_t avc_packet_type = stream->read_1bytes();
|
||||
int32_t composition_time = stream->read_3bytes();
|
||||
|
||||
// pts = dts + cts.
|
||||
sample->cts = composition_time;
|
||||
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
|
||||
|
||||
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
||||
// AVCDecoderConfigurationRecord
|
||||
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
||||
avc_extra_size = stream->left();
|
||||
if (avc_extra_size > 0) {
|
||||
srs_freepa(avc_extra_data);
|
||||
avc_extra_data = new char[avc_extra_size];
|
||||
memcpy(avc_extra_data, stream->current(), avc_extra_size);
|
||||
}
|
||||
|
||||
if (!stream->require(6)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
//int8_t configurationVersion = stream->read_1bytes();
|
||||
//int8_t AVCProfileIndication = stream->read_1bytes();
|
||||
//int8_t profile_compatibility = stream->read_1bytes();
|
||||
//int8_t AVCLevelIndication = stream->read_1bytes();
|
||||
stream->skip(4);
|
||||
// parse the NALU size.
|
||||
int8_t lengthSizeMinusOne = stream->read_1bytes();
|
||||
lengthSizeMinusOne &= 0x03;
|
||||
NAL_unit_length = lengthSizeMinusOne;
|
||||
|
||||
// 1 sps
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int8_t numOfSequenceParameterSets = stream->read_1bytes();
|
||||
numOfSequenceParameterSets &= 0x1f;
|
||||
if (numOfSequenceParameterSets != 1) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
sequenceParameterSetLength = stream->read_2bytes();
|
||||
if (!stream->require(sequenceParameterSetLength)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (sequenceParameterSetLength > 0) {
|
||||
srs_freepa(sequenceParameterSetNALUnit);
|
||||
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
|
||||
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
|
||||
stream->skip(sequenceParameterSetLength);
|
||||
}
|
||||
// 1 pps
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int8_t numOfPictureParameterSets = stream->read_1bytes();
|
||||
numOfPictureParameterSets &= 0x1f;
|
||||
if (numOfPictureParameterSets != 1) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
pictureParameterSetLength = stream->read_2bytes();
|
||||
if (!stream->require(pictureParameterSetLength)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (pictureParameterSetLength > 0) {
|
||||
srs_freepa(pictureParameterSetNALUnit);
|
||||
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
|
||||
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
|
||||
stream->skip(pictureParameterSetLength);
|
||||
}
|
||||
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
|
||||
// ensure the sequence header demuxed
|
||||
if (avc_extra_size <= 0 || !avc_extra_data) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// One or more NALUs (Full frames are required)
|
||||
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
|
||||
int PictureLength = stream->left();
|
||||
for (int i = 0; i < PictureLength;) {
|
||||
if (!stream->require(NAL_unit_length + 1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int32_t NALUnitLength = 0;
|
||||
if (NAL_unit_length == 3) {
|
||||
NALUnitLength = stream->read_4bytes();
|
||||
} else if (NALUnitLength == 2) {
|
||||
NALUnitLength = stream->read_3bytes();
|
||||
} else if (NALUnitLength == 1) {
|
||||
NALUnitLength = stream->read_2bytes();
|
||||
} else {
|
||||
NALUnitLength = stream->read_1bytes();
|
||||
}
|
||||
// NALUnit
|
||||
if (!stream->require(NALUnitLength)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
// 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) {
|
||||
srs_error("hls add video sample failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
stream->skip(NALUnitLength);
|
||||
|
||||
i += NAL_unit_length + 1 + NALUnitLength;
|
||||
}
|
||||
} else {
|
||||
// ignored.
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
// video decode
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video frame_type failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t frame_type = stream->read_1bytes();
|
||||
int8_t codec_id = frame_type & 0x0f;
|
||||
frame_type = (frame_type >> 4) & 0x0f;
|
||||
|
||||
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
|
||||
|
||||
// only support h.264/avc
|
||||
if (codec_id != SrsCodecVideoAVC) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
video_codec_id = codec_id;
|
||||
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int8_t avc_packet_type = stream->read_1bytes();
|
||||
int32_t composition_time = stream->read_3bytes();
|
||||
|
||||
// pts = dts + cts.
|
||||
sample->cts = composition_time;
|
||||
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
|
||||
|
||||
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
||||
// AVCDecoderConfigurationRecord
|
||||
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
||||
avc_extra_size = stream->left();
|
||||
if (avc_extra_size > 0) {
|
||||
srs_freepa(avc_extra_data);
|
||||
avc_extra_data = new char[avc_extra_size];
|
||||
memcpy(avc_extra_data, stream->current(), avc_extra_size);
|
||||
}
|
||||
|
||||
if (!stream->require(6)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
//int8_t configurationVersion = stream->read_1bytes();
|
||||
//int8_t AVCProfileIndication = stream->read_1bytes();
|
||||
//int8_t profile_compatibility = stream->read_1bytes();
|
||||
//int8_t AVCLevelIndication = stream->read_1bytes();
|
||||
stream->skip(4);
|
||||
// parse the NALU size.
|
||||
int8_t lengthSizeMinusOne = stream->read_1bytes();
|
||||
lengthSizeMinusOne &= 0x03;
|
||||
NAL_unit_length = lengthSizeMinusOne;
|
||||
|
||||
// 1 sps
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int8_t numOfSequenceParameterSets = stream->read_1bytes();
|
||||
numOfSequenceParameterSets &= 0x1f;
|
||||
if (numOfSequenceParameterSets != 1) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
sequenceParameterSetLength = stream->read_2bytes();
|
||||
if (!stream->require(sequenceParameterSetLength)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (sequenceParameterSetLength > 0) {
|
||||
srs_freepa(sequenceParameterSetNALUnit);
|
||||
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
|
||||
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
|
||||
stream->skip(sequenceParameterSetLength);
|
||||
}
|
||||
// 1 pps
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int8_t numOfPictureParameterSets = stream->read_1bytes();
|
||||
numOfPictureParameterSets &= 0x1f;
|
||||
if (numOfPictureParameterSets != 1) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
pictureParameterSetLength = stream->read_2bytes();
|
||||
if (!stream->require(pictureParameterSetLength)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (pictureParameterSetLength > 0) {
|
||||
srs_freepa(pictureParameterSetNALUnit);
|
||||
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
|
||||
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
|
||||
stream->skip(pictureParameterSetLength);
|
||||
}
|
||||
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
|
||||
// ensure the sequence header demuxed
|
||||
if (avc_extra_size <= 0 || !avc_extra_data) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// One or more NALUs (Full frames are required)
|
||||
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
|
||||
int PictureLength = stream->left();
|
||||
for (int i = 0; i < PictureLength;) {
|
||||
if (!stream->require(NAL_unit_length + 1)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int32_t NALUnitLength = 0;
|
||||
if (NAL_unit_length == 3) {
|
||||
NALUnitLength = stream->read_4bytes();
|
||||
} else if (NALUnitLength == 2) {
|
||||
NALUnitLength = stream->read_3bytes();
|
||||
} else if (NALUnitLength == 1) {
|
||||
NALUnitLength = stream->read_2bytes();
|
||||
} else {
|
||||
NALUnitLength = stream->read_1bytes();
|
||||
}
|
||||
// NALUnit
|
||||
if (!stream->require(NALUnitLength)) {
|
||||
ret = ERROR_HLS_DECODE_ERROR;
|
||||
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
// 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) {
|
||||
srs_error("hls add video sample failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
stream->skip(NALUnitLength);
|
||||
|
||||
i += NAL_unit_length + 1 + NALUnitLength;
|
||||
}
|
||||
} else {
|
||||
// ignored.
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
|
||||
{
|
||||
// 2bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
// 2bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char frame_type = *(char*)data;
|
||||
frame_type = (frame_type >> 4) & 0x0F;
|
||||
|
||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
||||
char frame_type = *(char*)data;
|
||||
frame_type = (frame_type >> 4) & 0x0F;
|
||||
|
||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
||||
}
|
||||
|
||||
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
|
||||
{
|
||||
// sequence header only for h264
|
||||
if (!video_is_h264(data, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2bytes required.
|
||||
if (size < 2) {
|
||||
return false;
|
||||
}
|
||||
// sequence header only for h264
|
||||
if (!video_is_h264(data, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2bytes required.
|
||||
if (size < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char frame_type = *(char*)data;
|
||||
frame_type = (frame_type >> 4) & 0x0F;
|
||||
char frame_type = *(char*)data;
|
||||
frame_type = (frame_type >> 4) & 0x0F;
|
||||
|
||||
char avc_packet_type = *(char*)(data + 1);
|
||||
|
||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame
|
||||
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
|
||||
char avc_packet_type = *(char*)(data + 1);
|
||||
|
||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame
|
||||
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
|
||||
}
|
||||
|
||||
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
|
||||
{
|
||||
// sequence header only for aac
|
||||
if (!audio_is_aac(data, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2bytes required.
|
||||
if (size < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char aac_packet_type = *(char*)(data + 1);
|
||||
|
||||
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
|
||||
// sequence header only for aac
|
||||
if (!audio_is_aac(data, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2bytes required.
|
||||
if (size < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char aac_packet_type = *(char*)(data + 1);
|
||||
|
||||
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
|
||||
}
|
||||
|
||||
bool SrsCodec::video_is_h264(int8_t* data, int size)
|
||||
{
|
||||
// 1bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
// 1bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char codec_id = *(char*)data;
|
||||
codec_id = codec_id & 0x0F;
|
||||
|
||||
return codec_id == SrsCodecVideoAVC;
|
||||
char codec_id = *(char*)data;
|
||||
codec_id = codec_id & 0x0F;
|
||||
|
||||
return codec_id == SrsCodecVideoAVC;
|
||||
}
|
||||
|
||||
bool SrsCodec::audio_is_aac(int8_t* data, int size)
|
||||
{
|
||||
// 1bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char sound_format = *(char*)data;
|
||||
sound_format = (sound_format >> 4) & 0x0F;
|
||||
|
||||
return sound_format == SrsCodecAudioAAC;
|
||||
// 1bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char sound_format = *(char*)data;
|
||||
sound_format = (sound_format >> 4) & 0x0F;
|
||||
|
||||
return sound_format == SrsCodecAudioAAC;
|
||||
}
|
||||
|
|
|
@ -37,104 +37,104 @@ class SrsStream;
|
|||
// E.4.3.1 VIDEODATA
|
||||
// CodecID UB [4]
|
||||
// Codec Identifier. The following values are defined:
|
||||
// 2 = Sorenson H.263
|
||||
// 3 = Screen video
|
||||
// 4 = On2 VP6
|
||||
// 5 = On2 VP6 with alpha channel
|
||||
// 6 = Screen video version 2
|
||||
// 7 = AVC
|
||||
// 2 = Sorenson H.263
|
||||
// 3 = Screen video
|
||||
// 4 = On2 VP6
|
||||
// 5 = On2 VP6 with alpha channel
|
||||
// 6 = Screen video version 2
|
||||
// 7 = AVC
|
||||
enum SrsCodecVideo
|
||||
{
|
||||
SrsCodecVideoReserved = 0,
|
||||
|
||||
SrsCodecVideoSorensonH263 = 2,
|
||||
SrsCodecVideoScreenVideo = 3,
|
||||
SrsCodecVideoOn2VP6 = 4,
|
||||
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
|
||||
SrsCodecVideoScreenVideoVersion2 = 6,
|
||||
SrsCodecVideoAVC = 7,
|
||||
SrsCodecVideoReserved = 0,
|
||||
|
||||
SrsCodecVideoSorensonH263 = 2,
|
||||
SrsCodecVideoScreenVideo = 3,
|
||||
SrsCodecVideoOn2VP6 = 4,
|
||||
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
|
||||
SrsCodecVideoScreenVideoVersion2 = 6,
|
||||
SrsCodecVideoAVC = 7,
|
||||
};
|
||||
|
||||
// E.4.3.1 VIDEODATA
|
||||
// Frame Type UB [4]
|
||||
// Type of video frame. The following values are defined:
|
||||
// 1 = key frame (for AVC, a seekable frame)
|
||||
// 2 = inter frame (for AVC, a non-seekable frame)
|
||||
// 3 = disposable inter frame (H.263 only)
|
||||
// 4 = generated key frame (reserved for server use only)
|
||||
// 5 = video info/command frame
|
||||
// 1 = key frame (for AVC, a seekable frame)
|
||||
// 2 = inter frame (for AVC, a non-seekable frame)
|
||||
// 3 = disposable inter frame (H.263 only)
|
||||
// 4 = generated key frame (reserved for server use only)
|
||||
// 5 = video info/command frame
|
||||
enum SrsCodecVideoAVCFrame
|
||||
{
|
||||
SrsCodecVideoAVCFrameReserved = 0,
|
||||
|
||||
SrsCodecVideoAVCFrameKeyFrame = 1,
|
||||
SrsCodecVideoAVCFrameInterFrame = 2,
|
||||
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
|
||||
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
|
||||
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
|
||||
SrsCodecVideoAVCFrameReserved = 0,
|
||||
|
||||
SrsCodecVideoAVCFrameKeyFrame = 1,
|
||||
SrsCodecVideoAVCFrameInterFrame = 2,
|
||||
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
|
||||
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
|
||||
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
|
||||
};
|
||||
|
||||
// AVCPacketType IF CodecID == 7 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AVC sequence header
|
||||
// 1 = AVC NALU
|
||||
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
||||
// not required or supported)
|
||||
// 0 = AVC sequence header
|
||||
// 1 = AVC NALU
|
||||
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
||||
// not required or supported)
|
||||
enum SrsCodecVideoAVCType
|
||||
{
|
||||
SrsCodecVideoAVCTypeReserved = -1,
|
||||
|
||||
SrsCodecVideoAVCTypeSequenceHeader = 0,
|
||||
SrsCodecVideoAVCTypeNALU = 1,
|
||||
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
|
||||
SrsCodecVideoAVCTypeReserved = -1,
|
||||
|
||||
SrsCodecVideoAVCTypeSequenceHeader = 0,
|
||||
SrsCodecVideoAVCTypeNALU = 1,
|
||||
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
|
||||
};
|
||||
|
||||
// SoundFormat UB [4]
|
||||
// Format of SoundData. The following values are defined:
|
||||
// 0 = Linear PCM, platform endian
|
||||
// 1 = ADPCM
|
||||
// 2 = MP3
|
||||
// 3 = Linear PCM, little endian
|
||||
// 4 = Nellymoser 16 kHz mono
|
||||
// 5 = Nellymoser 8 kHz mono
|
||||
// 6 = Nellymoser
|
||||
// 7 = G.711 A-law logarithmic PCM
|
||||
// 8 = G.711 mu-law logarithmic PCM
|
||||
// 9 = reserved
|
||||
// 10 = AAC
|
||||
// 11 = Speex
|
||||
// 14 = MP3 8 kHz
|
||||
// 15 = Device-specific sound
|
||||
// 0 = Linear PCM, platform endian
|
||||
// 1 = ADPCM
|
||||
// 2 = MP3
|
||||
// 3 = Linear PCM, little endian
|
||||
// 4 = Nellymoser 16 kHz mono
|
||||
// 5 = Nellymoser 8 kHz mono
|
||||
// 6 = Nellymoser
|
||||
// 7 = G.711 A-law logarithmic PCM
|
||||
// 8 = G.711 mu-law logarithmic PCM
|
||||
// 9 = reserved
|
||||
// 10 = AAC
|
||||
// 11 = Speex
|
||||
// 14 = MP3 8 kHz
|
||||
// 15 = Device-specific sound
|
||||
// Formats 7, 8, 14, and 15 are reserved.
|
||||
// AAC is supported in Flash Player 9,0,115,0 and higher.
|
||||
// Speex is supported in Flash Player 10 and higher.
|
||||
enum SrsCodecAudio
|
||||
{
|
||||
SrsCodecAudioLinearPCMPlatformEndian = 0,
|
||||
SrsCodecAudioADPCM = 1,
|
||||
SrsCodecAudioMP3 = 2,
|
||||
SrsCodecAudioLinearPCMLittleEndian = 3,
|
||||
SrsCodecAudioNellymoser16kHzMono = 4,
|
||||
SrsCodecAudioNellymoser8kHzMono = 5,
|
||||
SrsCodecAudioNellymoser = 6,
|
||||
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
|
||||
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
|
||||
SrsCodecAudioReserved = 9,
|
||||
SrsCodecAudioAAC = 10,
|
||||
SrsCodecAudioSpeex = 11,
|
||||
SrsCodecAudioReservedMP3_8kHz = 14,
|
||||
SrsCodecAudioReservedDeviceSpecificSound = 15,
|
||||
SrsCodecAudioLinearPCMPlatformEndian = 0,
|
||||
SrsCodecAudioADPCM = 1,
|
||||
SrsCodecAudioMP3 = 2,
|
||||
SrsCodecAudioLinearPCMLittleEndian = 3,
|
||||
SrsCodecAudioNellymoser16kHzMono = 4,
|
||||
SrsCodecAudioNellymoser8kHzMono = 5,
|
||||
SrsCodecAudioNellymoser = 6,
|
||||
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
|
||||
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
|
||||
SrsCodecAudioReserved = 9,
|
||||
SrsCodecAudioAAC = 10,
|
||||
SrsCodecAudioSpeex = 11,
|
||||
SrsCodecAudioReservedMP3_8kHz = 14,
|
||||
SrsCodecAudioReservedDeviceSpecificSound = 15,
|
||||
};
|
||||
|
||||
// AACPacketType IF SoundFormat == 10 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AAC sequence header
|
||||
// 1 = AAC raw
|
||||
// 0 = AAC sequence header
|
||||
// 1 = AAC raw
|
||||
enum SrsCodecAudioType
|
||||
{
|
||||
SrsCodecAudioTypeReserved = -1,
|
||||
SrsCodecAudioTypeSequenceHeader = 0,
|
||||
SrsCodecAudioTypeRawData = 1,
|
||||
SrsCodecAudioTypeReserved = -1,
|
||||
SrsCodecAudioTypeSequenceHeader = 0,
|
||||
SrsCodecAudioTypeRawData = 1,
|
||||
};
|
||||
|
||||
// Sampling rate. The following values are defined:
|
||||
|
@ -144,12 +144,12 @@ enum SrsCodecAudioType
|
|||
// 3 = 44 kHz = 44100 Hz
|
||||
enum SrsCodecAudioSampleRate
|
||||
{
|
||||
SrsCodecAudioSampleRateReserved = -1,
|
||||
|
||||
SrsCodecAudioSampleRate5512 = 0,
|
||||
SrsCodecAudioSampleRate11025 = 1,
|
||||
SrsCodecAudioSampleRate22050 = 2,
|
||||
SrsCodecAudioSampleRate44100 = 3,
|
||||
SrsCodecAudioSampleRateReserved = -1,
|
||||
|
||||
SrsCodecAudioSampleRate5512 = 0,
|
||||
SrsCodecAudioSampleRate11025 = 1,
|
||||
SrsCodecAudioSampleRate22050 = 2,
|
||||
SrsCodecAudioSampleRate44100 = 3,
|
||||
};
|
||||
|
||||
// Size of each audio sample. This parameter only pertains to
|
||||
|
@ -159,10 +159,10 @@ enum SrsCodecAudioSampleRate
|
|||
// 1 = 16-bit samples
|
||||
enum SrsCodecAudioSampleSize
|
||||
{
|
||||
SrsCodecAudioSampleSizeReserved = -1,
|
||||
|
||||
SrsCodecAudioSampleSize8bit = 0,
|
||||
SrsCodecAudioSampleSize16bit = 1,
|
||||
SrsCodecAudioSampleSizeReserved = -1,
|
||||
|
||||
SrsCodecAudioSampleSize8bit = 0,
|
||||
SrsCodecAudioSampleSize16bit = 1,
|
||||
};
|
||||
|
||||
// Mono or stereo sound
|
||||
|
@ -170,10 +170,10 @@ enum SrsCodecAudioSampleSize
|
|||
// 1 = Stereo sound
|
||||
enum SrsCodecAudioSoundType
|
||||
{
|
||||
SrsCodecAudioSoundTypeReserved = -1,
|
||||
|
||||
SrsCodecAudioSoundTypeMono = 0,
|
||||
SrsCodecAudioSoundTypeStereo = 1,
|
||||
SrsCodecAudioSoundTypeReserved = -1,
|
||||
|
||||
SrsCodecAudioSoundTypeMono = 0,
|
||||
SrsCodecAudioSoundTypeStereo = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -181,21 +181,21 @@ enum SrsCodecAudioSoundType
|
|||
*/
|
||||
struct SrsCodecBuffer
|
||||
{
|
||||
/**
|
||||
* @remark user must manage the bytes.
|
||||
*/
|
||||
int size;
|
||||
char* bytes;
|
||||
|
||||
SrsCodecBuffer();
|
||||
void append(void* data, int len);
|
||||
|
||||
/**
|
||||
* free the bytes,
|
||||
* user can invoke it to free the bytes,
|
||||
* the SrsCodecBuffer never free automatically.
|
||||
*/
|
||||
void free();
|
||||
/**
|
||||
* @remark user must manage the bytes.
|
||||
*/
|
||||
int size;
|
||||
char* bytes;
|
||||
|
||||
SrsCodecBuffer();
|
||||
void append(void* data, int len);
|
||||
|
||||
/**
|
||||
* free the bytes,
|
||||
* user can invoke it to free the bytes,
|
||||
* the SrsCodecBuffer never free automatically.
|
||||
*/
|
||||
void free();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -204,26 +204,26 @@ struct SrsCodecBuffer
|
|||
class SrsCodecSample
|
||||
{
|
||||
public:
|
||||
int nb_buffers;
|
||||
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
|
||||
int nb_buffers;
|
||||
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
|
||||
public:
|
||||
bool is_video;
|
||||
// video specified
|
||||
SrsCodecVideoAVCFrame frame_type;
|
||||
SrsCodecVideoAVCType avc_packet_type;
|
||||
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
|
||||
// cts = pts - dts, where dts = flvheader->timestamp.
|
||||
int32_t cts;
|
||||
// audio specified
|
||||
SrsCodecAudioSampleRate sound_rate;
|
||||
SrsCodecAudioSampleSize sound_size;
|
||||
SrsCodecAudioSoundType sound_type;
|
||||
SrsCodecAudioType aac_packet_type;
|
||||
bool is_video;
|
||||
// video specified
|
||||
SrsCodecVideoAVCFrame frame_type;
|
||||
SrsCodecVideoAVCType avc_packet_type;
|
||||
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
|
||||
// cts = pts - dts, where dts = flvheader->timestamp.
|
||||
int32_t cts;
|
||||
// audio specified
|
||||
SrsCodecAudioSampleRate sound_rate;
|
||||
SrsCodecAudioSampleSize sound_size;
|
||||
SrsCodecAudioSoundType sound_type;
|
||||
SrsCodecAudioType aac_packet_type;
|
||||
public:
|
||||
SrsCodecSample();
|
||||
virtual ~SrsCodecSample();
|
||||
void clear();
|
||||
int add_sample(char* bytes, int size);
|
||||
SrsCodecSample();
|
||||
virtual ~SrsCodecSample();
|
||||
void clear();
|
||||
int add_sample(char* bytes, int size);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -232,81 +232,81 @@ public:
|
|||
class SrsCodec
|
||||
{
|
||||
private:
|
||||
SrsStream* stream;
|
||||
SrsStream* stream;
|
||||
public:
|
||||
/**
|
||||
* video specified
|
||||
*/
|
||||
// @see: SrsCodecVideo
|
||||
int video_codec_id;
|
||||
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
||||
u_int8_t avc_profile;
|
||||
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
||||
u_int8_t avc_level;
|
||||
int width;
|
||||
int height;
|
||||
int video_data_rate; // in bps
|
||||
int frame_rate;
|
||||
int duration;
|
||||
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
||||
int8_t NAL_unit_length;
|
||||
u_int16_t sequenceParameterSetLength;
|
||||
char* sequenceParameterSetNALUnit;
|
||||
u_int16_t pictureParameterSetLength;
|
||||
char* pictureParameterSetNALUnit;
|
||||
/**
|
||||
* audio specified
|
||||
*/
|
||||
// @see: SrsCodecAudioType
|
||||
int audio_codec_id;
|
||||
int audio_data_rate; // in bps
|
||||
// 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.
|
||||
u_int8_t aac_profile;
|
||||
// samplingFrequencyIndex
|
||||
u_int8_t aac_sample_rate;
|
||||
// channelConfiguration
|
||||
u_int8_t aac_channels;
|
||||
// the avc extra data, the AVC sequence header,
|
||||
// without the flv codec header,
|
||||
// @see: ffmpeg, AVCodecContext::extradata
|
||||
int avc_extra_size;
|
||||
char* avc_extra_data;
|
||||
// the aac extra data, the AAC sequence header,
|
||||
// without the flv codec header,
|
||||
// @see: ffmpeg, AVCodecContext::extradata
|
||||
int aac_extra_size;
|
||||
char* aac_extra_data;
|
||||
/**
|
||||
* video specified
|
||||
*/
|
||||
// @see: SrsCodecVideo
|
||||
int video_codec_id;
|
||||
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
||||
u_int8_t avc_profile;
|
||||
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
||||
u_int8_t avc_level;
|
||||
int width;
|
||||
int height;
|
||||
int video_data_rate; // in bps
|
||||
int frame_rate;
|
||||
int duration;
|
||||
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
||||
int8_t NAL_unit_length;
|
||||
u_int16_t sequenceParameterSetLength;
|
||||
char* sequenceParameterSetNALUnit;
|
||||
u_int16_t pictureParameterSetLength;
|
||||
char* pictureParameterSetNALUnit;
|
||||
/**
|
||||
* audio specified
|
||||
*/
|
||||
// @see: SrsCodecAudioType
|
||||
int audio_codec_id;
|
||||
int audio_data_rate; // in bps
|
||||
// 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.
|
||||
u_int8_t aac_profile;
|
||||
// samplingFrequencyIndex
|
||||
u_int8_t aac_sample_rate;
|
||||
// channelConfiguration
|
||||
u_int8_t aac_channels;
|
||||
// the avc extra data, the AVC sequence header,
|
||||
// without the flv codec header,
|
||||
// @see: ffmpeg, AVCodecContext::extradata
|
||||
int avc_extra_size;
|
||||
char* avc_extra_data;
|
||||
// the aac extra data, the AAC sequence header,
|
||||
// without the flv codec header,
|
||||
// @see: ffmpeg, AVCodecContext::extradata
|
||||
int aac_extra_size;
|
||||
char* aac_extra_data;
|
||||
public:
|
||||
SrsCodec();
|
||||
virtual ~SrsCodec();
|
||||
SrsCodec();
|
||||
virtual ~SrsCodec();
|
||||
// the following function used for hls to build the codec info.
|
||||
public:
|
||||
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 audio_aac_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.
|
||||
public:
|
||||
/**
|
||||
* only check the frame_type, not check the codec type.
|
||||
*/
|
||||
static bool video_is_keyframe(int8_t* data, int size);
|
||||
/**
|
||||
* check codec h264, keyframe, sequence header
|
||||
*/
|
||||
static bool video_is_sequence_header(int8_t* data, int size);
|
||||
/**
|
||||
* check codec aac, sequence header
|
||||
*/
|
||||
static bool audio_is_sequence_header(int8_t* data, int size);
|
||||
/**
|
||||
* check codec h264.
|
||||
*/
|
||||
static bool video_is_h264(int8_t* data, int size);
|
||||
/**
|
||||
* only check the frame_type, not check the codec type.
|
||||
*/
|
||||
static bool video_is_keyframe(int8_t* data, int size);
|
||||
/**
|
||||
* check codec h264, keyframe, sequence header
|
||||
*/
|
||||
static bool video_is_sequence_header(int8_t* data, int size);
|
||||
/**
|
||||
* check codec aac, sequence header
|
||||
*/
|
||||
static bool audio_is_sequence_header(int8_t* data, int size);
|
||||
/**
|
||||
* check codec h264.
|
||||
*/
|
||||
static bool video_is_h264(int8_t* data, int size);
|
||||
private:
|
||||
/**
|
||||
* check codec aac.
|
||||
*/
|
||||
static bool audio_is_aac(int8_t* data, int size);
|
||||
/**
|
||||
* check codec aac.
|
||||
*/
|
||||
static bool audio_is_aac(int8_t* data, int size);
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -66,25 +66,25 @@ class SrsFileBuffer;
|
|||
class SrsConfDirective
|
||||
{
|
||||
public:
|
||||
int conf_line;
|
||||
std::string name;
|
||||
std::vector<std::string> args;
|
||||
std::vector<SrsConfDirective*> directives;
|
||||
int conf_line;
|
||||
std::string name;
|
||||
std::vector<std::string> args;
|
||||
std::vector<SrsConfDirective*> directives;
|
||||
public:
|
||||
SrsConfDirective();
|
||||
virtual ~SrsConfDirective();
|
||||
std::string arg0();
|
||||
std::string arg1();
|
||||
std::string arg2();
|
||||
SrsConfDirective* at(int index);
|
||||
SrsConfDirective* get(std::string _name);
|
||||
SrsConfDirective* get(std::string _name, std::string _arg0);
|
||||
SrsConfDirective();
|
||||
virtual ~SrsConfDirective();
|
||||
std::string arg0();
|
||||
std::string arg1();
|
||||
std::string arg2();
|
||||
SrsConfDirective* at(int index);
|
||||
SrsConfDirective* get(std::string _name);
|
||||
SrsConfDirective* get(std::string _name, std::string _arg0);
|
||||
public:
|
||||
virtual int parse(const char* filename);
|
||||
virtual int parse(const char* filename);
|
||||
public:
|
||||
enum SrsDirectiveType{parse_file, parse_block};
|
||||
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
|
||||
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
|
||||
enum SrsDirectiveType{parse_file, parse_block};
|
||||
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
|
||||
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -97,81 +97,81 @@ public:
|
|||
class SrsConfig
|
||||
{
|
||||
private:
|
||||
bool show_help;
|
||||
bool show_version;
|
||||
std::string config_file;
|
||||
SrsConfDirective* root;
|
||||
std::vector<ISrsReloadHandler*> subscribes;
|
||||
bool show_help;
|
||||
bool show_version;
|
||||
std::string config_file;
|
||||
SrsConfDirective* root;
|
||||
std::vector<ISrsReloadHandler*> subscribes;
|
||||
public:
|
||||
SrsConfig();
|
||||
virtual ~SrsConfig();
|
||||
SrsConfig();
|
||||
virtual ~SrsConfig();
|
||||
public:
|
||||
virtual int reload();
|
||||
virtual void subscribe(ISrsReloadHandler* handler);
|
||||
virtual void unsubscribe(ISrsReloadHandler* handler);
|
||||
virtual int reload();
|
||||
virtual void subscribe(ISrsReloadHandler* handler);
|
||||
virtual void unsubscribe(ISrsReloadHandler* handler);
|
||||
public:
|
||||
virtual int parse_options(int argc, char** argv);
|
||||
virtual int parse_options(int argc, char** argv);
|
||||
private:
|
||||
virtual int parse_file(const char* filename);
|
||||
virtual int parse_argv(int& i, char** argv);
|
||||
virtual void print_help(char** argv);
|
||||
virtual int parse_file(const char* filename);
|
||||
virtual int parse_argv(int& i, char** argv);
|
||||
virtual void print_help(char** argv);
|
||||
public:
|
||||
virtual SrsConfDirective* get_vhost(std::string vhost);
|
||||
virtual bool get_vhost_enabled(std::string vhost);
|
||||
virtual bool get_vhost_enabled(SrsConfDirective* vhost);
|
||||
virtual SrsConfDirective* get_vhost_on_connect(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_unpublish(std::string vhost);
|
||||
virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
|
||||
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
|
||||
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
|
||||
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
|
||||
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
|
||||
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
|
||||
virtual bool get_engine_enabled(SrsConfDirective* engine);
|
||||
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
|
||||
virtual int get_engine_vbitrate(SrsConfDirective* engine);
|
||||
virtual double get_engine_vfps(SrsConfDirective* engine);
|
||||
virtual int get_engine_vwidth(SrsConfDirective* engine);
|
||||
virtual int get_engine_vheight(SrsConfDirective* engine);
|
||||
virtual int get_engine_vthreads(SrsConfDirective* engine);
|
||||
virtual std::string get_engine_vprofile(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_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
|
||||
virtual std::string get_engine_acodec(SrsConfDirective* engine);
|
||||
virtual int get_engine_abitrate(SrsConfDirective* engine);
|
||||
virtual int get_engine_asample_rate(SrsConfDirective* engine);
|
||||
virtual int get_engine_achannels(SrsConfDirective* engine);
|
||||
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
|
||||
virtual std::string get_engine_output(SrsConfDirective* engine);
|
||||
virtual std::string get_log_dir();
|
||||
virtual int get_max_connections();
|
||||
virtual bool get_gop_cache(std::string vhost);
|
||||
virtual double get_queue_length(std::string vhost);
|
||||
virtual SrsConfDirective* get_forward(std::string vhost);
|
||||
virtual SrsConfDirective* get_vhost(std::string vhost);
|
||||
virtual bool get_vhost_enabled(std::string vhost);
|
||||
virtual bool get_vhost_enabled(SrsConfDirective* vhost);
|
||||
virtual SrsConfDirective* get_vhost_on_connect(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_unpublish(std::string vhost);
|
||||
virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
|
||||
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
|
||||
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
|
||||
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
|
||||
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
|
||||
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
|
||||
virtual bool get_engine_enabled(SrsConfDirective* engine);
|
||||
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
|
||||
virtual int get_engine_vbitrate(SrsConfDirective* engine);
|
||||
virtual double get_engine_vfps(SrsConfDirective* engine);
|
||||
virtual int get_engine_vwidth(SrsConfDirective* engine);
|
||||
virtual int get_engine_vheight(SrsConfDirective* engine);
|
||||
virtual int get_engine_vthreads(SrsConfDirective* engine);
|
||||
virtual std::string get_engine_vprofile(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_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
|
||||
virtual std::string get_engine_acodec(SrsConfDirective* engine);
|
||||
virtual int get_engine_abitrate(SrsConfDirective* engine);
|
||||
virtual int get_engine_asample_rate(SrsConfDirective* engine);
|
||||
virtual int get_engine_achannels(SrsConfDirective* engine);
|
||||
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
|
||||
virtual std::string get_engine_output(SrsConfDirective* engine);
|
||||
virtual std::string get_log_dir();
|
||||
virtual int get_max_connections();
|
||||
virtual bool get_gop_cache(std::string vhost);
|
||||
virtual double get_queue_length(std::string vhost);
|
||||
virtual SrsConfDirective* get_forward(std::string vhost);
|
||||
private:
|
||||
virtual SrsConfDirective* get_hls(std::string vhost);
|
||||
virtual SrsConfDirective* get_hls(std::string vhost);
|
||||
public:
|
||||
virtual bool get_hls_enabled(std::string vhost);
|
||||
virtual std::string get_hls_path(std::string vhost);
|
||||
virtual double get_hls_fragment(std::string vhost);
|
||||
virtual double get_hls_window(std::string vhost);
|
||||
virtual SrsConfDirective* get_refer(std::string vhost);
|
||||
virtual SrsConfDirective* get_refer_play(std::string vhost);
|
||||
virtual SrsConfDirective* get_refer_publish(std::string vhost);
|
||||
virtual SrsConfDirective* get_listen();
|
||||
virtual int get_chunk_size(const std::string& vhost);
|
||||
virtual int get_pithy_print_publish();
|
||||
virtual int get_pithy_print_forwarder();
|
||||
virtual int get_pithy_print_encoder();
|
||||
virtual int get_pithy_print_hls();
|
||||
virtual int get_pithy_print_play();
|
||||
virtual bool get_hls_enabled(std::string vhost);
|
||||
virtual std::string get_hls_path(std::string vhost);
|
||||
virtual double get_hls_fragment(std::string vhost);
|
||||
virtual double get_hls_window(std::string vhost);
|
||||
virtual SrsConfDirective* get_refer(std::string vhost);
|
||||
virtual SrsConfDirective* get_refer_play(std::string vhost);
|
||||
virtual SrsConfDirective* get_refer_publish(std::string vhost);
|
||||
virtual SrsConfDirective* get_listen();
|
||||
virtual int get_chunk_size(const std::string& vhost);
|
||||
virtual int get_pithy_print_publish();
|
||||
virtual int get_pithy_print_forwarder();
|
||||
virtual int get_pithy_print_encoder();
|
||||
virtual int get_pithy_print_hls();
|
||||
virtual int get_pithy_print_play();
|
||||
virtual bool get_bw_check_enabled(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_limit_kbps(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_limit_kbps(const std::string& vhost);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
server = srs_server;
|
||||
stfd = client_stfd;
|
||||
connection_id = 0;
|
||||
server = srs_server;
|
||||
stfd = client_stfd;
|
||||
connection_id = 0;
|
||||
}
|
||||
|
||||
SrsConnection::~SrsConnection()
|
||||
{
|
||||
srs_close_stfd(stfd);
|
||||
srs_close_stfd(stfd);
|
||||
}
|
||||
|
||||
int SrsConnection::start()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (st_thread_create(cycle_thread, this, 0, 0) == NULL) {
|
||||
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
||||
|
@ -49,44 +49,44 @@ int SrsConnection::start()
|
|||
return ret;
|
||||
}
|
||||
srs_verbose("create st conn cycle thread success.");
|
||||
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsConnection::cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
_srs_context->generate_id();
|
||||
connection_id = _srs_context->get_id();
|
||||
|
||||
ret = do_cycle();
|
||||
|
||||
// if socket io error, set to closed.
|
||||
if (srs_is_client_gracefully_close(ret)) {
|
||||
ret = ERROR_SOCKET_CLOSED;
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// success.
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
srs_trace("client process normally finished. ret=%d", ret);
|
||||
}
|
||||
|
||||
// client close peer.
|
||||
if (ret == ERROR_SOCKET_CLOSED) {
|
||||
srs_warn("client disconnect peer. ret=%d", ret);
|
||||
}
|
||||
|
||||
server->remove(this);
|
||||
_srs_context->generate_id();
|
||||
connection_id = _srs_context->get_id();
|
||||
|
||||
ret = do_cycle();
|
||||
|
||||
// if socket io error, set to closed.
|
||||
if (srs_is_client_gracefully_close(ret)) {
|
||||
ret = ERROR_SOCKET_CLOSED;
|
||||
}
|
||||
|
||||
// success.
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
srs_trace("client process normally finished. ret=%d", ret);
|
||||
}
|
||||
|
||||
// client close peer.
|
||||
if (ret == ERROR_SOCKET_CLOSED) {
|
||||
srs_warn("client disconnect peer. ret=%d", ret);
|
||||
}
|
||||
|
||||
server->remove(this);
|
||||
}
|
||||
|
||||
void* SrsConnection::cycle_thread(void* arg)
|
||||
{
|
||||
SrsConnection* conn = (SrsConnection*)arg;
|
||||
srs_assert(conn != NULL);
|
||||
|
||||
conn->cycle();
|
||||
|
||||
return NULL;
|
||||
SrsConnection* conn = (SrsConnection*)arg;
|
||||
srs_assert(conn != NULL);
|
||||
|
||||
conn->cycle();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,19 +36,19 @@ class SrsServer;
|
|||
class SrsConnection
|
||||
{
|
||||
protected:
|
||||
SrsServer* server;
|
||||
st_netfd_t stfd;
|
||||
int connection_id;
|
||||
SrsServer* server;
|
||||
st_netfd_t stfd;
|
||||
int connection_id;
|
||||
public:
|
||||
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||
virtual ~SrsConnection();
|
||||
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||
virtual ~SrsConnection();
|
||||
public:
|
||||
virtual int start();
|
||||
virtual int start();
|
||||
protected:
|
||||
virtual int do_cycle() = 0;
|
||||
virtual int do_cycle() = 0;
|
||||
private:
|
||||
virtual void cycle();
|
||||
static void* cycle_thread(void* arg);
|
||||
virtual void cycle();
|
||||
static void* cycle_thread(void* arg);
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -47,38 +47,38 @@ class SrsPithyPrint;
|
|||
class SrsFFMPEG
|
||||
{
|
||||
private:
|
||||
bool started;
|
||||
pid_t pid;
|
||||
bool started;
|
||||
pid_t pid;
|
||||
private:
|
||||
std::string log_file;
|
||||
int log_fd;
|
||||
std::string log_file;
|
||||
int log_fd;
|
||||
private:
|
||||
std::string ffmpeg;
|
||||
std::vector<std::string> vfilter;
|
||||
std::string vcodec;
|
||||
int vbitrate;
|
||||
double vfps;
|
||||
int vwidth;
|
||||
int vheight;
|
||||
int vthreads;
|
||||
std::string vprofile;
|
||||
std::string vpreset;
|
||||
std::vector<std::string> vparams;
|
||||
std::string acodec;
|
||||
int abitrate;
|
||||
int asample_rate;
|
||||
int achannels;
|
||||
std::vector<std::string> aparams;
|
||||
std::string output;
|
||||
std::string input;
|
||||
std::string ffmpeg;
|
||||
std::vector<std::string> vfilter;
|
||||
std::string vcodec;
|
||||
int vbitrate;
|
||||
double vfps;
|
||||
int vwidth;
|
||||
int vheight;
|
||||
int vthreads;
|
||||
std::string vprofile;
|
||||
std::string vpreset;
|
||||
std::vector<std::string> vparams;
|
||||
std::string acodec;
|
||||
int abitrate;
|
||||
int asample_rate;
|
||||
int achannels;
|
||||
std::vector<std::string> aparams;
|
||||
std::string output;
|
||||
std::string input;
|
||||
public:
|
||||
SrsFFMPEG(std::string ffmpeg_bin);
|
||||
virtual ~SrsFFMPEG();
|
||||
SrsFFMPEG(std::string ffmpeg_bin);
|
||||
virtual ~SrsFFMPEG();
|
||||
public:
|
||||
virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
|
||||
virtual int start();
|
||||
virtual int cycle();
|
||||
virtual void stop();
|
||||
virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
|
||||
virtual int start();
|
||||
virtual int cycle();
|
||||
virtual void stop();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -88,26 +88,26 @@ public:
|
|||
class SrsEncoder : public ISrsThreadHandler
|
||||
{
|
||||
private:
|
||||
std::vector<SrsFFMPEG*> ffmpegs;
|
||||
std::vector<SrsFFMPEG*> ffmpegs;
|
||||
private:
|
||||
SrsThread* pthread;
|
||||
SrsPithyPrint* pithy_print;
|
||||
SrsThread* pthread;
|
||||
SrsPithyPrint* pithy_print;
|
||||
public:
|
||||
SrsEncoder();
|
||||
virtual ~SrsEncoder();
|
||||
SrsEncoder();
|
||||
virtual ~SrsEncoder();
|
||||
public:
|
||||
virtual int on_publish(SrsRequest* req);
|
||||
virtual void on_unpublish();
|
||||
virtual int on_publish(SrsRequest* req);
|
||||
virtual void on_unpublish();
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual int cycle();
|
||||
virtual void on_leave_loop();
|
||||
virtual int cycle();
|
||||
virtual void on_leave_loop();
|
||||
private:
|
||||
virtual void clear_engines();
|
||||
virtual SrsFFMPEG* at(int index);
|
||||
virtual int parse_scope_engines(SrsRequest* req);
|
||||
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
|
||||
virtual void encoder();
|
||||
virtual void clear_engines();
|
||||
virtual SrsFFMPEG* at(int index);
|
||||
virtual int parse_scope_engines(SrsRequest* req);
|
||||
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
|
||||
virtual void encoder();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,203 +42,203 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
SrsForwarder::SrsForwarder(SrsSource* _source)
|
||||
{
|
||||
source = _source;
|
||||
|
||||
io = NULL;
|
||||
client = NULL;
|
||||
stfd = NULL;
|
||||
stream_id = 0;
|
||||
source = _source;
|
||||
|
||||
io = NULL;
|
||||
client = NULL;
|
||||
stfd = NULL;
|
||||
stream_id = 0;
|
||||
|
||||
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
|
||||
queue = new SrsMessageQueue();
|
||||
jitter = new SrsRtmpJitter();
|
||||
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
|
||||
queue = new SrsMessageQueue();
|
||||
jitter = new SrsRtmpJitter();
|
||||
}
|
||||
|
||||
SrsForwarder::~SrsForwarder()
|
||||
{
|
||||
on_unpublish();
|
||||
|
||||
srs_freep(pthread);
|
||||
srs_freep(queue);
|
||||
srs_freep(jitter);
|
||||
on_unpublish();
|
||||
|
||||
srs_freep(pthread);
|
||||
srs_freep(queue);
|
||||
srs_freep(jitter);
|
||||
}
|
||||
|
||||
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 ret = ERROR_SUCCESS;
|
||||
|
||||
// forward app
|
||||
app = req->app;
|
||||
|
||||
stream_name = req->stream;
|
||||
server = forward_server;
|
||||
std::string s_port = RTMP_DEFAULT_PORT;
|
||||
port = ::atoi(RTMP_DEFAULT_PORT);
|
||||
|
||||
size_t pos = forward_server.find(":");
|
||||
if (pos != std::string::npos) {
|
||||
s_port = forward_server.substr(pos + 1);
|
||||
server = forward_server.substr(0, pos);
|
||||
}
|
||||
// discovery vhost
|
||||
std::string vhost = req->vhost;
|
||||
srs_vhost_resolve(vhost, s_port);
|
||||
port = ::atoi(s_port.c_str());
|
||||
|
||||
// generate tcUrl
|
||||
tc_url = "rtmp://";
|
||||
tc_url += vhost;
|
||||
tc_url += "/";
|
||||
tc_url += req->app;
|
||||
|
||||
// dead loop check
|
||||
std::string source_ep = req->vhost;
|
||||
source_ep += ":";
|
||||
source_ep += req->port;
|
||||
|
||||
std::string dest_ep = vhost;
|
||||
dest_ep += ":";
|
||||
dest_ep += s_port;
|
||||
|
||||
if (source_ep == dest_ep) {
|
||||
ret = ERROR_SYSTEM_FORWARD_LOOP;
|
||||
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
|
||||
source_ep.c_str(), dest_ep.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
srs_trace("start forward %s to %s, stream: %s/%s",
|
||||
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
|
||||
stream_name.c_str());
|
||||
|
||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// forward app
|
||||
app = req->app;
|
||||
|
||||
stream_name = req->stream;
|
||||
server = forward_server;
|
||||
std::string s_port = RTMP_DEFAULT_PORT;
|
||||
port = ::atoi(RTMP_DEFAULT_PORT);
|
||||
|
||||
size_t pos = forward_server.find(":");
|
||||
if (pos != std::string::npos) {
|
||||
s_port = forward_server.substr(pos + 1);
|
||||
server = forward_server.substr(0, pos);
|
||||
}
|
||||
// discovery vhost
|
||||
std::string vhost = req->vhost;
|
||||
srs_vhost_resolve(vhost, s_port);
|
||||
port = ::atoi(s_port.c_str());
|
||||
|
||||
// generate tcUrl
|
||||
tc_url = "rtmp://";
|
||||
tc_url += vhost;
|
||||
tc_url += "/";
|
||||
tc_url += req->app;
|
||||
|
||||
// dead loop check
|
||||
std::string source_ep = req->vhost;
|
||||
source_ep += ":";
|
||||
source_ep += req->port;
|
||||
|
||||
std::string dest_ep = vhost;
|
||||
dest_ep += ":";
|
||||
dest_ep += s_port;
|
||||
|
||||
if (source_ep == dest_ep) {
|
||||
ret = ERROR_SYSTEM_FORWARD_LOOP;
|
||||
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
|
||||
source_ep.c_str(), dest_ep.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
srs_trace("start forward %s to %s, stream: %s/%s",
|
||||
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
|
||||
stream_name.c_str());
|
||||
|
||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||
srs_error("start srs thread failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsForwarder::on_unpublish()
|
||||
{
|
||||
pthread->stop();
|
||||
|
||||
close_underlayer_socket();
|
||||
|
||||
srs_freep(client);
|
||||
srs_freep(io);
|
||||
pthread->stop();
|
||||
|
||||
close_underlayer_socket();
|
||||
|
||||
srs_freep(client);
|
||||
srs_freep(io);
|
||||
}
|
||||
|
||||
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
|
||||
srs_freep(metadata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
|
||||
srs_freep(metadata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
||||
srs_freep(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
||||
srs_freep(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
||||
srs_freep(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
||||
srs_freep(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsForwarder::cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = connect_server()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
srs_assert(client);
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = connect_server()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
srs_assert(client);
|
||||
|
||||
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
|
||||
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
|
||||
|
||||
if ((ret = client->handshake()) != ERROR_SUCCESS) {
|
||||
srs_error("handshake with server failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
|
||||
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
|
||||
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
|
||||
stream_name.c_str(), stream_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
|
||||
srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = forward()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
|
||||
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
|
||||
|
||||
if ((ret = client->handshake()) != ERROR_SUCCESS) {
|
||||
srs_error("handshake with server failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
|
||||
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
|
||||
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
|
||||
stream_name.c_str(), stream_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
|
||||
srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = forward()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsForwarder::close_underlayer_socket()
|
||||
{
|
||||
srs_close_stfd(stfd);
|
||||
srs_close_stfd(stfd);
|
||||
}
|
||||
|
||||
int SrsForwarder::connect_server()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// reopen
|
||||
close_underlayer_socket();
|
||||
|
||||
// open socket.
|
||||
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
|
||||
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// reopen
|
||||
close_underlayer_socket();
|
||||
|
||||
// open socket.
|
||||
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
|
||||
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sock == -1){
|
||||
|
@ -255,20 +255,20 @@ int SrsForwarder::connect_server()
|
|||
return ret;
|
||||
}
|
||||
|
||||
srs_freep(client);
|
||||
srs_freep(io);
|
||||
|
||||
io = new SrsSocket(stfd);
|
||||
client = new SrsRtmpClient(io);
|
||||
|
||||
// connect to server.
|
||||
std::string ip = srs_dns_resolve(server);
|
||||
if (ip.empty()) {
|
||||
ret = ERROR_SYSTEM_IP_INVALID;
|
||||
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_freep(client);
|
||||
srs_freep(io);
|
||||
|
||||
io = new SrsSocket(stfd);
|
||||
client = new SrsRtmpClient(io);
|
||||
|
||||
// connect to server.
|
||||
std::string ip = srs_dns_resolve(server);
|
||||
if (ip.empty()) {
|
||||
ret = ERROR_SYSTEM_IP_INVALID;
|
||||
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
@ -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);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsForwarder::forward()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
|
||||
|
||||
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
|
||||
|
||||
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
|
||||
|
||||
while (pthread->can_loop()) {
|
||||
// switch to other st-threads.
|
||||
st_usleep(0);
|
||||
while (pthread->can_loop()) {
|
||||
// switch to other st-threads.
|
||||
st_usleep(0);
|
||||
|
||||
// read from client.
|
||||
if (true) {
|
||||
SrsCommonMessage* msg = NULL;
|
||||
ret = client->recv_message(&msg);
|
||||
|
||||
srs_verbose("play loop recv message. ret=%d", ret);
|
||||
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
|
||||
srs_error("recv server control message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// forward all messages.
|
||||
int count = 0;
|
||||
SrsSharedPtrMessage** msgs = NULL;
|
||||
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
|
||||
srs_error("get message to forward failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ignore when no messages.
|
||||
if (count <= 0) {
|
||||
srs_verbose("no packets to forward.");
|
||||
continue;
|
||||
}
|
||||
SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
|
||||
// read from client.
|
||||
if (true) {
|
||||
SrsCommonMessage* msg = NULL;
|
||||
ret = client->recv_message(&msg);
|
||||
|
||||
srs_verbose("play loop recv message. ret=%d", ret);
|
||||
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
|
||||
srs_error("recv server control message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// forward all messages.
|
||||
int count = 0;
|
||||
SrsSharedPtrMessage** msgs = NULL;
|
||||
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
|
||||
srs_error("get message to forward failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ignore when no messages.
|
||||
if (count <= 0) {
|
||||
srs_verbose("no packets to forward.");
|
||||
continue;
|
||||
}
|
||||
SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
|
||||
|
||||
// pithy print
|
||||
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
|
||||
if (pithy_print.can_print()) {
|
||||
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());
|
||||
}
|
||||
|
||||
// all msgs to forward.
|
||||
for (int i = 0; i < count; i++) {
|
||||
SrsSharedPtrMessage* msg = msgs[i];
|
||||
|
||||
srs_assert(msg);
|
||||
msgs[i] = NULL;
|
||||
|
||||
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("forwarder send message to server failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
// pithy print
|
||||
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
|
||||
if (pithy_print.can_print()) {
|
||||
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());
|
||||
}
|
||||
|
||||
// all msgs to forward.
|
||||
for (int i = 0; i < count; i++) {
|
||||
SrsSharedPtrMessage* msg = msgs[i];
|
||||
|
||||
srs_assert(msg);
|
||||
msgs[i] = NULL;
|
||||
|
||||
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("forwarder send message to server failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,39 +49,39 @@ class SrsSource;
|
|||
class SrsForwarder : public ISrsThreadHandler
|
||||
{
|
||||
private:
|
||||
std::string app;
|
||||
std::string tc_url;
|
||||
std::string stream_name;
|
||||
int stream_id;
|
||||
std::string server;
|
||||
int port;
|
||||
std::string app;
|
||||
std::string tc_url;
|
||||
std::string stream_name;
|
||||
int stream_id;
|
||||
std::string server;
|
||||
int port;
|
||||
private:
|
||||
st_netfd_t stfd;
|
||||
SrsThread* pthread;
|
||||
st_netfd_t stfd;
|
||||
SrsThread* pthread;
|
||||
private:
|
||||
SrsSource* source;
|
||||
ISrsProtocolReaderWriter* io;
|
||||
SrsRtmpClient* client;
|
||||
SrsRtmpJitter* jitter;
|
||||
SrsMessageQueue* queue;
|
||||
SrsSource* source;
|
||||
ISrsProtocolReaderWriter* io;
|
||||
SrsRtmpClient* client;
|
||||
SrsRtmpJitter* jitter;
|
||||
SrsMessageQueue* queue;
|
||||
public:
|
||||
SrsForwarder(SrsSource* _source);
|
||||
virtual ~SrsForwarder();
|
||||
SrsForwarder(SrsSource* _source);
|
||||
virtual ~SrsForwarder();
|
||||
public:
|
||||
virtual void set_queue_size(double queue_size);
|
||||
virtual void set_queue_size(double queue_size);
|
||||
public:
|
||||
virtual int on_publish(SrsRequest* req, std::string forward_server);
|
||||
virtual void on_unpublish();
|
||||
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
|
||||
virtual int on_audio(SrsSharedPtrMessage* msg);
|
||||
virtual int on_video(SrsSharedPtrMessage* msg);
|
||||
virtual int on_publish(SrsRequest* req, std::string forward_server);
|
||||
virtual void on_unpublish();
|
||||
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
|
||||
virtual int on_audio(SrsSharedPtrMessage* msg);
|
||||
virtual int on_video(SrsSharedPtrMessage* msg);
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual int cycle();
|
||||
virtual int cycle();
|
||||
private:
|
||||
virtual void close_underlayer_socket();
|
||||
virtual int connect_server();
|
||||
virtual int forward();
|
||||
virtual void close_underlayer_socket();
|
||||
virtual int connect_server();
|
||||
virtual int forward();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,40 +56,40 @@ class SrsSource;
|
|||
class SrsHlsAacJitter
|
||||
{
|
||||
private:
|
||||
int64_t base_pts;
|
||||
int64_t nb_samples;
|
||||
int sync_ms;
|
||||
int64_t base_pts;
|
||||
int64_t nb_samples;
|
||||
int sync_ms;
|
||||
public:
|
||||
SrsHlsAacJitter();
|
||||
virtual ~SrsHlsAacJitter();
|
||||
/**
|
||||
* when buffer start, calc the "correct" pts for ts,
|
||||
* @param flv_pts, the flv pts calc from flv header timestamp,
|
||||
* @return the calc correct pts.
|
||||
*/
|
||||
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
|
||||
/**
|
||||
* when buffer continue, muxer donot write to file,
|
||||
* the audio buffer continue grow and donot need a pts,
|
||||
* for the ts audio PES packet only has one pts at the first time.
|
||||
*/
|
||||
virtual void on_buffer_continue();
|
||||
SrsHlsAacJitter();
|
||||
virtual ~SrsHlsAacJitter();
|
||||
/**
|
||||
* when buffer start, calc the "correct" pts for ts,
|
||||
* @param flv_pts, the flv pts calc from flv header timestamp,
|
||||
* @return the calc correct pts.
|
||||
*/
|
||||
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
|
||||
/**
|
||||
* when buffer continue, muxer donot write to file,
|
||||
* the audio buffer continue grow and donot need a pts,
|
||||
* for the ts audio PES packet only has one pts at the first time.
|
||||
*/
|
||||
virtual void on_buffer_continue();
|
||||
};
|
||||
|
||||
//TODO: refine the ts muxer, do more jobs.
|
||||
class SrsTSMuxer
|
||||
{
|
||||
private:
|
||||
int fd;
|
||||
std::string path;
|
||||
int fd;
|
||||
std::string path;
|
||||
public:
|
||||
SrsTSMuxer();
|
||||
virtual ~SrsTSMuxer();
|
||||
SrsTSMuxer();
|
||||
virtual ~SrsTSMuxer();
|
||||
public:
|
||||
virtual int open(std::string _path);
|
||||
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
||||
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
||||
virtual void close();
|
||||
virtual int open(std::string _path);
|
||||
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
||||
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
||||
virtual void close();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -98,26 +98,26 @@ public:
|
|||
*/
|
||||
struct SrsM3u8Segment
|
||||
{
|
||||
// duration in seconds in m3u8.
|
||||
double duration;
|
||||
// sequence number in m3u8.
|
||||
int sequence_no;
|
||||
// ts uri in m3u8.
|
||||
std::string uri;
|
||||
// ts full file to write.
|
||||
std::string full_path;
|
||||
// the muxer to write ts.
|
||||
SrsTSMuxer* muxer;
|
||||
// current segment start dts for m3u8
|
||||
int64_t segment_start_dts;
|
||||
|
||||
SrsM3u8Segment();
|
||||
virtual ~SrsM3u8Segment();
|
||||
|
||||
/**
|
||||
* update the segment duration.
|
||||
*/
|
||||
virtual double update_duration(int64_t video_stream_dts);
|
||||
// duration in seconds in m3u8.
|
||||
double duration;
|
||||
// sequence number in m3u8.
|
||||
int sequence_no;
|
||||
// ts uri in m3u8.
|
||||
std::string uri;
|
||||
// ts full file to write.
|
||||
std::string full_path;
|
||||
// the muxer to write ts.
|
||||
SrsTSMuxer* muxer;
|
||||
// current segment start dts for m3u8
|
||||
int64_t segment_start_dts;
|
||||
|
||||
SrsM3u8Segment();
|
||||
virtual ~SrsM3u8Segment();
|
||||
|
||||
/**
|
||||
* update the segment duration.
|
||||
*/
|
||||
virtual double update_duration(int64_t video_stream_dts);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -126,39 +126,39 @@ struct SrsM3u8Segment
|
|||
class SrsM3u8Muxer
|
||||
{
|
||||
private:
|
||||
std::string app;
|
||||
std::string stream;
|
||||
std::string app;
|
||||
std::string stream;
|
||||
private:
|
||||
std::string hls_path;
|
||||
int hls_fragment;
|
||||
int hls_window;
|
||||
std::string hls_path;
|
||||
int hls_fragment;
|
||||
int hls_window;
|
||||
private:
|
||||
int file_index;
|
||||
std::string m3u8;
|
||||
int file_index;
|
||||
std::string m3u8;
|
||||
private:
|
||||
/**
|
||||
* m3u8 segments.
|
||||
*/
|
||||
std::vector<SrsM3u8Segment*> segments;
|
||||
/**
|
||||
* current writing segment.
|
||||
*/
|
||||
SrsM3u8Segment* current;
|
||||
// last known dts
|
||||
int64_t video_stream_dts;
|
||||
/**
|
||||
* m3u8 segments.
|
||||
*/
|
||||
std::vector<SrsM3u8Segment*> segments;
|
||||
/**
|
||||
* current writing segment.
|
||||
*/
|
||||
SrsM3u8Segment* current;
|
||||
// last known dts
|
||||
int64_t video_stream_dts;
|
||||
public:
|
||||
SrsM3u8Muxer();
|
||||
virtual ~SrsM3u8Muxer();
|
||||
SrsM3u8Muxer();
|
||||
virtual ~SrsM3u8Muxer();
|
||||
public:
|
||||
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
|
||||
virtual int segment_open();
|
||||
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
||||
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
||||
virtual int segment_close();
|
||||
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
|
||||
virtual int segment_open();
|
||||
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
||||
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
||||
virtual int segment_close();
|
||||
private:
|
||||
virtual int refresh_m3u8();
|
||||
virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
|
||||
virtual int create_dir();
|
||||
virtual int refresh_m3u8();
|
||||
virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
|
||||
virtual int create_dir();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -167,35 +167,35 @@ private:
|
|||
class SrsTSCache
|
||||
{
|
||||
private:
|
||||
// current frame and buffer
|
||||
SrsMpegtsFrame* af;
|
||||
SrsCodecBuffer* ab;
|
||||
SrsMpegtsFrame* vf;
|
||||
SrsCodecBuffer* vb;
|
||||
// current frame and buffer
|
||||
SrsMpegtsFrame* af;
|
||||
SrsCodecBuffer* ab;
|
||||
SrsMpegtsFrame* vf;
|
||||
SrsCodecBuffer* vb;
|
||||
private:
|
||||
// the audio cache buffer start pts, to flush audio if full.
|
||||
int64_t audio_buffer_start_pts;
|
||||
// time jitter for aac
|
||||
SrsHlsAacJitter* aac_jitter;
|
||||
// the audio cache buffer start pts, to flush audio if full.
|
||||
int64_t audio_buffer_start_pts;
|
||||
// time jitter for aac
|
||||
SrsHlsAacJitter* aac_jitter;
|
||||
public:
|
||||
SrsTSCache();
|
||||
virtual ~SrsTSCache();
|
||||
SrsTSCache();
|
||||
virtual ~SrsTSCache();
|
||||
public:
|
||||
/**
|
||||
* write audio to cache, if need to flush, flush to muxer.
|
||||
*/
|
||||
virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample);
|
||||
/**
|
||||
* write video to muxer.
|
||||
*/
|
||||
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
|
||||
/**
|
||||
* flush audio in cache to muxer.
|
||||
*/
|
||||
virtual int flush_audio(SrsM3u8Muxer* 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);
|
||||
/**
|
||||
* write video to muxer.
|
||||
*/
|
||||
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
|
||||
/**
|
||||
* flush audio in cache to muxer.
|
||||
*/
|
||||
virtual int flush_audio(SrsM3u8Muxer* muxer);
|
||||
private:
|
||||
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
|
||||
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
|
||||
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
|
||||
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -204,43 +204,43 @@ private:
|
|||
class SrsHls
|
||||
{
|
||||
private:
|
||||
SrsM3u8Muxer* muxer;
|
||||
SrsTSCache* ts_cache;
|
||||
SrsM3u8Muxer* muxer;
|
||||
SrsTSCache* ts_cache;
|
||||
private:
|
||||
bool hls_enabled;
|
||||
SrsSource* source;
|
||||
SrsCodec* codec;
|
||||
SrsCodecSample* sample;
|
||||
SrsRtmpJitter* jitter;
|
||||
SrsPithyPrint* pithy_print;
|
||||
bool hls_enabled;
|
||||
SrsSource* source;
|
||||
SrsCodec* codec;
|
||||
SrsCodecSample* sample;
|
||||
SrsRtmpJitter* jitter;
|
||||
SrsPithyPrint* pithy_print;
|
||||
public:
|
||||
SrsHls(SrsSource* _source);
|
||||
virtual ~SrsHls();
|
||||
SrsHls(SrsSource* _source);
|
||||
virtual ~SrsHls();
|
||||
public:
|
||||
/**
|
||||
* publish stream event, continue to write the m3u8,
|
||||
* for the muxer object not destroyed.
|
||||
*/
|
||||
virtual int on_publish(SrsRequest* req);
|
||||
/**
|
||||
* the unpublish event, only close the muxer, donot destroy the
|
||||
* muxer, for when we continue to publish, the m3u8 will continue.
|
||||
*/
|
||||
virtual void on_unpublish();
|
||||
/**
|
||||
* get some information from metadata, it's optinal.
|
||||
*/
|
||||
virtual int on_meta_data(SrsAmf0Object* metadata);
|
||||
/**
|
||||
* mux the audio packets to ts.
|
||||
*/
|
||||
virtual int on_audio(SrsSharedPtrMessage* audio);
|
||||
/**
|
||||
* mux the video packets to ts.
|
||||
*/
|
||||
virtual int on_video(SrsSharedPtrMessage* video);
|
||||
/**
|
||||
* publish stream event, continue to write the m3u8,
|
||||
* for the muxer object not destroyed.
|
||||
*/
|
||||
virtual int on_publish(SrsRequest* req);
|
||||
/**
|
||||
* the unpublish event, only close the muxer, donot destroy the
|
||||
* muxer, for when we continue to publish, the m3u8 will continue.
|
||||
*/
|
||||
virtual void on_unpublish();
|
||||
/**
|
||||
* get some information from metadata, it's optinal.
|
||||
*/
|
||||
virtual int on_meta_data(SrsAmf0Object* metadata);
|
||||
/**
|
||||
* mux the audio packets to ts.
|
||||
*/
|
||||
virtual int on_audio(SrsSharedPtrMessage* audio);
|
||||
/**
|
||||
* mux the video packets to ts.
|
||||
*/
|
||||
virtual int on_video(SrsSharedPtrMessage* video);
|
||||
private:
|
||||
virtual void hls_mux();
|
||||
virtual void hls_mux();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
SrsHttpUri::SrsHttpUri()
|
||||
{
|
||||
port = SRS_DEFAULT_HTTP_PORT;
|
||||
port = SRS_DEFAULT_HTTP_PORT;
|
||||
}
|
||||
|
||||
SrsHttpUri::~SrsHttpUri()
|
||||
|
@ -51,7 +51,7 @@ SrsHttpUri::~SrsHttpUri()
|
|||
|
||||
int SrsHttpUri::initialize(std::string _url)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
url = _url;
|
||||
const char* purl = url.c_str();
|
||||
|
@ -65,7 +65,7 @@ int SrsHttpUri::initialize(std::string _url)
|
|||
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()){
|
||||
schema = field;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ int SrsHttpUri::initialize(std::string _url)
|
|||
path = get_uri_field(url, &hp_u, UF_PATH);
|
||||
srs_info("parse url %s success", purl);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* SrsHttpUri::get_url()
|
||||
|
@ -128,24 +128,24 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht
|
|||
|
||||
SrsHttpClient::SrsHttpClient()
|
||||
{
|
||||
connected = false;
|
||||
stfd = NULL;
|
||||
connected = false;
|
||||
stfd = NULL;
|
||||
}
|
||||
|
||||
SrsHttpClient::~SrsHttpClient()
|
||||
{
|
||||
disconnect();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = connect(uri)) != ERROR_SUCCESS) {
|
||||
srs_error("http connect server failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = connect(uri)) != ERROR_SUCCESS) {
|
||||
srs_error("http connect server failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// send POST request to uri
|
||||
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
|
||||
std::stringstream ss;
|
||||
|
@ -176,33 +176,33 @@ int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
|
|||
return ret;
|
||||
}
|
||||
srs_info("parse http post response success.");
|
||||
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsHttpClient::disconnect()
|
||||
{
|
||||
connected = false;
|
||||
|
||||
srs_close_stfd(stfd);
|
||||
connected = false;
|
||||
|
||||
srs_close_stfd(stfd);
|
||||
}
|
||||
|
||||
int SrsHttpClient::connect(SrsHttpUri* uri)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (connected) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
disconnect();
|
||||
|
||||
std::string ip = srs_dns_resolve(uri->get_host());
|
||||
if (ip.empty()) {
|
||||
ret = ERROR_SYSTEM_IP_INVALID;
|
||||
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (connected) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
disconnect();
|
||||
|
||||
std::string ip = srs_dns_resolve(uri->get_host());
|
||||
if (ip.empty()) {
|
||||
ret = ERROR_SYSTEM_IP_INVALID;
|
||||
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sock == -1){
|
||||
|
@ -217,7 +217,7 @@ int SrsHttpClient::connect(SrsHttpUri* uri)
|
|||
srs_error("st_netfd_open_socket failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(uri->get_port());
|
||||
|
@ -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){
|
||||
ret = ERROR_ST_CONNECT;
|
||||
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;
|
||||
}
|
||||
srs_info("connect to server success. "
|
||||
"http url=%s, server=%s, ip=%s, port=%d",
|
||||
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
|
||||
"http url=%s, server=%s, ip=%s, port=%d",
|
||||
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
|
||||
|
||||
connected = true;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
return parse_response_body_data(
|
||||
uri, skt, response, (size_t)body_left,
|
||||
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
||||
uri, skt, response, (size_t)body_left,
|
||||
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
||||
);
|
||||
} else {
|
||||
// if ignore response, use shared fast memory.
|
||||
static char buf[SRS_HTTP_BODY_BUFFER];
|
||||
|
||||
return parse_response_body_data(
|
||||
uri, skt, response, (size_t)body_left,
|
||||
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
||||
);
|
||||
uri, skt, response, (size_t)body_left,
|
||||
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -351,7 +351,7 @@ int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std
|
|||
|
||||
while (body_left > 0) {
|
||||
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) {
|
||||
srs_error("read header from server failed. ret=%d", 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 ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_connect url failed. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_connect",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"pageUrl": "http://www.test.com/live.html"
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_connect url failed. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_connect",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"pageUrl": "http://www.test.com/live.html"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_connect" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// pageUrl
|
||||
<< '"' << "pageUrl" << '"' << ':'
|
||||
<< '"' << req->pageUrl << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_connect uri failed. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_error("http hook on_connect validate failed. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_connect success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_connect" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// pageUrl
|
||||
<< '"' << "pageUrl" << '"' << ':'
|
||||
<< '"' << req->pageUrl << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_connect uri failed. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_error("http hook on_connect validate failed. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_connect success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_close url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_close",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_close url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_close",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_close" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_warn("http post on_close uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_close validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_close success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return;
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_close" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_warn("http post on_close uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_close validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_close success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_publish url failed. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_publish",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_publish url failed. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_publish",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_publish" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_publish uri failed. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_error("http hook on_publish validate failed. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_publish success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_publish" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_publish uri failed. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_error("http hook on_publish validate failed. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_publish success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_unpublish url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_unpublish",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_unpublish url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_unpublish",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_unpublish" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_warn("http post on_unpublish uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_unpublish validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_unpublish success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return;
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_unpublish" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_warn("http post on_unpublish uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_unpublish validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_unpublish success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_play url failed. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_play",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_play url failed. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_play",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_play" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_play uri failed. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_error("http hook on_play validate failed. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_play success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_play" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_play uri failed. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_error("http hook on_play validate failed. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_play success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_stop url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_stop",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_warn("http uri parse on_stop url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
{
|
||||
"action": "on_stop",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream"
|
||||
}
|
||||
*/
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_stop" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_warn("http post on_stop uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_stop validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_stop success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return;
|
||||
std::stringstream ss;
|
||||
ss << "{"
|
||||
// action
|
||||
<< '"' << "action" << '"' << ':'
|
||||
<< '"' << "on_stop" << '"'
|
||||
<< ','
|
||||
// client_id
|
||||
<< '"' << "client_id" << '"' << ':'
|
||||
<< std::dec << client_id
|
||||
<< ','
|
||||
// ip
|
||||
<< '"' << "ip" << '"' << ':'
|
||||
<< '"' << ip << '"'
|
||||
<< ','
|
||||
// vhost
|
||||
<< '"' << "vhost" << '"' << ':'
|
||||
<< '"' << req->vhost << '"'
|
||||
<< ','
|
||||
// app
|
||||
<< '"' << "app" << '"' << ':'
|
||||
<< '"' << req->app << '"'
|
||||
<< ','
|
||||
// stream
|
||||
<< '"' << "stream" << '"' << ':'
|
||||
<< '"' << req->stream << '"'
|
||||
//<< ','
|
||||
<< "}";
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||
srs_warn("http post on_stop uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_stop validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_stop success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,8 +40,8 @@ class SrsSocket;
|
|||
|
||||
#include <http_parser.h>
|
||||
|
||||
#define SRS_HTTP_HEADER_BUFFER 1024
|
||||
#define SRS_HTTP_BODY_BUFFER 32 * 1024
|
||||
#define SRS_HTTP_HEADER_BUFFER 1024
|
||||
#define SRS_HTTP_BODY_BUFFER 32 * 1024
|
||||
|
||||
/**
|
||||
* used to resolve the http uri.
|
||||
|
@ -55,13 +55,13 @@ private:
|
|||
int port;
|
||||
std::string path;
|
||||
public:
|
||||
SrsHttpUri();
|
||||
virtual ~SrsHttpUri();
|
||||
SrsHttpUri();
|
||||
virtual ~SrsHttpUri();
|
||||
public:
|
||||
/**
|
||||
* initialize the http uri.
|
||||
*/
|
||||
virtual int initialize(std::string _url);
|
||||
/**
|
||||
* initialize the http uri.
|
||||
*/
|
||||
virtual int initialize(std::string _url);
|
||||
public:
|
||||
virtual const char* get_url();
|
||||
virtual const char* get_schema();
|
||||
|
@ -82,23 +82,23 @@ private:
|
|||
class SrsHttpClient
|
||||
{
|
||||
private:
|
||||
bool connected;
|
||||
st_netfd_t stfd;
|
||||
bool connected;
|
||||
st_netfd_t stfd;
|
||||
private:
|
||||
http_parser http_header;
|
||||
public:
|
||||
SrsHttpClient();
|
||||
virtual ~SrsHttpClient();
|
||||
SrsHttpClient();
|
||||
virtual ~SrsHttpClient();
|
||||
public:
|
||||
/**
|
||||
* to post data to the uri.
|
||||
* @param req the data post to uri.
|
||||
* @param res the response data from server.
|
||||
*/
|
||||
virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
|
||||
/**
|
||||
* to post data to the uri.
|
||||
* @param req the data post to uri.
|
||||
* @param res the response data from server.
|
||||
*/
|
||||
virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
|
||||
private:
|
||||
virtual void disconnect();
|
||||
virtual int connect(SrsHttpUri* uri);
|
||||
virtual void disconnect();
|
||||
virtual int connect(SrsHttpUri* uri);
|
||||
private:
|
||||
virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);
|
||||
virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);
|
||||
|
@ -117,54 +117,54 @@ private:
|
|||
class SrsHttpHooks
|
||||
{
|
||||
public:
|
||||
SrsHttpHooks();
|
||||
virtual ~SrsHttpHooks();
|
||||
SrsHttpHooks();
|
||||
virtual ~SrsHttpHooks();
|
||||
public:
|
||||
/**
|
||||
* on_connect hook, when client connect to srs.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
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.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
*/
|
||||
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
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
* on_unpublish hook, when client(encoder) stop publish stream.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
*/
|
||||
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
* on_play hook, when client start to play stream.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
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.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
*/
|
||||
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
* on_connect hook, when client connect to srs.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
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.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
*/
|
||||
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
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
* on_unpublish hook, when client(encoder) stop publish stream.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
*/
|
||||
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
* on_play hook, when client start to play stream.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
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.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
*/
|
||||
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@ SrsThreadContext::~SrsThreadContext()
|
|||
|
||||
void SrsThreadContext::generate_id()
|
||||
{
|
||||
static int id = 1;
|
||||
static int id = 1;
|
||||
cache[st_thread_self()] = id++;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ int SrsThreadContext::get_id()
|
|||
|
||||
SrsFastLog::SrsFastLog()
|
||||
{
|
||||
level = SrsLogLevel::Trace;
|
||||
level = SrsLogLevel::Trace;
|
||||
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;
|
||||
|
||||
if (tag) {
|
||||
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
||||
"[%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),
|
||||
level_name, tag, context_id, errno);
|
||||
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
||||
"[%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),
|
||||
level_name, tag, context_id, errno);
|
||||
} else {
|
||||
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
||||
"[%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),
|
||||
level_name, context_id, errno);
|
||||
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
||||
"[%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),
|
||||
level_name, context_id, errno);
|
||||
}
|
||||
|
||||
if (log_header_size == -1) {
|
||||
|
|
|
@ -35,132 +35,132 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
struct SrsStageInfo : public ISrsReloadHandler
|
||||
{
|
||||
int stage_id;
|
||||
int pithy_print_time_ms;
|
||||
int nb_clients;
|
||||
|
||||
SrsStageInfo(int _stage_id)
|
||||
{
|
||||
stage_id = _stage_id;
|
||||
nb_clients = 0;
|
||||
|
||||
update_print_time();
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
}
|
||||
virtual ~SrsStageInfo()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
}
|
||||
void update_print_time()
|
||||
{
|
||||
switch (stage_id) {
|
||||
case SRS_STAGE_PLAY_USER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_play();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_PUBLISH_USER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_publish();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_FORWARDER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_ENCODER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_HLS: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_hls();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int stage_id;
|
||||
int pithy_print_time_ms;
|
||||
int nb_clients;
|
||||
|
||||
SrsStageInfo(int _stage_id)
|
||||
{
|
||||
stage_id = _stage_id;
|
||||
nb_clients = 0;
|
||||
|
||||
update_print_time();
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
}
|
||||
virtual ~SrsStageInfo()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
}
|
||||
void update_print_time()
|
||||
{
|
||||
switch (stage_id) {
|
||||
case SRS_STAGE_PLAY_USER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_play();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_PUBLISH_USER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_publish();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_FORWARDER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_ENCODER: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
|
||||
break;
|
||||
}
|
||||
case SRS_STAGE_HLS: {
|
||||
pithy_print_time_ms = _srs_config->get_pithy_print_hls();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
virtual int on_reload_pithy_print()
|
||||
{
|
||||
update_print_time();
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
virtual int on_reload_pithy_print()
|
||||
{
|
||||
update_print_time();
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
};
|
||||
static std::map<int, SrsStageInfo*> _srs_stages;
|
||||
|
||||
SrsPithyPrint::SrsPithyPrint(int _stage_id)
|
||||
{
|
||||
stage_id = _stage_id;
|
||||
client_id = enter_stage();
|
||||
printed_age = age = 0;
|
||||
stage_id = _stage_id;
|
||||
client_id = enter_stage();
|
||||
printed_age = age = 0;
|
||||
}
|
||||
|
||||
SrsPithyPrint::~SrsPithyPrint()
|
||||
{
|
||||
leave_stage();
|
||||
leave_stage();
|
||||
}
|
||||
|
||||
int SrsPithyPrint::enter_stage()
|
||||
{
|
||||
SrsStageInfo* stage = NULL;
|
||||
|
||||
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
|
||||
if (it == _srs_stages.end()) {
|
||||
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
|
||||
} else {
|
||||
stage = it->second;
|
||||
}
|
||||
|
||||
srs_assert(stage != NULL);
|
||||
client_id = stage->nb_clients++;
|
||||
SrsStageInfo* stage = NULL;
|
||||
|
||||
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
|
||||
if (it == _srs_stages.end()) {
|
||||
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
|
||||
} else {
|
||||
stage = it->second;
|
||||
}
|
||||
|
||||
srs_assert(stage != NULL);
|
||||
client_id = stage->nb_clients++;
|
||||
|
||||
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);
|
||||
|
||||
return client_id;
|
||||
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);
|
||||
|
||||
return client_id;
|
||||
}
|
||||
|
||||
void SrsPithyPrint::leave_stage()
|
||||
{
|
||||
SrsStageInfo* stage = _srs_stages[stage_id];
|
||||
srs_assert(stage != NULL);
|
||||
|
||||
stage->nb_clients--;
|
||||
SrsStageInfo* stage = _srs_stages[stage_id];
|
||||
srs_assert(stage != NULL);
|
||||
|
||||
stage->nb_clients--;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void SrsPithyPrint::elapse(int64_t time_ms)
|
||||
{
|
||||
age += time_ms;
|
||||
age += time_ms;
|
||||
}
|
||||
|
||||
bool SrsPithyPrint::can_print()
|
||||
{
|
||||
SrsStageInfo* stage = _srs_stages[stage_id];
|
||||
srs_assert(stage != NULL);
|
||||
|
||||
int64_t alive_age = age - printed_age;
|
||||
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
|
||||
|
||||
bool can_print = alive_age >= can_print_age;
|
||||
if (can_print) {
|
||||
printed_age = age;
|
||||
}
|
||||
|
||||
return can_print;
|
||||
SrsStageInfo* stage = _srs_stages[stage_id];
|
||||
srs_assert(stage != NULL);
|
||||
|
||||
int64_t alive_age = age - printed_age;
|
||||
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
|
||||
|
||||
bool can_print = alive_age >= can_print_age;
|
||||
if (can_print) {
|
||||
printed_age = age;
|
||||
}
|
||||
|
||||
return can_print;
|
||||
}
|
||||
|
||||
int64_t SrsPithyPrint::get_age()
|
||||
{
|
||||
return age;
|
||||
return age;
|
||||
}
|
||||
|
||||
void SrsPithyPrint::set_age(int64_t _age)
|
||||
{
|
||||
age = _age;
|
||||
age = _age;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,39 +50,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
class SrsPithyPrint
|
||||
{
|
||||
private:
|
||||
int client_id;
|
||||
int stage_id;
|
||||
int64_t age;
|
||||
int64_t printed_age;
|
||||
int client_id;
|
||||
int stage_id;
|
||||
int64_t age;
|
||||
int64_t printed_age;
|
||||
public:
|
||||
/**
|
||||
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
|
||||
*/
|
||||
SrsPithyPrint(int _stage_id);
|
||||
virtual ~SrsPithyPrint();
|
||||
/**
|
||||
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
|
||||
*/
|
||||
SrsPithyPrint(int _stage_id);
|
||||
virtual ~SrsPithyPrint();
|
||||
private:
|
||||
/**
|
||||
* enter the specified stage, return the client id.
|
||||
*/
|
||||
virtual int enter_stage();
|
||||
/**
|
||||
* leave the specified stage, release the client id.
|
||||
*/
|
||||
virtual void leave_stage();
|
||||
/**
|
||||
* enter the specified stage, return the client id.
|
||||
*/
|
||||
virtual int enter_stage();
|
||||
/**
|
||||
* leave the specified stage, release the client id.
|
||||
*/
|
||||
virtual void leave_stage();
|
||||
public:
|
||||
/**
|
||||
* specified client elapse some time.
|
||||
*/
|
||||
virtual void elapse(int64_t time_ms);
|
||||
/**
|
||||
* whether current client can print.
|
||||
*/
|
||||
virtual bool can_print();
|
||||
/**
|
||||
* get the elapsed time in ms.
|
||||
*/
|
||||
virtual int64_t get_age();
|
||||
virtual void set_age(int64_t _age);
|
||||
/**
|
||||
* specified client elapse some time.
|
||||
*/
|
||||
virtual void elapse(int64_t time_ms);
|
||||
/**
|
||||
* whether current client can print.
|
||||
*/
|
||||
virtual bool can_print();
|
||||
/**
|
||||
* get the elapsed time in ms.
|
||||
*/
|
||||
virtual int64_t get_age();
|
||||
virtual void set_age(int64_t _age);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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 ret = ERROR_SUCCESS;
|
||||
|
||||
if (!refer) {
|
||||
srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)refer->args.size(); i++) {
|
||||
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
|
||||
srs_verbose("check refer success. page_url=%s, refer=%s",
|
||||
page_url.c_str(), refer->args.at(i).c_str());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||
srs_error("check refer failed. ret=%d", ret);
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (!refer) {
|
||||
srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)refer->args.size(); i++) {
|
||||
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
|
||||
srs_verbose("check refer success. page_url=%s, refer=%s",
|
||||
page_url.c_str(), refer->args.at(i).c_str());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||
srs_error("check refer failed. ret=%d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRefer::check_single_refer(std::string page_url, std::string refer)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
size_t pos = std::string::npos;
|
||||
|
||||
std::string domain_name = page_url;
|
||||
if ((pos = domain_name.find("://")) != std::string::npos) {
|
||||
domain_name = domain_name.substr(pos + 3);
|
||||
}
|
||||
|
||||
if ((pos = domain_name.find("/")) != std::string::npos) {
|
||||
domain_name = domain_name.substr(0, pos);
|
||||
}
|
||||
|
||||
if ((pos = domain_name.find(":")) != std::string::npos) {
|
||||
domain_name = domain_name.substr(0, pos);
|
||||
}
|
||||
|
||||
pos = domain_name.find(refer);
|
||||
if (pos == std::string::npos) {
|
||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||
}
|
||||
// match primary domain.
|
||||
if (pos != domain_name.length() - refer.length()) {
|
||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
size_t pos = std::string::npos;
|
||||
|
||||
std::string domain_name = page_url;
|
||||
if ((pos = domain_name.find("://")) != std::string::npos) {
|
||||
domain_name = domain_name.substr(pos + 3);
|
||||
}
|
||||
|
||||
if ((pos = domain_name.find("/")) != std::string::npos) {
|
||||
domain_name = domain_name.substr(0, pos);
|
||||
}
|
||||
|
||||
if ((pos = domain_name.find(":")) != std::string::npos) {
|
||||
domain_name = domain_name.substr(0, pos);
|
||||
}
|
||||
|
||||
pos = domain_name.find(refer);
|
||||
if (pos == std::string::npos) {
|
||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||
}
|
||||
// match primary domain.
|
||||
if (pos != domain_name.length() - refer.length()) {
|
||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,14 +36,14 @@ class SrsConfDirective;
|
|||
class SrsRefer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* to check the refer.
|
||||
* @param page_url the client page url.
|
||||
* @param refer the refer in config.
|
||||
*/
|
||||
virtual int check(std::string page_url, SrsConfDirective* refer);
|
||||
/**
|
||||
* to check the refer.
|
||||
* @param page_url the client page url.
|
||||
* @param refer the refer in config.
|
||||
*/
|
||||
virtual int check(std::string page_url, SrsConfDirective* refer);
|
||||
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
|
|
@ -37,41 +37,41 @@ ISrsReloadHandler::~ISrsReloadHandler()
|
|||
|
||||
int ISrsReloadHandler::on_reload_listen()
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_pithy_print()
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_forward(string /*vhost*/)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_hls(string /*vhost*/)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ISrsReloadHandler::on_reload_transcode(string /*vhost*/)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,17 +37,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
class ISrsReloadHandler
|
||||
{
|
||||
public:
|
||||
ISrsReloadHandler();
|
||||
virtual ~ISrsReloadHandler();
|
||||
ISrsReloadHandler();
|
||||
virtual ~ISrsReloadHandler();
|
||||
public:
|
||||
virtual int on_reload_listen();
|
||||
virtual int on_reload_pithy_print();
|
||||
virtual int on_reload_vhost_removed(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_forward(std::string vhost);
|
||||
virtual int on_reload_hls(std::string vhost);
|
||||
virtual int on_reload_transcode(std::string vhost);
|
||||
virtual int on_reload_listen();
|
||||
virtual int on_reload_pithy_print();
|
||||
virtual int on_reload_vhost_removed(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_forward(std::string vhost);
|
||||
virtual int on_reload_hls(std::string vhost);
|
||||
virtual int on_reload_transcode(std::string vhost);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -40,40 +40,40 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
|
||||
{
|
||||
fd = -1;
|
||||
stfd = NULL;
|
||||
|
||||
port = 0;
|
||||
server = _server;
|
||||
type = _type;
|
||||
fd = -1;
|
||||
stfd = NULL;
|
||||
|
||||
port = 0;
|
||||
server = _server;
|
||||
type = _type;
|
||||
|
||||
pthread = new SrsThread(this, 0);
|
||||
pthread = new SrsThread(this, 0);
|
||||
}
|
||||
|
||||
SrsListener::~SrsListener()
|
||||
{
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
pthread->stop();
|
||||
srs_freep(pthread);
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(fd);
|
||||
srs_close_stfd(stfd);
|
||||
|
||||
pthread->stop();
|
||||
srs_freep(pthread);
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int SrsListener::listen(int _port)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
port = _port;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
port = _port;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||
ret = ERROR_SOCKET_CREATE;
|
||||
srs_error("create linux socket error. ret=%d", 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;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
||||
|
@ -115,19 +115,19 @@ int SrsListener::listen(int _port)
|
|||
srs_verbose("create st listen thread success.");
|
||||
|
||||
srs_trace("server started, listen at port=%d, fd=%d", port, fd);
|
||||
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 ret = ERROR_SUCCESS;
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
||||
|
||||
if(client_stfd == NULL){
|
||||
|
@ -136,45 +136,45 @@ int SrsListener::cycle()
|
|||
return ret;
|
||||
}
|
||||
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
||||
|
||||
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
|
||||
srs_warn("accept client error. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
|
||||
|
||||
return ret;
|
||||
|
||||
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
|
||||
srs_warn("accept client error. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsServer::SrsServer()
|
||||
{
|
||||
signal_reload = false;
|
||||
signal_gmc_stop = false;
|
||||
|
||||
srs_assert(_srs_config);
|
||||
_srs_config->subscribe(this);
|
||||
signal_reload = false;
|
||||
signal_gmc_stop = false;
|
||||
|
||||
srs_assert(_srs_config);
|
||||
_srs_config->subscribe(this);
|
||||
}
|
||||
|
||||
SrsServer::~SrsServer()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
|
||||
if (true) {
|
||||
std::vector<SrsConnection*>::iterator it;
|
||||
for (it = conns.begin(); it != conns.end(); ++it) {
|
||||
SrsConnection* conn = *it;
|
||||
srs_freep(conn);
|
||||
}
|
||||
conns.clear();
|
||||
}
|
||||
|
||||
close_listeners();
|
||||
_srs_config->unsubscribe(this);
|
||||
|
||||
if (true) {
|
||||
std::vector<SrsConnection*>::iterator it;
|
||||
for (it = conns.begin(); it != conns.end(); ++it) {
|
||||
SrsConnection* conn = *it;
|
||||
srs_freep(conn);
|
||||
}
|
||||
conns.clear();
|
||||
}
|
||||
|
||||
close_listeners();
|
||||
}
|
||||
|
||||
int SrsServer::initialize()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// use linux epoll.
|
||||
if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
|
||||
|
@ -190,159 +190,159 @@ int SrsServer::initialize()
|
|||
return ret;
|
||||
}
|
||||
srs_verbose("st_init success");
|
||||
|
||||
// set current log id.
|
||||
_srs_context->generate_id();
|
||||
srs_info("log set id success");
|
||||
|
||||
return ret;
|
||||
|
||||
// set current log id.
|
||||
_srs_context->generate_id();
|
||||
srs_info("log set id success");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsServer::listen()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsConfDirective* conf = NULL;
|
||||
|
||||
// stream service port.
|
||||
conf = _srs_config->get_listen();
|
||||
srs_assert(conf);
|
||||
|
||||
close_listeners();
|
||||
|
||||
for (int i = 0; i < (int)conf->args.size(); i++) {
|
||||
SrsListener* listener = new SrsListener(this, SrsListenerStream);
|
||||
listeners.push_back(listener);
|
||||
|
||||
int port = ::atoi(conf->args.at(i).c_str());
|
||||
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
||||
srs_error("listen at port %d failed. ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsConfDirective* conf = NULL;
|
||||
|
||||
// stream service port.
|
||||
conf = _srs_config->get_listen();
|
||||
srs_assert(conf);
|
||||
|
||||
close_listeners();
|
||||
|
||||
for (int i = 0; i < (int)conf->args.size(); i++) {
|
||||
SrsListener* listener = new SrsListener(this, SrsListenerStream);
|
||||
listeners.push_back(listener);
|
||||
|
||||
int port = ::atoi(conf->args.at(i).c_str());
|
||||
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
||||
srs_error("listen at port %d failed. ret=%d", port, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsServer::cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// the deamon thread, update the time cache
|
||||
while (true) {
|
||||
st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
|
||||
srs_update_system_time_ms();
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// the deamon thread, update the time cache
|
||||
while (true) {
|
||||
st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
|
||||
srs_update_system_time_ms();
|
||||
|
||||
// for gperf heap checker,
|
||||
// @see: research/gperftools/heap-checker/heap_checker.cc
|
||||
// if user interrupt the program, exit to check mem leak.
|
||||
// but, if gperf, use reload to ensure main return normally,
|
||||
// because directly exit will cause core-dump.
|
||||
#ifdef SRS_GPERF_MC
|
||||
if (signal_gmc_stop) {
|
||||
break;
|
||||
}
|
||||
if (signal_gmc_stop) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (signal_reload) {
|
||||
signal_reload = false;
|
||||
srs_info("get signal reload, to reload the config.");
|
||||
|
||||
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
|
||||
srs_error("reload config failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_trace("reload config success.");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
if (signal_reload) {
|
||||
signal_reload = false;
|
||||
srs_info("get signal reload, to reload the config.");
|
||||
|
||||
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
|
||||
srs_error("reload config failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_trace("reload config success.");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsServer::remove(SrsConnection* conn)
|
||||
{
|
||||
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
|
||||
|
||||
if (it != conns.end()) {
|
||||
conns.erase(it);
|
||||
}
|
||||
|
||||
srs_info("conn removed. conns=%d", (int)conns.size());
|
||||
|
||||
// all connections are created by server,
|
||||
// so we free it here.
|
||||
srs_freep(conn);
|
||||
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
|
||||
|
||||
if (it != conns.end()) {
|
||||
conns.erase(it);
|
||||
}
|
||||
|
||||
srs_info("conn removed. conns=%d", (int)conns.size());
|
||||
|
||||
// all connections are created by server,
|
||||
// so we free it here.
|
||||
srs_freep(conn);
|
||||
}
|
||||
|
||||
void SrsServer::on_signal(int signo)
|
||||
{
|
||||
if (signo == SIGNAL_RELOAD) {
|
||||
signal_reload = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (signo == SIGINT) {
|
||||
if (signo == SIGNAL_RELOAD) {
|
||||
signal_reload = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (signo == SIGINT) {
|
||||
#ifdef SRS_GPERF_MC
|
||||
srs_trace("gmc is on, main cycle will terminate normally.");
|
||||
signal_gmc_stop = true;
|
||||
srs_trace("gmc is on, main cycle will terminate normally.");
|
||||
signal_gmc_stop = true;
|
||||
#else
|
||||
srs_trace("user terminate program");
|
||||
exit(0);
|
||||
srs_trace("user terminate program");
|
||||
exit(0);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: handle the SIGINT, SIGTERM.
|
||||
// TODO: handle the SIGINT, SIGTERM.
|
||||
}
|
||||
|
||||
void SrsServer::close_listeners()
|
||||
{
|
||||
std::vector<SrsListener*>::iterator it;
|
||||
for (it = listeners.begin(); it != listeners.end(); ++it) {
|
||||
SrsListener* listener = *it;
|
||||
srs_freep(listener);
|
||||
}
|
||||
listeners.clear();
|
||||
std::vector<SrsListener*>::iterator it;
|
||||
for (it = listeners.begin(); it != listeners.end(); ++it) {
|
||||
SrsListener* listener = *it;
|
||||
srs_freep(listener);
|
||||
}
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
int max_connections = _srs_config->get_max_connections();
|
||||
if ((int)conns.size() >= max_connections) {
|
||||
int fd = st_netfd_fileno(client_stfd);
|
||||
|
||||
srs_error("exceed the max connections, drop client: "
|
||||
"clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
|
||||
|
||||
srs_close_stfd(client_stfd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsConnection* conn = NULL;
|
||||
if (type == SrsListenerStream) {
|
||||
conn = new SrsClient(this, client_stfd);
|
||||
} else {
|
||||
// handler others
|
||||
}
|
||||
srs_assert(conn);
|
||||
|
||||
// directly enqueue, the cycle thread will remove the client.
|
||||
conns.push_back(conn);
|
||||
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.
|
||||
if ((ret = conn->start()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("conn start finished. ret=%d", ret);
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
return ret;
|
||||
int max_connections = _srs_config->get_max_connections();
|
||||
if ((int)conns.size() >= max_connections) {
|
||||
int fd = st_netfd_fileno(client_stfd);
|
||||
|
||||
srs_error("exceed the max connections, drop client: "
|
||||
"clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
|
||||
|
||||
srs_close_stfd(client_stfd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsConnection* conn = NULL;
|
||||
if (type == SrsListenerStream) {
|
||||
conn = new SrsClient(this, client_stfd);
|
||||
} else {
|
||||
// handler others
|
||||
}
|
||||
srs_assert(conn);
|
||||
|
||||
// directly enqueue, the cycle thread will remove the client.
|
||||
conns.push_back(conn);
|
||||
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.
|
||||
if ((ret = conn->start()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("conn start finished. ret=%d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsServer::on_reload_listen()
|
||||
{
|
||||
return listen();
|
||||
return listen();
|
||||
}
|
||||
|
|
|
@ -41,53 +41,53 @@ class SrsConnection;
|
|||
|
||||
enum SrsListenerType
|
||||
{
|
||||
SrsListenerStream = 0,
|
||||
SrsListenerApi
|
||||
SrsListenerStream = 0,
|
||||
SrsListenerApi
|
||||
};
|
||||
|
||||
class SrsListener : public ISrsThreadHandler
|
||||
{
|
||||
public:
|
||||
SrsListenerType type;
|
||||
SrsListenerType type;
|
||||
private:
|
||||
int fd;
|
||||
st_netfd_t stfd;
|
||||
int port;
|
||||
SrsServer* server;
|
||||
SrsThread* pthread;
|
||||
int fd;
|
||||
st_netfd_t stfd;
|
||||
int port;
|
||||
SrsServer* server;
|
||||
SrsThread* pthread;
|
||||
public:
|
||||
SrsListener(SrsServer* _server, SrsListenerType _type);
|
||||
virtual ~SrsListener();
|
||||
SrsListener(SrsServer* _server, SrsListenerType _type);
|
||||
virtual ~SrsListener();
|
||||
public:
|
||||
virtual int listen(int port);
|
||||
virtual int listen(int port);
|
||||
// interface ISrsThreadHandler.
|
||||
public:
|
||||
virtual void on_enter_loop();
|
||||
virtual int cycle();
|
||||
virtual void on_enter_loop();
|
||||
virtual int cycle();
|
||||
};
|
||||
|
||||
class SrsServer : public ISrsReloadHandler
|
||||
{
|
||||
friend class SrsListener;
|
||||
friend class SrsListener;
|
||||
private:
|
||||
std::vector<SrsConnection*> conns;
|
||||
std::vector<SrsListener*> listeners;
|
||||
bool signal_reload;
|
||||
bool signal_gmc_stop;
|
||||
std::vector<SrsConnection*> conns;
|
||||
std::vector<SrsListener*> listeners;
|
||||
bool signal_reload;
|
||||
bool signal_gmc_stop;
|
||||
public:
|
||||
SrsServer();
|
||||
virtual ~SrsServer();
|
||||
SrsServer();
|
||||
virtual ~SrsServer();
|
||||
public:
|
||||
virtual int initialize();
|
||||
virtual int listen();
|
||||
virtual int cycle();
|
||||
virtual void remove(SrsConnection* conn);
|
||||
virtual void on_signal(int signo);
|
||||
virtual int initialize();
|
||||
virtual int listen();
|
||||
virtual int cycle();
|
||||
virtual void remove(SrsConnection* conn);
|
||||
virtual void on_signal(int signo);
|
||||
private:
|
||||
virtual void close_listeners();
|
||||
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
|
||||
virtual void close_listeners();
|
||||
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
|
||||
public:
|
||||
virtual int on_reload_listen();
|
||||
virtual int on_reload_listen();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -28,9 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
SrsSocket::SrsSocket(st_netfd_t client_stfd)
|
||||
{
|
||||
stfd = client_stfd;
|
||||
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
|
||||
recv_bytes = send_bytes = 0;
|
||||
start_time_ms = srs_get_system_time_ms();
|
||||
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
|
||||
recv_bytes = send_bytes = 0;
|
||||
start_time_ms = srs_get_system_time_ms();
|
||||
}
|
||||
|
||||
SrsSocket::~SrsSocket()
|
||||
|
@ -39,59 +39,59 @@ SrsSocket::~SrsSocket()
|
|||
|
||||
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)
|
||||
{
|
||||
recv_timeout = timeout_us;
|
||||
recv_timeout = timeout_us;
|
||||
}
|
||||
|
||||
int64_t SrsSocket::get_recv_timeout()
|
||||
{
|
||||
return recv_timeout;
|
||||
return recv_timeout;
|
||||
}
|
||||
|
||||
void SrsSocket::set_send_timeout(int64_t timeout_us)
|
||||
{
|
||||
send_timeout = timeout_us;
|
||||
send_timeout = timeout_us;
|
||||
}
|
||||
|
||||
int64_t SrsSocket::get_send_timeout()
|
||||
{
|
||||
return send_timeout;
|
||||
return send_timeout;
|
||||
}
|
||||
|
||||
int64_t SrsSocket::get_recv_bytes()
|
||||
{
|
||||
return recv_bytes;
|
||||
return recv_bytes;
|
||||
}
|
||||
|
||||
int64_t SrsSocket::get_send_bytes()
|
||||
{
|
||||
return send_bytes;
|
||||
return send_bytes;
|
||||
}
|
||||
|
||||
int SrsSocket::get_recv_kbps()
|
||||
{
|
||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||
|
||||
if (diff_ms <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return recv_bytes * 8 / diff_ms;
|
||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||
|
||||
if (diff_ms <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return recv_bytes * 8 / diff_ms;
|
||||
}
|
||||
|
||||
int SrsSocket::get_send_kbps()
|
||||
{
|
||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||
|
||||
if (diff_ms <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return send_bytes * 8 / diff_ms;
|
||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||
|
||||
if (diff_ms <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return send_bytes * 8 / diff_ms;
|
||||
}
|
||||
|
||||
int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
|
||||
|
@ -103,10 +103,10 @@ 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
|
||||
// (a value of 0 means the network connection is closed or end of file is reached).
|
||||
if (*nread <= 0) {
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (*nread == 0) {
|
||||
errno = ECONNRESET;
|
||||
}
|
||||
|
@ -128,10 +128,10 @@ 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
|
||||
// (a value less than nbyte means the network connection is closed or end of file is reached)
|
||||
if (*nread != (ssize_t)size) {
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (*nread >= 0) {
|
||||
errno = ECONNRESET;
|
||||
}
|
||||
|
@ -151,10 +151,10 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite)
|
|||
*nwrite = st_write(stfd, (void*)buf, size, send_timeout);
|
||||
|
||||
if (*nwrite <= 0) {
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
return ERROR_SOCKET_WRITE;
|
||||
}
|
||||
|
||||
|
@ -170,10 +170,10 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
|
|||
*nwrite = st_writev(stfd, iov, iov_size, send_timeout);
|
||||
|
||||
if (*nwrite <= 0) {
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
if (errno == ETIME) {
|
||||
return ERROR_SOCKET_TIMEOUT;
|
||||
}
|
||||
|
||||
return ERROR_SOCKET_WRITE;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,25 +40,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
class SrsSocket : public ISrsProtocolReaderWriter
|
||||
{
|
||||
private:
|
||||
int64_t recv_timeout;
|
||||
int64_t send_timeout;
|
||||
int64_t recv_bytes;
|
||||
int64_t send_bytes;
|
||||
int64_t start_time_ms;
|
||||
int64_t recv_timeout;
|
||||
int64_t send_timeout;
|
||||
int64_t recv_bytes;
|
||||
int64_t send_bytes;
|
||||
int64_t start_time_ms;
|
||||
st_netfd_t stfd;
|
||||
public:
|
||||
SrsSocket(st_netfd_t client_stfd);
|
||||
virtual ~SrsSocket();
|
||||
public:
|
||||
virtual bool is_never_timeout(int64_t timeout_us);
|
||||
virtual void set_recv_timeout(int64_t timeout_us);
|
||||
virtual int64_t get_recv_timeout();
|
||||
virtual void set_send_timeout(int64_t timeout_us);
|
||||
virtual int64_t get_send_timeout();
|
||||
virtual int64_t get_recv_bytes();
|
||||
virtual int64_t get_send_bytes();
|
||||
virtual int get_recv_kbps();
|
||||
virtual int get_send_kbps();
|
||||
virtual bool is_never_timeout(int64_t timeout_us);
|
||||
virtual void set_recv_timeout(int64_t timeout_us);
|
||||
virtual int64_t get_recv_timeout();
|
||||
virtual void set_send_timeout(int64_t timeout_us);
|
||||
virtual int64_t get_send_timeout();
|
||||
virtual int64_t get_recv_bytes();
|
||||
virtual int64_t get_send_bytes();
|
||||
virtual int get_recv_kbps();
|
||||
virtual int get_send_kbps();
|
||||
public:
|
||||
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);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,20 +57,20 @@ class SrsEncoder;
|
|||
class SrsRtmpJitter
|
||||
{
|
||||
private:
|
||||
int64_t last_pkt_time;
|
||||
int64_t last_pkt_correct_time;
|
||||
int64_t last_pkt_time;
|
||||
int64_t last_pkt_correct_time;
|
||||
public:
|
||||
SrsRtmpJitter();
|
||||
virtual ~SrsRtmpJitter();
|
||||
SrsRtmpJitter();
|
||||
virtual ~SrsRtmpJitter();
|
||||
public:
|
||||
/**
|
||||
* detect the time jitter and correct it.
|
||||
*/
|
||||
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||
/**
|
||||
* get current client time, the last packet time.
|
||||
*/
|
||||
virtual int get_time();
|
||||
/**
|
||||
* detect the time jitter and correct it.
|
||||
*/
|
||||
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||
/**
|
||||
* get current client time, the last packet time.
|
||||
*/
|
||||
virtual int get_time();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -80,39 +80,39 @@ public:
|
|||
class SrsMessageQueue
|
||||
{
|
||||
private:
|
||||
int64_t av_start_time;
|
||||
int64_t av_end_time;
|
||||
int queue_size_ms;
|
||||
std::vector<SrsSharedPtrMessage*> msgs;
|
||||
int64_t av_start_time;
|
||||
int64_t av_end_time;
|
||||
int queue_size_ms;
|
||||
std::vector<SrsSharedPtrMessage*> msgs;
|
||||
public:
|
||||
SrsMessageQueue();
|
||||
virtual ~SrsMessageQueue();
|
||||
SrsMessageQueue();
|
||||
virtual ~SrsMessageQueue();
|
||||
public:
|
||||
/**
|
||||
* set the queue size
|
||||
* @param queue_size the queue size in seconds.
|
||||
*/
|
||||
virtual void set_queue_size(double queue_size);
|
||||
/**
|
||||
* set the queue size
|
||||
* @param queue_size the queue size in seconds.
|
||||
*/
|
||||
virtual void set_queue_size(double queue_size);
|
||||
public:
|
||||
/**
|
||||
* enqueue the message, the timestamp always monotonically.
|
||||
* @param msg, the msg to enqueue, user never free it whatever the return code.
|
||||
*/
|
||||
virtual int enqueue(SrsSharedPtrMessage* msg);
|
||||
/**
|
||||
* get packets in consumer queue.
|
||||
* @pmsgs SrsMessages*[], output the prt array.
|
||||
* @count the count in array.
|
||||
* @max_count the max count to dequeue, 0 to dequeue all.
|
||||
*/
|
||||
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
||||
/**
|
||||
* enqueue the message, the timestamp always monotonically.
|
||||
* @param msg, the msg to enqueue, user never free it whatever the return code.
|
||||
*/
|
||||
virtual int enqueue(SrsSharedPtrMessage* msg);
|
||||
/**
|
||||
* get packets in consumer queue.
|
||||
* @pmsgs SrsMessages*[], output the prt array.
|
||||
* @count the count in array.
|
||||
* @max_count the max count to dequeue, 0 to dequeue all.
|
||||
*/
|
||||
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
||||
private:
|
||||
/**
|
||||
* remove a gop from the front.
|
||||
* if no iframe found, clear it.
|
||||
*/
|
||||
virtual void shrink();
|
||||
virtual void clear();
|
||||
/**
|
||||
* remove a gop from the front.
|
||||
* if no iframe found, clear it.
|
||||
*/
|
||||
virtual void shrink();
|
||||
virtual void clear();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -121,39 +121,39 @@ private:
|
|||
class SrsConsumer
|
||||
{
|
||||
private:
|
||||
SrsRtmpJitter* jitter;
|
||||
SrsSource* source;
|
||||
SrsMessageQueue* queue;
|
||||
bool paused;
|
||||
SrsRtmpJitter* jitter;
|
||||
SrsSource* source;
|
||||
SrsMessageQueue* queue;
|
||||
bool paused;
|
||||
public:
|
||||
SrsConsumer(SrsSource* _source);
|
||||
virtual ~SrsConsumer();
|
||||
SrsConsumer(SrsSource* _source);
|
||||
virtual ~SrsConsumer();
|
||||
public:
|
||||
virtual void set_queue_size(double queue_size);
|
||||
virtual void set_queue_size(double queue_size);
|
||||
public:
|
||||
/**
|
||||
* get current client time, the last packet time.
|
||||
*/
|
||||
virtual int get_time();
|
||||
/**
|
||||
* enqueue an shared ptr message.
|
||||
* @param tba timebase of audio.
|
||||
* used to calc the audio time delta if time-jitter detected.
|
||||
* @param tbv timebase of video.
|
||||
* used to calc the video time delta if time-jitter detected.
|
||||
*/
|
||||
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||
/**
|
||||
* get packets in consumer queue.
|
||||
* @pmsgs SrsMessages*[], output the prt array.
|
||||
* @count the count in array.
|
||||
* @max_count the max count to dequeue, 0 to dequeue all.
|
||||
*/
|
||||
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
||||
/**
|
||||
* when client send the pause message.
|
||||
*/
|
||||
virtual int on_play_client_pause(bool is_pause);
|
||||
/**
|
||||
* get current client time, the last packet time.
|
||||
*/
|
||||
virtual int get_time();
|
||||
/**
|
||||
* enqueue an shared ptr message.
|
||||
* @param tba timebase of audio.
|
||||
* used to calc the audio time delta if time-jitter detected.
|
||||
* @param tbv timebase of video.
|
||||
* used to calc the video time delta if time-jitter detected.
|
||||
*/
|
||||
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||
/**
|
||||
* get packets in consumer queue.
|
||||
* @pmsgs SrsMessages*[], output the prt array.
|
||||
* @count the count in array.
|
||||
* @max_count the max count to dequeue, 0 to dequeue all.
|
||||
*/
|
||||
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
||||
/**
|
||||
* when client send the pause message.
|
||||
*/
|
||||
virtual int on_play_client_pause(bool is_pause);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -164,33 +164,33 @@ public:
|
|||
class SrsGopCache
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* if disabled the gop cache,
|
||||
* the client will wait for the next keyframe for h264,
|
||||
* and will be black-screen.
|
||||
*/
|
||||
bool enable_gop_cache;
|
||||
/**
|
||||
* the video frame count, avoid cache for pure audio stream.
|
||||
*/
|
||||
int cached_video_count;
|
||||
/**
|
||||
* cached gop.
|
||||
*/
|
||||
std::vector<SrsSharedPtrMessage*> gop_cache;
|
||||
/**
|
||||
* if disabled the gop cache,
|
||||
* the client will wait for the next keyframe for h264,
|
||||
* and will be black-screen.
|
||||
*/
|
||||
bool enable_gop_cache;
|
||||
/**
|
||||
* the video frame count, avoid cache for pure audio stream.
|
||||
*/
|
||||
int cached_video_count;
|
||||
/**
|
||||
* cached gop.
|
||||
*/
|
||||
std::vector<SrsSharedPtrMessage*> gop_cache;
|
||||
public:
|
||||
SrsGopCache();
|
||||
virtual ~SrsGopCache();
|
||||
SrsGopCache();
|
||||
virtual ~SrsGopCache();
|
||||
public:
|
||||
virtual void set(bool enabled);
|
||||
/**
|
||||
* only for h264 codec
|
||||
* 1. cache the gop when got h264 video packet.
|
||||
* 2. clear gop when got keyframe.
|
||||
*/
|
||||
virtual int cache(SrsSharedPtrMessage* msg);
|
||||
virtual void clear();
|
||||
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
|
||||
virtual void set(bool enabled);
|
||||
/**
|
||||
* only for h264 codec
|
||||
* 1. cache the gop when got h264 video packet.
|
||||
* 2. clear gop when got keyframe.
|
||||
*/
|
||||
virtual int cache(SrsSharedPtrMessage* msg);
|
||||
virtual void clear();
|
||||
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -199,89 +199,89 @@ public:
|
|||
class SrsSource : public ISrsReloadHandler
|
||||
{
|
||||
private:
|
||||
static std::map<std::string, SrsSource*> pool;
|
||||
static std::map<std::string, SrsSource*> pool;
|
||||
public:
|
||||
/**
|
||||
* find stream by vhost/app/stream.
|
||||
* @param req the client request.
|
||||
* @return the matched source, never be NULL.
|
||||
* @remark stream_url should without port and schema.
|
||||
*/
|
||||
static SrsSource* find(SrsRequest* req);
|
||||
/**
|
||||
* find stream by vhost/app/stream.
|
||||
* @param req the client request.
|
||||
* @return the matched source, never be NULL.
|
||||
* @remark stream_url should without port and schema.
|
||||
*/
|
||||
static SrsSource* find(SrsRequest* req);
|
||||
private:
|
||||
// deep copy of client request.
|
||||
SrsRequest* req;
|
||||
// to delivery stream to clients.
|
||||
std::vector<SrsConsumer*> consumers;
|
||||
// hls handler.
|
||||
// deep copy of client request.
|
||||
SrsRequest* req;
|
||||
// to delivery stream to clients.
|
||||
std::vector<SrsConsumer*> consumers;
|
||||
// hls handler.
|
||||
#ifdef SRS_HLS
|
||||
SrsHls* hls;
|
||||
SrsHls* hls;
|
||||
#endif
|
||||
// transcoding handler.
|
||||
// transcoding handler.
|
||||
#ifdef SRS_FFMPEG
|
||||
SrsEncoder* encoder;
|
||||
SrsEncoder* encoder;
|
||||
#endif
|
||||
// gop cache for client fast startup.
|
||||
SrsGopCache* gop_cache;
|
||||
// to forward stream to other servers
|
||||
std::vector<SrsForwarder*> forwarders;
|
||||
// gop cache for client fast startup.
|
||||
SrsGopCache* gop_cache;
|
||||
// to forward stream to other servers
|
||||
std::vector<SrsForwarder*> forwarders;
|
||||
private:
|
||||
/**
|
||||
* the sample rate of audio in metadata.
|
||||
*/
|
||||
int sample_rate;
|
||||
/**
|
||||
* the video frame rate in metadata.
|
||||
*/
|
||||
int frame_rate;
|
||||
/**
|
||||
* can publish, true when is not streaming
|
||||
*/
|
||||
bool _can_publish;
|
||||
/**
|
||||
* the sample rate of audio in metadata.
|
||||
*/
|
||||
int sample_rate;
|
||||
/**
|
||||
* the video frame rate in metadata.
|
||||
*/
|
||||
int frame_rate;
|
||||
/**
|
||||
* can publish, true when is not streaming
|
||||
*/
|
||||
bool _can_publish;
|
||||
private:
|
||||
SrsSharedPtrMessage* cache_metadata;
|
||||
// the cached video sequence header.
|
||||
SrsSharedPtrMessage* cache_sh_video;
|
||||
// the cached audio sequence header.
|
||||
SrsSharedPtrMessage* cache_sh_audio;
|
||||
SrsSharedPtrMessage* cache_metadata;
|
||||
// the cached video sequence header.
|
||||
SrsSharedPtrMessage* cache_sh_video;
|
||||
// the cached audio sequence header.
|
||||
SrsSharedPtrMessage* cache_sh_audio;
|
||||
public:
|
||||
/**
|
||||
* @param _req the client request object,
|
||||
* this object will deep copy it for reload.
|
||||
*/
|
||||
SrsSource(SrsRequest* _req);
|
||||
virtual ~SrsSource();
|
||||
/**
|
||||
* @param _req the client request object,
|
||||
* this object will deep copy it for reload.
|
||||
*/
|
||||
SrsSource(SrsRequest* _req);
|
||||
virtual ~SrsSource();
|
||||
// interface ISrsReloadHandler
|
||||
public:
|
||||
virtual int on_reload_gop_cache(std::string vhost);
|
||||
virtual int on_reload_queue_length(std::string vhost);
|
||||
virtual int on_reload_forward(std::string vhost);
|
||||
virtual int on_reload_hls(std::string vhost);
|
||||
virtual int on_reload_transcode(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_forward(std::string vhost);
|
||||
virtual int on_reload_hls(std::string vhost);
|
||||
virtual int on_reload_transcode(std::string vhost);
|
||||
public:
|
||||
// for the SrsForwarder to callback to request the sequence headers.
|
||||
virtual int on_forwarder_start(SrsForwarder* forwarder);
|
||||
// for the SrsHls to callback to request the sequence headers.
|
||||
virtual int on_hls_start();
|
||||
// for the SrsForwarder to callback to request the sequence headers.
|
||||
virtual int on_forwarder_start(SrsForwarder* forwarder);
|
||||
// for the SrsHls to callback to request the sequence headers.
|
||||
virtual int on_hls_start();
|
||||
public:
|
||||
virtual bool can_publish();
|
||||
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
|
||||
virtual int on_audio(SrsCommonMessage* audio);
|
||||
virtual int on_video(SrsCommonMessage* video);
|
||||
/**
|
||||
* publish stream event notify.
|
||||
* @param _req the request from client, the source will deep copy it,
|
||||
* for when reload the request of client maybe invalid.
|
||||
*/
|
||||
virtual int on_publish(SrsRequest* _req);
|
||||
virtual void on_unpublish();
|
||||
virtual bool can_publish();
|
||||
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
|
||||
virtual int on_audio(SrsCommonMessage* audio);
|
||||
virtual int on_video(SrsCommonMessage* video);
|
||||
/**
|
||||
* publish stream event notify.
|
||||
* @param _req the request from client, the source will deep copy it,
|
||||
* for when reload the request of client maybe invalid.
|
||||
*/
|
||||
virtual int on_publish(SrsRequest* _req);
|
||||
virtual void on_unpublish();
|
||||
public:
|
||||
virtual int create_consumer(SrsConsumer*& consumer);
|
||||
virtual void on_consumer_destroy(SrsConsumer* consumer);
|
||||
virtual void set_cache(bool enabled);
|
||||
virtual int create_consumer(SrsConsumer*& consumer);
|
||||
virtual void on_consumer_destroy(SrsConsumer* consumer);
|
||||
virtual void set_cache(bool enabled);
|
||||
private:
|
||||
virtual int create_forwarders();
|
||||
virtual void destroy_forwarders();
|
||||
virtual int create_forwarders();
|
||||
virtual void destroy_forwarders();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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)
|
||||
{
|
||||
if (stfd) {
|
||||
int fd = st_netfd_fileno(stfd);
|
||||
st_netfd_close(stfd);
|
||||
stfd = NULL;
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(fd);
|
||||
}
|
||||
if (stfd) {
|
||||
int fd = st_netfd_fileno(stfd);
|
||||
st_netfd_close(stfd);
|
||||
stfd = NULL;
|
||||
|
||||
// st does not close it sometimes,
|
||||
// close it manually.
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,14 +40,14 @@ void ISrsThreadHandler::on_enter_loop()
|
|||
|
||||
int ISrsThreadHandler::on_before_cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ISrsThreadHandler::on_end_cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ISrsThreadHandler::on_leave_loop()
|
||||
|
@ -56,29 +56,29 @@ void ISrsThreadHandler::on_leave_loop()
|
|||
|
||||
SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us)
|
||||
{
|
||||
handler = thread_handler;
|
||||
cycle_interval_us = interval_us;
|
||||
|
||||
tid = NULL;
|
||||
loop = false;
|
||||
handler = thread_handler;
|
||||
cycle_interval_us = interval_us;
|
||||
|
||||
tid = NULL;
|
||||
loop = false;
|
||||
}
|
||||
|
||||
SrsThread::~SrsThread()
|
||||
{
|
||||
stop();
|
||||
stop();
|
||||
}
|
||||
|
||||
int SrsThread::start()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if(tid) {
|
||||
srs_info("thread already running.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
@ -88,74 +88,74 @@ int SrsThread::start()
|
|||
|
||||
void SrsThread::stop()
|
||||
{
|
||||
if (tid) {
|
||||
loop = false;
|
||||
|
||||
// the interrupt will cause the socket to read/write error,
|
||||
// which will terminate the cycle thread.
|
||||
st_thread_interrupt(tid);
|
||||
|
||||
// wait the thread to exit.
|
||||
st_thread_join(tid, NULL);
|
||||
|
||||
tid = NULL;
|
||||
}
|
||||
if (tid) {
|
||||
loop = false;
|
||||
|
||||
// the interrupt will cause the socket to read/write error,
|
||||
// which will terminate the cycle thread.
|
||||
st_thread_interrupt(tid);
|
||||
|
||||
// wait the thread to exit.
|
||||
st_thread_join(tid, NULL);
|
||||
|
||||
tid = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool SrsThread::can_loop()
|
||||
{
|
||||
return loop;
|
||||
return loop;
|
||||
}
|
||||
|
||||
void SrsThread::thread_cycle()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
srs_assert(handler);
|
||||
|
||||
_srs_context->generate_id();
|
||||
srs_trace("thread cycle start");
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
srs_assert(handler);
|
||||
|
||||
_srs_context->generate_id();
|
||||
srs_trace("thread cycle start");
|
||||
|
||||
handler->on_end_cycle();
|
||||
|
||||
loop = true;
|
||||
while (loop) {
|
||||
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
|
||||
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
|
||||
goto failed;
|
||||
}
|
||||
srs_info("thread on before cycle success");
|
||||
|
||||
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
|
||||
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
|
||||
goto failed;
|
||||
}
|
||||
srs_info("thread cycle success");
|
||||
|
||||
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
|
||||
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
|
||||
goto failed;
|
||||
}
|
||||
srs_info("thread on end cycle success");
|
||||
handler->on_end_cycle();
|
||||
|
||||
loop = true;
|
||||
while (loop) {
|
||||
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
|
||||
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
|
||||
goto failed;
|
||||
}
|
||||
srs_info("thread on before cycle success");
|
||||
|
||||
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
|
||||
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
|
||||
goto failed;
|
||||
}
|
||||
srs_info("thread cycle success");
|
||||
|
||||
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
|
||||
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
|
||||
goto failed;
|
||||
}
|
||||
srs_info("thread on end cycle success");
|
||||
|
||||
failed:
|
||||
if (!loop) {
|
||||
break;
|
||||
}
|
||||
|
||||
st_usleep(cycle_interval_us);
|
||||
}
|
||||
|
||||
handler->on_leave_loop();
|
||||
srs_trace("thread cycle finished");
|
||||
if (!loop) {
|
||||
break;
|
||||
}
|
||||
|
||||
st_usleep(cycle_interval_us);
|
||||
}
|
||||
|
||||
handler->on_leave_loop();
|
||||
srs_trace("thread cycle finished");
|
||||
}
|
||||
|
||||
void* SrsThread::thread_fun(void* arg)
|
||||
{
|
||||
SrsThread* obj = (SrsThread*)arg;
|
||||
srs_assert(obj);
|
||||
|
||||
obj->thread_cycle();
|
||||
|
||||
return NULL;
|
||||
SrsThread* obj = (SrsThread*)arg;
|
||||
srs_assert(obj);
|
||||
|
||||
obj->thread_cycle();
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -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 thread model defines as:
|
||||
* handler->on_enter_loop()
|
||||
* while loop:
|
||||
* handler->on_before_cycle()
|
||||
* handler->cycle()
|
||||
* handler->on_end_cycle()
|
||||
* if !loop then break for user stop thread.
|
||||
* sleep(CycleIntervalMilliseconds)
|
||||
* handler->on_leave_loop()
|
||||
* handler->on_enter_loop()
|
||||
* while loop:
|
||||
* handler->on_before_cycle()
|
||||
* handler->cycle()
|
||||
* handler->on_end_cycle()
|
||||
* if !loop then break for user stop thread.
|
||||
* sleep(CycleIntervalMilliseconds)
|
||||
* handler->on_leave_loop()
|
||||
* when stop, the thread will interrupt the st_thread,
|
||||
* which will cause the socket to return error and
|
||||
* 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,
|
||||
* espectially on st_usleep(), so the cycle must check the loop,
|
||||
* when handler->cycle() has loop itself, for example:
|
||||
* handler->cycle() is:
|
||||
* while (true):
|
||||
* st_usleep(0);
|
||||
* if (read_from_socket(skt) < 0) break;
|
||||
* handler->cycle() is:
|
||||
* while (true):
|
||||
* st_usleep(0);
|
||||
* if (read_from_socket(skt) < 0) 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
|
||||
* death loop.
|
||||
* in a word, the handler->cycle() must:
|
||||
* handler->cycle() is:
|
||||
* while (pthread->can_loop()):
|
||||
* st_usleep(0);
|
||||
* if (read_from_socket(skt) < 0) break;
|
||||
* handler->cycle() is:
|
||||
* while (pthread->can_loop()):
|
||||
* st_usleep(0);
|
||||
* if (read_from_socket(skt) < 0) break;
|
||||
* check the loop, then it works.
|
||||
*/
|
||||
class ISrsThreadHandler
|
||||
{
|
||||
public:
|
||||
ISrsThreadHandler();
|
||||
virtual ~ISrsThreadHandler();
|
||||
ISrsThreadHandler();
|
||||
virtual ~ISrsThreadHandler();
|
||||
public:
|
||||
virtual void on_enter_loop();
|
||||
virtual int on_before_cycle();
|
||||
virtual int cycle() = 0;
|
||||
virtual int on_end_cycle();
|
||||
virtual void on_leave_loop();
|
||||
virtual void on_enter_loop();
|
||||
virtual int on_before_cycle();
|
||||
virtual int cycle() = 0;
|
||||
virtual int on_end_cycle();
|
||||
virtual void on_leave_loop();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -83,41 +83,41 @@ public:
|
|||
class SrsThread
|
||||
{
|
||||
private:
|
||||
st_thread_t tid;
|
||||
bool loop;
|
||||
st_thread_t tid;
|
||||
bool loop;
|
||||
private:
|
||||
ISrsThreadHandler* handler;
|
||||
int64_t cycle_interval_us;
|
||||
ISrsThreadHandler* handler;
|
||||
int64_t cycle_interval_us;
|
||||
public:
|
||||
/**
|
||||
* initialize the thread.
|
||||
* @param thread_handler, the cycle handler for the thread.
|
||||
* @param interval_us, the sleep interval when cycle finished.
|
||||
*/
|
||||
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
|
||||
virtual ~SrsThread();
|
||||
/**
|
||||
* initialize the thread.
|
||||
* @param thread_handler, the cycle handler for the thread.
|
||||
* @param interval_us, the sleep interval when cycle finished.
|
||||
*/
|
||||
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
|
||||
virtual ~SrsThread();
|
||||
public:
|
||||
/**
|
||||
* start the thread, invoke the cycle of handler util
|
||||
* user stop the thread.
|
||||
* @remark ignore any error of cycle of handler.
|
||||
* @remark user can start multiple times, ignore if already started.
|
||||
*/
|
||||
virtual int start();
|
||||
/**
|
||||
* stop the thread, wait for the thread to terminate.
|
||||
* @remark user can stop multiple times, ignore if already stopped.
|
||||
*/
|
||||
virtual void stop();
|
||||
/**
|
||||
* whether the thread should loop,
|
||||
* used for handler->cycle() which has a loop method,
|
||||
* to check this method, break if false.
|
||||
*/
|
||||
virtual bool can_loop();
|
||||
/**
|
||||
* start the thread, invoke the cycle of handler util
|
||||
* user stop the thread.
|
||||
* @remark ignore any error of cycle of handler.
|
||||
* @remark user can start multiple times, ignore if already started.
|
||||
*/
|
||||
virtual int start();
|
||||
/**
|
||||
* stop the thread, wait for the thread to terminate.
|
||||
* @remark user can stop multiple times, ignore if already stopped.
|
||||
*/
|
||||
virtual void stop();
|
||||
/**
|
||||
* whether the thread should loop,
|
||||
* used for handler->cycle() which has a loop method,
|
||||
* to check this method, break if false.
|
||||
*/
|
||||
virtual bool can_loop();
|
||||
private:
|
||||
virtual void thread_cycle();
|
||||
static void* thread_fun(void* arg);
|
||||
virtual void thread_cycle();
|
||||
static void* thread_fun(void* arg);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue