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 SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServer* _rtmp)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
rtmp = _rtmp;
|
rtmp = _rtmp;
|
||||||
req = _req;
|
req = _req;
|
||||||
|
|
||||||
if (!_srs_config->get_bw_check_enabled(req->vhost)) {
|
if (!_srs_config->get_bw_check_enabled(req->vhost)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate the bandwidth check key
|
// validate the bandwidth check key
|
||||||
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
|
std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost);
|
||||||
if (req->tcUrl.find(key) == std::string::npos) {
|
if (req->tcUrl.find(key) == std::string::npos) {
|
||||||
ret = ERROR_SYSTEM_BANDWIDTH_KEY;
|
ret = ERROR_SYSTEM_BANDWIDTH_KEY;
|
||||||
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
|
srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d",
|
||||||
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
|
req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// shared global last check time,
|
// shared global last check time,
|
||||||
// to avoid attach by bandwidth check,
|
// to avoid attach by bandwidth check,
|
||||||
// if client request check in the window(specifeid by interval),
|
// if client request check in the window(specifeid by interval),
|
||||||
// directly reject the request.
|
// directly reject the request.
|
||||||
static int64_t last_check_time = 0;
|
static int64_t last_check_time = 0;
|
||||||
int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost);
|
int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost);
|
||||||
|
|
||||||
|
@ -75,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) {
|
if (last_check_time > 0 && time_now - last_check_time < interval_ms) {
|
||||||
ret = ERROR_SYSTEM_BANDWIDTH_DENIED;
|
ret = ERROR_SYSTEM_BANDWIDTH_DENIED;
|
||||||
srs_trace("bandcheck denied, "
|
srs_trace("bandcheck denied, "
|
||||||
"last_check=%"PRId64", now=%"PRId64", interval=%d",
|
"last_check=%"PRId64", now=%"PRId64", interval=%d",
|
||||||
last_check_time, time_now, interval_ms);
|
last_check_time, time_now, interval_ms);
|
||||||
|
|
||||||
rtmp->response_connect_reject(req, "bandcheck rejected");
|
rtmp->response_connect_reject(req, "bandcheck rejected");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept and do bandwidth check.
|
// accept and do bandwidth check.
|
||||||
last_check_time = time_now;
|
last_check_time = time_now;
|
||||||
|
|
||||||
char* local_ip = 0;
|
char* local_ip = 0;
|
||||||
if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) {
|
if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) {
|
||||||
srs_error("get local ip failed. ret = %d", ret);
|
srs_error("get local ip failed. ret = %d", ret);
|
||||||
|
@ -137,7 +137,7 @@ int SrsBandwidth::do_bandwidth_check()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsProtocol* protocol = rtmp->get_protocol();
|
SrsProtocol* protocol = rtmp->get_protocol();
|
||||||
|
|
||||||
int play_duration_ms = 3000;
|
int play_duration_ms = 3000;
|
||||||
int play_interval_ms = 0;
|
int play_interval_ms = 0;
|
||||||
|
@ -154,14 +154,14 @@ int SrsBandwidth::do_bandwidth_check()
|
||||||
int64_t start_time = srs_get_system_time_ms();
|
int64_t start_time = srs_get_system_time_ms();
|
||||||
|
|
||||||
ret = check_play(play_duration_ms,
|
ret = check_play(play_duration_ms,
|
||||||
play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps);
|
play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps);
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
srs_error("band width play check failed. ret=%d", ret);
|
srs_error("band width play check failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_publish(publish_duration_ms,
|
ret = check_publish(publish_duration_ms,
|
||||||
publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps);
|
publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps);
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
srs_error("band width publish check failed. ret=%d", ret);
|
srs_error("band width publish check failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -188,29 +188,29 @@ int SrsBandwidth::do_bandwidth_check()
|
||||||
pkt->data->set("publish_bytes", SrsAmf0Any::number(publish_bytes));
|
pkt->data->set("publish_bytes", SrsAmf0Any::number(publish_bytes));
|
||||||
pkt->data->set("publish_time", SrsAmf0Any::number(publish_actual_duration_ms));
|
pkt->data->set("publish_time", SrsAmf0Any::number(publish_actual_duration_ms));
|
||||||
|
|
||||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("send bandwidth check finish message failed. ret=%d", ret);
|
srs_error("send bandwidth check finish message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if flash, we notice the result, and expect a final packet.
|
// if flash, we notice the result, and expect a final packet.
|
||||||
while (true) {
|
while (true) {
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
SrsBandwidthPacket* pkt = NULL;
|
SrsBandwidthPacket* pkt = NULL;
|
||||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||||
// info level to ignore and return success.
|
// info level to ignore and return success.
|
||||||
srs_info("expect final message failed. ret=%d", ret);
|
srs_info("expect final message failed. ret=%d", ret);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||||
srs_info("get final message success.");
|
srs_info("get final message success.");
|
||||||
|
|
||||||
if (pkt->is_flash_final()) {
|
if (pkt->is_flash_final()) {
|
||||||
srs_info("BW check recv flash final response.");
|
srs_info("BW check recv flash final response.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_info("BW check finished.");
|
srs_info("BW check finished.");
|
||||||
|
|
||||||
|
@ -218,44 +218,44 @@ int SrsBandwidth::do_bandwidth_check()
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsBandwidth::check_play(
|
int SrsBandwidth::check_play(
|
||||||
int duration_ms, int interval_ms, int& actual_duration_ms,
|
int duration_ms, int interval_ms, int& actual_duration_ms,
|
||||||
int& play_bytes, int max_play_kbps)
|
int& play_bytes, int max_play_kbps)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsProtocol* protocol = rtmp->get_protocol();
|
SrsProtocol* protocol = rtmp->get_protocol();
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// send start play command to client
|
// send start play command to client
|
||||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
|
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play();
|
||||||
|
|
||||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||||
|
|
||||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("send bandwidth check start play message failed. ret=%d", ret);
|
srs_error("send bandwidth check start play message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("BW check begin.");
|
srs_info("BW check begin.");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// recv client's starting play response
|
// recv client's starting play response
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
SrsBandwidthPacket* pkt = NULL;
|
SrsBandwidthPacket* pkt = NULL;
|
||||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||||
srs_info("get bandwidth message succes.");
|
srs_info("get bandwidth message succes.");
|
||||||
|
|
||||||
if (pkt->is_starting_play()) {
|
if (pkt->is_starting_play()) {
|
||||||
srs_info("BW check recv play begin response.");
|
srs_info("BW check recv play begin response.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send play data to client
|
// send play data to client
|
||||||
int64_t current_time = srs_get_system_time_ms();
|
int64_t current_time = srs_get_system_time_ms();
|
||||||
|
@ -280,10 +280,10 @@ int SrsBandwidth::check_play(
|
||||||
}
|
}
|
||||||
data_count += 2;
|
data_count += 2;
|
||||||
|
|
||||||
// TODO: FIXME: get length from the rtmp protocol stack.
|
// TODO: FIXME: get length from the rtmp protocol stack.
|
||||||
play_bytes += pkt->get_payload_length();
|
play_bytes += pkt->get_payload_length();
|
||||||
|
|
||||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("send bandwidth check play messages failed. ret=%d", ret);
|
srs_error("send bandwidth check play messages failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -305,81 +305,81 @@ int SrsBandwidth::check_play(
|
||||||
actual_duration_ms = srs_get_system_time_ms() - current_time;
|
actual_duration_ms = srs_get_system_time_ms() - current_time;
|
||||||
srs_info("BW check send play bytes over.");
|
srs_info("BW check send play bytes over.");
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// notify client to stop play
|
// notify client to stop play
|
||||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
|
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play();
|
||||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||||
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
||||||
pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes));
|
pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes));
|
||||||
|
|
||||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("send bandwidth check stop play message failed. ret=%d", ret);
|
srs_error("send bandwidth check stop play message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("BW check stop play bytes.");
|
srs_info("BW check stop play bytes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// recv client's stop play response.
|
// recv client's stop play response.
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
SrsBandwidthPacket* pkt = NULL;
|
SrsBandwidthPacket* pkt = NULL;
|
||||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||||
srs_info("get bandwidth message succes.");
|
srs_info("get bandwidth message succes.");
|
||||||
|
|
||||||
if (pkt->is_stopped_play()) {
|
if (pkt->is_stopped_play()) {
|
||||||
srs_info("BW check recv stop play response.");
|
srs_info("BW check recv stop play response.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsBandwidth::check_publish(
|
int SrsBandwidth::check_publish(
|
||||||
int duration_ms, int interval_ms, int& actual_duration_ms,
|
int duration_ms, int interval_ms, int& actual_duration_ms,
|
||||||
int& publish_bytes, int max_pub_kbps)
|
int& publish_bytes, int max_pub_kbps)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsProtocol* protocol = rtmp->get_protocol();
|
SrsProtocol* protocol = rtmp->get_protocol();
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// notify client to start publish
|
// notify client to start publish
|
||||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
|
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish();
|
||||||
|
|
||||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||||
|
|
||||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("send bandwidth check start publish message failed. ret=%d", ret);
|
srs_error("send bandwidth check start publish message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("BW check publish begin.");
|
srs_info("BW check publish begin.");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// read client's notification of starting publish
|
// read client's notification of starting publish
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
SrsBandwidthPacket* pkt = NULL;
|
SrsBandwidthPacket* pkt = NULL;
|
||||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||||
srs_info("get bandwidth message succes.");
|
srs_info("get bandwidth message succes.");
|
||||||
|
|
||||||
if (pkt->is_starting_publish()) {
|
if (pkt->is_starting_publish()) {
|
||||||
srs_info("BW check recv publish begin response.");
|
srs_info("BW check recv publish begin response.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recv publish msgs until @duration_ms ms
|
// recv publish msgs until @duration_ms ms
|
||||||
int64_t current_time = srs_get_system_time_ms();
|
int64_t current_time = srs_get_system_time_ms();
|
||||||
|
@ -393,7 +393,7 @@ int SrsBandwidth::check_publish(
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||||
|
|
||||||
// TODO: FIXME.
|
// TODO: FIXME.
|
||||||
publish_bytes += msg->header.payload_length;
|
publish_bytes += msg->header.payload_length;
|
||||||
|
|
||||||
int kbps = 0;
|
int kbps = 0;
|
||||||
|
@ -411,21 +411,21 @@ int SrsBandwidth::check_publish(
|
||||||
actual_duration_ms = srs_get_system_time_ms() - current_time;
|
actual_duration_ms = srs_get_system_time_ms() - current_time;
|
||||||
srs_info("BW check recv publish data over.");
|
srs_info("BW check recv publish data over.");
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// notify client to stop publish
|
// notify client to stop publish
|
||||||
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
|
SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish();
|
||||||
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms));
|
||||||
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms));
|
||||||
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms));
|
||||||
pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes));
|
pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes));
|
||||||
|
|
||||||
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0);
|
||||||
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
|
srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("BW check stop publish bytes.");
|
srs_info("BW check stop publish bytes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// expect client to stop publish
|
// expect client to stop publish
|
||||||
// if flash client, we never expect the client stop publish bytes,
|
// if flash client, we never expect the client stop publish bytes,
|
||||||
|
@ -433,22 +433,22 @@ int SrsBandwidth::check_publish(
|
||||||
// there are many many packets in the queue.
|
// there are many many packets in the queue.
|
||||||
// we just ignore the packet and send the bandwidth test data.
|
// we just ignore the packet and send the bandwidth test data.
|
||||||
// TODO: FIXME: check whether flash client.
|
// TODO: FIXME: check whether flash client.
|
||||||
while (false) {
|
while (false) {
|
||||||
// recv client's stop publish response.
|
// recv client's stop publish response.
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
SrsBandwidthPacket* pkt = NULL;
|
SrsBandwidthPacket* pkt = NULL;
|
||||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||||
srs_error("expect bandwidth message failed. ret=%d", ret);
|
srs_error("expect bandwidth message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsCommonMessage, msg, false);
|
SrsAutoFree(SrsCommonMessage, msg, false);
|
||||||
srs_info("get bandwidth message succes.");
|
srs_info("get bandwidth message succes.");
|
||||||
|
|
||||||
if (pkt->is_stopped_publish()) {
|
if (pkt->is_stopped_publish()) {
|
||||||
srs_info("BW check recv stop publish response.");
|
srs_info("BW check recv stop publish response.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,7 +42,7 @@ class SrsRefer;
|
||||||
class SrsConsumer;
|
class SrsConsumer;
|
||||||
class SrsCommonMessage;
|
class SrsCommonMessage;
|
||||||
class SrsSocket;
|
class SrsSocket;
|
||||||
#ifdef SRS_HTTP_CALLBACK
|
#ifdef SRS_HTTP_CALLBACK
|
||||||
class SrsHttpHooks;
|
class SrsHttpHooks;
|
||||||
#endif
|
#endif
|
||||||
class SrsBandwidth;
|
class SrsBandwidth;
|
||||||
|
@ -53,43 +53,43 @@ class SrsBandwidth;
|
||||||
class SrsClient : public SrsConnection, public ISrsReloadHandler
|
class SrsClient : public SrsConnection, public ISrsReloadHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
char* ip;
|
char* ip;
|
||||||
SrsRequest* req;
|
SrsRequest* req;
|
||||||
SrsResponse* res;
|
SrsResponse* res;
|
||||||
SrsSocket* skt;
|
SrsSocket* skt;
|
||||||
SrsRtmpServer* rtmp;
|
SrsRtmpServer* rtmp;
|
||||||
SrsRefer* refer;
|
SrsRefer* refer;
|
||||||
#ifdef SRS_HTTP_CALLBACK
|
#ifdef SRS_HTTP_CALLBACK
|
||||||
SrsHttpHooks* http_hooks;
|
SrsHttpHooks* http_hooks;
|
||||||
#endif
|
#endif
|
||||||
SrsBandwidth* bandwidth;
|
SrsBandwidth* bandwidth;
|
||||||
public:
|
public:
|
||||||
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
|
SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||||
virtual ~SrsClient();
|
virtual ~SrsClient();
|
||||||
protected:
|
protected:
|
||||||
virtual int do_cycle();
|
virtual int do_cycle();
|
||||||
// interface ISrsReloadHandler
|
// interface ISrsReloadHandler
|
||||||
public:
|
public:
|
||||||
virtual int on_reload_vhost_removed(std::string vhost);
|
virtual int on_reload_vhost_removed(std::string vhost);
|
||||||
private:
|
private:
|
||||||
// when valid and connected to vhost/app, service the client.
|
// when valid and connected to vhost/app, service the client.
|
||||||
virtual int service_cycle();
|
virtual int service_cycle();
|
||||||
// stream(play/publish) service cycle, identify client first.
|
// stream(play/publish) service cycle, identify client first.
|
||||||
virtual int stream_service_cycle();
|
virtual int stream_service_cycle();
|
||||||
virtual int check_vhost();
|
virtual int check_vhost();
|
||||||
virtual int playing(SrsSource* source);
|
virtual int playing(SrsSource* source);
|
||||||
virtual int fmle_publish(SrsSource* source);
|
virtual int fmle_publish(SrsSource* source);
|
||||||
virtual int flash_publish(SrsSource* source);
|
virtual int flash_publish(SrsSource* source);
|
||||||
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
|
virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg);
|
||||||
virtual int get_peer_ip();
|
virtual int get_peer_ip();
|
||||||
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
|
virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
|
||||||
private:
|
private:
|
||||||
virtual int on_connect();
|
virtual int on_connect();
|
||||||
virtual void on_close();
|
virtual void on_close();
|
||||||
virtual int on_publish();
|
virtual int on_publish();
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
virtual int on_play();
|
virtual int on_play();
|
||||||
virtual void on_stop();
|
virtual void on_stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,29 +33,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
SrsCodecBuffer::SrsCodecBuffer()
|
SrsCodecBuffer::SrsCodecBuffer()
|
||||||
{
|
{
|
||||||
size = 0;
|
size = 0;
|
||||||
bytes = NULL;
|
bytes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsCodecBuffer::append(void* data, int len)
|
void SrsCodecBuffer::append(void* data, int len)
|
||||||
{
|
{
|
||||||
srs_assert(data);
|
srs_assert(data);
|
||||||
srs_assert(len > 0);
|
srs_assert(len > 0);
|
||||||
|
|
||||||
bytes = (char*)realloc(bytes, size + len);
|
bytes = (char*)realloc(bytes, size + len);
|
||||||
memcpy(bytes + size, data, len);
|
memcpy(bytes + size, data, len);
|
||||||
size += len;
|
size += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsCodecBuffer::free()
|
void SrsCodecBuffer::free()
|
||||||
{
|
{
|
||||||
size = 0;
|
size = 0;
|
||||||
srs_freepa(bytes);
|
srs_freepa(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCodecSample::SrsCodecSample()
|
SrsCodecSample::SrsCodecSample()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCodecSample::~SrsCodecSample()
|
SrsCodecSample::~SrsCodecSample()
|
||||||
|
@ -64,468 +64,468 @@ SrsCodecSample::~SrsCodecSample()
|
||||||
|
|
||||||
void SrsCodecSample::clear()
|
void SrsCodecSample::clear()
|
||||||
{
|
{
|
||||||
is_video = false;
|
is_video = false;
|
||||||
nb_buffers = 0;
|
nb_buffers = 0;
|
||||||
|
|
||||||
cts = 0;
|
cts = 0;
|
||||||
frame_type = SrsCodecVideoAVCFrameReserved;
|
frame_type = SrsCodecVideoAVCFrameReserved;
|
||||||
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
||||||
|
|
||||||
sound_rate = SrsCodecAudioSampleRateReserved;
|
sound_rate = SrsCodecAudioSampleRateReserved;
|
||||||
sound_size = SrsCodecAudioSampleSizeReserved;
|
sound_size = SrsCodecAudioSampleSizeReserved;
|
||||||
sound_type = SrsCodecAudioSoundTypeReserved;
|
sound_type = SrsCodecAudioSoundTypeReserved;
|
||||||
aac_packet_type = SrsCodecAudioTypeReserved;
|
aac_packet_type = SrsCodecAudioTypeReserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsCodecSample::add_sample(char* bytes, int size)
|
int SrsCodecSample::add_sample(char* bytes, int size)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
|
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode samples error, "
|
srs_error("hls decode samples error, "
|
||||||
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
|
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCodecBuffer* buf = &buffers[nb_buffers++];
|
SrsCodecBuffer* buf = &buffers[nb_buffers++];
|
||||||
buf->bytes = bytes;
|
buf->bytes = bytes;
|
||||||
buf->size = size;
|
buf->size = size;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCodec::SrsCodec()
|
SrsCodec::SrsCodec()
|
||||||
{
|
{
|
||||||
width = 0;
|
width = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
duration = 0;
|
duration = 0;
|
||||||
NAL_unit_length = 0;
|
NAL_unit_length = 0;
|
||||||
frame_rate = 0;
|
frame_rate = 0;
|
||||||
video_data_rate = 0;
|
video_data_rate = 0;
|
||||||
video_codec_id = 0;
|
video_codec_id = 0;
|
||||||
audio_data_rate = 0;
|
audio_data_rate = 0;
|
||||||
audio_codec_id = 0;
|
audio_codec_id = 0;
|
||||||
avc_profile = 0;
|
avc_profile = 0;
|
||||||
avc_level = 0;
|
avc_level = 0;
|
||||||
aac_profile = 0;
|
aac_profile = 0;
|
||||||
aac_sample_rate = 0;
|
aac_sample_rate = 0;
|
||||||
aac_channels = 0;
|
aac_channels = 0;
|
||||||
avc_extra_size = 0;
|
avc_extra_size = 0;
|
||||||
avc_extra_data = NULL;
|
avc_extra_data = NULL;
|
||||||
aac_extra_size = 0;
|
aac_extra_size = 0;
|
||||||
aac_extra_data = NULL;
|
aac_extra_data = NULL;
|
||||||
sequenceParameterSetLength = 0;
|
sequenceParameterSetLength = 0;
|
||||||
sequenceParameterSetNALUnit = NULL;
|
sequenceParameterSetNALUnit = NULL;
|
||||||
pictureParameterSetLength = 0;
|
pictureParameterSetLength = 0;
|
||||||
pictureParameterSetNALUnit = NULL;
|
pictureParameterSetNALUnit = NULL;
|
||||||
|
|
||||||
stream = new SrsStream();
|
stream = new SrsStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCodec::~SrsCodec()
|
SrsCodec::~SrsCodec()
|
||||||
{
|
{
|
||||||
srs_freepa(avc_extra_data);
|
srs_freepa(avc_extra_data);
|
||||||
srs_freepa(aac_extra_data);
|
srs_freepa(aac_extra_data);
|
||||||
|
|
||||||
srs_freep(stream);
|
srs_freep(stream);
|
||||||
srs_freepa(sequenceParameterSetNALUnit);
|
srs_freepa(sequenceParameterSetNALUnit);
|
||||||
srs_freepa(pictureParameterSetNALUnit);
|
srs_freepa(pictureParameterSetNALUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
|
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
sample->is_video = false;
|
sample->is_video = false;
|
||||||
|
|
||||||
if (!data || size <= 0) {
|
if (!data || size <= 0) {
|
||||||
srs_trace("no audio present, hls ignore it.");
|
srs_trace("no audio present, hls ignore it.");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio decode
|
// audio decode
|
||||||
if (!stream->require(1)) {
|
if (!stream->require(1)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode audio sound_format failed. ret=%d", ret);
|
srs_error("hls decode audio sound_format failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t sound_format = stream->read_1bytes();
|
int8_t sound_format = stream->read_1bytes();
|
||||||
|
|
||||||
int8_t sound_type = sound_format & 0x01;
|
int8_t sound_type = sound_format & 0x01;
|
||||||
int8_t sound_size = (sound_format >> 1) & 0x01;
|
int8_t sound_size = (sound_format >> 1) & 0x01;
|
||||||
int8_t sound_rate = (sound_format >> 2) & 0x03;
|
int8_t sound_rate = (sound_format >> 2) & 0x03;
|
||||||
sound_format = (sound_format >> 4) & 0x0f;
|
sound_format = (sound_format >> 4) & 0x0f;
|
||||||
|
|
||||||
audio_codec_id = sound_format;
|
audio_codec_id = sound_format;
|
||||||
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
|
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
|
||||||
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
|
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
|
||||||
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
|
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
|
||||||
|
|
||||||
// reset the sample rate by sequence header
|
// reset the sample rate by sequence header
|
||||||
static int aac_sample_rates[] = {
|
static int aac_sample_rates[] = {
|
||||||
96000, 88200, 64000, 48000,
|
96000, 88200, 64000, 48000,
|
||||||
44100, 32000, 24000, 22050,
|
44100, 32000, 24000, 22050,
|
||||||
16000, 12000, 11025, 8000,
|
16000, 12000, 11025, 8000,
|
||||||
7350, 0, 0, 0
|
7350, 0, 0, 0
|
||||||
};
|
};
|
||||||
switch (aac_sample_rates[aac_sample_rate]) {
|
switch (aac_sample_rates[aac_sample_rate]) {
|
||||||
case 11025:
|
case 11025:
|
||||||
sample->sound_rate = SrsCodecAudioSampleRate11025;
|
sample->sound_rate = SrsCodecAudioSampleRate11025;
|
||||||
break;
|
break;
|
||||||
case 22050:
|
case 22050:
|
||||||
sample->sound_rate = SrsCodecAudioSampleRate22050;
|
sample->sound_rate = SrsCodecAudioSampleRate22050;
|
||||||
break;
|
break;
|
||||||
case 44100:
|
case 44100:
|
||||||
sample->sound_rate = SrsCodecAudioSampleRate44100;
|
sample->sound_rate = SrsCodecAudioSampleRate44100;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
// only support aac
|
// only support aac
|
||||||
if (audio_codec_id != SrsCodecAudioAAC) {
|
if (audio_codec_id != SrsCodecAudioAAC) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls only support audio aac codec. ret=%d", ret);
|
srs_error("hls only support audio aac codec. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stream->require(1)) {
|
if (!stream->require(1)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
|
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t aac_packet_type = stream->read_1bytes();
|
int8_t aac_packet_type = stream->read_1bytes();
|
||||||
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
|
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
|
||||||
|
|
||||||
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
||||||
// AudioSpecificConfig
|
// AudioSpecificConfig
|
||||||
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
||||||
aac_extra_size = stream->left();
|
aac_extra_size = stream->left();
|
||||||
if (aac_extra_size > 0) {
|
if (aac_extra_size > 0) {
|
||||||
srs_freepa(aac_extra_data);
|
srs_freepa(aac_extra_data);
|
||||||
aac_extra_data = new char[aac_extra_size];
|
aac_extra_data = new char[aac_extra_size];
|
||||||
memcpy(aac_extra_data, stream->current(), aac_extra_size);
|
memcpy(aac_extra_data, stream->current(), aac_extra_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only need to decode the first 2bytes:
|
// only need to decode the first 2bytes:
|
||||||
// audioObjectType, aac_profile, 5bits.
|
// audioObjectType, aac_profile, 5bits.
|
||||||
// samplingFrequencyIndex, aac_sample_rate, 4bits.
|
// samplingFrequencyIndex, aac_sample_rate, 4bits.
|
||||||
// channelConfiguration, aac_channels, 4bits
|
// channelConfiguration, aac_channels, 4bits
|
||||||
if (!stream->require(2)) {
|
if (!stream->require(2)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
|
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
aac_profile = stream->read_1bytes();
|
aac_profile = stream->read_1bytes();
|
||||||
aac_sample_rate = stream->read_1bytes();
|
aac_sample_rate = stream->read_1bytes();
|
||||||
|
|
||||||
aac_channels = (aac_sample_rate >> 3) & 0x0f;
|
aac_channels = (aac_sample_rate >> 3) & 0x0f;
|
||||||
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
|
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
|
||||||
aac_profile = (aac_profile >> 3) & 0x1f;
|
aac_profile = (aac_profile >> 3) & 0x1f;
|
||||||
|
|
||||||
if (aac_profile == 0 || aac_profile == 0x1f) {
|
if (aac_profile == 0 || aac_profile == 0x1f) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode audio aac sequence header failed, "
|
srs_error("hls decode audio aac sequence header failed, "
|
||||||
"adts object=%d invalid. ret=%d", aac_profile, ret);
|
"adts object=%d invalid. ret=%d", aac_profile, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// aac_profile = audioObjectType - 1
|
// aac_profile = audioObjectType - 1
|
||||||
aac_profile--;
|
aac_profile--;
|
||||||
|
|
||||||
if (aac_profile > 3) {
|
if (aac_profile > 3) {
|
||||||
// Mark all extended profiles as LC
|
// Mark all extended profiles as LC
|
||||||
// to make Android as happy as possible.
|
// to make Android as happy as possible.
|
||||||
// @see: ngx_rtmp_hls_parse_aac_header
|
// @see: ngx_rtmp_hls_parse_aac_header
|
||||||
aac_profile = 1;
|
aac_profile = 1;
|
||||||
}
|
}
|
||||||
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
|
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
|
||||||
// ensure the sequence header demuxed
|
// ensure the sequence header demuxed
|
||||||
if (aac_extra_size <= 0 || !aac_extra_data) {
|
if (aac_extra_size <= 0 || !aac_extra_data) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
|
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw AAC frame data in UI8 []
|
// Raw AAC frame data in UI8 []
|
||||||
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
|
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
|
||||||
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
|
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
|
||||||
srs_error("hls add audio sample failed. ret=%d", ret);
|
srs_error("hls add audio sample failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ignored.
|
// ignored.
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
|
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
|
||||||
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
|
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
|
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
sample->is_video = true;
|
sample->is_video = true;
|
||||||
|
|
||||||
if (!data || size <= 0) {
|
if (!data || size <= 0) {
|
||||||
srs_trace("no video present, hls ignore it.");
|
srs_trace("no video present, hls ignore it.");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// video decode
|
// video decode
|
||||||
if (!stream->require(1)) {
|
if (!stream->require(1)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video frame_type failed. ret=%d", ret);
|
srs_error("hls decode video frame_type failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t frame_type = stream->read_1bytes();
|
int8_t frame_type = stream->read_1bytes();
|
||||||
int8_t codec_id = frame_type & 0x0f;
|
int8_t codec_id = frame_type & 0x0f;
|
||||||
frame_type = (frame_type >> 4) & 0x0f;
|
frame_type = (frame_type >> 4) & 0x0f;
|
||||||
|
|
||||||
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
|
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
|
||||||
|
|
||||||
// only support h.264/avc
|
// only support h.264/avc
|
||||||
if (codec_id != SrsCodecVideoAVC) {
|
if (codec_id != SrsCodecVideoAVC) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
|
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
video_codec_id = codec_id;
|
video_codec_id = codec_id;
|
||||||
|
|
||||||
if (!stream->require(4)) {
|
if (!stream->require(4)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
|
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int8_t avc_packet_type = stream->read_1bytes();
|
int8_t avc_packet_type = stream->read_1bytes();
|
||||||
int32_t composition_time = stream->read_3bytes();
|
int32_t composition_time = stream->read_3bytes();
|
||||||
|
|
||||||
// pts = dts + cts.
|
// pts = dts + cts.
|
||||||
sample->cts = composition_time;
|
sample->cts = composition_time;
|
||||||
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
|
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
|
||||||
|
|
||||||
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
||||||
// AVCDecoderConfigurationRecord
|
// AVCDecoderConfigurationRecord
|
||||||
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
||||||
avc_extra_size = stream->left();
|
avc_extra_size = stream->left();
|
||||||
if (avc_extra_size > 0) {
|
if (avc_extra_size > 0) {
|
||||||
srs_freepa(avc_extra_data);
|
srs_freepa(avc_extra_data);
|
||||||
avc_extra_data = new char[avc_extra_size];
|
avc_extra_data = new char[avc_extra_size];
|
||||||
memcpy(avc_extra_data, stream->current(), avc_extra_size);
|
memcpy(avc_extra_data, stream->current(), avc_extra_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stream->require(6)) {
|
if (!stream->require(6)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
//int8_t configurationVersion = stream->read_1bytes();
|
//int8_t configurationVersion = stream->read_1bytes();
|
||||||
//int8_t AVCProfileIndication = stream->read_1bytes();
|
//int8_t AVCProfileIndication = stream->read_1bytes();
|
||||||
//int8_t profile_compatibility = stream->read_1bytes();
|
//int8_t profile_compatibility = stream->read_1bytes();
|
||||||
//int8_t AVCLevelIndication = stream->read_1bytes();
|
//int8_t AVCLevelIndication = stream->read_1bytes();
|
||||||
stream->skip(4);
|
stream->skip(4);
|
||||||
// parse the NALU size.
|
// parse the NALU size.
|
||||||
int8_t lengthSizeMinusOne = stream->read_1bytes();
|
int8_t lengthSizeMinusOne = stream->read_1bytes();
|
||||||
lengthSizeMinusOne &= 0x03;
|
lengthSizeMinusOne &= 0x03;
|
||||||
NAL_unit_length = lengthSizeMinusOne;
|
NAL_unit_length = lengthSizeMinusOne;
|
||||||
|
|
||||||
// 1 sps
|
// 1 sps
|
||||||
if (!stream->require(1)) {
|
if (!stream->require(1)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int8_t numOfSequenceParameterSets = stream->read_1bytes();
|
int8_t numOfSequenceParameterSets = stream->read_1bytes();
|
||||||
numOfSequenceParameterSets &= 0x1f;
|
numOfSequenceParameterSets &= 0x1f;
|
||||||
if (numOfSequenceParameterSets != 1) {
|
if (numOfSequenceParameterSets != 1) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (!stream->require(2)) {
|
if (!stream->require(2)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
sequenceParameterSetLength = stream->read_2bytes();
|
sequenceParameterSetLength = stream->read_2bytes();
|
||||||
if (!stream->require(sequenceParameterSetLength)) {
|
if (!stream->require(sequenceParameterSetLength)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (sequenceParameterSetLength > 0) {
|
if (sequenceParameterSetLength > 0) {
|
||||||
srs_freepa(sequenceParameterSetNALUnit);
|
srs_freepa(sequenceParameterSetNALUnit);
|
||||||
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
|
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
|
||||||
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
|
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
|
||||||
stream->skip(sequenceParameterSetLength);
|
stream->skip(sequenceParameterSetLength);
|
||||||
}
|
}
|
||||||
// 1 pps
|
// 1 pps
|
||||||
if (!stream->require(1)) {
|
if (!stream->require(1)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int8_t numOfPictureParameterSets = stream->read_1bytes();
|
int8_t numOfPictureParameterSets = stream->read_1bytes();
|
||||||
numOfPictureParameterSets &= 0x1f;
|
numOfPictureParameterSets &= 0x1f;
|
||||||
if (numOfPictureParameterSets != 1) {
|
if (numOfPictureParameterSets != 1) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (!stream->require(2)) {
|
if (!stream->require(2)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pictureParameterSetLength = stream->read_2bytes();
|
pictureParameterSetLength = stream->read_2bytes();
|
||||||
if (!stream->require(pictureParameterSetLength)) {
|
if (!stream->require(pictureParameterSetLength)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
|
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (pictureParameterSetLength > 0) {
|
if (pictureParameterSetLength > 0) {
|
||||||
srs_freepa(pictureParameterSetNALUnit);
|
srs_freepa(pictureParameterSetNALUnit);
|
||||||
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
|
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
|
||||||
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
|
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
|
||||||
stream->skip(pictureParameterSetLength);
|
stream->skip(pictureParameterSetLength);
|
||||||
}
|
}
|
||||||
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
|
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
|
||||||
// ensure the sequence header demuxed
|
// ensure the sequence header demuxed
|
||||||
if (avc_extra_size <= 0 || !avc_extra_data) {
|
if (avc_extra_size <= 0 || !avc_extra_data) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
|
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// One or more NALUs (Full frames are required)
|
// One or more NALUs (Full frames are required)
|
||||||
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
|
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
|
||||||
int PictureLength = stream->left();
|
int PictureLength = stream->left();
|
||||||
for (int i = 0; i < PictureLength;) {
|
for (int i = 0; i < PictureLength;) {
|
||||||
if (!stream->require(NAL_unit_length + 1)) {
|
if (!stream->require(NAL_unit_length + 1)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
|
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int32_t NALUnitLength = 0;
|
int32_t NALUnitLength = 0;
|
||||||
if (NAL_unit_length == 3) {
|
if (NAL_unit_length == 3) {
|
||||||
NALUnitLength = stream->read_4bytes();
|
NALUnitLength = stream->read_4bytes();
|
||||||
} else if (NALUnitLength == 2) {
|
} else if (NALUnitLength == 2) {
|
||||||
NALUnitLength = stream->read_3bytes();
|
NALUnitLength = stream->read_3bytes();
|
||||||
} else if (NALUnitLength == 1) {
|
} else if (NALUnitLength == 1) {
|
||||||
NALUnitLength = stream->read_2bytes();
|
NALUnitLength = stream->read_2bytes();
|
||||||
} else {
|
} else {
|
||||||
NALUnitLength = stream->read_1bytes();
|
NALUnitLength = stream->read_1bytes();
|
||||||
}
|
}
|
||||||
// NALUnit
|
// NALUnit
|
||||||
if (!stream->require(NALUnitLength)) {
|
if (!stream->require(NALUnitLength)) {
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
|
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
|
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
|
||||||
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
|
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
|
||||||
srs_error("hls add video sample failed. ret=%d", ret);
|
srs_error("hls add video sample failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
stream->skip(NALUnitLength);
|
stream->skip(NALUnitLength);
|
||||||
|
|
||||||
i += NAL_unit_length + 1 + NALUnitLength;
|
i += NAL_unit_length + 1 + NALUnitLength;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ignored.
|
// ignored.
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
|
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
|
||||||
frame_type, video_codec_id, avc_packet_type, composition_time, size);
|
frame_type, video_codec_id, avc_packet_type, composition_time, size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
|
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
|
||||||
{
|
{
|
||||||
// 2bytes required.
|
// 2bytes required.
|
||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char frame_type = *(char*)data;
|
char frame_type = *(char*)data;
|
||||||
frame_type = (frame_type >> 4) & 0x0F;
|
frame_type = (frame_type >> 4) & 0x0F;
|
||||||
|
|
||||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
|
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
|
||||||
{
|
{
|
||||||
// sequence header only for h264
|
// sequence header only for h264
|
||||||
if (!video_is_h264(data, size)) {
|
if (!video_is_h264(data, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2bytes required.
|
// 2bytes required.
|
||||||
if (size < 2) {
|
if (size < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char frame_type = *(char*)data;
|
char frame_type = *(char*)data;
|
||||||
frame_type = (frame_type >> 4) & 0x0F;
|
frame_type = (frame_type >> 4) & 0x0F;
|
||||||
|
|
||||||
char avc_packet_type = *(char*)(data + 1);
|
char avc_packet_type = *(char*)(data + 1);
|
||||||
|
|
||||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame
|
return frame_type == SrsCodecVideoAVCFrameKeyFrame
|
||||||
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
|
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
|
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
|
||||||
{
|
{
|
||||||
// sequence header only for aac
|
// sequence header only for aac
|
||||||
if (!audio_is_aac(data, size)) {
|
if (!audio_is_aac(data, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2bytes required.
|
// 2bytes required.
|
||||||
if (size < 2) {
|
if (size < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char aac_packet_type = *(char*)(data + 1);
|
char aac_packet_type = *(char*)(data + 1);
|
||||||
|
|
||||||
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
|
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsCodec::video_is_h264(int8_t* data, int size)
|
bool SrsCodec::video_is_h264(int8_t* data, int size)
|
||||||
{
|
{
|
||||||
// 1bytes required.
|
// 1bytes required.
|
||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char codec_id = *(char*)data;
|
char codec_id = *(char*)data;
|
||||||
codec_id = codec_id & 0x0F;
|
codec_id = codec_id & 0x0F;
|
||||||
|
|
||||||
return codec_id == SrsCodecVideoAVC;
|
return codec_id == SrsCodecVideoAVC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsCodec::audio_is_aac(int8_t* data, int size)
|
bool SrsCodec::audio_is_aac(int8_t* data, int size)
|
||||||
{
|
{
|
||||||
// 1bytes required.
|
// 1bytes required.
|
||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char sound_format = *(char*)data;
|
char sound_format = *(char*)data;
|
||||||
sound_format = (sound_format >> 4) & 0x0F;
|
sound_format = (sound_format >> 4) & 0x0F;
|
||||||
|
|
||||||
return sound_format == SrsCodecAudioAAC;
|
return sound_format == SrsCodecAudioAAC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,104 +37,104 @@ class SrsStream;
|
||||||
// E.4.3.1 VIDEODATA
|
// E.4.3.1 VIDEODATA
|
||||||
// CodecID UB [4]
|
// CodecID UB [4]
|
||||||
// Codec Identifier. The following values are defined:
|
// Codec Identifier. The following values are defined:
|
||||||
// 2 = Sorenson H.263
|
// 2 = Sorenson H.263
|
||||||
// 3 = Screen video
|
// 3 = Screen video
|
||||||
// 4 = On2 VP6
|
// 4 = On2 VP6
|
||||||
// 5 = On2 VP6 with alpha channel
|
// 5 = On2 VP6 with alpha channel
|
||||||
// 6 = Screen video version 2
|
// 6 = Screen video version 2
|
||||||
// 7 = AVC
|
// 7 = AVC
|
||||||
enum SrsCodecVideo
|
enum SrsCodecVideo
|
||||||
{
|
{
|
||||||
SrsCodecVideoReserved = 0,
|
SrsCodecVideoReserved = 0,
|
||||||
|
|
||||||
SrsCodecVideoSorensonH263 = 2,
|
SrsCodecVideoSorensonH263 = 2,
|
||||||
SrsCodecVideoScreenVideo = 3,
|
SrsCodecVideoScreenVideo = 3,
|
||||||
SrsCodecVideoOn2VP6 = 4,
|
SrsCodecVideoOn2VP6 = 4,
|
||||||
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
|
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
|
||||||
SrsCodecVideoScreenVideoVersion2 = 6,
|
SrsCodecVideoScreenVideoVersion2 = 6,
|
||||||
SrsCodecVideoAVC = 7,
|
SrsCodecVideoAVC = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
// E.4.3.1 VIDEODATA
|
// E.4.3.1 VIDEODATA
|
||||||
// Frame Type UB [4]
|
// Frame Type UB [4]
|
||||||
// Type of video frame. The following values are defined:
|
// Type of video frame. The following values are defined:
|
||||||
// 1 = key frame (for AVC, a seekable frame)
|
// 1 = key frame (for AVC, a seekable frame)
|
||||||
// 2 = inter frame (for AVC, a non-seekable frame)
|
// 2 = inter frame (for AVC, a non-seekable frame)
|
||||||
// 3 = disposable inter frame (H.263 only)
|
// 3 = disposable inter frame (H.263 only)
|
||||||
// 4 = generated key frame (reserved for server use only)
|
// 4 = generated key frame (reserved for server use only)
|
||||||
// 5 = video info/command frame
|
// 5 = video info/command frame
|
||||||
enum SrsCodecVideoAVCFrame
|
enum SrsCodecVideoAVCFrame
|
||||||
{
|
{
|
||||||
SrsCodecVideoAVCFrameReserved = 0,
|
SrsCodecVideoAVCFrameReserved = 0,
|
||||||
|
|
||||||
SrsCodecVideoAVCFrameKeyFrame = 1,
|
SrsCodecVideoAVCFrameKeyFrame = 1,
|
||||||
SrsCodecVideoAVCFrameInterFrame = 2,
|
SrsCodecVideoAVCFrameInterFrame = 2,
|
||||||
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
|
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
|
||||||
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
|
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
|
||||||
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
|
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
// AVCPacketType IF CodecID == 7 UI8
|
// AVCPacketType IF CodecID == 7 UI8
|
||||||
// The following values are defined:
|
// The following values are defined:
|
||||||
// 0 = AVC sequence header
|
// 0 = AVC sequence header
|
||||||
// 1 = AVC NALU
|
// 1 = AVC NALU
|
||||||
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
||||||
// not required or supported)
|
// not required or supported)
|
||||||
enum SrsCodecVideoAVCType
|
enum SrsCodecVideoAVCType
|
||||||
{
|
{
|
||||||
SrsCodecVideoAVCTypeReserved = -1,
|
SrsCodecVideoAVCTypeReserved = -1,
|
||||||
|
|
||||||
SrsCodecVideoAVCTypeSequenceHeader = 0,
|
SrsCodecVideoAVCTypeSequenceHeader = 0,
|
||||||
SrsCodecVideoAVCTypeNALU = 1,
|
SrsCodecVideoAVCTypeNALU = 1,
|
||||||
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
|
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
// SoundFormat UB [4]
|
// SoundFormat UB [4]
|
||||||
// Format of SoundData. The following values are defined:
|
// Format of SoundData. The following values are defined:
|
||||||
// 0 = Linear PCM, platform endian
|
// 0 = Linear PCM, platform endian
|
||||||
// 1 = ADPCM
|
// 1 = ADPCM
|
||||||
// 2 = MP3
|
// 2 = MP3
|
||||||
// 3 = Linear PCM, little endian
|
// 3 = Linear PCM, little endian
|
||||||
// 4 = Nellymoser 16 kHz mono
|
// 4 = Nellymoser 16 kHz mono
|
||||||
// 5 = Nellymoser 8 kHz mono
|
// 5 = Nellymoser 8 kHz mono
|
||||||
// 6 = Nellymoser
|
// 6 = Nellymoser
|
||||||
// 7 = G.711 A-law logarithmic PCM
|
// 7 = G.711 A-law logarithmic PCM
|
||||||
// 8 = G.711 mu-law logarithmic PCM
|
// 8 = G.711 mu-law logarithmic PCM
|
||||||
// 9 = reserved
|
// 9 = reserved
|
||||||
// 10 = AAC
|
// 10 = AAC
|
||||||
// 11 = Speex
|
// 11 = Speex
|
||||||
// 14 = MP3 8 kHz
|
// 14 = MP3 8 kHz
|
||||||
// 15 = Device-specific sound
|
// 15 = Device-specific sound
|
||||||
// Formats 7, 8, 14, and 15 are reserved.
|
// Formats 7, 8, 14, and 15 are reserved.
|
||||||
// AAC is supported in Flash Player 9,0,115,0 and higher.
|
// AAC is supported in Flash Player 9,0,115,0 and higher.
|
||||||
// Speex is supported in Flash Player 10 and higher.
|
// Speex is supported in Flash Player 10 and higher.
|
||||||
enum SrsCodecAudio
|
enum SrsCodecAudio
|
||||||
{
|
{
|
||||||
SrsCodecAudioLinearPCMPlatformEndian = 0,
|
SrsCodecAudioLinearPCMPlatformEndian = 0,
|
||||||
SrsCodecAudioADPCM = 1,
|
SrsCodecAudioADPCM = 1,
|
||||||
SrsCodecAudioMP3 = 2,
|
SrsCodecAudioMP3 = 2,
|
||||||
SrsCodecAudioLinearPCMLittleEndian = 3,
|
SrsCodecAudioLinearPCMLittleEndian = 3,
|
||||||
SrsCodecAudioNellymoser16kHzMono = 4,
|
SrsCodecAudioNellymoser16kHzMono = 4,
|
||||||
SrsCodecAudioNellymoser8kHzMono = 5,
|
SrsCodecAudioNellymoser8kHzMono = 5,
|
||||||
SrsCodecAudioNellymoser = 6,
|
SrsCodecAudioNellymoser = 6,
|
||||||
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
|
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
|
||||||
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
|
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
|
||||||
SrsCodecAudioReserved = 9,
|
SrsCodecAudioReserved = 9,
|
||||||
SrsCodecAudioAAC = 10,
|
SrsCodecAudioAAC = 10,
|
||||||
SrsCodecAudioSpeex = 11,
|
SrsCodecAudioSpeex = 11,
|
||||||
SrsCodecAudioReservedMP3_8kHz = 14,
|
SrsCodecAudioReservedMP3_8kHz = 14,
|
||||||
SrsCodecAudioReservedDeviceSpecificSound = 15,
|
SrsCodecAudioReservedDeviceSpecificSound = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
// AACPacketType IF SoundFormat == 10 UI8
|
// AACPacketType IF SoundFormat == 10 UI8
|
||||||
// The following values are defined:
|
// The following values are defined:
|
||||||
// 0 = AAC sequence header
|
// 0 = AAC sequence header
|
||||||
// 1 = AAC raw
|
// 1 = AAC raw
|
||||||
enum SrsCodecAudioType
|
enum SrsCodecAudioType
|
||||||
{
|
{
|
||||||
SrsCodecAudioTypeReserved = -1,
|
SrsCodecAudioTypeReserved = -1,
|
||||||
SrsCodecAudioTypeSequenceHeader = 0,
|
SrsCodecAudioTypeSequenceHeader = 0,
|
||||||
SrsCodecAudioTypeRawData = 1,
|
SrsCodecAudioTypeRawData = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sampling rate. The following values are defined:
|
// Sampling rate. The following values are defined:
|
||||||
|
@ -144,12 +144,12 @@ enum SrsCodecAudioType
|
||||||
// 3 = 44 kHz = 44100 Hz
|
// 3 = 44 kHz = 44100 Hz
|
||||||
enum SrsCodecAudioSampleRate
|
enum SrsCodecAudioSampleRate
|
||||||
{
|
{
|
||||||
SrsCodecAudioSampleRateReserved = -1,
|
SrsCodecAudioSampleRateReserved = -1,
|
||||||
|
|
||||||
SrsCodecAudioSampleRate5512 = 0,
|
SrsCodecAudioSampleRate5512 = 0,
|
||||||
SrsCodecAudioSampleRate11025 = 1,
|
SrsCodecAudioSampleRate11025 = 1,
|
||||||
SrsCodecAudioSampleRate22050 = 2,
|
SrsCodecAudioSampleRate22050 = 2,
|
||||||
SrsCodecAudioSampleRate44100 = 3,
|
SrsCodecAudioSampleRate44100 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Size of each audio sample. This parameter only pertains to
|
// Size of each audio sample. This parameter only pertains to
|
||||||
|
@ -159,10 +159,10 @@ enum SrsCodecAudioSampleRate
|
||||||
// 1 = 16-bit samples
|
// 1 = 16-bit samples
|
||||||
enum SrsCodecAudioSampleSize
|
enum SrsCodecAudioSampleSize
|
||||||
{
|
{
|
||||||
SrsCodecAudioSampleSizeReserved = -1,
|
SrsCodecAudioSampleSizeReserved = -1,
|
||||||
|
|
||||||
SrsCodecAudioSampleSize8bit = 0,
|
SrsCodecAudioSampleSize8bit = 0,
|
||||||
SrsCodecAudioSampleSize16bit = 1,
|
SrsCodecAudioSampleSize16bit = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mono or stereo sound
|
// Mono or stereo sound
|
||||||
|
@ -170,10 +170,10 @@ enum SrsCodecAudioSampleSize
|
||||||
// 1 = Stereo sound
|
// 1 = Stereo sound
|
||||||
enum SrsCodecAudioSoundType
|
enum SrsCodecAudioSoundType
|
||||||
{
|
{
|
||||||
SrsCodecAudioSoundTypeReserved = -1,
|
SrsCodecAudioSoundTypeReserved = -1,
|
||||||
|
|
||||||
SrsCodecAudioSoundTypeMono = 0,
|
SrsCodecAudioSoundTypeMono = 0,
|
||||||
SrsCodecAudioSoundTypeStereo = 1,
|
SrsCodecAudioSoundTypeStereo = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,21 +181,21 @@ enum SrsCodecAudioSoundType
|
||||||
*/
|
*/
|
||||||
struct SrsCodecBuffer
|
struct SrsCodecBuffer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @remark user must manage the bytes.
|
* @remark user must manage the bytes.
|
||||||
*/
|
*/
|
||||||
int size;
|
int size;
|
||||||
char* bytes;
|
char* bytes;
|
||||||
|
|
||||||
SrsCodecBuffer();
|
SrsCodecBuffer();
|
||||||
void append(void* data, int len);
|
void append(void* data, int len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* free the bytes,
|
* free the bytes,
|
||||||
* user can invoke it to free the bytes,
|
* user can invoke it to free the bytes,
|
||||||
* the SrsCodecBuffer never free automatically.
|
* the SrsCodecBuffer never free automatically.
|
||||||
*/
|
*/
|
||||||
void free();
|
void free();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,26 +204,26 @@ struct SrsCodecBuffer
|
||||||
class SrsCodecSample
|
class SrsCodecSample
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int nb_buffers;
|
int nb_buffers;
|
||||||
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
|
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
|
||||||
public:
|
public:
|
||||||
bool is_video;
|
bool is_video;
|
||||||
// video specified
|
// video specified
|
||||||
SrsCodecVideoAVCFrame frame_type;
|
SrsCodecVideoAVCFrame frame_type;
|
||||||
SrsCodecVideoAVCType avc_packet_type;
|
SrsCodecVideoAVCType avc_packet_type;
|
||||||
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
|
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
|
||||||
// cts = pts - dts, where dts = flvheader->timestamp.
|
// cts = pts - dts, where dts = flvheader->timestamp.
|
||||||
int32_t cts;
|
int32_t cts;
|
||||||
// audio specified
|
// audio specified
|
||||||
SrsCodecAudioSampleRate sound_rate;
|
SrsCodecAudioSampleRate sound_rate;
|
||||||
SrsCodecAudioSampleSize sound_size;
|
SrsCodecAudioSampleSize sound_size;
|
||||||
SrsCodecAudioSoundType sound_type;
|
SrsCodecAudioSoundType sound_type;
|
||||||
SrsCodecAudioType aac_packet_type;
|
SrsCodecAudioType aac_packet_type;
|
||||||
public:
|
public:
|
||||||
SrsCodecSample();
|
SrsCodecSample();
|
||||||
virtual ~SrsCodecSample();
|
virtual ~SrsCodecSample();
|
||||||
void clear();
|
void clear();
|
||||||
int add_sample(char* bytes, int size);
|
int add_sample(char* bytes, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,81 +232,81 @@ public:
|
||||||
class SrsCodec
|
class SrsCodec
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsStream* stream;
|
SrsStream* stream;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* video specified
|
* video specified
|
||||||
*/
|
*/
|
||||||
// @see: SrsCodecVideo
|
// @see: SrsCodecVideo
|
||||||
int video_codec_id;
|
int video_codec_id;
|
||||||
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
||||||
u_int8_t avc_profile;
|
u_int8_t avc_profile;
|
||||||
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
|
||||||
u_int8_t avc_level;
|
u_int8_t avc_level;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int video_data_rate; // in bps
|
int video_data_rate; // in bps
|
||||||
int frame_rate;
|
int frame_rate;
|
||||||
int duration;
|
int duration;
|
||||||
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
||||||
int8_t NAL_unit_length;
|
int8_t NAL_unit_length;
|
||||||
u_int16_t sequenceParameterSetLength;
|
u_int16_t sequenceParameterSetLength;
|
||||||
char* sequenceParameterSetNALUnit;
|
char* sequenceParameterSetNALUnit;
|
||||||
u_int16_t pictureParameterSetLength;
|
u_int16_t pictureParameterSetLength;
|
||||||
char* pictureParameterSetNALUnit;
|
char* pictureParameterSetNALUnit;
|
||||||
/**
|
/**
|
||||||
* audio specified
|
* audio specified
|
||||||
*/
|
*/
|
||||||
// @see: SrsCodecAudioType
|
// @see: SrsCodecAudioType
|
||||||
int audio_codec_id;
|
int audio_codec_id;
|
||||||
int audio_data_rate; // in bps
|
int audio_data_rate; // in bps
|
||||||
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
||||||
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
|
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
|
||||||
u_int8_t aac_profile;
|
u_int8_t aac_profile;
|
||||||
// samplingFrequencyIndex
|
// samplingFrequencyIndex
|
||||||
u_int8_t aac_sample_rate;
|
u_int8_t aac_sample_rate;
|
||||||
// channelConfiguration
|
// channelConfiguration
|
||||||
u_int8_t aac_channels;
|
u_int8_t aac_channels;
|
||||||
// the avc extra data, the AVC sequence header,
|
// the avc extra data, the AVC sequence header,
|
||||||
// without the flv codec header,
|
// without the flv codec header,
|
||||||
// @see: ffmpeg, AVCodecContext::extradata
|
// @see: ffmpeg, AVCodecContext::extradata
|
||||||
int avc_extra_size;
|
int avc_extra_size;
|
||||||
char* avc_extra_data;
|
char* avc_extra_data;
|
||||||
// the aac extra data, the AAC sequence header,
|
// the aac extra data, the AAC sequence header,
|
||||||
// without the flv codec header,
|
// without the flv codec header,
|
||||||
// @see: ffmpeg, AVCodecContext::extradata
|
// @see: ffmpeg, AVCodecContext::extradata
|
||||||
int aac_extra_size;
|
int aac_extra_size;
|
||||||
char* aac_extra_data;
|
char* aac_extra_data;
|
||||||
public:
|
public:
|
||||||
SrsCodec();
|
SrsCodec();
|
||||||
virtual ~SrsCodec();
|
virtual ~SrsCodec();
|
||||||
// the following function used for hls to build the codec info.
|
// the following function used for hls to build the codec info.
|
||||||
public:
|
public:
|
||||||
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
|
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
|
||||||
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
|
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
|
||||||
// the following function used to finger out the flv/rtmp packet detail.
|
// the following function used to finger out the flv/rtmp packet detail.
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* only check the frame_type, not check the codec type.
|
* only check the frame_type, not check the codec type.
|
||||||
*/
|
*/
|
||||||
static bool video_is_keyframe(int8_t* data, int size);
|
static bool video_is_keyframe(int8_t* data, int size);
|
||||||
/**
|
/**
|
||||||
* check codec h264, keyframe, sequence header
|
* check codec h264, keyframe, sequence header
|
||||||
*/
|
*/
|
||||||
static bool video_is_sequence_header(int8_t* data, int size);
|
static bool video_is_sequence_header(int8_t* data, int size);
|
||||||
/**
|
/**
|
||||||
* check codec aac, sequence header
|
* check codec aac, sequence header
|
||||||
*/
|
*/
|
||||||
static bool audio_is_sequence_header(int8_t* data, int size);
|
static bool audio_is_sequence_header(int8_t* data, int size);
|
||||||
/**
|
/**
|
||||||
* check codec h264.
|
* check codec h264.
|
||||||
*/
|
*/
|
||||||
static bool video_is_h264(int8_t* data, int size);
|
static bool video_is_h264(int8_t* data, int size);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* check codec aac.
|
* check codec aac.
|
||||||
*/
|
*/
|
||||||
static bool audio_is_aac(int8_t* data, int size);
|
static bool audio_is_aac(int8_t* data, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -66,25 +66,25 @@ class SrsFileBuffer;
|
||||||
class SrsConfDirective
|
class SrsConfDirective
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int conf_line;
|
int conf_line;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
std::vector<SrsConfDirective*> directives;
|
std::vector<SrsConfDirective*> directives;
|
||||||
public:
|
public:
|
||||||
SrsConfDirective();
|
SrsConfDirective();
|
||||||
virtual ~SrsConfDirective();
|
virtual ~SrsConfDirective();
|
||||||
std::string arg0();
|
std::string arg0();
|
||||||
std::string arg1();
|
std::string arg1();
|
||||||
std::string arg2();
|
std::string arg2();
|
||||||
SrsConfDirective* at(int index);
|
SrsConfDirective* at(int index);
|
||||||
SrsConfDirective* get(std::string _name);
|
SrsConfDirective* get(std::string _name);
|
||||||
SrsConfDirective* get(std::string _name, std::string _arg0);
|
SrsConfDirective* get(std::string _name, std::string _arg0);
|
||||||
public:
|
public:
|
||||||
virtual int parse(const char* filename);
|
virtual int parse(const char* filename);
|
||||||
public:
|
public:
|
||||||
enum SrsDirectiveType{parse_file, parse_block};
|
enum SrsDirectiveType{parse_file, parse_block};
|
||||||
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
|
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
|
||||||
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
|
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,81 +97,81 @@ public:
|
||||||
class SrsConfig
|
class SrsConfig
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool show_help;
|
bool show_help;
|
||||||
bool show_version;
|
bool show_version;
|
||||||
std::string config_file;
|
std::string config_file;
|
||||||
SrsConfDirective* root;
|
SrsConfDirective* root;
|
||||||
std::vector<ISrsReloadHandler*> subscribes;
|
std::vector<ISrsReloadHandler*> subscribes;
|
||||||
public:
|
public:
|
||||||
SrsConfig();
|
SrsConfig();
|
||||||
virtual ~SrsConfig();
|
virtual ~SrsConfig();
|
||||||
public:
|
public:
|
||||||
virtual int reload();
|
virtual int reload();
|
||||||
virtual void subscribe(ISrsReloadHandler* handler);
|
virtual void subscribe(ISrsReloadHandler* handler);
|
||||||
virtual void unsubscribe(ISrsReloadHandler* handler);
|
virtual void unsubscribe(ISrsReloadHandler* handler);
|
||||||
public:
|
public:
|
||||||
virtual int parse_options(int argc, char** argv);
|
virtual int parse_options(int argc, char** argv);
|
||||||
private:
|
private:
|
||||||
virtual int parse_file(const char* filename);
|
virtual int parse_file(const char* filename);
|
||||||
virtual int parse_argv(int& i, char** argv);
|
virtual int parse_argv(int& i, char** argv);
|
||||||
virtual void print_help(char** argv);
|
virtual void print_help(char** argv);
|
||||||
public:
|
public:
|
||||||
virtual SrsConfDirective* get_vhost(std::string vhost);
|
virtual SrsConfDirective* get_vhost(std::string vhost);
|
||||||
virtual bool get_vhost_enabled(std::string vhost);
|
virtual bool get_vhost_enabled(std::string vhost);
|
||||||
virtual bool get_vhost_enabled(SrsConfDirective* vhost);
|
virtual bool get_vhost_enabled(SrsConfDirective* vhost);
|
||||||
virtual SrsConfDirective* get_vhost_on_connect(std::string vhost);
|
virtual SrsConfDirective* get_vhost_on_connect(std::string vhost);
|
||||||
virtual SrsConfDirective* get_vhost_on_close(std::string vhost);
|
virtual SrsConfDirective* get_vhost_on_close(std::string vhost);
|
||||||
virtual SrsConfDirective* get_vhost_on_publish(std::string vhost);
|
virtual SrsConfDirective* get_vhost_on_publish(std::string vhost);
|
||||||
virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);
|
virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);
|
||||||
virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
|
virtual SrsConfDirective* get_vhost_on_play(std::string vhost);
|
||||||
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
|
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
|
||||||
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
|
virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
|
||||||
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
|
virtual bool get_transcode_enabled(SrsConfDirective* transcode);
|
||||||
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
|
virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
|
||||||
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
|
virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
|
||||||
virtual bool get_engine_enabled(SrsConfDirective* engine);
|
virtual bool get_engine_enabled(SrsConfDirective* engine);
|
||||||
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
|
virtual std::string get_engine_vcodec(SrsConfDirective* engine);
|
||||||
virtual int get_engine_vbitrate(SrsConfDirective* engine);
|
virtual int get_engine_vbitrate(SrsConfDirective* engine);
|
||||||
virtual double get_engine_vfps(SrsConfDirective* engine);
|
virtual double get_engine_vfps(SrsConfDirective* engine);
|
||||||
virtual int get_engine_vwidth(SrsConfDirective* engine);
|
virtual int get_engine_vwidth(SrsConfDirective* engine);
|
||||||
virtual int get_engine_vheight(SrsConfDirective* engine);
|
virtual int get_engine_vheight(SrsConfDirective* engine);
|
||||||
virtual int get_engine_vthreads(SrsConfDirective* engine);
|
virtual int get_engine_vthreads(SrsConfDirective* engine);
|
||||||
virtual std::string get_engine_vprofile(SrsConfDirective* engine);
|
virtual std::string get_engine_vprofile(SrsConfDirective* engine);
|
||||||
virtual std::string get_engine_vpreset(SrsConfDirective* engine);
|
virtual std::string get_engine_vpreset(SrsConfDirective* engine);
|
||||||
virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams);
|
virtual void get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams);
|
||||||
virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
|
virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter);
|
||||||
virtual std::string get_engine_acodec(SrsConfDirective* engine);
|
virtual std::string get_engine_acodec(SrsConfDirective* engine);
|
||||||
virtual int get_engine_abitrate(SrsConfDirective* engine);
|
virtual int get_engine_abitrate(SrsConfDirective* engine);
|
||||||
virtual int get_engine_asample_rate(SrsConfDirective* engine);
|
virtual int get_engine_asample_rate(SrsConfDirective* engine);
|
||||||
virtual int get_engine_achannels(SrsConfDirective* engine);
|
virtual int get_engine_achannels(SrsConfDirective* engine);
|
||||||
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
|
virtual void get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams);
|
||||||
virtual std::string get_engine_output(SrsConfDirective* engine);
|
virtual std::string get_engine_output(SrsConfDirective* engine);
|
||||||
virtual std::string get_log_dir();
|
virtual std::string get_log_dir();
|
||||||
virtual int get_max_connections();
|
virtual int get_max_connections();
|
||||||
virtual bool get_gop_cache(std::string vhost);
|
virtual bool get_gop_cache(std::string vhost);
|
||||||
virtual double get_queue_length(std::string vhost);
|
virtual double get_queue_length(std::string vhost);
|
||||||
virtual SrsConfDirective* get_forward(std::string vhost);
|
virtual SrsConfDirective* get_forward(std::string vhost);
|
||||||
private:
|
private:
|
||||||
virtual SrsConfDirective* get_hls(std::string vhost);
|
virtual SrsConfDirective* get_hls(std::string vhost);
|
||||||
public:
|
public:
|
||||||
virtual bool get_hls_enabled(std::string vhost);
|
virtual bool get_hls_enabled(std::string vhost);
|
||||||
virtual std::string get_hls_path(std::string vhost);
|
virtual std::string get_hls_path(std::string vhost);
|
||||||
virtual double get_hls_fragment(std::string vhost);
|
virtual double get_hls_fragment(std::string vhost);
|
||||||
virtual double get_hls_window(std::string vhost);
|
virtual double get_hls_window(std::string vhost);
|
||||||
virtual SrsConfDirective* get_refer(std::string vhost);
|
virtual SrsConfDirective* get_refer(std::string vhost);
|
||||||
virtual SrsConfDirective* get_refer_play(std::string vhost);
|
virtual SrsConfDirective* get_refer_play(std::string vhost);
|
||||||
virtual SrsConfDirective* get_refer_publish(std::string vhost);
|
virtual SrsConfDirective* get_refer_publish(std::string vhost);
|
||||||
virtual SrsConfDirective* get_listen();
|
virtual SrsConfDirective* get_listen();
|
||||||
virtual int get_chunk_size(const std::string& vhost);
|
virtual int get_chunk_size(const std::string& vhost);
|
||||||
virtual int get_pithy_print_publish();
|
virtual int get_pithy_print_publish();
|
||||||
virtual int get_pithy_print_forwarder();
|
virtual int get_pithy_print_forwarder();
|
||||||
virtual int get_pithy_print_encoder();
|
virtual int get_pithy_print_encoder();
|
||||||
virtual int get_pithy_print_hls();
|
virtual int get_pithy_print_hls();
|
||||||
virtual int get_pithy_print_play();
|
virtual int get_pithy_print_play();
|
||||||
virtual bool get_bw_check_enabled(const std::string& vhost);
|
virtual bool get_bw_check_enabled(const std::string& vhost);
|
||||||
virtual std::string get_bw_check_key(const std::string& vhost);
|
virtual std::string get_bw_check_key(const std::string& vhost);
|
||||||
virtual int get_bw_check_interval_ms(const std::string& vhost);
|
virtual int get_bw_check_interval_ms(const std::string& vhost);
|
||||||
virtual int get_bw_check_limit_kbps(const std::string& vhost);
|
virtual int get_bw_check_limit_kbps(const std::string& vhost);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,19 +29,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd)
|
SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd)
|
||||||
{
|
{
|
||||||
server = srs_server;
|
server = srs_server;
|
||||||
stfd = client_stfd;
|
stfd = client_stfd;
|
||||||
connection_id = 0;
|
connection_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConnection::~SrsConnection()
|
SrsConnection::~SrsConnection()
|
||||||
{
|
{
|
||||||
srs_close_stfd(stfd);
|
srs_close_stfd(stfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsConnection::start()
|
int SrsConnection::start()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (st_thread_create(cycle_thread, this, 0, 0) == NULL) {
|
if (st_thread_create(cycle_thread, this, 0, 0) == NULL) {
|
||||||
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
||||||
|
@ -49,44 +49,44 @@ int SrsConnection::start()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("create st conn cycle thread success.");
|
srs_verbose("create st conn cycle thread success.");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsConnection::cycle()
|
void SrsConnection::cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
_srs_context->generate_id();
|
|
||||||
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.
|
_srs_context->generate_id();
|
||||||
if (ret == ERROR_SUCCESS) {
|
connection_id = _srs_context->get_id();
|
||||||
srs_trace("client process normally finished. ret=%d", ret);
|
|
||||||
}
|
ret = do_cycle();
|
||||||
|
|
||||||
// client close peer.
|
// if socket io error, set to closed.
|
||||||
if (ret == ERROR_SOCKET_CLOSED) {
|
if (srs_is_client_gracefully_close(ret)) {
|
||||||
srs_warn("client disconnect peer. ret=%d", ret);
|
ret = ERROR_SOCKET_CLOSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
server->remove(this);
|
// 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)
|
void* SrsConnection::cycle_thread(void* arg)
|
||||||
{
|
{
|
||||||
SrsConnection* conn = (SrsConnection*)arg;
|
SrsConnection* conn = (SrsConnection*)arg;
|
||||||
srs_assert(conn != NULL);
|
srs_assert(conn != NULL);
|
||||||
|
|
||||||
conn->cycle();
|
conn->cycle();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,19 +36,19 @@ class SrsServer;
|
||||||
class SrsConnection
|
class SrsConnection
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
SrsServer* server;
|
SrsServer* server;
|
||||||
st_netfd_t stfd;
|
st_netfd_t stfd;
|
||||||
int connection_id;
|
int connection_id;
|
||||||
public:
|
public:
|
||||||
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
|
SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd);
|
||||||
virtual ~SrsConnection();
|
virtual ~SrsConnection();
|
||||||
public:
|
public:
|
||||||
virtual int start();
|
virtual int start();
|
||||||
protected:
|
protected:
|
||||||
virtual int do_cycle() = 0;
|
virtual int do_cycle() = 0;
|
||||||
private:
|
private:
|
||||||
virtual void cycle();
|
virtual void cycle();
|
||||||
static void* cycle_thread(void* arg);
|
static void* cycle_thread(void* arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -47,38 +47,38 @@ class SrsPithyPrint;
|
||||||
class SrsFFMPEG
|
class SrsFFMPEG
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool started;
|
bool started;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
private:
|
private:
|
||||||
std::string log_file;
|
std::string log_file;
|
||||||
int log_fd;
|
int log_fd;
|
||||||
private:
|
private:
|
||||||
std::string ffmpeg;
|
std::string ffmpeg;
|
||||||
std::vector<std::string> vfilter;
|
std::vector<std::string> vfilter;
|
||||||
std::string vcodec;
|
std::string vcodec;
|
||||||
int vbitrate;
|
int vbitrate;
|
||||||
double vfps;
|
double vfps;
|
||||||
int vwidth;
|
int vwidth;
|
||||||
int vheight;
|
int vheight;
|
||||||
int vthreads;
|
int vthreads;
|
||||||
std::string vprofile;
|
std::string vprofile;
|
||||||
std::string vpreset;
|
std::string vpreset;
|
||||||
std::vector<std::string> vparams;
|
std::vector<std::string> vparams;
|
||||||
std::string acodec;
|
std::string acodec;
|
||||||
int abitrate;
|
int abitrate;
|
||||||
int asample_rate;
|
int asample_rate;
|
||||||
int achannels;
|
int achannels;
|
||||||
std::vector<std::string> aparams;
|
std::vector<std::string> aparams;
|
||||||
std::string output;
|
std::string output;
|
||||||
std::string input;
|
std::string input;
|
||||||
public:
|
public:
|
||||||
SrsFFMPEG(std::string ffmpeg_bin);
|
SrsFFMPEG(std::string ffmpeg_bin);
|
||||||
virtual ~SrsFFMPEG();
|
virtual ~SrsFFMPEG();
|
||||||
public:
|
public:
|
||||||
virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
|
virtual int initialize(SrsRequest* req, SrsConfDirective* engine);
|
||||||
virtual int start();
|
virtual int start();
|
||||||
virtual int cycle();
|
virtual int cycle();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,26 +88,26 @@ public:
|
||||||
class SrsEncoder : public ISrsThreadHandler
|
class SrsEncoder : public ISrsThreadHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<SrsFFMPEG*> ffmpegs;
|
std::vector<SrsFFMPEG*> ffmpegs;
|
||||||
private:
|
private:
|
||||||
SrsThread* pthread;
|
SrsThread* pthread;
|
||||||
SrsPithyPrint* pithy_print;
|
SrsPithyPrint* pithy_print;
|
||||||
public:
|
public:
|
||||||
SrsEncoder();
|
SrsEncoder();
|
||||||
virtual ~SrsEncoder();
|
virtual ~SrsEncoder();
|
||||||
public:
|
public:
|
||||||
virtual int on_publish(SrsRequest* req);
|
virtual int on_publish(SrsRequest* req);
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
// interface ISrsThreadHandler.
|
// interface ISrsThreadHandler.
|
||||||
public:
|
public:
|
||||||
virtual int cycle();
|
virtual int cycle();
|
||||||
virtual void on_leave_loop();
|
virtual void on_leave_loop();
|
||||||
private:
|
private:
|
||||||
virtual void clear_engines();
|
virtual void clear_engines();
|
||||||
virtual SrsFFMPEG* at(int index);
|
virtual SrsFFMPEG* at(int index);
|
||||||
virtual int parse_scope_engines(SrsRequest* req);
|
virtual int parse_scope_engines(SrsRequest* req);
|
||||||
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
|
virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf);
|
||||||
virtual void encoder();
|
virtual void encoder();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,203 +42,203 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
SrsForwarder::SrsForwarder(SrsSource* _source)
|
SrsForwarder::SrsForwarder(SrsSource* _source)
|
||||||
{
|
{
|
||||||
source = _source;
|
source = _source;
|
||||||
|
|
||||||
io = NULL;
|
io = NULL;
|
||||||
client = NULL;
|
client = NULL;
|
||||||
stfd = NULL;
|
stfd = NULL;
|
||||||
stream_id = 0;
|
stream_id = 0;
|
||||||
|
|
||||||
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
|
pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US);
|
||||||
queue = new SrsMessageQueue();
|
queue = new SrsMessageQueue();
|
||||||
jitter = new SrsRtmpJitter();
|
jitter = new SrsRtmpJitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsForwarder::~SrsForwarder()
|
SrsForwarder::~SrsForwarder()
|
||||||
{
|
{
|
||||||
on_unpublish();
|
on_unpublish();
|
||||||
|
|
||||||
srs_freep(pthread);
|
srs_freep(pthread);
|
||||||
srs_freep(queue);
|
srs_freep(queue);
|
||||||
srs_freep(jitter);
|
srs_freep(jitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsForwarder::set_queue_size(double queue_size)
|
void SrsForwarder::set_queue_size(double queue_size)
|
||||||
{
|
{
|
||||||
queue->set_queue_size(queue_size);
|
queue->set_queue_size(queue_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server)
|
int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// forward app
|
// forward app
|
||||||
app = req->app;
|
app = req->app;
|
||||||
|
|
||||||
stream_name = req->stream;
|
stream_name = req->stream;
|
||||||
server = forward_server;
|
server = forward_server;
|
||||||
std::string s_port = RTMP_DEFAULT_PORT;
|
std::string s_port = RTMP_DEFAULT_PORT;
|
||||||
port = ::atoi(RTMP_DEFAULT_PORT);
|
port = ::atoi(RTMP_DEFAULT_PORT);
|
||||||
|
|
||||||
size_t pos = forward_server.find(":");
|
size_t pos = forward_server.find(":");
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
s_port = forward_server.substr(pos + 1);
|
s_port = forward_server.substr(pos + 1);
|
||||||
server = forward_server.substr(0, pos);
|
server = forward_server.substr(0, pos);
|
||||||
}
|
}
|
||||||
// discovery vhost
|
// discovery vhost
|
||||||
std::string vhost = req->vhost;
|
std::string vhost = req->vhost;
|
||||||
srs_vhost_resolve(vhost, s_port);
|
srs_vhost_resolve(vhost, s_port);
|
||||||
port = ::atoi(s_port.c_str());
|
port = ::atoi(s_port.c_str());
|
||||||
|
|
||||||
// generate tcUrl
|
// generate tcUrl
|
||||||
tc_url = "rtmp://";
|
tc_url = "rtmp://";
|
||||||
tc_url += vhost;
|
tc_url += vhost;
|
||||||
tc_url += "/";
|
tc_url += "/";
|
||||||
tc_url += req->app;
|
tc_url += req->app;
|
||||||
|
|
||||||
// dead loop check
|
// dead loop check
|
||||||
std::string source_ep = req->vhost;
|
std::string source_ep = req->vhost;
|
||||||
source_ep += ":";
|
source_ep += ":";
|
||||||
source_ep += req->port;
|
source_ep += req->port;
|
||||||
|
|
||||||
std::string dest_ep = vhost;
|
std::string dest_ep = vhost;
|
||||||
dest_ep += ":";
|
dest_ep += ":";
|
||||||
dest_ep += s_port;
|
dest_ep += s_port;
|
||||||
|
|
||||||
if (source_ep == dest_ep) {
|
if (source_ep == dest_ep) {
|
||||||
ret = ERROR_SYSTEM_FORWARD_LOOP;
|
ret = ERROR_SYSTEM_FORWARD_LOOP;
|
||||||
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
|
srs_warn("farder loop detected. src=%s, dest=%s, ret=%d",
|
||||||
source_ep.c_str(), dest_ep.c_str(), ret);
|
source_ep.c_str(), dest_ep.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_trace("start forward %s to %s, stream: %s/%s",
|
srs_trace("start forward %s to %s, stream: %s/%s",
|
||||||
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
|
source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(),
|
||||||
stream_name.c_str());
|
stream_name.c_str());
|
||||||
|
|
||||||
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
||||||
srs_error("start srs thread failed. ret=%d", ret);
|
srs_error("start srs thread failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsForwarder::on_unpublish()
|
void SrsForwarder::on_unpublish()
|
||||||
{
|
{
|
||||||
pthread->stop();
|
pthread->stop();
|
||||||
|
|
||||||
close_underlayer_socket();
|
close_underlayer_socket();
|
||||||
|
|
||||||
srs_freep(client);
|
srs_freep(client);
|
||||||
srs_freep(io);
|
srs_freep(io);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
|
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) {
|
||||||
srs_freep(metadata);
|
srs_freep(metadata);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
|
if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
|
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
||||||
srs_freep(msg);
|
srs_freep(msg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
|
int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) {
|
||||||
srs_freep(msg);
|
srs_freep(msg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::cycle()
|
int SrsForwarder::cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = connect_server()) != ERROR_SUCCESS) {
|
if ((ret = connect_server()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_assert(client);
|
srs_assert(client);
|
||||||
|
|
||||||
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
|
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
|
||||||
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
|
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
|
||||||
|
|
||||||
if ((ret = client->handshake()) != ERROR_SUCCESS) {
|
if ((ret = client->handshake()) != ERROR_SUCCESS) {
|
||||||
srs_error("handshake with server failed. ret=%d", ret);
|
srs_error("handshake with server failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
|
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
|
||||||
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
|
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
|
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
|
||||||
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
|
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
|
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
|
||||||
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
|
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
|
||||||
stream_name.c_str(), stream_id, ret);
|
stream_name.c_str(), stream_id, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
|
if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) {
|
||||||
srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
|
srs_error("callback the source to feed the sequence header failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = forward()) != ERROR_SUCCESS) {
|
if ((ret = forward()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsForwarder::close_underlayer_socket()
|
void SrsForwarder::close_underlayer_socket()
|
||||||
{
|
{
|
||||||
srs_close_stfd(stfd);
|
srs_close_stfd(stfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::connect_server()
|
int SrsForwarder::connect_server()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// reopen
|
// reopen
|
||||||
close_underlayer_socket();
|
close_underlayer_socket();
|
||||||
|
|
||||||
// open socket.
|
// open socket.
|
||||||
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
|
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
|
||||||
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
|
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
|
||||||
|
|
||||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if(sock == -1){
|
if(sock == -1){
|
||||||
|
@ -255,20 +255,20 @@ int SrsForwarder::connect_server()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_freep(client);
|
srs_freep(client);
|
||||||
srs_freep(io);
|
srs_freep(io);
|
||||||
|
|
||||||
io = new SrsSocket(stfd);
|
io = new SrsSocket(stfd);
|
||||||
client = new SrsRtmpClient(io);
|
client = new SrsRtmpClient(io);
|
||||||
|
|
||||||
// connect to server.
|
// connect to server.
|
||||||
std::string ip = srs_dns_resolve(server);
|
std::string ip = srs_dns_resolve(server);
|
||||||
if (ip.empty()) {
|
if (ip.empty()) {
|
||||||
ret = ERROR_SYSTEM_IP_INVALID;
|
ret = ERROR_SYSTEM_IP_INVALID;
|
||||||
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_in addr;
|
sockaddr_in addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(port);
|
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);
|
srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsForwarder::forward()
|
int SrsForwarder::forward()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
|
client->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
|
||||||
|
|
||||||
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
|
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
|
||||||
|
|
||||||
while (pthread->can_loop()) {
|
while (pthread->can_loop()) {
|
||||||
// switch to other st-threads.
|
// switch to other st-threads.
|
||||||
st_usleep(0);
|
st_usleep(0);
|
||||||
|
|
||||||
// read from client.
|
// read from client.
|
||||||
if (true) {
|
if (true) {
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
ret = client->recv_message(&msg);
|
ret = client->recv_message(&msg);
|
||||||
|
|
||||||
srs_verbose("play loop recv message. ret=%d", ret);
|
srs_verbose("play loop recv message. ret=%d", ret);
|
||||||
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
|
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
|
||||||
srs_error("recv server control message failed. ret=%d", ret);
|
srs_error("recv server control message failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// forward all messages.
|
// forward all messages.
|
||||||
int count = 0;
|
int count = 0;
|
||||||
SrsSharedPtrMessage** msgs = NULL;
|
SrsSharedPtrMessage** msgs = NULL;
|
||||||
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
|
if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
|
||||||
srs_error("get message to forward failed. ret=%d", ret);
|
srs_error("get message to forward failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore when no messages.
|
// ignore when no messages.
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
srs_verbose("no packets to forward.");
|
srs_verbose("no packets to forward.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
|
SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
|
||||||
|
|
||||||
// pithy print
|
// pithy print
|
||||||
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
|
pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
|
||||||
if (pithy_print.can_print()) {
|
if (pithy_print.can_print()) {
|
||||||
srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
|
srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
|
||||||
pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
|
pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
|
||||||
}
|
}
|
||||||
|
|
||||||
// all msgs to forward.
|
// all msgs to forward.
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
SrsSharedPtrMessage* msg = msgs[i];
|
SrsSharedPtrMessage* msg = msgs[i];
|
||||||
|
|
||||||
srs_assert(msg);
|
srs_assert(msg);
|
||||||
msgs[i] = NULL;
|
msgs[i] = NULL;
|
||||||
|
|
||||||
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
srs_error("forwarder send message to server failed. ret=%d", ret);
|
srs_error("forwarder send message to server failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,39 +49,39 @@ class SrsSource;
|
||||||
class SrsForwarder : public ISrsThreadHandler
|
class SrsForwarder : public ISrsThreadHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::string app;
|
std::string app;
|
||||||
std::string tc_url;
|
std::string tc_url;
|
||||||
std::string stream_name;
|
std::string stream_name;
|
||||||
int stream_id;
|
int stream_id;
|
||||||
std::string server;
|
std::string server;
|
||||||
int port;
|
int port;
|
||||||
private:
|
private:
|
||||||
st_netfd_t stfd;
|
st_netfd_t stfd;
|
||||||
SrsThread* pthread;
|
SrsThread* pthread;
|
||||||
private:
|
private:
|
||||||
SrsSource* source;
|
SrsSource* source;
|
||||||
ISrsProtocolReaderWriter* io;
|
ISrsProtocolReaderWriter* io;
|
||||||
SrsRtmpClient* client;
|
SrsRtmpClient* client;
|
||||||
SrsRtmpJitter* jitter;
|
SrsRtmpJitter* jitter;
|
||||||
SrsMessageQueue* queue;
|
SrsMessageQueue* queue;
|
||||||
public:
|
public:
|
||||||
SrsForwarder(SrsSource* _source);
|
SrsForwarder(SrsSource* _source);
|
||||||
virtual ~SrsForwarder();
|
virtual ~SrsForwarder();
|
||||||
public:
|
public:
|
||||||
virtual void set_queue_size(double queue_size);
|
virtual void set_queue_size(double queue_size);
|
||||||
public:
|
public:
|
||||||
virtual int on_publish(SrsRequest* req, std::string forward_server);
|
virtual int on_publish(SrsRequest* req, std::string forward_server);
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
|
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
|
||||||
virtual int on_audio(SrsSharedPtrMessage* msg);
|
virtual int on_audio(SrsSharedPtrMessage* msg);
|
||||||
virtual int on_video(SrsSharedPtrMessage* msg);
|
virtual int on_video(SrsSharedPtrMessage* msg);
|
||||||
// interface ISrsThreadHandler.
|
// interface ISrsThreadHandler.
|
||||||
public:
|
public:
|
||||||
virtual int cycle();
|
virtual int cycle();
|
||||||
private:
|
private:
|
||||||
virtual void close_underlayer_socket();
|
virtual void close_underlayer_socket();
|
||||||
virtual int connect_server();
|
virtual int connect_server();
|
||||||
virtual int forward();
|
virtual int forward();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,40 +56,40 @@ class SrsSource;
|
||||||
class SrsHlsAacJitter
|
class SrsHlsAacJitter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int64_t base_pts;
|
int64_t base_pts;
|
||||||
int64_t nb_samples;
|
int64_t nb_samples;
|
||||||
int sync_ms;
|
int sync_ms;
|
||||||
public:
|
public:
|
||||||
SrsHlsAacJitter();
|
SrsHlsAacJitter();
|
||||||
virtual ~SrsHlsAacJitter();
|
virtual ~SrsHlsAacJitter();
|
||||||
/**
|
/**
|
||||||
* when buffer start, calc the "correct" pts for ts,
|
* when buffer start, calc the "correct" pts for ts,
|
||||||
* @param flv_pts, the flv pts calc from flv header timestamp,
|
* @param flv_pts, the flv pts calc from flv header timestamp,
|
||||||
* @return the calc correct pts.
|
* @return the calc correct pts.
|
||||||
*/
|
*/
|
||||||
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
|
virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate);
|
||||||
/**
|
/**
|
||||||
* when buffer continue, muxer donot write to file,
|
* when buffer continue, muxer donot write to file,
|
||||||
* the audio buffer continue grow and donot need a pts,
|
* the audio buffer continue grow and donot need a pts,
|
||||||
* for the ts audio PES packet only has one pts at the first time.
|
* for the ts audio PES packet only has one pts at the first time.
|
||||||
*/
|
*/
|
||||||
virtual void on_buffer_continue();
|
virtual void on_buffer_continue();
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: refine the ts muxer, do more jobs.
|
//TODO: refine the ts muxer, do more jobs.
|
||||||
class SrsTSMuxer
|
class SrsTSMuxer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int fd;
|
int fd;
|
||||||
std::string path;
|
std::string path;
|
||||||
public:
|
public:
|
||||||
SrsTSMuxer();
|
SrsTSMuxer();
|
||||||
virtual ~SrsTSMuxer();
|
virtual ~SrsTSMuxer();
|
||||||
public:
|
public:
|
||||||
virtual int open(std::string _path);
|
virtual int open(std::string _path);
|
||||||
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
||||||
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,26 +98,26 @@ public:
|
||||||
*/
|
*/
|
||||||
struct SrsM3u8Segment
|
struct SrsM3u8Segment
|
||||||
{
|
{
|
||||||
// duration in seconds in m3u8.
|
// duration in seconds in m3u8.
|
||||||
double duration;
|
double duration;
|
||||||
// sequence number in m3u8.
|
// sequence number in m3u8.
|
||||||
int sequence_no;
|
int sequence_no;
|
||||||
// ts uri in m3u8.
|
// ts uri in m3u8.
|
||||||
std::string uri;
|
std::string uri;
|
||||||
// ts full file to write.
|
// ts full file to write.
|
||||||
std::string full_path;
|
std::string full_path;
|
||||||
// the muxer to write ts.
|
// the muxer to write ts.
|
||||||
SrsTSMuxer* muxer;
|
SrsTSMuxer* muxer;
|
||||||
// current segment start dts for m3u8
|
// current segment start dts for m3u8
|
||||||
int64_t segment_start_dts;
|
int64_t segment_start_dts;
|
||||||
|
|
||||||
SrsM3u8Segment();
|
SrsM3u8Segment();
|
||||||
virtual ~SrsM3u8Segment();
|
virtual ~SrsM3u8Segment();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update the segment duration.
|
* update the segment duration.
|
||||||
*/
|
*/
|
||||||
virtual double update_duration(int64_t video_stream_dts);
|
virtual double update_duration(int64_t video_stream_dts);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,39 +126,39 @@ struct SrsM3u8Segment
|
||||||
class SrsM3u8Muxer
|
class SrsM3u8Muxer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::string app;
|
std::string app;
|
||||||
std::string stream;
|
std::string stream;
|
||||||
private:
|
private:
|
||||||
std::string hls_path;
|
std::string hls_path;
|
||||||
int hls_fragment;
|
int hls_fragment;
|
||||||
int hls_window;
|
int hls_window;
|
||||||
private:
|
private:
|
||||||
int file_index;
|
int file_index;
|
||||||
std::string m3u8;
|
std::string m3u8;
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* m3u8 segments.
|
* m3u8 segments.
|
||||||
*/
|
*/
|
||||||
std::vector<SrsM3u8Segment*> segments;
|
std::vector<SrsM3u8Segment*> segments;
|
||||||
/**
|
/**
|
||||||
* current writing segment.
|
* current writing segment.
|
||||||
*/
|
*/
|
||||||
SrsM3u8Segment* current;
|
SrsM3u8Segment* current;
|
||||||
// last known dts
|
// last known dts
|
||||||
int64_t video_stream_dts;
|
int64_t video_stream_dts;
|
||||||
public:
|
public:
|
||||||
SrsM3u8Muxer();
|
SrsM3u8Muxer();
|
||||||
virtual ~SrsM3u8Muxer();
|
virtual ~SrsM3u8Muxer();
|
||||||
public:
|
public:
|
||||||
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
|
virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window);
|
||||||
virtual int segment_open();
|
virtual int segment_open();
|
||||||
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab);
|
||||||
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb);
|
||||||
virtual int segment_close();
|
virtual int segment_close();
|
||||||
private:
|
private:
|
||||||
virtual int refresh_m3u8();
|
virtual int refresh_m3u8();
|
||||||
virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
|
virtual int _refresh_m3u8(int& fd, std::string m3u8_file);
|
||||||
virtual int create_dir();
|
virtual int create_dir();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,35 +167,35 @@ private:
|
||||||
class SrsTSCache
|
class SrsTSCache
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// current frame and buffer
|
// current frame and buffer
|
||||||
SrsMpegtsFrame* af;
|
SrsMpegtsFrame* af;
|
||||||
SrsCodecBuffer* ab;
|
SrsCodecBuffer* ab;
|
||||||
SrsMpegtsFrame* vf;
|
SrsMpegtsFrame* vf;
|
||||||
SrsCodecBuffer* vb;
|
SrsCodecBuffer* vb;
|
||||||
private:
|
private:
|
||||||
// the audio cache buffer start pts, to flush audio if full.
|
// the audio cache buffer start pts, to flush audio if full.
|
||||||
int64_t audio_buffer_start_pts;
|
int64_t audio_buffer_start_pts;
|
||||||
// time jitter for aac
|
// time jitter for aac
|
||||||
SrsHlsAacJitter* aac_jitter;
|
SrsHlsAacJitter* aac_jitter;
|
||||||
public:
|
public:
|
||||||
SrsTSCache();
|
SrsTSCache();
|
||||||
virtual ~SrsTSCache();
|
virtual ~SrsTSCache();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* write audio to cache, if need to flush, flush to muxer.
|
* write audio to cache, if need to flush, flush to muxer.
|
||||||
*/
|
*/
|
||||||
virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample);
|
virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample);
|
||||||
/**
|
/**
|
||||||
* write video to muxer.
|
* write video to muxer.
|
||||||
*/
|
*/
|
||||||
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
|
virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample);
|
||||||
/**
|
/**
|
||||||
* flush audio in cache to muxer.
|
* flush audio in cache to muxer.
|
||||||
*/
|
*/
|
||||||
virtual int flush_audio(SrsM3u8Muxer* muxer);
|
virtual int flush_audio(SrsM3u8Muxer* muxer);
|
||||||
private:
|
private:
|
||||||
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
|
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
|
||||||
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
|
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,43 +204,43 @@ private:
|
||||||
class SrsHls
|
class SrsHls
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsM3u8Muxer* muxer;
|
SrsM3u8Muxer* muxer;
|
||||||
SrsTSCache* ts_cache;
|
SrsTSCache* ts_cache;
|
||||||
private:
|
private:
|
||||||
bool hls_enabled;
|
bool hls_enabled;
|
||||||
SrsSource* source;
|
SrsSource* source;
|
||||||
SrsCodec* codec;
|
SrsCodec* codec;
|
||||||
SrsCodecSample* sample;
|
SrsCodecSample* sample;
|
||||||
SrsRtmpJitter* jitter;
|
SrsRtmpJitter* jitter;
|
||||||
SrsPithyPrint* pithy_print;
|
SrsPithyPrint* pithy_print;
|
||||||
public:
|
public:
|
||||||
SrsHls(SrsSource* _source);
|
SrsHls(SrsSource* _source);
|
||||||
virtual ~SrsHls();
|
virtual ~SrsHls();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* publish stream event, continue to write the m3u8,
|
* publish stream event, continue to write the m3u8,
|
||||||
* for the muxer object not destroyed.
|
* for the muxer object not destroyed.
|
||||||
*/
|
*/
|
||||||
virtual int on_publish(SrsRequest* req);
|
virtual int on_publish(SrsRequest* req);
|
||||||
/**
|
/**
|
||||||
* the unpublish event, only close the muxer, donot destroy the
|
* the unpublish event, only close the muxer, donot destroy the
|
||||||
* muxer, for when we continue to publish, the m3u8 will continue.
|
* muxer, for when we continue to publish, the m3u8 will continue.
|
||||||
*/
|
*/
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
/**
|
/**
|
||||||
* get some information from metadata, it's optinal.
|
* get some information from metadata, it's optinal.
|
||||||
*/
|
*/
|
||||||
virtual int on_meta_data(SrsAmf0Object* metadata);
|
virtual int on_meta_data(SrsAmf0Object* metadata);
|
||||||
/**
|
/**
|
||||||
* mux the audio packets to ts.
|
* mux the audio packets to ts.
|
||||||
*/
|
*/
|
||||||
virtual int on_audio(SrsSharedPtrMessage* audio);
|
virtual int on_audio(SrsSharedPtrMessage* audio);
|
||||||
/**
|
/**
|
||||||
* mux the video packets to ts.
|
* mux the video packets to ts.
|
||||||
*/
|
*/
|
||||||
virtual int on_video(SrsSharedPtrMessage* video);
|
virtual int on_video(SrsSharedPtrMessage* video);
|
||||||
private:
|
private:
|
||||||
virtual void hls_mux();
|
virtual void hls_mux();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
SrsHttpUri::SrsHttpUri()
|
SrsHttpUri::SrsHttpUri()
|
||||||
{
|
{
|
||||||
port = SRS_DEFAULT_HTTP_PORT;
|
port = SRS_DEFAULT_HTTP_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpUri::~SrsHttpUri()
|
SrsHttpUri::~SrsHttpUri()
|
||||||
|
@ -51,7 +51,7 @@ SrsHttpUri::~SrsHttpUri()
|
||||||
|
|
||||||
int SrsHttpUri::initialize(std::string _url)
|
int SrsHttpUri::initialize(std::string _url)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
url = _url;
|
url = _url;
|
||||||
const char* purl = url.c_str();
|
const char* purl = url.c_str();
|
||||||
|
@ -65,7 +65,7 @@ int SrsHttpUri::initialize(std::string _url)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
|
std::string field = get_uri_field(url, &hp_u, UF_SCHEMA);
|
||||||
if(!field.empty()){
|
if(!field.empty()){
|
||||||
schema = field;
|
schema = field;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ int SrsHttpUri::initialize(std::string _url)
|
||||||
path = get_uri_field(url, &hp_u, UF_PATH);
|
path = get_uri_field(url, &hp_u, UF_PATH);
|
||||||
srs_info("parse url %s success", purl);
|
srs_info("parse url %s success", purl);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SrsHttpUri::get_url()
|
const char* SrsHttpUri::get_url()
|
||||||
|
@ -128,24 +128,24 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht
|
||||||
|
|
||||||
SrsHttpClient::SrsHttpClient()
|
SrsHttpClient::SrsHttpClient()
|
||||||
{
|
{
|
||||||
connected = false;
|
connected = false;
|
||||||
stfd = NULL;
|
stfd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpClient::~SrsHttpClient()
|
SrsHttpClient::~SrsHttpClient()
|
||||||
{
|
{
|
||||||
disconnect();
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
|
int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if ((ret = connect(uri)) != ERROR_SUCCESS) {
|
if ((ret = connect(uri)) != ERROR_SUCCESS) {
|
||||||
srs_error("http connect server failed. ret=%d", ret);
|
srs_error("http connect server failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send POST request to uri
|
// send POST request to uri
|
||||||
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
|
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
@ -176,33 +176,33 @@ int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("parse http post response success.");
|
srs_info("parse http post response success.");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsHttpClient::disconnect()
|
void SrsHttpClient::disconnect()
|
||||||
{
|
{
|
||||||
connected = false;
|
connected = false;
|
||||||
|
|
||||||
srs_close_stfd(stfd);
|
srs_close_stfd(stfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpClient::connect(SrsHttpUri* uri)
|
int SrsHttpClient::connect(SrsHttpUri* uri)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (connected) {
|
if (connected) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|
||||||
std::string ip = srs_dns_resolve(uri->get_host());
|
std::string ip = srs_dns_resolve(uri->get_host());
|
||||||
if (ip.empty()) {
|
if (ip.empty()) {
|
||||||
ret = ERROR_SYSTEM_IP_INVALID;
|
ret = ERROR_SYSTEM_IP_INVALID;
|
||||||
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
srs_error("dns resolve server error, ip empty. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if(sock == -1){
|
if(sock == -1){
|
||||||
|
@ -217,7 +217,7 @@ int SrsHttpClient::connect(SrsHttpUri* uri)
|
||||||
srs_error("st_netfd_open_socket failed. ret=%d", ret);
|
srs_error("st_netfd_open_socket failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_in addr;
|
sockaddr_in addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(uri->get_port());
|
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){
|
if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
|
||||||
ret = ERROR_ST_CONNECT;
|
ret = ERROR_ST_CONNECT;
|
||||||
srs_error("connect to server error. "
|
srs_error("connect to server error. "
|
||||||
"ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);
|
"ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_info("connect to server success. "
|
srs_info("connect to server success. "
|
||||||
"http url=%s, server=%s, ip=%s, port=%d",
|
"http url=%s, server=%s, ip=%s, port=%d",
|
||||||
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
|
uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port());
|
||||||
|
|
||||||
connected = true;
|
connected = true;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response)
|
int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response)
|
||||||
|
@ -327,17 +327,17 @@ int SrsHttpClient::parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::str
|
||||||
char buf[SRS_HTTP_BODY_BUFFER];
|
char buf[SRS_HTTP_BODY_BUFFER];
|
||||||
|
|
||||||
return parse_response_body_data(
|
return parse_response_body_data(
|
||||||
uri, skt, response, (size_t)body_left,
|
uri, skt, response, (size_t)body_left,
|
||||||
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// if ignore response, use shared fast memory.
|
// if ignore response, use shared fast memory.
|
||||||
static char buf[SRS_HTTP_BODY_BUFFER];
|
static char buf[SRS_HTTP_BODY_BUFFER];
|
||||||
|
|
||||||
return parse_response_body_data(
|
return parse_response_body_data(
|
||||||
uri, skt, response, (size_t)body_left,
|
uri, skt, response, (size_t)body_left,
|
||||||
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
(const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -351,7 +351,7 @@ int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std
|
||||||
|
|
||||||
while (body_left > 0) {
|
while (body_left > 0) {
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int size_to_read = srs_min(size, body_left);
|
int size_to_read = srs_min(size, body_left);
|
||||||
if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) {
|
if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) {
|
||||||
srs_error("read header from server failed. ret=%d", ret);
|
srs_error("read header from server failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -394,424 +394,424 @@ SrsHttpHooks::~SrsHttpHooks()
|
||||||
|
|
||||||
int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req)
|
int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||||
srs_error("http uri parse on_connect url failed. "
|
srs_error("http uri parse on_connect url failed. "
|
||||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
{
|
{
|
||||||
"action": "on_connect",
|
"action": "on_connect",
|
||||||
"client_id": 1985,
|
"client_id": 1985,
|
||||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||||
"pageUrl": "http://www.test.com/live.html"
|
"pageUrl": "http://www.test.com/live.html"
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{"
|
ss << "{"
|
||||||
// action
|
// action
|
||||||
<< '"' << "action" << '"' << ':'
|
<< '"' << "action" << '"' << ':'
|
||||||
<< '"' << "on_connect" << '"'
|
<< '"' << "on_connect" << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// client_id
|
// client_id
|
||||||
<< '"' << "client_id" << '"' << ':'
|
<< '"' << "client_id" << '"' << ':'
|
||||||
<< std::dec << client_id
|
<< std::dec << client_id
|
||||||
<< ','
|
<< ','
|
||||||
// ip
|
// ip
|
||||||
<< '"' << "ip" << '"' << ':'
|
<< '"' << "ip" << '"' << ':'
|
||||||
<< '"' << ip << '"'
|
<< '"' << ip << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// vhost
|
// vhost
|
||||||
<< '"' << "vhost" << '"' << ':'
|
<< '"' << "vhost" << '"' << ':'
|
||||||
<< '"' << req->vhost << '"'
|
<< '"' << req->vhost << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// app
|
// app
|
||||||
<< '"' << "app" << '"' << ':'
|
<< '"' << "app" << '"' << ':'
|
||||||
<< '"' << req->app << '"'
|
<< '"' << req->app << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// pageUrl
|
// pageUrl
|
||||||
<< '"' << "pageUrl" << '"' << ':'
|
<< '"' << "pageUrl" << '"' << ':'
|
||||||
<< '"' << req->pageUrl << '"'
|
<< '"' << req->pageUrl << '"'
|
||||||
//<< ','
|
//<< ','
|
||||||
<< "}";
|
<< "}";
|
||||||
std::string data = ss.str();
|
std::string data = ss.str();
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsHttpClient http;
|
||||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||||
srs_error("http post on_connect uri failed. "
|
srs_error("http post on_connect uri failed. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||||
srs_error("http hook on_connect validate failed. "
|
srs_error("http hook on_connect validate failed. "
|
||||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_trace("http hook on_connect success. "
|
srs_trace("http hook on_connect success. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)
|
void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||||
srs_warn("http uri parse on_close url failed, ignored. "
|
srs_warn("http uri parse on_close url failed, ignored. "
|
||||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
{
|
{
|
||||||
"action": "on_close",
|
"action": "on_close",
|
||||||
"client_id": 1985,
|
"client_id": 1985,
|
||||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||||
"stream": "livestream"
|
"stream": "livestream"
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{"
|
ss << "{"
|
||||||
// action
|
// action
|
||||||
<< '"' << "action" << '"' << ':'
|
<< '"' << "action" << '"' << ':'
|
||||||
<< '"' << "on_close" << '"'
|
<< '"' << "on_close" << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// client_id
|
// client_id
|
||||||
<< '"' << "client_id" << '"' << ':'
|
<< '"' << "client_id" << '"' << ':'
|
||||||
<< std::dec << client_id
|
<< std::dec << client_id
|
||||||
<< ','
|
<< ','
|
||||||
// ip
|
// ip
|
||||||
<< '"' << "ip" << '"' << ':'
|
<< '"' << "ip" << '"' << ':'
|
||||||
<< '"' << ip << '"'
|
<< '"' << ip << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// vhost
|
// vhost
|
||||||
<< '"' << "vhost" << '"' << ':'
|
<< '"' << "vhost" << '"' << ':'
|
||||||
<< '"' << req->vhost << '"'
|
<< '"' << req->vhost << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// app
|
// app
|
||||||
<< '"' << "app" << '"' << ':'
|
<< '"' << "app" << '"' << ':'
|
||||||
<< '"' << req->app << '"'
|
<< '"' << req->app << '"'
|
||||||
//<< ','
|
//<< ','
|
||||||
<< "}";
|
<< "}";
|
||||||
std::string data = ss.str();
|
std::string data = ss.str();
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsHttpClient http;
|
||||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||||
srs_warn("http post on_close uri failed, ignored. "
|
srs_warn("http post on_close uri failed, ignored. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||||
srs_warn("http hook on_close validate failed, ignored. "
|
srs_warn("http hook on_close validate failed, ignored. "
|
||||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_trace("http hook on_close success. "
|
srs_trace("http hook on_close success. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)
|
int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||||
srs_error("http uri parse on_publish url failed. "
|
srs_error("http uri parse on_publish url failed. "
|
||||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
{
|
{
|
||||||
"action": "on_publish",
|
"action": "on_publish",
|
||||||
"client_id": 1985,
|
"client_id": 1985,
|
||||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||||
"stream": "livestream"
|
"stream": "livestream"
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{"
|
ss << "{"
|
||||||
// action
|
// action
|
||||||
<< '"' << "action" << '"' << ':'
|
<< '"' << "action" << '"' << ':'
|
||||||
<< '"' << "on_publish" << '"'
|
<< '"' << "on_publish" << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// client_id
|
// client_id
|
||||||
<< '"' << "client_id" << '"' << ':'
|
<< '"' << "client_id" << '"' << ':'
|
||||||
<< std::dec << client_id
|
<< std::dec << client_id
|
||||||
<< ','
|
<< ','
|
||||||
// ip
|
// ip
|
||||||
<< '"' << "ip" << '"' << ':'
|
<< '"' << "ip" << '"' << ':'
|
||||||
<< '"' << ip << '"'
|
<< '"' << ip << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// vhost
|
// vhost
|
||||||
<< '"' << "vhost" << '"' << ':'
|
<< '"' << "vhost" << '"' << ':'
|
||||||
<< '"' << req->vhost << '"'
|
<< '"' << req->vhost << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// app
|
// app
|
||||||
<< '"' << "app" << '"' << ':'
|
<< '"' << "app" << '"' << ':'
|
||||||
<< '"' << req->app << '"'
|
<< '"' << req->app << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// stream
|
// stream
|
||||||
<< '"' << "stream" << '"' << ':'
|
<< '"' << "stream" << '"' << ':'
|
||||||
<< '"' << req->stream << '"'
|
<< '"' << req->stream << '"'
|
||||||
//<< ','
|
//<< ','
|
||||||
<< "}";
|
<< "}";
|
||||||
std::string data = ss.str();
|
std::string data = ss.str();
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsHttpClient http;
|
||||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||||
srs_error("http post on_publish uri failed. "
|
srs_error("http post on_publish uri failed. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||||
srs_error("http hook on_publish validate failed. "
|
srs_error("http hook on_publish validate failed. "
|
||||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_trace("http hook on_publish success. "
|
srs_trace("http hook on_publish success. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)
|
void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||||
srs_warn("http uri parse on_unpublish url failed, ignored. "
|
srs_warn("http uri parse on_unpublish url failed, ignored. "
|
||||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
{
|
{
|
||||||
"action": "on_unpublish",
|
"action": "on_unpublish",
|
||||||
"client_id": 1985,
|
"client_id": 1985,
|
||||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||||
"stream": "livestream"
|
"stream": "livestream"
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{"
|
ss << "{"
|
||||||
// action
|
// action
|
||||||
<< '"' << "action" << '"' << ':'
|
<< '"' << "action" << '"' << ':'
|
||||||
<< '"' << "on_unpublish" << '"'
|
<< '"' << "on_unpublish" << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// client_id
|
// client_id
|
||||||
<< '"' << "client_id" << '"' << ':'
|
<< '"' << "client_id" << '"' << ':'
|
||||||
<< std::dec << client_id
|
<< std::dec << client_id
|
||||||
<< ','
|
<< ','
|
||||||
// ip
|
// ip
|
||||||
<< '"' << "ip" << '"' << ':'
|
<< '"' << "ip" << '"' << ':'
|
||||||
<< '"' << ip << '"'
|
<< '"' << ip << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// vhost
|
// vhost
|
||||||
<< '"' << "vhost" << '"' << ':'
|
<< '"' << "vhost" << '"' << ':'
|
||||||
<< '"' << req->vhost << '"'
|
<< '"' << req->vhost << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// app
|
// app
|
||||||
<< '"' << "app" << '"' << ':'
|
<< '"' << "app" << '"' << ':'
|
||||||
<< '"' << req->app << '"'
|
<< '"' << req->app << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// stream
|
// stream
|
||||||
<< '"' << "stream" << '"' << ':'
|
<< '"' << "stream" << '"' << ':'
|
||||||
<< '"' << req->stream << '"'
|
<< '"' << req->stream << '"'
|
||||||
//<< ','
|
//<< ','
|
||||||
<< "}";
|
<< "}";
|
||||||
std::string data = ss.str();
|
std::string data = ss.str();
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsHttpClient http;
|
||||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||||
srs_warn("http post on_unpublish uri failed, ignored. "
|
srs_warn("http post on_unpublish uri failed, ignored. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||||
srs_warn("http hook on_unpublish validate failed, ignored. "
|
srs_warn("http hook on_unpublish validate failed, ignored. "
|
||||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_trace("http hook on_unpublish success. "
|
srs_trace("http hook on_unpublish success. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)
|
int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||||
srs_error("http uri parse on_play url failed. "
|
srs_error("http uri parse on_play url failed. "
|
||||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
{
|
{
|
||||||
"action": "on_play",
|
"action": "on_play",
|
||||||
"client_id": 1985,
|
"client_id": 1985,
|
||||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||||
"stream": "livestream"
|
"stream": "livestream"
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{"
|
ss << "{"
|
||||||
// action
|
// action
|
||||||
<< '"' << "action" << '"' << ':'
|
<< '"' << "action" << '"' << ':'
|
||||||
<< '"' << "on_play" << '"'
|
<< '"' << "on_play" << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// client_id
|
// client_id
|
||||||
<< '"' << "client_id" << '"' << ':'
|
<< '"' << "client_id" << '"' << ':'
|
||||||
<< std::dec << client_id
|
<< std::dec << client_id
|
||||||
<< ','
|
<< ','
|
||||||
// ip
|
// ip
|
||||||
<< '"' << "ip" << '"' << ':'
|
<< '"' << "ip" << '"' << ':'
|
||||||
<< '"' << ip << '"'
|
<< '"' << ip << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// vhost
|
// vhost
|
||||||
<< '"' << "vhost" << '"' << ':'
|
<< '"' << "vhost" << '"' << ':'
|
||||||
<< '"' << req->vhost << '"'
|
<< '"' << req->vhost << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// app
|
// app
|
||||||
<< '"' << "app" << '"' << ':'
|
<< '"' << "app" << '"' << ':'
|
||||||
<< '"' << req->app << '"'
|
<< '"' << req->app << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// stream
|
// stream
|
||||||
<< '"' << "stream" << '"' << ':'
|
<< '"' << "stream" << '"' << ':'
|
||||||
<< '"' << req->stream << '"'
|
<< '"' << req->stream << '"'
|
||||||
//<< ','
|
//<< ','
|
||||||
<< "}";
|
<< "}";
|
||||||
std::string data = ss.str();
|
std::string data = ss.str();
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsHttpClient http;
|
||||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||||
srs_error("http post on_play uri failed. "
|
srs_error("http post on_play uri failed. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||||
srs_error("http hook on_play validate failed. "
|
srs_error("http hook on_play validate failed. "
|
||||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_trace("http hook on_play success. "
|
srs_trace("http hook on_play success. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)
|
void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||||
srs_warn("http uri parse on_stop url failed, ignored. "
|
srs_warn("http uri parse on_stop url failed, ignored. "
|
||||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
{
|
{
|
||||||
"action": "on_stop",
|
"action": "on_stop",
|
||||||
"client_id": 1985,
|
"client_id": 1985,
|
||||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||||
"stream": "livestream"
|
"stream": "livestream"
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{"
|
ss << "{"
|
||||||
// action
|
// action
|
||||||
<< '"' << "action" << '"' << ':'
|
<< '"' << "action" << '"' << ':'
|
||||||
<< '"' << "on_stop" << '"'
|
<< '"' << "on_stop" << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// client_id
|
// client_id
|
||||||
<< '"' << "client_id" << '"' << ':'
|
<< '"' << "client_id" << '"' << ':'
|
||||||
<< std::dec << client_id
|
<< std::dec << client_id
|
||||||
<< ','
|
<< ','
|
||||||
// ip
|
// ip
|
||||||
<< '"' << "ip" << '"' << ':'
|
<< '"' << "ip" << '"' << ':'
|
||||||
<< '"' << ip << '"'
|
<< '"' << ip << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// vhost
|
// vhost
|
||||||
<< '"' << "vhost" << '"' << ':'
|
<< '"' << "vhost" << '"' << ':'
|
||||||
<< '"' << req->vhost << '"'
|
<< '"' << req->vhost << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// app
|
// app
|
||||||
<< '"' << "app" << '"' << ':'
|
<< '"' << "app" << '"' << ':'
|
||||||
<< '"' << req->app << '"'
|
<< '"' << req->app << '"'
|
||||||
<< ','
|
<< ','
|
||||||
// stream
|
// stream
|
||||||
<< '"' << "stream" << '"' << ':'
|
<< '"' << "stream" << '"' << ':'
|
||||||
<< '"' << req->stream << '"'
|
<< '"' << req->stream << '"'
|
||||||
//<< ','
|
//<< ','
|
||||||
<< "}";
|
<< "}";
|
||||||
std::string data = ss.str();
|
std::string data = ss.str();
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsHttpClient http;
|
||||||
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) {
|
||||||
srs_warn("http post on_stop uri failed, ignored. "
|
srs_warn("http post on_stop uri failed, ignored. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||||
srs_warn("http hook on_stop validate failed, ignored. "
|
srs_warn("http hook on_stop validate failed, ignored. "
|
||||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_trace("http hook on_stop success. "
|
srs_trace("http hook on_stop success. "
|
||||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,8 +40,8 @@ class SrsSocket;
|
||||||
|
|
||||||
#include <http_parser.h>
|
#include <http_parser.h>
|
||||||
|
|
||||||
#define SRS_HTTP_HEADER_BUFFER 1024
|
#define SRS_HTTP_HEADER_BUFFER 1024
|
||||||
#define SRS_HTTP_BODY_BUFFER 32 * 1024
|
#define SRS_HTTP_BODY_BUFFER 32 * 1024
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used to resolve the http uri.
|
* used to resolve the http uri.
|
||||||
|
@ -55,13 +55,13 @@ private:
|
||||||
int port;
|
int port;
|
||||||
std::string path;
|
std::string path;
|
||||||
public:
|
public:
|
||||||
SrsHttpUri();
|
SrsHttpUri();
|
||||||
virtual ~SrsHttpUri();
|
virtual ~SrsHttpUri();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* initialize the http uri.
|
* initialize the http uri.
|
||||||
*/
|
*/
|
||||||
virtual int initialize(std::string _url);
|
virtual int initialize(std::string _url);
|
||||||
public:
|
public:
|
||||||
virtual const char* get_url();
|
virtual const char* get_url();
|
||||||
virtual const char* get_schema();
|
virtual const char* get_schema();
|
||||||
|
@ -82,23 +82,23 @@ private:
|
||||||
class SrsHttpClient
|
class SrsHttpClient
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool connected;
|
bool connected;
|
||||||
st_netfd_t stfd;
|
st_netfd_t stfd;
|
||||||
private:
|
private:
|
||||||
http_parser http_header;
|
http_parser http_header;
|
||||||
public:
|
public:
|
||||||
SrsHttpClient();
|
SrsHttpClient();
|
||||||
virtual ~SrsHttpClient();
|
virtual ~SrsHttpClient();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* to post data to the uri.
|
* to post data to the uri.
|
||||||
* @param req the data post to uri.
|
* @param req the data post to uri.
|
||||||
* @param res the response data from server.
|
* @param res the response data from server.
|
||||||
*/
|
*/
|
||||||
virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
|
virtual int post(SrsHttpUri* uri, std::string req, std::string& res);
|
||||||
private:
|
private:
|
||||||
virtual void disconnect();
|
virtual void disconnect();
|
||||||
virtual int connect(SrsHttpUri* uri);
|
virtual int connect(SrsHttpUri* uri);
|
||||||
private:
|
private:
|
||||||
virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);
|
virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response);
|
||||||
virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);
|
virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received);
|
||||||
|
@ -117,54 +117,54 @@ private:
|
||||||
class SrsHttpHooks
|
class SrsHttpHooks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsHttpHooks();
|
SrsHttpHooks();
|
||||||
virtual ~SrsHttpHooks();
|
virtual ~SrsHttpHooks();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* on_connect hook, when client connect to srs.
|
* on_connect hook, when client connect to srs.
|
||||||
* @param client_id the id of client on server.
|
* @param client_id the id of client on server.
|
||||||
* @param url the api server url, to valid the client.
|
* @param url the api server url, to valid the client.
|
||||||
* ignore if empty.
|
* ignore if empty.
|
||||||
* @return valid failed or connect to the url failed.
|
* @return valid failed or connect to the url failed.
|
||||||
*/
|
*/
|
||||||
virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
|
virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||||
/**
|
/**
|
||||||
* on_close hook, when client disconnect to srs, where client is valid by on_connect.
|
* on_close hook, when client disconnect to srs, where client is valid by on_connect.
|
||||||
* @param client_id the id of client on server.
|
* @param client_id the id of client on server.
|
||||||
* @param url the api server url, to process the event.
|
* @param url the api server url, to process the event.
|
||||||
* ignore if empty.
|
* ignore if empty.
|
||||||
*/
|
*/
|
||||||
virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);
|
virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||||
/**
|
/**
|
||||||
* on_publish hook, when client(encoder) start to publish stream
|
* on_publish hook, when client(encoder) start to publish stream
|
||||||
* @param client_id the id of client on server.
|
* @param client_id the id of client on server.
|
||||||
* @param url the api server url, to valid the client.
|
* @param url the api server url, to valid the client.
|
||||||
* ignore if empty.
|
* ignore if empty.
|
||||||
* @return valid failed or connect to the url failed.
|
* @return valid failed or connect to the url failed.
|
||||||
*/
|
*/
|
||||||
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||||
/**
|
/**
|
||||||
* on_unpublish hook, when client(encoder) stop publish stream.
|
* on_unpublish hook, when client(encoder) stop publish stream.
|
||||||
* @param client_id the id of client on server.
|
* @param client_id the id of client on server.
|
||||||
* @param url the api server url, to process the event.
|
* @param url the api server url, to process the event.
|
||||||
* ignore if empty.
|
* ignore if empty.
|
||||||
*/
|
*/
|
||||||
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||||
/**
|
/**
|
||||||
* on_play hook, when client start to play stream.
|
* on_play hook, when client start to play stream.
|
||||||
* @param client_id the id of client on server.
|
* @param client_id the id of client on server.
|
||||||
* @param url the api server url, to valid the client.
|
* @param url the api server url, to valid the client.
|
||||||
* ignore if empty.
|
* ignore if empty.
|
||||||
* @return valid failed or connect to the url failed.
|
* @return valid failed or connect to the url failed.
|
||||||
*/
|
*/
|
||||||
virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
|
virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||||
/**
|
/**
|
||||||
* on_stop hook, when client stop to play the stream.
|
* on_stop hook, when client stop to play the stream.
|
||||||
* @param client_id the id of client on server.
|
* @param client_id the id of client on server.
|
||||||
* @param url the api server url, to process the event.
|
* @param url the api server url, to process the event.
|
||||||
* ignore if empty.
|
* ignore if empty.
|
||||||
*/
|
*/
|
||||||
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
|
virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,7 +36,7 @@ SrsThreadContext::~SrsThreadContext()
|
||||||
|
|
||||||
void SrsThreadContext::generate_id()
|
void SrsThreadContext::generate_id()
|
||||||
{
|
{
|
||||||
static int id = 1;
|
static int id = 1;
|
||||||
cache[st_thread_self()] = id++;
|
cache[st_thread_self()] = id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ int SrsThreadContext::get_id()
|
||||||
|
|
||||||
SrsFastLog::SrsFastLog()
|
SrsFastLog::SrsFastLog()
|
||||||
{
|
{
|
||||||
level = SrsLogLevel::Trace;
|
level = SrsLogLevel::Trace;
|
||||||
log_data = new char[LOG_MAX_SIZE];
|
log_data = new char[LOG_MAX_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,15 +185,15 @@ bool SrsFastLog::generate_header(const char* tag, int context_id, const char* le
|
||||||
int log_header_size = -1;
|
int log_header_size = -1;
|
||||||
|
|
||||||
if (tag) {
|
if (tag) {
|
||||||
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
||||||
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ",
|
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ",
|
||||||
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000),
|
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000),
|
||||||
level_name, tag, context_id, errno);
|
level_name, tag, context_id, errno);
|
||||||
} else {
|
} else {
|
||||||
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
log_header_size = snprintf(log_data, LOG_MAX_SIZE,
|
||||||
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ",
|
"[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ",
|
||||||
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000),
|
1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000),
|
||||||
level_name, context_id, errno);
|
level_name, context_id, errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_header_size == -1) {
|
if (log_header_size == -1) {
|
||||||
|
|
|
@ -35,132 +35,132 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
struct SrsStageInfo : public ISrsReloadHandler
|
struct SrsStageInfo : public ISrsReloadHandler
|
||||||
{
|
{
|
||||||
int stage_id;
|
int stage_id;
|
||||||
int pithy_print_time_ms;
|
int pithy_print_time_ms;
|
||||||
int nb_clients;
|
int nb_clients;
|
||||||
|
|
||||||
SrsStageInfo(int _stage_id)
|
SrsStageInfo(int _stage_id)
|
||||||
{
|
{
|
||||||
stage_id = _stage_id;
|
stage_id = _stage_id;
|
||||||
nb_clients = 0;
|
nb_clients = 0;
|
||||||
|
|
||||||
update_print_time();
|
update_print_time();
|
||||||
|
|
||||||
_srs_config->subscribe(this);
|
_srs_config->subscribe(this);
|
||||||
}
|
}
|
||||||
virtual ~SrsStageInfo()
|
virtual ~SrsStageInfo()
|
||||||
{
|
{
|
||||||
_srs_config->unsubscribe(this);
|
_srs_config->unsubscribe(this);
|
||||||
}
|
}
|
||||||
void update_print_time()
|
void update_print_time()
|
||||||
{
|
{
|
||||||
switch (stage_id) {
|
switch (stage_id) {
|
||||||
case SRS_STAGE_PLAY_USER: {
|
case SRS_STAGE_PLAY_USER: {
|
||||||
pithy_print_time_ms = _srs_config->get_pithy_print_play();
|
pithy_print_time_ms = _srs_config->get_pithy_print_play();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SRS_STAGE_PUBLISH_USER: {
|
case SRS_STAGE_PUBLISH_USER: {
|
||||||
pithy_print_time_ms = _srs_config->get_pithy_print_publish();
|
pithy_print_time_ms = _srs_config->get_pithy_print_publish();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SRS_STAGE_FORWARDER: {
|
case SRS_STAGE_FORWARDER: {
|
||||||
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
|
pithy_print_time_ms = _srs_config->get_pithy_print_forwarder();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SRS_STAGE_ENCODER: {
|
case SRS_STAGE_ENCODER: {
|
||||||
pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
|
pithy_print_time_ms = _srs_config->get_pithy_print_encoder();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SRS_STAGE_HLS: {
|
case SRS_STAGE_HLS: {
|
||||||
pithy_print_time_ms = _srs_config->get_pithy_print_hls();
|
pithy_print_time_ms = _srs_config->get_pithy_print_hls();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
|
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
virtual int on_reload_pithy_print()
|
virtual int on_reload_pithy_print()
|
||||||
{
|
{
|
||||||
update_print_time();
|
update_print_time();
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static std::map<int, SrsStageInfo*> _srs_stages;
|
static std::map<int, SrsStageInfo*> _srs_stages;
|
||||||
|
|
||||||
SrsPithyPrint::SrsPithyPrint(int _stage_id)
|
SrsPithyPrint::SrsPithyPrint(int _stage_id)
|
||||||
{
|
{
|
||||||
stage_id = _stage_id;
|
stage_id = _stage_id;
|
||||||
client_id = enter_stage();
|
client_id = enter_stage();
|
||||||
printed_age = age = 0;
|
printed_age = age = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsPithyPrint::~SrsPithyPrint()
|
SrsPithyPrint::~SrsPithyPrint()
|
||||||
{
|
{
|
||||||
leave_stage();
|
leave_stage();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsPithyPrint::enter_stage()
|
int SrsPithyPrint::enter_stage()
|
||||||
{
|
{
|
||||||
SrsStageInfo* stage = NULL;
|
SrsStageInfo* stage = NULL;
|
||||||
|
|
||||||
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
|
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
|
||||||
if (it == _srs_stages.end()) {
|
if (it == _srs_stages.end()) {
|
||||||
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
|
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
|
||||||
} else {
|
} else {
|
||||||
stage = it->second;
|
stage = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_assert(stage != NULL);
|
srs_assert(stage != NULL);
|
||||||
client_id = stage->nb_clients++;
|
client_id = stage->nb_clients++;
|
||||||
|
|
||||||
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
|
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
|
||||||
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
|
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
|
||||||
|
|
||||||
return client_id;
|
return client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsPithyPrint::leave_stage()
|
void SrsPithyPrint::leave_stage()
|
||||||
{
|
{
|
||||||
SrsStageInfo* stage = _srs_stages[stage_id];
|
SrsStageInfo* stage = _srs_stages[stage_id];
|
||||||
srs_assert(stage != NULL);
|
srs_assert(stage != NULL);
|
||||||
|
|
||||||
stage->nb_clients--;
|
stage->nb_clients--;
|
||||||
|
|
||||||
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
|
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
|
||||||
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
|
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsPithyPrint::elapse(int64_t time_ms)
|
void SrsPithyPrint::elapse(int64_t time_ms)
|
||||||
{
|
{
|
||||||
age += time_ms;
|
age += time_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsPithyPrint::can_print()
|
bool SrsPithyPrint::can_print()
|
||||||
{
|
{
|
||||||
SrsStageInfo* stage = _srs_stages[stage_id];
|
SrsStageInfo* stage = _srs_stages[stage_id];
|
||||||
srs_assert(stage != NULL);
|
srs_assert(stage != NULL);
|
||||||
|
|
||||||
int64_t alive_age = age - printed_age;
|
int64_t alive_age = age - printed_age;
|
||||||
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
|
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
|
||||||
|
|
||||||
bool can_print = alive_age >= can_print_age;
|
bool can_print = alive_age >= can_print_age;
|
||||||
if (can_print) {
|
if (can_print) {
|
||||||
printed_age = age;
|
printed_age = age;
|
||||||
}
|
}
|
||||||
|
|
||||||
return can_print;
|
return can_print;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SrsPithyPrint::get_age()
|
int64_t SrsPithyPrint::get_age()
|
||||||
{
|
{
|
||||||
return age;
|
return age;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsPithyPrint::set_age(int64_t _age)
|
void SrsPithyPrint::set_age(int64_t _age)
|
||||||
{
|
{
|
||||||
age = _age;
|
age = _age;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,39 +50,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class SrsPithyPrint
|
class SrsPithyPrint
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int client_id;
|
int client_id;
|
||||||
int stage_id;
|
int stage_id;
|
||||||
int64_t age;
|
int64_t age;
|
||||||
int64_t printed_age;
|
int64_t printed_age;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
|
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
|
||||||
*/
|
*/
|
||||||
SrsPithyPrint(int _stage_id);
|
SrsPithyPrint(int _stage_id);
|
||||||
virtual ~SrsPithyPrint();
|
virtual ~SrsPithyPrint();
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* enter the specified stage, return the client id.
|
* enter the specified stage, return the client id.
|
||||||
*/
|
*/
|
||||||
virtual int enter_stage();
|
virtual int enter_stage();
|
||||||
/**
|
/**
|
||||||
* leave the specified stage, release the client id.
|
* leave the specified stage, release the client id.
|
||||||
*/
|
*/
|
||||||
virtual void leave_stage();
|
virtual void leave_stage();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* specified client elapse some time.
|
* specified client elapse some time.
|
||||||
*/
|
*/
|
||||||
virtual void elapse(int64_t time_ms);
|
virtual void elapse(int64_t time_ms);
|
||||||
/**
|
/**
|
||||||
* whether current client can print.
|
* whether current client can print.
|
||||||
*/
|
*/
|
||||||
virtual bool can_print();
|
virtual bool can_print();
|
||||||
/**
|
/**
|
||||||
* get the elapsed time in ms.
|
* get the elapsed time in ms.
|
||||||
*/
|
*/
|
||||||
virtual int64_t get_age();
|
virtual int64_t get_age();
|
||||||
virtual void set_age(int64_t _age);
|
virtual void set_age(int64_t _age);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -29,60 +29,60 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
int SrsRefer::check(std::string page_url, SrsConfDirective* refer)
|
int SrsRefer::check(std::string page_url, SrsConfDirective* refer)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (!refer) {
|
if (!refer) {
|
||||||
srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
|
srs_verbose("ignore refer check for page_url=%s", page_url.c_str());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < (int)refer->args.size(); i++) {
|
for (int i = 0; i < (int)refer->args.size(); i++) {
|
||||||
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
|
if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) {
|
||||||
srs_verbose("check refer success. page_url=%s, refer=%s",
|
srs_verbose("check refer success. page_url=%s, refer=%s",
|
||||||
page_url.c_str(), refer->args.at(i).c_str());
|
page_url.c_str(), refer->args.at(i).c_str());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||||
srs_error("check refer failed. ret=%d", ret);
|
srs_error("check refer failed. ret=%d", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsRefer::check_single_refer(std::string page_url, std::string refer)
|
int SrsRefer::check_single_refer(std::string page_url, std::string refer)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
size_t pos = std::string::npos;
|
size_t pos = std::string::npos;
|
||||||
|
|
||||||
std::string domain_name = page_url;
|
std::string domain_name = page_url;
|
||||||
if ((pos = domain_name.find("://")) != std::string::npos) {
|
if ((pos = domain_name.find("://")) != std::string::npos) {
|
||||||
domain_name = domain_name.substr(pos + 3);
|
domain_name = domain_name.substr(pos + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pos = domain_name.find("/")) != std::string::npos) {
|
if ((pos = domain_name.find("/")) != std::string::npos) {
|
||||||
domain_name = domain_name.substr(0, pos);
|
domain_name = domain_name.substr(0, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pos = domain_name.find(":")) != std::string::npos) {
|
if ((pos = domain_name.find(":")) != std::string::npos) {
|
||||||
domain_name = domain_name.substr(0, pos);
|
domain_name = domain_name.substr(0, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = domain_name.find(refer);
|
pos = domain_name.find(refer);
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
// match primary domain.
|
// match primary domain.
|
||||||
if (pos != domain_name.length() - refer.length()) {
|
if (pos != domain_name.length() - refer.length()) {
|
||||||
ret = ERROR_RTMP_ACCESS_DENIED;
|
ret = ERROR_RTMP_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d",
|
srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d",
|
||||||
page_url.c_str(), domain_name.c_str(), refer.c_str(), ret);
|
page_url.c_str(), domain_name.c_str(), refer.c_str(), ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,14 +36,14 @@ class SrsConfDirective;
|
||||||
class SrsRefer
|
class SrsRefer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* to check the refer.
|
* to check the refer.
|
||||||
* @param page_url the client page url.
|
* @param page_url the client page url.
|
||||||
* @param refer the refer in config.
|
* @param refer the refer in config.
|
||||||
*/
|
*/
|
||||||
virtual int check(std::string page_url, SrsConfDirective* refer);
|
virtual int check(std::string page_url, SrsConfDirective* refer);
|
||||||
private:
|
private:
|
||||||
virtual int check_single_refer(std::string page_url, std::string refer);
|
virtual int check_single_refer(std::string page_url, std::string refer);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -37,41 +37,41 @@ ISrsReloadHandler::~ISrsReloadHandler()
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_listen()
|
int ISrsReloadHandler::on_reload_listen()
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_pithy_print()
|
int ISrsReloadHandler::on_reload_pithy_print()
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/)
|
int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/)
|
int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/)
|
int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_forward(string /*vhost*/)
|
int ISrsReloadHandler::on_reload_forward(string /*vhost*/)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_hls(string /*vhost*/)
|
int ISrsReloadHandler::on_reload_hls(string /*vhost*/)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsReloadHandler::on_reload_transcode(string /*vhost*/)
|
int ISrsReloadHandler::on_reload_transcode(string /*vhost*/)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,17 +37,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class ISrsReloadHandler
|
class ISrsReloadHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsReloadHandler();
|
ISrsReloadHandler();
|
||||||
virtual ~ISrsReloadHandler();
|
virtual ~ISrsReloadHandler();
|
||||||
public:
|
public:
|
||||||
virtual int on_reload_listen();
|
virtual int on_reload_listen();
|
||||||
virtual int on_reload_pithy_print();
|
virtual int on_reload_pithy_print();
|
||||||
virtual int on_reload_vhost_removed(std::string vhost);
|
virtual int on_reload_vhost_removed(std::string vhost);
|
||||||
virtual int on_reload_gop_cache(std::string vhost);
|
virtual int on_reload_gop_cache(std::string vhost);
|
||||||
virtual int on_reload_queue_length(std::string vhost);
|
virtual int on_reload_queue_length(std::string vhost);
|
||||||
virtual int on_reload_forward(std::string vhost);
|
virtual int on_reload_forward(std::string vhost);
|
||||||
virtual int on_reload_hls(std::string vhost);
|
virtual int on_reload_hls(std::string vhost);
|
||||||
virtual int on_reload_transcode(std::string vhost);
|
virtual int on_reload_transcode(std::string vhost);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -40,40 +40,40 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
|
SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type)
|
||||||
{
|
{
|
||||||
fd = -1;
|
fd = -1;
|
||||||
stfd = NULL;
|
stfd = NULL;
|
||||||
|
|
||||||
port = 0;
|
port = 0;
|
||||||
server = _server;
|
server = _server;
|
||||||
type = _type;
|
type = _type;
|
||||||
|
|
||||||
pthread = new SrsThread(this, 0);
|
pthread = new SrsThread(this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsListener::~SrsListener()
|
SrsListener::~SrsListener()
|
||||||
{
|
{
|
||||||
srs_close_stfd(stfd);
|
srs_close_stfd(stfd);
|
||||||
|
|
||||||
pthread->stop();
|
pthread->stop();
|
||||||
srs_freep(pthread);
|
srs_freep(pthread);
|
||||||
|
|
||||||
// st does not close it sometimes,
|
// st does not close it sometimes,
|
||||||
// close it manually.
|
// close it manually.
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsListener::listen(int _port)
|
int SrsListener::listen(int _port)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
port = _port;
|
port = _port;
|
||||||
|
|
||||||
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
||||||
ret = ERROR_SOCKET_CREATE;
|
ret = ERROR_SOCKET_CREATE;
|
||||||
srs_error("create linux socket error. ret=%d", ret);
|
srs_error("create linux socket error. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("create linux socket success. fd=%d", fd);
|
srs_verbose("create linux socket success. fd=%d", fd);
|
||||||
|
|
||||||
int reuse_socket = 1;
|
int reuse_socket = 1;
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
||||||
|
@ -115,19 +115,19 @@ int SrsListener::listen(int _port)
|
||||||
srs_verbose("create st listen thread success.");
|
srs_verbose("create st listen thread success.");
|
||||||
|
|
||||||
srs_trace("server started, listen at port=%d, fd=%d", port, fd);
|
srs_trace("server started, listen at port=%d, fd=%d", port, fd);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsListener::on_enter_loop()
|
void SrsListener::on_enter_loop()
|
||||||
{
|
{
|
||||||
srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd);
|
srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsListener::cycle()
|
int SrsListener::cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
||||||
|
|
||||||
if(client_stfd == NULL){
|
if(client_stfd == NULL){
|
||||||
|
@ -136,45 +136,45 @@ int SrsListener::cycle()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
||||||
|
|
||||||
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
|
if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
|
||||||
srs_warn("accept client error. ret=%d", ret);
|
srs_warn("accept client error. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
|
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsServer::SrsServer()
|
SrsServer::SrsServer()
|
||||||
{
|
{
|
||||||
signal_reload = false;
|
signal_reload = false;
|
||||||
signal_gmc_stop = false;
|
signal_gmc_stop = false;
|
||||||
|
|
||||||
srs_assert(_srs_config);
|
srs_assert(_srs_config);
|
||||||
_srs_config->subscribe(this);
|
_srs_config->subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsServer::~SrsServer()
|
SrsServer::~SrsServer()
|
||||||
{
|
{
|
||||||
_srs_config->unsubscribe(this);
|
_srs_config->unsubscribe(this);
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
std::vector<SrsConnection*>::iterator it;
|
std::vector<SrsConnection*>::iterator it;
|
||||||
for (it = conns.begin(); it != conns.end(); ++it) {
|
for (it = conns.begin(); it != conns.end(); ++it) {
|
||||||
SrsConnection* conn = *it;
|
SrsConnection* conn = *it;
|
||||||
srs_freep(conn);
|
srs_freep(conn);
|
||||||
}
|
}
|
||||||
conns.clear();
|
conns.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
close_listeners();
|
close_listeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsServer::initialize()
|
int SrsServer::initialize()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// use linux epoll.
|
// use linux epoll.
|
||||||
if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
|
if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
|
||||||
|
@ -190,159 +190,159 @@ int SrsServer::initialize()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("st_init success");
|
srs_verbose("st_init success");
|
||||||
|
|
||||||
// set current log id.
|
// set current log id.
|
||||||
_srs_context->generate_id();
|
_srs_context->generate_id();
|
||||||
srs_info("log set id success");
|
srs_info("log set id success");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsServer::listen()
|
int SrsServer::listen()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsConfDirective* conf = NULL;
|
SrsConfDirective* conf = NULL;
|
||||||
|
|
||||||
// stream service port.
|
// stream service port.
|
||||||
conf = _srs_config->get_listen();
|
conf = _srs_config->get_listen();
|
||||||
srs_assert(conf);
|
srs_assert(conf);
|
||||||
|
|
||||||
close_listeners();
|
close_listeners();
|
||||||
|
|
||||||
for (int i = 0; i < (int)conf->args.size(); i++) {
|
for (int i = 0; i < (int)conf->args.size(); i++) {
|
||||||
SrsListener* listener = new SrsListener(this, SrsListenerStream);
|
SrsListener* listener = new SrsListener(this, SrsListenerStream);
|
||||||
listeners.push_back(listener);
|
listeners.push_back(listener);
|
||||||
|
|
||||||
int port = ::atoi(conf->args.at(i).c_str());
|
int port = ::atoi(conf->args.at(i).c_str());
|
||||||
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
||||||
srs_error("listen at port %d failed. ret=%d", port, ret);
|
srs_error("listen at port %d failed. ret=%d", port, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsServer::cycle()
|
int SrsServer::cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// the deamon thread, update the time cache
|
// the deamon thread, update the time cache
|
||||||
while (true) {
|
while (true) {
|
||||||
st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
|
st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
|
||||||
srs_update_system_time_ms();
|
srs_update_system_time_ms();
|
||||||
|
|
||||||
// for gperf heap checker,
|
// for gperf heap checker,
|
||||||
// @see: research/gperftools/heap-checker/heap_checker.cc
|
// @see: research/gperftools/heap-checker/heap_checker.cc
|
||||||
// if user interrupt the program, exit to check mem leak.
|
// if user interrupt the program, exit to check mem leak.
|
||||||
// but, if gperf, use reload to ensure main return normally,
|
// but, if gperf, use reload to ensure main return normally,
|
||||||
// because directly exit will cause core-dump.
|
// because directly exit will cause core-dump.
|
||||||
#ifdef SRS_GPERF_MC
|
#ifdef SRS_GPERF_MC
|
||||||
if (signal_gmc_stop) {
|
if (signal_gmc_stop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (signal_reload) {
|
if (signal_reload) {
|
||||||
signal_reload = false;
|
signal_reload = false;
|
||||||
srs_info("get signal reload, to reload the config.");
|
srs_info("get signal reload, to reload the config.");
|
||||||
|
|
||||||
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
|
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
|
||||||
srs_error("reload config failed. ret=%d", ret);
|
srs_error("reload config failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_trace("reload config success.");
|
srs_trace("reload config success.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsServer::remove(SrsConnection* conn)
|
void SrsServer::remove(SrsConnection* conn)
|
||||||
{
|
{
|
||||||
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
|
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
|
||||||
|
|
||||||
if (it != conns.end()) {
|
if (it != conns.end()) {
|
||||||
conns.erase(it);
|
conns.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_info("conn removed. conns=%d", (int)conns.size());
|
srs_info("conn removed. conns=%d", (int)conns.size());
|
||||||
|
|
||||||
// all connections are created by server,
|
// all connections are created by server,
|
||||||
// so we free it here.
|
// so we free it here.
|
||||||
srs_freep(conn);
|
srs_freep(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsServer::on_signal(int signo)
|
void SrsServer::on_signal(int signo)
|
||||||
{
|
{
|
||||||
if (signo == SIGNAL_RELOAD) {
|
if (signo == SIGNAL_RELOAD) {
|
||||||
signal_reload = true;
|
signal_reload = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signo == SIGINT) {
|
if (signo == SIGINT) {
|
||||||
#ifdef SRS_GPERF_MC
|
#ifdef SRS_GPERF_MC
|
||||||
srs_trace("gmc is on, main cycle will terminate normally.");
|
srs_trace("gmc is on, main cycle will terminate normally.");
|
||||||
signal_gmc_stop = true;
|
signal_gmc_stop = true;
|
||||||
#else
|
#else
|
||||||
srs_trace("user terminate program");
|
srs_trace("user terminate program");
|
||||||
exit(0);
|
exit(0);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle the SIGINT, SIGTERM.
|
// TODO: handle the SIGINT, SIGTERM.
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsServer::close_listeners()
|
void SrsServer::close_listeners()
|
||||||
{
|
{
|
||||||
std::vector<SrsListener*>::iterator it;
|
std::vector<SrsListener*>::iterator it;
|
||||||
for (it = listeners.begin(); it != listeners.end(); ++it) {
|
for (it = listeners.begin(); it != listeners.end(); ++it) {
|
||||||
SrsListener* listener = *it;
|
SrsListener* listener = *it;
|
||||||
srs_freep(listener);
|
srs_freep(listener);
|
||||||
}
|
}
|
||||||
listeners.clear();
|
listeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
|
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
int max_connections = _srs_config->get_max_connections();
|
|
||||||
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 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()
|
int SrsServer::on_reload_listen()
|
||||||
{
|
{
|
||||||
return listen();
|
return listen();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,53 +41,53 @@ class SrsConnection;
|
||||||
|
|
||||||
enum SrsListenerType
|
enum SrsListenerType
|
||||||
{
|
{
|
||||||
SrsListenerStream = 0,
|
SrsListenerStream = 0,
|
||||||
SrsListenerApi
|
SrsListenerApi
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsListener : public ISrsThreadHandler
|
class SrsListener : public ISrsThreadHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsListenerType type;
|
SrsListenerType type;
|
||||||
private:
|
private:
|
||||||
int fd;
|
int fd;
|
||||||
st_netfd_t stfd;
|
st_netfd_t stfd;
|
||||||
int port;
|
int port;
|
||||||
SrsServer* server;
|
SrsServer* server;
|
||||||
SrsThread* pthread;
|
SrsThread* pthread;
|
||||||
public:
|
public:
|
||||||
SrsListener(SrsServer* _server, SrsListenerType _type);
|
SrsListener(SrsServer* _server, SrsListenerType _type);
|
||||||
virtual ~SrsListener();
|
virtual ~SrsListener();
|
||||||
public:
|
public:
|
||||||
virtual int listen(int port);
|
virtual int listen(int port);
|
||||||
// interface ISrsThreadHandler.
|
// interface ISrsThreadHandler.
|
||||||
public:
|
public:
|
||||||
virtual void on_enter_loop();
|
virtual void on_enter_loop();
|
||||||
virtual int cycle();
|
virtual int cycle();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsServer : public ISrsReloadHandler
|
class SrsServer : public ISrsReloadHandler
|
||||||
{
|
{
|
||||||
friend class SrsListener;
|
friend class SrsListener;
|
||||||
private:
|
private:
|
||||||
std::vector<SrsConnection*> conns;
|
std::vector<SrsConnection*> conns;
|
||||||
std::vector<SrsListener*> listeners;
|
std::vector<SrsListener*> listeners;
|
||||||
bool signal_reload;
|
bool signal_reload;
|
||||||
bool signal_gmc_stop;
|
bool signal_gmc_stop;
|
||||||
public:
|
public:
|
||||||
SrsServer();
|
SrsServer();
|
||||||
virtual ~SrsServer();
|
virtual ~SrsServer();
|
||||||
public:
|
public:
|
||||||
virtual int initialize();
|
virtual int initialize();
|
||||||
virtual int listen();
|
virtual int listen();
|
||||||
virtual int cycle();
|
virtual int cycle();
|
||||||
virtual void remove(SrsConnection* conn);
|
virtual void remove(SrsConnection* conn);
|
||||||
virtual void on_signal(int signo);
|
virtual void on_signal(int signo);
|
||||||
private:
|
private:
|
||||||
virtual void close_listeners();
|
virtual void close_listeners();
|
||||||
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
|
virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
|
||||||
public:
|
public:
|
||||||
virtual int on_reload_listen();
|
virtual int on_reload_listen();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -28,9 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
SrsSocket::SrsSocket(st_netfd_t client_stfd)
|
SrsSocket::SrsSocket(st_netfd_t client_stfd)
|
||||||
{
|
{
|
||||||
stfd = client_stfd;
|
stfd = client_stfd;
|
||||||
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
|
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
|
||||||
recv_bytes = send_bytes = 0;
|
recv_bytes = send_bytes = 0;
|
||||||
start_time_ms = srs_get_system_time_ms();
|
start_time_ms = srs_get_system_time_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsSocket::~SrsSocket()
|
SrsSocket::~SrsSocket()
|
||||||
|
@ -39,59 +39,59 @@ SrsSocket::~SrsSocket()
|
||||||
|
|
||||||
bool SrsSocket::is_never_timeout(int64_t timeout_us)
|
bool SrsSocket::is_never_timeout(int64_t timeout_us)
|
||||||
{
|
{
|
||||||
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
|
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsSocket::set_recv_timeout(int64_t timeout_us)
|
void SrsSocket::set_recv_timeout(int64_t timeout_us)
|
||||||
{
|
{
|
||||||
recv_timeout = timeout_us;
|
recv_timeout = timeout_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SrsSocket::get_recv_timeout()
|
int64_t SrsSocket::get_recv_timeout()
|
||||||
{
|
{
|
||||||
return recv_timeout;
|
return recv_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsSocket::set_send_timeout(int64_t timeout_us)
|
void SrsSocket::set_send_timeout(int64_t timeout_us)
|
||||||
{
|
{
|
||||||
send_timeout = timeout_us;
|
send_timeout = timeout_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SrsSocket::get_send_timeout()
|
int64_t SrsSocket::get_send_timeout()
|
||||||
{
|
{
|
||||||
return send_timeout;
|
return send_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SrsSocket::get_recv_bytes()
|
int64_t SrsSocket::get_recv_bytes()
|
||||||
{
|
{
|
||||||
return recv_bytes;
|
return recv_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SrsSocket::get_send_bytes()
|
int64_t SrsSocket::get_send_bytes()
|
||||||
{
|
{
|
||||||
return send_bytes;
|
return send_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsSocket::get_recv_kbps()
|
int SrsSocket::get_recv_kbps()
|
||||||
{
|
{
|
||||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||||
|
|
||||||
if (diff_ms <= 0) {
|
if (diff_ms <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recv_bytes * 8 / diff_ms;
|
return recv_bytes * 8 / diff_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsSocket::get_send_kbps()
|
int SrsSocket::get_send_kbps()
|
||||||
{
|
{
|
||||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||||
|
|
||||||
if (diff_ms <= 0) {
|
if (diff_ms <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_bytes * 8 / diff_ms;
|
return send_bytes * 8 / diff_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
|
int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
|
||||||
|
@ -103,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
|
// On success a non-negative integer indicating the number of bytes actually read is returned
|
||||||
// (a value of 0 means the network connection is closed or end of file is reached).
|
// (a value of 0 means the network connection is closed or end of file is reached).
|
||||||
if (*nread <= 0) {
|
if (*nread <= 0) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*nread == 0) {
|
if (*nread == 0) {
|
||||||
errno = ECONNRESET;
|
errno = ECONNRESET;
|
||||||
}
|
}
|
||||||
|
@ -128,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
|
// On success a non-negative integer indicating the number of bytes actually read is returned
|
||||||
// (a value less than nbyte means the network connection is closed or end of file is reached)
|
// (a value less than nbyte means the network connection is closed or end of file is reached)
|
||||||
if (*nread != (ssize_t)size) {
|
if (*nread != (ssize_t)size) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*nread >= 0) {
|
if (*nread >= 0) {
|
||||||
errno = ECONNRESET;
|
errno = ECONNRESET;
|
||||||
}
|
}
|
||||||
|
@ -151,10 +151,10 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite)
|
||||||
*nwrite = st_write(stfd, (void*)buf, size, send_timeout);
|
*nwrite = st_write(stfd, (void*)buf, size, send_timeout);
|
||||||
|
|
||||||
if (*nwrite <= 0) {
|
if (*nwrite <= 0) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SOCKET_WRITE;
|
return ERROR_SOCKET_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,10 +170,10 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
|
||||||
*nwrite = st_writev(stfd, iov, iov_size, send_timeout);
|
*nwrite = st_writev(stfd, iov, iov_size, send_timeout);
|
||||||
|
|
||||||
if (*nwrite <= 0) {
|
if (*nwrite <= 0) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SOCKET_WRITE;
|
return ERROR_SOCKET_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,25 +40,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class SrsSocket : public ISrsProtocolReaderWriter
|
class SrsSocket : public ISrsProtocolReaderWriter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int64_t recv_timeout;
|
int64_t recv_timeout;
|
||||||
int64_t send_timeout;
|
int64_t send_timeout;
|
||||||
int64_t recv_bytes;
|
int64_t recv_bytes;
|
||||||
int64_t send_bytes;
|
int64_t send_bytes;
|
||||||
int64_t start_time_ms;
|
int64_t start_time_ms;
|
||||||
st_netfd_t stfd;
|
st_netfd_t stfd;
|
||||||
public:
|
public:
|
||||||
SrsSocket(st_netfd_t client_stfd);
|
SrsSocket(st_netfd_t client_stfd);
|
||||||
virtual ~SrsSocket();
|
virtual ~SrsSocket();
|
||||||
public:
|
public:
|
||||||
virtual bool is_never_timeout(int64_t timeout_us);
|
virtual bool is_never_timeout(int64_t timeout_us);
|
||||||
virtual void set_recv_timeout(int64_t timeout_us);
|
virtual void set_recv_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_recv_timeout();
|
virtual int64_t get_recv_timeout();
|
||||||
virtual void set_send_timeout(int64_t timeout_us);
|
virtual void set_send_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_send_timeout();
|
virtual int64_t get_send_timeout();
|
||||||
virtual int64_t get_recv_bytes();
|
virtual int64_t get_recv_bytes();
|
||||||
virtual int64_t get_send_bytes();
|
virtual int64_t get_send_bytes();
|
||||||
virtual int get_recv_kbps();
|
virtual int get_recv_kbps();
|
||||||
virtual int get_send_kbps();
|
virtual int get_send_kbps();
|
||||||
public:
|
public:
|
||||||
virtual int read(const void* buf, size_t size, ssize_t* nread);
|
virtual int read(const void* buf, size_t size, ssize_t* nread);
|
||||||
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
|
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,20 +57,20 @@ class SrsEncoder;
|
||||||
class SrsRtmpJitter
|
class SrsRtmpJitter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int64_t last_pkt_time;
|
int64_t last_pkt_time;
|
||||||
int64_t last_pkt_correct_time;
|
int64_t last_pkt_correct_time;
|
||||||
public:
|
public:
|
||||||
SrsRtmpJitter();
|
SrsRtmpJitter();
|
||||||
virtual ~SrsRtmpJitter();
|
virtual ~SrsRtmpJitter();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* detect the time jitter and correct it.
|
* detect the time jitter and correct it.
|
||||||
*/
|
*/
|
||||||
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
|
virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||||
/**
|
/**
|
||||||
* get current client time, the last packet time.
|
* get current client time, the last packet time.
|
||||||
*/
|
*/
|
||||||
virtual int get_time();
|
virtual int get_time();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,39 +80,39 @@ public:
|
||||||
class SrsMessageQueue
|
class SrsMessageQueue
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int64_t av_start_time;
|
int64_t av_start_time;
|
||||||
int64_t av_end_time;
|
int64_t av_end_time;
|
||||||
int queue_size_ms;
|
int queue_size_ms;
|
||||||
std::vector<SrsSharedPtrMessage*> msgs;
|
std::vector<SrsSharedPtrMessage*> msgs;
|
||||||
public:
|
public:
|
||||||
SrsMessageQueue();
|
SrsMessageQueue();
|
||||||
virtual ~SrsMessageQueue();
|
virtual ~SrsMessageQueue();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* set the queue size
|
* set the queue size
|
||||||
* @param queue_size the queue size in seconds.
|
* @param queue_size the queue size in seconds.
|
||||||
*/
|
*/
|
||||||
virtual void set_queue_size(double queue_size);
|
virtual void set_queue_size(double queue_size);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* enqueue the message, the timestamp always monotonically.
|
* enqueue the message, the timestamp always monotonically.
|
||||||
* @param msg, the msg to enqueue, user never free it whatever the return code.
|
* @param msg, the msg to enqueue, user never free it whatever the return code.
|
||||||
*/
|
*/
|
||||||
virtual int enqueue(SrsSharedPtrMessage* msg);
|
virtual int enqueue(SrsSharedPtrMessage* msg);
|
||||||
/**
|
/**
|
||||||
* get packets in consumer queue.
|
* get packets in consumer queue.
|
||||||
* @pmsgs SrsMessages*[], output the prt array.
|
* @pmsgs SrsMessages*[], output the prt array.
|
||||||
* @count the count in array.
|
* @count the count in array.
|
||||||
* @max_count the max count to dequeue, 0 to dequeue all.
|
* @max_count the max count to dequeue, 0 to dequeue all.
|
||||||
*/
|
*/
|
||||||
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* remove a gop from the front.
|
* remove a gop from the front.
|
||||||
* if no iframe found, clear it.
|
* if no iframe found, clear it.
|
||||||
*/
|
*/
|
||||||
virtual void shrink();
|
virtual void shrink();
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,39 +121,39 @@ private:
|
||||||
class SrsConsumer
|
class SrsConsumer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsRtmpJitter* jitter;
|
SrsRtmpJitter* jitter;
|
||||||
SrsSource* source;
|
SrsSource* source;
|
||||||
SrsMessageQueue* queue;
|
SrsMessageQueue* queue;
|
||||||
bool paused;
|
bool paused;
|
||||||
public:
|
public:
|
||||||
SrsConsumer(SrsSource* _source);
|
SrsConsumer(SrsSource* _source);
|
||||||
virtual ~SrsConsumer();
|
virtual ~SrsConsumer();
|
||||||
public:
|
public:
|
||||||
virtual void set_queue_size(double queue_size);
|
virtual void set_queue_size(double queue_size);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* get current client time, the last packet time.
|
* get current client time, the last packet time.
|
||||||
*/
|
*/
|
||||||
virtual int get_time();
|
virtual int get_time();
|
||||||
/**
|
/**
|
||||||
* enqueue an shared ptr message.
|
* enqueue an shared ptr message.
|
||||||
* @param tba timebase of audio.
|
* @param tba timebase of audio.
|
||||||
* used to calc the audio time delta if time-jitter detected.
|
* used to calc the audio time delta if time-jitter detected.
|
||||||
* @param tbv timebase of video.
|
* @param tbv timebase of video.
|
||||||
* used to calc the video time delta if time-jitter detected.
|
* used to calc the video time delta if time-jitter detected.
|
||||||
*/
|
*/
|
||||||
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
|
virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv);
|
||||||
/**
|
/**
|
||||||
* get packets in consumer queue.
|
* get packets in consumer queue.
|
||||||
* @pmsgs SrsMessages*[], output the prt array.
|
* @pmsgs SrsMessages*[], output the prt array.
|
||||||
* @count the count in array.
|
* @count the count in array.
|
||||||
* @max_count the max count to dequeue, 0 to dequeue all.
|
* @max_count the max count to dequeue, 0 to dequeue all.
|
||||||
*/
|
*/
|
||||||
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
|
||||||
/**
|
/**
|
||||||
* when client send the pause message.
|
* when client send the pause message.
|
||||||
*/
|
*/
|
||||||
virtual int on_play_client_pause(bool is_pause);
|
virtual int on_play_client_pause(bool is_pause);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,33 +164,33 @@ public:
|
||||||
class SrsGopCache
|
class SrsGopCache
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* if disabled the gop cache,
|
* if disabled the gop cache,
|
||||||
* the client will wait for the next keyframe for h264,
|
* the client will wait for the next keyframe for h264,
|
||||||
* and will be black-screen.
|
* and will be black-screen.
|
||||||
*/
|
*/
|
||||||
bool enable_gop_cache;
|
bool enable_gop_cache;
|
||||||
/**
|
/**
|
||||||
* the video frame count, avoid cache for pure audio stream.
|
* the video frame count, avoid cache for pure audio stream.
|
||||||
*/
|
*/
|
||||||
int cached_video_count;
|
int cached_video_count;
|
||||||
/**
|
/**
|
||||||
* cached gop.
|
* cached gop.
|
||||||
*/
|
*/
|
||||||
std::vector<SrsSharedPtrMessage*> gop_cache;
|
std::vector<SrsSharedPtrMessage*> gop_cache;
|
||||||
public:
|
public:
|
||||||
SrsGopCache();
|
SrsGopCache();
|
||||||
virtual ~SrsGopCache();
|
virtual ~SrsGopCache();
|
||||||
public:
|
public:
|
||||||
virtual void set(bool enabled);
|
virtual void set(bool enabled);
|
||||||
/**
|
/**
|
||||||
* only for h264 codec
|
* only for h264 codec
|
||||||
* 1. cache the gop when got h264 video packet.
|
* 1. cache the gop when got h264 video packet.
|
||||||
* 2. clear gop when got keyframe.
|
* 2. clear gop when got keyframe.
|
||||||
*/
|
*/
|
||||||
virtual int cache(SrsSharedPtrMessage* msg);
|
virtual int cache(SrsSharedPtrMessage* msg);
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
|
virtual int dump(SrsConsumer* consumer, int tba, int tbv);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,89 +199,89 @@ public:
|
||||||
class SrsSource : public ISrsReloadHandler
|
class SrsSource : public ISrsReloadHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static std::map<std::string, SrsSource*> pool;
|
static std::map<std::string, SrsSource*> pool;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* find stream by vhost/app/stream.
|
* find stream by vhost/app/stream.
|
||||||
* @param req the client request.
|
* @param req the client request.
|
||||||
* @return the matched source, never be NULL.
|
* @return the matched source, never be NULL.
|
||||||
* @remark stream_url should without port and schema.
|
* @remark stream_url should without port and schema.
|
||||||
*/
|
*/
|
||||||
static SrsSource* find(SrsRequest* req);
|
static SrsSource* find(SrsRequest* req);
|
||||||
private:
|
private:
|
||||||
// deep copy of client request.
|
// deep copy of client request.
|
||||||
SrsRequest* req;
|
SrsRequest* req;
|
||||||
// to delivery stream to clients.
|
// to delivery stream to clients.
|
||||||
std::vector<SrsConsumer*> consumers;
|
std::vector<SrsConsumer*> consumers;
|
||||||
// hls handler.
|
// hls handler.
|
||||||
#ifdef SRS_HLS
|
#ifdef SRS_HLS
|
||||||
SrsHls* hls;
|
SrsHls* hls;
|
||||||
#endif
|
#endif
|
||||||
// transcoding handler.
|
// transcoding handler.
|
||||||
#ifdef SRS_FFMPEG
|
#ifdef SRS_FFMPEG
|
||||||
SrsEncoder* encoder;
|
SrsEncoder* encoder;
|
||||||
#endif
|
#endif
|
||||||
// gop cache for client fast startup.
|
// gop cache for client fast startup.
|
||||||
SrsGopCache* gop_cache;
|
SrsGopCache* gop_cache;
|
||||||
// to forward stream to other servers
|
// to forward stream to other servers
|
||||||
std::vector<SrsForwarder*> forwarders;
|
std::vector<SrsForwarder*> forwarders;
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* the sample rate of audio in metadata.
|
* the sample rate of audio in metadata.
|
||||||
*/
|
*/
|
||||||
int sample_rate;
|
int sample_rate;
|
||||||
/**
|
/**
|
||||||
* the video frame rate in metadata.
|
* the video frame rate in metadata.
|
||||||
*/
|
*/
|
||||||
int frame_rate;
|
int frame_rate;
|
||||||
/**
|
/**
|
||||||
* can publish, true when is not streaming
|
* can publish, true when is not streaming
|
||||||
*/
|
*/
|
||||||
bool _can_publish;
|
bool _can_publish;
|
||||||
private:
|
private:
|
||||||
SrsSharedPtrMessage* cache_metadata;
|
SrsSharedPtrMessage* cache_metadata;
|
||||||
// the cached video sequence header.
|
// the cached video sequence header.
|
||||||
SrsSharedPtrMessage* cache_sh_video;
|
SrsSharedPtrMessage* cache_sh_video;
|
||||||
// the cached audio sequence header.
|
// the cached audio sequence header.
|
||||||
SrsSharedPtrMessage* cache_sh_audio;
|
SrsSharedPtrMessage* cache_sh_audio;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param _req the client request object,
|
* @param _req the client request object,
|
||||||
* this object will deep copy it for reload.
|
* this object will deep copy it for reload.
|
||||||
*/
|
*/
|
||||||
SrsSource(SrsRequest* _req);
|
SrsSource(SrsRequest* _req);
|
||||||
virtual ~SrsSource();
|
virtual ~SrsSource();
|
||||||
// interface ISrsReloadHandler
|
// interface ISrsReloadHandler
|
||||||
public:
|
public:
|
||||||
virtual int on_reload_gop_cache(std::string vhost);
|
virtual int on_reload_gop_cache(std::string vhost);
|
||||||
virtual int on_reload_queue_length(std::string vhost);
|
virtual int on_reload_queue_length(std::string vhost);
|
||||||
virtual int on_reload_forward(std::string vhost);
|
virtual int on_reload_forward(std::string vhost);
|
||||||
virtual int on_reload_hls(std::string vhost);
|
virtual int on_reload_hls(std::string vhost);
|
||||||
virtual int on_reload_transcode(std::string vhost);
|
virtual int on_reload_transcode(std::string vhost);
|
||||||
public:
|
public:
|
||||||
// for the SrsForwarder to callback to request the sequence headers.
|
// for the SrsForwarder to callback to request the sequence headers.
|
||||||
virtual int on_forwarder_start(SrsForwarder* forwarder);
|
virtual int on_forwarder_start(SrsForwarder* forwarder);
|
||||||
// for the SrsHls to callback to request the sequence headers.
|
// for the SrsHls to callback to request the sequence headers.
|
||||||
virtual int on_hls_start();
|
virtual int on_hls_start();
|
||||||
public:
|
public:
|
||||||
virtual bool can_publish();
|
virtual bool can_publish();
|
||||||
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
|
virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
|
||||||
virtual int on_audio(SrsCommonMessage* audio);
|
virtual int on_audio(SrsCommonMessage* audio);
|
||||||
virtual int on_video(SrsCommonMessage* video);
|
virtual int on_video(SrsCommonMessage* video);
|
||||||
/**
|
/**
|
||||||
* publish stream event notify.
|
* publish stream event notify.
|
||||||
* @param _req the request from client, the source will deep copy it,
|
* @param _req the request from client, the source will deep copy it,
|
||||||
* for when reload the request of client maybe invalid.
|
* for when reload the request of client maybe invalid.
|
||||||
*/
|
*/
|
||||||
virtual int on_publish(SrsRequest* _req);
|
virtual int on_publish(SrsRequest* _req);
|
||||||
virtual void on_unpublish();
|
virtual void on_unpublish();
|
||||||
public:
|
public:
|
||||||
virtual int create_consumer(SrsConsumer*& consumer);
|
virtual int create_consumer(SrsConsumer*& consumer);
|
||||||
virtual void on_consumer_destroy(SrsConsumer* consumer);
|
virtual void on_consumer_destroy(SrsConsumer* consumer);
|
||||||
virtual void set_cache(bool enabled);
|
virtual void set_cache(bool enabled);
|
||||||
private:
|
private:
|
||||||
virtual int create_forwarders();
|
virtual int create_forwarders();
|
||||||
virtual void destroy_forwarders();
|
virtual void destroy_forwarders();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
void srs_close_stfd(st_netfd_t& stfd)
|
void srs_close_stfd(st_netfd_t& stfd)
|
||||||
{
|
{
|
||||||
if (stfd) {
|
if (stfd) {
|
||||||
int fd = st_netfd_fileno(stfd);
|
int fd = st_netfd_fileno(stfd);
|
||||||
st_netfd_close(stfd);
|
st_netfd_close(stfd);
|
||||||
stfd = NULL;
|
stfd = NULL;
|
||||||
|
|
||||||
// st does not close it sometimes,
|
// st does not close it sometimes,
|
||||||
// close it manually.
|
// close it manually.
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,14 +40,14 @@ void ISrsThreadHandler::on_enter_loop()
|
||||||
|
|
||||||
int ISrsThreadHandler::on_before_cycle()
|
int ISrsThreadHandler::on_before_cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ISrsThreadHandler::on_end_cycle()
|
int ISrsThreadHandler::on_end_cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISrsThreadHandler::on_leave_loop()
|
void ISrsThreadHandler::on_leave_loop()
|
||||||
|
@ -56,29 +56,29 @@ void ISrsThreadHandler::on_leave_loop()
|
||||||
|
|
||||||
SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us)
|
SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us)
|
||||||
{
|
{
|
||||||
handler = thread_handler;
|
handler = thread_handler;
|
||||||
cycle_interval_us = interval_us;
|
cycle_interval_us = interval_us;
|
||||||
|
|
||||||
tid = NULL;
|
tid = NULL;
|
||||||
loop = false;
|
loop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsThread::~SrsThread()
|
SrsThread::~SrsThread()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsThread::start()
|
int SrsThread::start()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if(tid) {
|
if(tid) {
|
||||||
srs_info("thread already running.");
|
srs_info("thread already running.");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((tid = st_thread_create(thread_fun, this, 1, 0)) == NULL){
|
if((tid = st_thread_create(thread_fun, this, 1, 0)) == NULL){
|
||||||
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
ret = ERROR_ST_CREATE_CYCLE_THREAD;
|
||||||
srs_error("st_thread_create failed. ret=%d", ret);
|
srs_error("st_thread_create failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -88,74 +88,74 @@ int SrsThread::start()
|
||||||
|
|
||||||
void SrsThread::stop()
|
void SrsThread::stop()
|
||||||
{
|
{
|
||||||
if (tid) {
|
if (tid) {
|
||||||
loop = false;
|
loop = false;
|
||||||
|
|
||||||
// the interrupt will cause the socket to read/write error,
|
// the interrupt will cause the socket to read/write error,
|
||||||
// which will terminate the cycle thread.
|
// which will terminate the cycle thread.
|
||||||
st_thread_interrupt(tid);
|
st_thread_interrupt(tid);
|
||||||
|
|
||||||
// wait the thread to exit.
|
// wait the thread to exit.
|
||||||
st_thread_join(tid, NULL);
|
st_thread_join(tid, NULL);
|
||||||
|
|
||||||
tid = NULL;
|
tid = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsThread::can_loop()
|
bool SrsThread::can_loop()
|
||||||
{
|
{
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsThread::thread_cycle()
|
void SrsThread::thread_cycle()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(handler);
|
srs_assert(handler);
|
||||||
|
|
||||||
_srs_context->generate_id();
|
_srs_context->generate_id();
|
||||||
srs_trace("thread cycle start");
|
srs_trace("thread cycle start");
|
||||||
|
|
||||||
handler->on_end_cycle();
|
handler->on_end_cycle();
|
||||||
|
|
||||||
loop = true;
|
loop = true;
|
||||||
while (loop) {
|
while (loop) {
|
||||||
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
|
if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) {
|
||||||
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
|
srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
srs_info("thread on before cycle success");
|
srs_info("thread on before cycle success");
|
||||||
|
|
||||||
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
|
if ((ret = handler->cycle()) != ERROR_SUCCESS) {
|
||||||
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
|
srs_warn("thread cycle failed, ignored and retry, ret=%d", ret);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
srs_info("thread cycle success");
|
srs_info("thread cycle success");
|
||||||
|
|
||||||
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
|
if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) {
|
||||||
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
|
srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
srs_info("thread on end cycle success");
|
srs_info("thread on end cycle success");
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
if (!loop) {
|
if (!loop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
st_usleep(cycle_interval_us);
|
st_usleep(cycle_interval_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->on_leave_loop();
|
handler->on_leave_loop();
|
||||||
srs_trace("thread cycle finished");
|
srs_trace("thread cycle finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
void* SrsThread::thread_fun(void* arg)
|
void* SrsThread::thread_fun(void* arg)
|
||||||
{
|
{
|
||||||
SrsThread* obj = (SrsThread*)arg;
|
SrsThread* obj = (SrsThread*)arg;
|
||||||
srs_assert(obj);
|
srs_assert(obj);
|
||||||
|
|
||||||
obj->thread_cycle();
|
obj->thread_cycle();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
|
@ -34,14 +34,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
/**
|
/**
|
||||||
* the handler for the thread, callback interface.
|
* the handler for the thread, callback interface.
|
||||||
* the thread model defines as:
|
* the thread model defines as:
|
||||||
* handler->on_enter_loop()
|
* handler->on_enter_loop()
|
||||||
* while loop:
|
* while loop:
|
||||||
* handler->on_before_cycle()
|
* handler->on_before_cycle()
|
||||||
* handler->cycle()
|
* handler->cycle()
|
||||||
* handler->on_end_cycle()
|
* handler->on_end_cycle()
|
||||||
* if !loop then break for user stop thread.
|
* if !loop then break for user stop thread.
|
||||||
* sleep(CycleIntervalMilliseconds)
|
* sleep(CycleIntervalMilliseconds)
|
||||||
* handler->on_leave_loop()
|
* handler->on_leave_loop()
|
||||||
* when stop, the thread will interrupt the st_thread,
|
* when stop, the thread will interrupt the st_thread,
|
||||||
* which will cause the socket to return error and
|
* which will cause the socket to return error and
|
||||||
* terminate the cycle thread.
|
* terminate the cycle thread.
|
||||||
|
@ -49,31 +49,31 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
* when thread interrupt, the socket maybe not got EINT,
|
* when thread interrupt, the socket maybe not got EINT,
|
||||||
* espectially on st_usleep(), so the cycle must check the loop,
|
* espectially on st_usleep(), so the cycle must check the loop,
|
||||||
* when handler->cycle() has loop itself, for example:
|
* when handler->cycle() has loop itself, for example:
|
||||||
* handler->cycle() is:
|
* handler->cycle() is:
|
||||||
* while (true):
|
* while (true):
|
||||||
* st_usleep(0);
|
* st_usleep(0);
|
||||||
* if (read_from_socket(skt) < 0) break;
|
* if (read_from_socket(skt) < 0) break;
|
||||||
* if thread stop when read_from_socket, it's ok, the loop will break,
|
* if thread stop when read_from_socket, it's ok, the loop will break,
|
||||||
* but when thread stop interrupt the s_usleep(0), then the loop is
|
* but when thread stop interrupt the s_usleep(0), then the loop is
|
||||||
* death loop.
|
* death loop.
|
||||||
* in a word, the handler->cycle() must:
|
* in a word, the handler->cycle() must:
|
||||||
* handler->cycle() is:
|
* handler->cycle() is:
|
||||||
* while (pthread->can_loop()):
|
* while (pthread->can_loop()):
|
||||||
* st_usleep(0);
|
* st_usleep(0);
|
||||||
* if (read_from_socket(skt) < 0) break;
|
* if (read_from_socket(skt) < 0) break;
|
||||||
* check the loop, then it works.
|
* check the loop, then it works.
|
||||||
*/
|
*/
|
||||||
class ISrsThreadHandler
|
class ISrsThreadHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsThreadHandler();
|
ISrsThreadHandler();
|
||||||
virtual ~ISrsThreadHandler();
|
virtual ~ISrsThreadHandler();
|
||||||
public:
|
public:
|
||||||
virtual void on_enter_loop();
|
virtual void on_enter_loop();
|
||||||
virtual int on_before_cycle();
|
virtual int on_before_cycle();
|
||||||
virtual int cycle() = 0;
|
virtual int cycle() = 0;
|
||||||
virtual int on_end_cycle();
|
virtual int on_end_cycle();
|
||||||
virtual void on_leave_loop();
|
virtual void on_leave_loop();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,41 +83,41 @@ public:
|
||||||
class SrsThread
|
class SrsThread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
st_thread_t tid;
|
st_thread_t tid;
|
||||||
bool loop;
|
bool loop;
|
||||||
private:
|
private:
|
||||||
ISrsThreadHandler* handler;
|
ISrsThreadHandler* handler;
|
||||||
int64_t cycle_interval_us;
|
int64_t cycle_interval_us;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* initialize the thread.
|
* initialize the thread.
|
||||||
* @param thread_handler, the cycle handler for the thread.
|
* @param thread_handler, the cycle handler for the thread.
|
||||||
* @param interval_us, the sleep interval when cycle finished.
|
* @param interval_us, the sleep interval when cycle finished.
|
||||||
*/
|
*/
|
||||||
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
|
SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us);
|
||||||
virtual ~SrsThread();
|
virtual ~SrsThread();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* start the thread, invoke the cycle of handler util
|
* start the thread, invoke the cycle of handler util
|
||||||
* user stop the thread.
|
* user stop the thread.
|
||||||
* @remark ignore any error of cycle of handler.
|
* @remark ignore any error of cycle of handler.
|
||||||
* @remark user can start multiple times, ignore if already started.
|
* @remark user can start multiple times, ignore if already started.
|
||||||
*/
|
*/
|
||||||
virtual int start();
|
virtual int start();
|
||||||
/**
|
/**
|
||||||
* stop the thread, wait for the thread to terminate.
|
* stop the thread, wait for the thread to terminate.
|
||||||
* @remark user can stop multiple times, ignore if already stopped.
|
* @remark user can stop multiple times, ignore if already stopped.
|
||||||
*/
|
*/
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
/**
|
/**
|
||||||
* whether the thread should loop,
|
* whether the thread should loop,
|
||||||
* used for handler->cycle() which has a loop method,
|
* used for handler->cycle() which has a loop method,
|
||||||
* to check this method, break if false.
|
* to check this method, break if false.
|
||||||
*/
|
*/
|
||||||
virtual bool can_loop();
|
virtual bool can_loop();
|
||||||
private:
|
private:
|
||||||
virtual void thread_cycle();
|
virtual void thread_cycle();
|
||||||
static void* thread_fun(void* arg);
|
static void* thread_fun(void* arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,7 +32,7 @@ static int64_t _srs_system_time_us_cache = 0;
|
||||||
|
|
||||||
int64_t srs_get_system_time_ms()
|
int64_t srs_get_system_time_ms()
|
||||||
{
|
{
|
||||||
return _srs_system_time_us_cache / 1000;
|
return _srs_system_time_us_cache / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void srs_update_system_time_ms()
|
void srs_update_system_time_ms()
|
||||||
|
@ -49,19 +49,19 @@ void srs_update_system_time_ms()
|
||||||
|
|
||||||
std::string srs_replace(std::string str, std::string old_str, std::string new_str)
|
std::string srs_replace(std::string str, std::string old_str, std::string new_str)
|
||||||
{
|
{
|
||||||
std::string ret = str;
|
std::string ret = str;
|
||||||
|
|
||||||
if (old_str == new_str) {
|
if (old_str == new_str) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = ret.find(old_str, pos)) != std::string::npos) {
|
while ((pos = ret.find(old_str, pos)) != std::string::npos) {
|
||||||
ret = ret.replace(pos, old_str.length(), new_str);
|
ret = ret.replace(pos, old_str.length(), new_str);
|
||||||
pos += new_str.length();
|
pos += new_str.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string srs_dns_resolve(std::string host)
|
std::string srs_dns_resolve(std::string host)
|
||||||
|
|
|
@ -69,18 +69,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// free the p and set to NULL.
|
// free the p and set to NULL.
|
||||||
// p must be a T*.
|
// p must be a T*.
|
||||||
#define srs_freep(p) \
|
#define srs_freep(p) \
|
||||||
if (p) { \
|
if (p) { \
|
||||||
delete p; \
|
delete p; \
|
||||||
p = NULL; \
|
p = NULL; \
|
||||||
} \
|
} \
|
||||||
(void)0
|
(void)0
|
||||||
// free the p which represents a array
|
// free the p which represents a array
|
||||||
#define srs_freepa(p) \
|
#define srs_freepa(p) \
|
||||||
if (p) { \
|
if (p) { \
|
||||||
delete[] p; \
|
delete[] p; \
|
||||||
p = NULL; \
|
p = NULL; \
|
||||||
} \
|
} \
|
||||||
(void)0
|
(void)0
|
||||||
|
|
||||||
// compare
|
// compare
|
||||||
#define srs_min(a, b) (((a) < (b))? (a) : (b))
|
#define srs_min(a, b) (((a) < (b))? (a) : (b))
|
||||||
|
|
|
@ -34,7 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
* auto free the instance in the current scope.
|
* auto free the instance in the current scope.
|
||||||
*/
|
*/
|
||||||
#define SrsAutoFree(className, instance, is_array) \
|
#define SrsAutoFree(className, instance, is_array) \
|
||||||
__SrsAutoFree<className> _auto_free_##instance(&instance, is_array)
|
__SrsAutoFree<className> _auto_free_##instance(&instance, is_array)
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class __SrsAutoFree
|
class __SrsAutoFree
|
||||||
|
|
|
@ -46,46 +46,46 @@ SrsBuffer::~SrsBuffer()
|
||||||
|
|
||||||
int SrsBuffer::size()
|
int SrsBuffer::size()
|
||||||
{
|
{
|
||||||
return (int)data.size();
|
return (int)data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
char* SrsBuffer::bytes()
|
char* SrsBuffer::bytes()
|
||||||
{
|
{
|
||||||
return &data.at(0);
|
return &data.at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsBuffer::erase(int size)
|
void SrsBuffer::erase(int size)
|
||||||
{
|
{
|
||||||
data.erase(data.begin(), data.begin() + size);
|
data.erase(data.begin(), data.begin() + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsBuffer::append(char* bytes, int size)
|
void SrsBuffer::append(char* bytes, int size)
|
||||||
{
|
{
|
||||||
data.insert(data.end(), bytes, bytes + size);
|
data.insert(data.end(), bytes, bytes + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsBuffer::ensure_buffer_bytes(ISrsBufferReader* skt, int required_size)
|
int SrsBuffer::ensure_buffer_bytes(ISrsBufferReader* skt, int required_size)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (required_size < 0) {
|
if (required_size < 0) {
|
||||||
ret = ERROR_SYSTEM_SIZE_NEGATIVE;
|
ret = ERROR_SYSTEM_SIZE_NEGATIVE;
|
||||||
srs_error("size is negative. size=%d, ret=%d", required_size, ret);
|
srs_error("size is negative. size=%d, ret=%d", required_size, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (size() < required_size) {
|
while (size() < required_size) {
|
||||||
char buffer[SOCKET_READ_SIZE];
|
char buffer[SOCKET_READ_SIZE];
|
||||||
|
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) {
|
if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_assert((int)nread > 0);
|
srs_assert((int)nread > 0);
|
||||||
append(buffer, (int)nread);
|
append(buffer, (int)nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class ISrsBufferReader
|
class ISrsBufferReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsBufferReader();
|
ISrsBufferReader();
|
||||||
virtual ~ISrsBufferReader();
|
virtual ~ISrsBufferReader();
|
||||||
// for protocol/amf0/msg-codec
|
// for protocol/amf0/msg-codec
|
||||||
public:
|
public:
|
||||||
virtual int read(const void* buf, size_t size, ssize_t* nread) = 0;
|
virtual int read(const void* buf, size_t size, ssize_t* nread) = 0;
|
||||||
|
@ -53,18 +53,18 @@ public:
|
||||||
class SrsBuffer
|
class SrsBuffer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<char> data;
|
std::vector<char> data;
|
||||||
public:
|
public:
|
||||||
SrsBuffer();
|
SrsBuffer();
|
||||||
virtual ~SrsBuffer();
|
virtual ~SrsBuffer();
|
||||||
public:
|
public:
|
||||||
virtual int size();
|
virtual int size();
|
||||||
virtual char* bytes();
|
virtual char* bytes();
|
||||||
virtual void erase(int size);
|
virtual void erase(int size);
|
||||||
private:
|
private:
|
||||||
virtual void append(char* bytes, int size);
|
virtual void append(char* bytes, int size);
|
||||||
public:
|
public:
|
||||||
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
|
virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
bool srs_is_system_control_error(int error_code)
|
bool srs_is_system_control_error(int error_code)
|
||||||
{
|
{
|
||||||
return error_code == ERROR_CONTROL_RTMP_CLOSE
|
return error_code == ERROR_CONTROL_RTMP_CLOSE
|
||||||
|| error_code == ERROR_CONTROL_REPUBLISH;
|
|| error_code == ERROR_CONTROL_REPUBLISH;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool srs_is_client_gracefully_close(int error_code)
|
bool srs_is_client_gracefully_close(int error_code)
|
||||||
{
|
{
|
||||||
return error_code == ERROR_SOCKET_READ
|
return error_code == ERROR_SOCKET_READ
|
||||||
|| error_code == ERROR_SOCKET_READ_FULLY
|
|| error_code == ERROR_SOCKET_READ_FULLY
|
||||||
|| error_code == ERROR_SOCKET_WRITE;
|
|| error_code == ERROR_SOCKET_WRITE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,133 +30,133 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
|
||||||
#define ERROR_SUCCESS 0
|
#define ERROR_SUCCESS 0
|
||||||
|
|
||||||
#define ERROR_ST_SET_EPOLL 100
|
#define ERROR_ST_SET_EPOLL 100
|
||||||
#define ERROR_ST_INITIALIZE 101
|
#define ERROR_ST_INITIALIZE 101
|
||||||
#define ERROR_ST_OPEN_SOCKET 102
|
#define ERROR_ST_OPEN_SOCKET 102
|
||||||
#define ERROR_ST_CREATE_LISTEN_THREAD 103
|
#define ERROR_ST_CREATE_LISTEN_THREAD 103
|
||||||
#define ERROR_ST_CREATE_CYCLE_THREAD 104
|
#define ERROR_ST_CREATE_CYCLE_THREAD 104
|
||||||
#define ERROR_ST_CONNECT 105
|
#define ERROR_ST_CONNECT 105
|
||||||
|
|
||||||
#define ERROR_SOCKET_CREATE 200
|
#define ERROR_SOCKET_CREATE 200
|
||||||
#define ERROR_SOCKET_SETREUSE 201
|
#define ERROR_SOCKET_SETREUSE 201
|
||||||
#define ERROR_SOCKET_BIND 202
|
#define ERROR_SOCKET_BIND 202
|
||||||
#define ERROR_SOCKET_LISTEN 203
|
#define ERROR_SOCKET_LISTEN 203
|
||||||
#define ERROR_SOCKET_CLOSED 204
|
#define ERROR_SOCKET_CLOSED 204
|
||||||
#define ERROR_SOCKET_GET_PEER_NAME 205
|
#define ERROR_SOCKET_GET_PEER_NAME 205
|
||||||
#define ERROR_SOCKET_GET_PEER_IP 206
|
#define ERROR_SOCKET_GET_PEER_IP 206
|
||||||
#define ERROR_SOCKET_READ 207
|
#define ERROR_SOCKET_READ 207
|
||||||
#define ERROR_SOCKET_READ_FULLY 208
|
#define ERROR_SOCKET_READ_FULLY 208
|
||||||
#define ERROR_SOCKET_WRITE 209
|
#define ERROR_SOCKET_WRITE 209
|
||||||
#define ERROR_SOCKET_WAIT 210
|
#define ERROR_SOCKET_WAIT 210
|
||||||
#define ERROR_SOCKET_TIMEOUT 211
|
#define ERROR_SOCKET_TIMEOUT 211
|
||||||
#define ERROR_SOCKET_GET_LOCAL_IP 212
|
#define ERROR_SOCKET_GET_LOCAL_IP 212
|
||||||
|
|
||||||
#define ERROR_RTMP_PLAIN_REQUIRED 300
|
#define ERROR_RTMP_PLAIN_REQUIRED 300
|
||||||
#define ERROR_RTMP_CHUNK_START 301
|
#define ERROR_RTMP_CHUNK_START 301
|
||||||
#define ERROR_RTMP_MSG_INVLIAD_SIZE 302
|
#define ERROR_RTMP_MSG_INVLIAD_SIZE 302
|
||||||
#define ERROR_RTMP_AMF0_DECODE 303
|
#define ERROR_RTMP_AMF0_DECODE 303
|
||||||
#define ERROR_RTMP_AMF0_INVALID 304
|
#define ERROR_RTMP_AMF0_INVALID 304
|
||||||
#define ERROR_RTMP_REQ_CONNECT 305
|
#define ERROR_RTMP_REQ_CONNECT 305
|
||||||
#define ERROR_RTMP_REQ_TCURL 306
|
#define ERROR_RTMP_REQ_TCURL 306
|
||||||
#define ERROR_RTMP_MESSAGE_DECODE 307
|
#define ERROR_RTMP_MESSAGE_DECODE 307
|
||||||
#define ERROR_RTMP_MESSAGE_ENCODE 308
|
#define ERROR_RTMP_MESSAGE_ENCODE 308
|
||||||
#define ERROR_RTMP_AMF0_ENCODE 309
|
#define ERROR_RTMP_AMF0_ENCODE 309
|
||||||
#define ERROR_RTMP_CHUNK_SIZE 310
|
#define ERROR_RTMP_CHUNK_SIZE 310
|
||||||
#define ERROR_RTMP_TRY_SIMPLE_HS 311
|
#define ERROR_RTMP_TRY_SIMPLE_HS 311
|
||||||
#define ERROR_RTMP_CH_SCHEMA 312
|
#define ERROR_RTMP_CH_SCHEMA 312
|
||||||
#define ERROR_RTMP_PACKET_SIZE 313
|
#define ERROR_RTMP_PACKET_SIZE 313
|
||||||
#define ERROR_RTMP_VHOST_NOT_FOUND 314
|
#define ERROR_RTMP_VHOST_NOT_FOUND 314
|
||||||
#define ERROR_RTMP_ACCESS_DENIED 315
|
#define ERROR_RTMP_ACCESS_DENIED 315
|
||||||
#define ERROR_RTMP_HANDSHAKE 316
|
#define ERROR_RTMP_HANDSHAKE 316
|
||||||
#define ERROR_RTMP_NO_REQUEST 317
|
#define ERROR_RTMP_NO_REQUEST 317
|
||||||
// if user use complex handshake, but without ssl,
|
// if user use complex handshake, but without ssl,
|
||||||
// 1. srs is ok, ignore and turn to simple handshake.
|
// 1. srs is ok, ignore and turn to simple handshake.
|
||||||
// 2. srs-librtmp return error, to terminate the program.
|
// 2. srs-librtmp return error, to terminate the program.
|
||||||
#define ERROR_RTMP_HS_SSL_REQUIRE 318
|
#define ERROR_RTMP_HS_SSL_REQUIRE 318
|
||||||
|
|
||||||
#define ERROR_SYSTEM_STREAM_INIT 400
|
#define ERROR_SYSTEM_STREAM_INIT 400
|
||||||
#define ERROR_SYSTEM_PACKET_INVALID 401
|
#define ERROR_SYSTEM_PACKET_INVALID 401
|
||||||
#define ERROR_SYSTEM_CLIENT_INVALID 402
|
#define ERROR_SYSTEM_CLIENT_INVALID 402
|
||||||
#define ERROR_SYSTEM_ASSERT_FAILED 403
|
#define ERROR_SYSTEM_ASSERT_FAILED 403
|
||||||
#define ERROR_SYSTEM_SIZE_NEGATIVE 404
|
#define ERROR_SYSTEM_SIZE_NEGATIVE 404
|
||||||
#define ERROR_SYSTEM_CONFIG_INVALID 405
|
#define ERROR_SYSTEM_CONFIG_INVALID 405
|
||||||
#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406
|
#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406
|
||||||
#define ERROR_SYSTEM_CONFIG_BLOCK_START 407
|
#define ERROR_SYSTEM_CONFIG_BLOCK_START 407
|
||||||
#define ERROR_SYSTEM_CONFIG_BLOCK_END 408
|
#define ERROR_SYSTEM_CONFIG_BLOCK_END 408
|
||||||
#define ERROR_SYSTEM_CONFIG_EOF 409
|
#define ERROR_SYSTEM_CONFIG_EOF 409
|
||||||
#define ERROR_SYSTEM_STREAM_BUSY 410
|
#define ERROR_SYSTEM_STREAM_BUSY 410
|
||||||
#define ERROR_SYSTEM_IP_INVALID 411
|
#define ERROR_SYSTEM_IP_INVALID 411
|
||||||
#define ERROR_SYSTEM_FORWARD_LOOP 412
|
#define ERROR_SYSTEM_FORWARD_LOOP 412
|
||||||
#define ERROR_SYSTEM_WAITPID 413
|
#define ERROR_SYSTEM_WAITPID 413
|
||||||
#define ERROR_SYSTEM_BANDWIDTH_KEY 414
|
#define ERROR_SYSTEM_BANDWIDTH_KEY 414
|
||||||
#define ERROR_SYSTEM_BANDWIDTH_DENIED 415
|
#define ERROR_SYSTEM_BANDWIDTH_DENIED 415
|
||||||
|
|
||||||
// see librtmp.
|
// see librtmp.
|
||||||
// failed when open ssl create the dh
|
// failed when open ssl create the dh
|
||||||
#define ERROR_OpenSslCreateDH 500
|
#define ERROR_OpenSslCreateDH 500
|
||||||
// failed when open ssl create the Private key.
|
// failed when open ssl create the Private key.
|
||||||
#define ERROR_OpenSslCreateP 501
|
#define ERROR_OpenSslCreateP 501
|
||||||
// when open ssl create G.
|
// when open ssl create G.
|
||||||
#define ERROR_OpenSslCreateG 502
|
#define ERROR_OpenSslCreateG 502
|
||||||
// when open ssl parse P1024
|
// when open ssl parse P1024
|
||||||
#define ERROR_OpenSslParseP1024 503
|
#define ERROR_OpenSslParseP1024 503
|
||||||
// when open ssl set G
|
// when open ssl set G
|
||||||
#define ERROR_OpenSslSetG 504
|
#define ERROR_OpenSslSetG 504
|
||||||
// when open ssl generate DHKeys
|
// when open ssl generate DHKeys
|
||||||
#define ERROR_OpenSslGenerateDHKeys 505
|
#define ERROR_OpenSslGenerateDHKeys 505
|
||||||
// when open ssl share key already computed.
|
// when open ssl share key already computed.
|
||||||
#define ERROR_OpenSslShareKeyComputed 506
|
#define ERROR_OpenSslShareKeyComputed 506
|
||||||
// when open ssl get shared key size.
|
// when open ssl get shared key size.
|
||||||
#define ERROR_OpenSslGetSharedKeySize 507
|
#define ERROR_OpenSslGetSharedKeySize 507
|
||||||
// when open ssl get peer public key.
|
// when open ssl get peer public key.
|
||||||
#define ERROR_OpenSslGetPeerPublicKey 508
|
#define ERROR_OpenSslGetPeerPublicKey 508
|
||||||
// when open ssl compute shared key.
|
// when open ssl compute shared key.
|
||||||
#define ERROR_OpenSslComputeSharedKey 509
|
#define ERROR_OpenSslComputeSharedKey 509
|
||||||
// when open ssl is invalid DH state.
|
// when open ssl is invalid DH state.
|
||||||
#define ERROR_OpenSslInvalidDHState 510
|
#define ERROR_OpenSslInvalidDHState 510
|
||||||
// when open ssl copy key
|
// when open ssl copy key
|
||||||
#define ERROR_OpenSslCopyKey 511
|
#define ERROR_OpenSslCopyKey 511
|
||||||
// when open ssl sha256 digest key invalid size.
|
// when open ssl sha256 digest key invalid size.
|
||||||
#define ERROR_OpenSslSha256DigestSize 512
|
#define ERROR_OpenSslSha256DigestSize 512
|
||||||
|
|
||||||
#define ERROR_HLS_METADATA 600
|
#define ERROR_HLS_METADATA 600
|
||||||
#define ERROR_HLS_DECODE_ERROR 601
|
#define ERROR_HLS_DECODE_ERROR 601
|
||||||
#define ERROR_HLS_CREATE_DIR 602
|
#define ERROR_HLS_CREATE_DIR 602
|
||||||
#define ERROR_HLS_OPEN_FAILED 603
|
#define ERROR_HLS_OPEN_FAILED 603
|
||||||
#define ERROR_HLS_WRITE_FAILED 604
|
#define ERROR_HLS_WRITE_FAILED 604
|
||||||
#define ERROR_HLS_AAC_FRAME_LENGTH 605
|
#define ERROR_HLS_AAC_FRAME_LENGTH 605
|
||||||
#define ERROR_HLS_AVC_SAMPLE_SIZE 606
|
#define ERROR_HLS_AVC_SAMPLE_SIZE 606
|
||||||
|
|
||||||
#define ERROR_ENCODER_VCODEC 700
|
#define ERROR_ENCODER_VCODEC 700
|
||||||
#define ERROR_ENCODER_OUTPUT 701
|
#define ERROR_ENCODER_OUTPUT 701
|
||||||
#define ERROR_ENCODER_ACHANNELS 702
|
#define ERROR_ENCODER_ACHANNELS 702
|
||||||
#define ERROR_ENCODER_ASAMPLE_RATE 703
|
#define ERROR_ENCODER_ASAMPLE_RATE 703
|
||||||
#define ERROR_ENCODER_ABITRATE 704
|
#define ERROR_ENCODER_ABITRATE 704
|
||||||
#define ERROR_ENCODER_ACODEC 705
|
#define ERROR_ENCODER_ACODEC 705
|
||||||
#define ERROR_ENCODER_VPRESET 706
|
#define ERROR_ENCODER_VPRESET 706
|
||||||
#define ERROR_ENCODER_VPROFILE 707
|
#define ERROR_ENCODER_VPROFILE 707
|
||||||
#define ERROR_ENCODER_VTHREADS 708
|
#define ERROR_ENCODER_VTHREADS 708
|
||||||
#define ERROR_ENCODER_VHEIGHT 709
|
#define ERROR_ENCODER_VHEIGHT 709
|
||||||
#define ERROR_ENCODER_VWIDTH 710
|
#define ERROR_ENCODER_VWIDTH 710
|
||||||
#define ERROR_ENCODER_VFPS 711
|
#define ERROR_ENCODER_VFPS 711
|
||||||
#define ERROR_ENCODER_VBITRATE 712
|
#define ERROR_ENCODER_VBITRATE 712
|
||||||
#define ERROR_ENCODER_FORK 713
|
#define ERROR_ENCODER_FORK 713
|
||||||
#define ERROR_ENCODER_LOOP 714
|
#define ERROR_ENCODER_LOOP 714
|
||||||
#define ERROR_ENCODER_OPEN 715
|
#define ERROR_ENCODER_OPEN 715
|
||||||
#define ERROR_ENCODER_DUP2 716
|
#define ERROR_ENCODER_DUP2 716
|
||||||
|
|
||||||
#define ERROR_HTTP_PARSE_URI 800
|
#define ERROR_HTTP_PARSE_URI 800
|
||||||
#define ERROR_HTTP_DATA_INVLIAD 801
|
#define ERROR_HTTP_DATA_INVLIAD 801
|
||||||
#define ERROR_HTTP_PARSE_HEADER 802
|
#define ERROR_HTTP_PARSE_HEADER 802
|
||||||
|
|
||||||
// system control message,
|
// system control message,
|
||||||
// not an error, but special control logic.
|
// not an error, but special control logic.
|
||||||
// sys ctl: rtmp close stream, support replay.
|
// sys ctl: rtmp close stream, support replay.
|
||||||
#define ERROR_CONTROL_RTMP_CLOSE 900
|
#define ERROR_CONTROL_RTMP_CLOSE 900
|
||||||
// FMLE stop publish and republish.
|
// FMLE stop publish and republish.
|
||||||
#define ERROR_CONTROL_REPUBLISH 901
|
#define ERROR_CONTROL_REPUBLISH 901
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether the error code is an system control error.
|
* whether the error code is an system control error.
|
||||||
|
|
|
@ -65,6 +65,6 @@ void ISrsThreadContext::generate_id()
|
||||||
|
|
||||||
int ISrsThreadContext::get_id()
|
int ISrsThreadContext::get_id()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,16 +110,16 @@ extern ISrsThreadContext* _srs_context;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#undef srs_verbose
|
#undef srs_verbose
|
||||||
#define srs_verbose(msg, ...) (void)0
|
#define srs_verbose(msg, ...) (void)0
|
||||||
#endif
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
#undef srs_info
|
#undef srs_info
|
||||||
#define srs_info(msg, ...) (void)0
|
#define srs_info(msg, ...) (void)0
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
#undef srs_trace
|
#undef srs_trace
|
||||||
#define srs_trace(msg, ...) (void)0
|
#define srs_trace(msg, ...) (void)0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,8 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
SrsStream::SrsStream()
|
SrsStream::SrsStream()
|
||||||
{
|
{
|
||||||
p = bytes = NULL;
|
p = bytes = NULL;
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsStream::~SrsStream()
|
SrsStream::~SrsStream()
|
||||||
|
@ -38,113 +38,113 @@ SrsStream::~SrsStream()
|
||||||
|
|
||||||
int SrsStream::initialize(char* _bytes, int _size)
|
int SrsStream::initialize(char* _bytes, int _size)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (!_bytes) {
|
if (!_bytes) {
|
||||||
ret = ERROR_SYSTEM_STREAM_INIT;
|
ret = ERROR_SYSTEM_STREAM_INIT;
|
||||||
srs_error("stream param bytes must not be NULL. ret=%d", ret);
|
srs_error("stream param bytes must not be NULL. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_size <= 0) {
|
if (_size <= 0) {
|
||||||
ret = ERROR_SYSTEM_STREAM_INIT;
|
ret = ERROR_SYSTEM_STREAM_INIT;
|
||||||
srs_error("stream param size must be positive. ret=%d", ret);
|
srs_error("stream param size must be positive. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = _size;
|
size = _size;
|
||||||
p = bytes = _bytes;
|
p = bytes = _bytes;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::reset()
|
void SrsStream::reset()
|
||||||
{
|
{
|
||||||
p = bytes;
|
p = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsStream::empty()
|
bool SrsStream::empty()
|
||||||
{
|
{
|
||||||
return !p || !bytes || (p >= bytes + size);
|
return !p || !bytes || (p >= bytes + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrsStream::require(int required_size)
|
bool SrsStream::require(int required_size)
|
||||||
{
|
{
|
||||||
return !empty() && (required_size <= bytes + size - p);
|
return !empty() && (required_size <= bytes + size - p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::skip(int size)
|
void SrsStream::skip(int size)
|
||||||
{
|
{
|
||||||
p += size;
|
p += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsStream::pos()
|
int SrsStream::pos()
|
||||||
{
|
{
|
||||||
return p - bytes;
|
return p - bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsStream::left()
|
int SrsStream::left()
|
||||||
{
|
{
|
||||||
return size - pos();
|
return size - pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
char* SrsStream::current()
|
char* SrsStream::current()
|
||||||
{
|
{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t SrsStream::read_1bytes()
|
int8_t SrsStream::read_1bytes()
|
||||||
{
|
{
|
||||||
srs_assert(require(1));
|
srs_assert(require(1));
|
||||||
|
|
||||||
return (int8_t)*p++;
|
return (int8_t)*p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t SrsStream::read_2bytes()
|
int16_t SrsStream::read_2bytes()
|
||||||
{
|
{
|
||||||
srs_assert(require(2));
|
srs_assert(require(2));
|
||||||
|
|
||||||
int16_t value;
|
int16_t value;
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
pp[1] = *p++;
|
pp[1] = *p++;
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t SrsStream::read_3bytes()
|
int32_t SrsStream::read_3bytes()
|
||||||
{
|
{
|
||||||
srs_assert(require(3));
|
srs_assert(require(3));
|
||||||
|
|
||||||
int32_t value = 0x00;
|
int32_t value = 0x00;
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
pp[2] = *p++;
|
pp[2] = *p++;
|
||||||
pp[1] = *p++;
|
pp[1] = *p++;
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t SrsStream::read_4bytes()
|
int32_t SrsStream::read_4bytes()
|
||||||
{
|
{
|
||||||
srs_assert(require(4));
|
srs_assert(require(4));
|
||||||
|
|
||||||
int32_t value;
|
int32_t value;
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
pp[3] = *p++;
|
pp[3] = *p++;
|
||||||
pp[2] = *p++;
|
pp[2] = *p++;
|
||||||
pp[1] = *p++;
|
pp[1] = *p++;
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SrsStream::read_8bytes()
|
int64_t SrsStream::read_8bytes()
|
||||||
{
|
{
|
||||||
srs_assert(require(8));
|
srs_assert(require(8));
|
||||||
|
|
||||||
int64_t value;
|
int64_t value;
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
pp[7] = *p++;
|
pp[7] = *p++;
|
||||||
pp[6] = *p++;
|
pp[6] = *p++;
|
||||||
pp[5] = *p++;
|
pp[5] = *p++;
|
||||||
|
@ -153,69 +153,69 @@ int64_t SrsStream::read_8bytes()
|
||||||
pp[2] = *p++;
|
pp[2] = *p++;
|
||||||
pp[1] = *p++;
|
pp[1] = *p++;
|
||||||
pp[0] = *p++;
|
pp[0] = *p++;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SrsStream::read_string(int len)
|
std::string SrsStream::read_string(int len)
|
||||||
{
|
{
|
||||||
srs_assert(require(len));
|
srs_assert(require(len));
|
||||||
|
|
||||||
std::string value;
|
std::string value;
|
||||||
value.append(p, len);
|
value.append(p, len);
|
||||||
|
|
||||||
p += len;
|
p += len;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::write_1bytes(int8_t value)
|
void SrsStream::write_1bytes(int8_t value)
|
||||||
{
|
{
|
||||||
srs_assert(require(1));
|
srs_assert(require(1));
|
||||||
|
|
||||||
*p++ = value;
|
*p++ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::write_2bytes(int16_t value)
|
void SrsStream::write_2bytes(int16_t value)
|
||||||
{
|
{
|
||||||
srs_assert(require(2));
|
srs_assert(require(2));
|
||||||
|
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
*p++ = pp[1];
|
*p++ = pp[1];
|
||||||
*p++ = pp[0];
|
*p++ = pp[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::write_4bytes(int32_t value)
|
void SrsStream::write_4bytes(int32_t value)
|
||||||
{
|
{
|
||||||
srs_assert(require(4));
|
srs_assert(require(4));
|
||||||
|
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
*p++ = pp[3];
|
*p++ = pp[3];
|
||||||
*p++ = pp[2];
|
*p++ = pp[2];
|
||||||
*p++ = pp[1];
|
*p++ = pp[1];
|
||||||
*p++ = pp[0];
|
*p++ = pp[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::write_8bytes(int64_t value)
|
void SrsStream::write_8bytes(int64_t value)
|
||||||
{
|
{
|
||||||
srs_assert(require(8));
|
srs_assert(require(8));
|
||||||
|
|
||||||
pp = (char*)&value;
|
pp = (char*)&value;
|
||||||
*p++ = pp[7];
|
*p++ = pp[7];
|
||||||
*p++ = pp[6];
|
*p++ = pp[6];
|
||||||
*p++ = pp[5];
|
*p++ = pp[5];
|
||||||
*p++ = pp[4];
|
*p++ = pp[4];
|
||||||
*p++ = pp[3];
|
*p++ = pp[3];
|
||||||
*p++ = pp[2];
|
*p++ = pp[2];
|
||||||
*p++ = pp[1];
|
*p++ = pp[1];
|
||||||
*p++ = pp[0];
|
*p++ = pp[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStream::write_string(std::string value)
|
void SrsStream::write_string(std::string value)
|
||||||
{
|
{
|
||||||
srs_assert(require(value.length()));
|
srs_assert(require(value.length()));
|
||||||
|
|
||||||
memcpy(p, value.data(), value.length());
|
memcpy(p, value.data(), value.length());
|
||||||
p += value.length();
|
p += value.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,95 +36,95 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class SrsStream
|
class SrsStream
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
char* p;
|
char* p;
|
||||||
char* pp;
|
char* pp;
|
||||||
char* bytes;
|
char* bytes;
|
||||||
int size;
|
int size;
|
||||||
public:
|
public:
|
||||||
SrsStream();
|
SrsStream();
|
||||||
virtual ~SrsStream();
|
virtual ~SrsStream();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* initialize the stream from bytes.
|
* initialize the stream from bytes.
|
||||||
* @_bytes, must not be NULL, or return error.
|
* @_bytes, must not be NULL, or return error.
|
||||||
* @_size, must be positive, or return error.
|
* @_size, must be positive, or return error.
|
||||||
* @remark, stream never free the _bytes, user must free it.
|
* @remark, stream never free the _bytes, user must free it.
|
||||||
*/
|
*/
|
||||||
virtual int initialize(char* _bytes, int _size);
|
virtual int initialize(char* _bytes, int _size);
|
||||||
/**
|
/**
|
||||||
* reset the position to beginning.
|
* reset the position to beginning.
|
||||||
*/
|
*/
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
/**
|
/**
|
||||||
* whether stream is empty.
|
* whether stream is empty.
|
||||||
* if empty, never read or write.
|
* if empty, never read or write.
|
||||||
*/
|
*/
|
||||||
virtual bool empty();
|
virtual bool empty();
|
||||||
/**
|
/**
|
||||||
* whether required size is ok.
|
* whether required size is ok.
|
||||||
* @return true if stream can read/write specified required_size bytes.
|
* @return true if stream can read/write specified required_size bytes.
|
||||||
*/
|
*/
|
||||||
virtual bool require(int required_size);
|
virtual bool require(int required_size);
|
||||||
/**
|
/**
|
||||||
* to skip some size.
|
* to skip some size.
|
||||||
* @size can be any value. positive to forward; nagetive to backward.
|
* @size can be any value. positive to forward; nagetive to backward.
|
||||||
*/
|
*/
|
||||||
virtual void skip(int size);
|
virtual void skip(int size);
|
||||||
/**
|
/**
|
||||||
* tell the current pos.
|
* tell the current pos.
|
||||||
*/
|
*/
|
||||||
virtual int pos();
|
virtual int pos();
|
||||||
/**
|
/**
|
||||||
* left size of bytes.
|
* left size of bytes.
|
||||||
*/
|
*/
|
||||||
virtual int left();
|
virtual int left();
|
||||||
virtual char* current();
|
virtual char* current();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* get 1bytes char from stream.
|
* get 1bytes char from stream.
|
||||||
*/
|
*/
|
||||||
virtual int8_t read_1bytes();
|
virtual int8_t read_1bytes();
|
||||||
/**
|
/**
|
||||||
* get 2bytes int from stream.
|
* get 2bytes int from stream.
|
||||||
*/
|
*/
|
||||||
virtual int16_t read_2bytes();
|
virtual int16_t read_2bytes();
|
||||||
/**
|
/**
|
||||||
* get 3bytes int from stream.
|
* get 3bytes int from stream.
|
||||||
*/
|
*/
|
||||||
virtual int32_t read_3bytes();
|
virtual int32_t read_3bytes();
|
||||||
/**
|
/**
|
||||||
* get 4bytes int from stream.
|
* get 4bytes int from stream.
|
||||||
*/
|
*/
|
||||||
virtual int32_t read_4bytes();
|
virtual int32_t read_4bytes();
|
||||||
/**
|
/**
|
||||||
* get 8bytes int from stream.
|
* get 8bytes int from stream.
|
||||||
*/
|
*/
|
||||||
virtual int64_t read_8bytes();
|
virtual int64_t read_8bytes();
|
||||||
/**
|
/**
|
||||||
* get string from stream, length specifies by param len.
|
* get string from stream, length specifies by param len.
|
||||||
*/
|
*/
|
||||||
virtual std::string read_string(int len);
|
virtual std::string read_string(int len);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* write 1bytes char to stream.
|
* write 1bytes char to stream.
|
||||||
*/
|
*/
|
||||||
virtual void write_1bytes(int8_t value);
|
virtual void write_1bytes(int8_t value);
|
||||||
/**
|
/**
|
||||||
* write 2bytes int to stream.
|
* write 2bytes int to stream.
|
||||||
*/
|
*/
|
||||||
virtual void write_2bytes(int16_t value);
|
virtual void write_2bytes(int16_t value);
|
||||||
/**
|
/**
|
||||||
* write 4bytes int to stream.
|
* write 4bytes int to stream.
|
||||||
*/
|
*/
|
||||||
virtual void write_4bytes(int32_t value);
|
virtual void write_4bytes(int32_t value);
|
||||||
/**
|
/**
|
||||||
* write 8bytes int to stream.
|
* write 8bytes int to stream.
|
||||||
*/
|
*/
|
||||||
virtual void write_8bytes(int64_t value);
|
virtual void write_8bytes(int64_t value);
|
||||||
/**
|
/**
|
||||||
* write string to stream
|
* write string to stream
|
||||||
*/
|
*/
|
||||||
virtual void write_string(std::string value);
|
virtual void write_string(std::string value);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -34,25 +34,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#ifndef ST_UTIME_NO_TIMEOUT
|
#ifndef ST_UTIME_NO_TIMEOUT
|
||||||
#define ST_UTIME_NO_TIMEOUT -1
|
#define ST_UTIME_NO_TIMEOUT -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SimpleSocketStream::SimpleSocketStream()
|
SimpleSocketStream::SimpleSocketStream()
|
||||||
{
|
{
|
||||||
fd = -1;
|
fd = -1;
|
||||||
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
|
send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT;
|
||||||
recv_bytes = send_bytes = 0;
|
recv_bytes = send_bytes = 0;
|
||||||
|
|
||||||
srs_update_system_time_ms();
|
srs_update_system_time_ms();
|
||||||
start_time_ms = srs_get_system_time_ms();
|
start_time_ms = srs_get_system_time_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleSocketStream::~SimpleSocketStream()
|
SimpleSocketStream::~SimpleSocketStream()
|
||||||
{
|
{
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
::close(fd);
|
::close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::create_socket()
|
int SimpleSocketStream::create_socket()
|
||||||
|
@ -61,7 +61,7 @@ int SimpleSocketStream::create_socket()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::connect(const char* server_ip, int port)
|
int SimpleSocketStream::connect(const char* server_ip, int port)
|
||||||
|
@ -75,23 +75,23 @@ int SimpleSocketStream::connect(const char* server_ip, int port)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISrsBufferReader
|
// ISrsBufferReader
|
||||||
int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
|
int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
*nread = ::recv(fd, (void*)buf, size, 0);
|
*nread = ::recv(fd, (void*)buf, size, 0);
|
||||||
|
|
||||||
// On success a non-negative integer indicating the number of bytes actually read is returned
|
// On success a non-negative integer indicating the number of bytes actually read is returned
|
||||||
// (a value of 0 means the network connection is closed or end of file is reached).
|
// (a value of 0 means the network connection is closed or end of file is reached).
|
||||||
if (*nread <= 0) {
|
if (*nread <= 0) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*nread == 0) {
|
if (*nread == 0) {
|
||||||
errno = ECONNRESET;
|
errno = ECONNRESET;
|
||||||
}
|
}
|
||||||
|
@ -100,131 +100,131 @@ int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_bytes += *nread;
|
recv_bytes += *nread;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISrsProtocolReader
|
// ISrsProtocolReader
|
||||||
void SimpleSocketStream::set_recv_timeout(int64_t timeout_us)
|
void SimpleSocketStream::set_recv_timeout(int64_t timeout_us)
|
||||||
{
|
{
|
||||||
recv_timeout = timeout_us;
|
recv_timeout = timeout_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SimpleSocketStream::get_recv_timeout()
|
int64_t SimpleSocketStream::get_recv_timeout()
|
||||||
{
|
{
|
||||||
return recv_timeout;
|
return recv_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SimpleSocketStream::get_recv_bytes()
|
int64_t SimpleSocketStream::get_recv_bytes()
|
||||||
{
|
{
|
||||||
return recv_bytes;
|
return recv_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::get_recv_kbps()
|
int SimpleSocketStream::get_recv_kbps()
|
||||||
{
|
{
|
||||||
srs_update_system_time_ms();
|
srs_update_system_time_ms();
|
||||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||||
|
|
||||||
if (diff_ms <= 0) {
|
if (diff_ms <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recv_bytes * 8 / diff_ms;
|
return recv_bytes * 8 / diff_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISrsProtocolWriter
|
// ISrsProtocolWriter
|
||||||
void SimpleSocketStream::set_send_timeout(int64_t timeout_us)
|
void SimpleSocketStream::set_send_timeout(int64_t timeout_us)
|
||||||
{
|
{
|
||||||
send_timeout = timeout_us;
|
send_timeout = timeout_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SimpleSocketStream::get_send_timeout()
|
int64_t SimpleSocketStream::get_send_timeout()
|
||||||
{
|
{
|
||||||
return send_timeout;
|
return send_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t SimpleSocketStream::get_send_bytes()
|
int64_t SimpleSocketStream::get_send_bytes()
|
||||||
{
|
{
|
||||||
return send_bytes;
|
return send_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::get_send_kbps()
|
int SimpleSocketStream::get_send_kbps()
|
||||||
{
|
{
|
||||||
srs_update_system_time_ms();
|
srs_update_system_time_ms();
|
||||||
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
int64_t diff_ms = srs_get_system_time_ms() - start_time_ms;
|
||||||
|
|
||||||
if (diff_ms <= 0) {
|
if (diff_ms <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_bytes * 8 / diff_ms;
|
return send_bytes * 8 / diff_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
|
int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
*nwrite = ::writev(fd, iov, iov_size);
|
*nwrite = ::writev(fd, iov, iov_size);
|
||||||
|
|
||||||
if (*nwrite <= 0) {
|
if (*nwrite <= 0) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SOCKET_WRITE;
|
return ERROR_SOCKET_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_bytes += *nwrite;
|
send_bytes += *nwrite;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ISrsProtocolReaderWriter
|
// ISrsProtocolReaderWriter
|
||||||
bool SimpleSocketStream::is_never_timeout(int64_t timeout_us)
|
bool SimpleSocketStream::is_never_timeout(int64_t timeout_us)
|
||||||
{
|
{
|
||||||
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
|
return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread)
|
int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
size_t left = size;
|
size_t left = size;
|
||||||
*nread = 0;
|
*nread = 0;
|
||||||
|
|
||||||
while (left > 0) {
|
while (left > 0) {
|
||||||
char* this_buf = (char*)buf + *nread;
|
char* this_buf = (char*)buf + *nread;
|
||||||
ssize_t this_nread;
|
ssize_t this_nread;
|
||||||
|
|
||||||
if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) {
|
if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
*nread += this_nread;
|
*nread += this_nread;
|
||||||
left -= this_nread;
|
left -= this_nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_bytes += *nread;
|
recv_bytes += *nread;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite)
|
int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
*nwrite = ::send(fd, (void*)buf, size, 0);
|
*nwrite = ::send(fd, (void*)buf, size, 0);
|
||||||
|
|
||||||
if (*nwrite <= 0) {
|
if (*nwrite <= 0) {
|
||||||
if (errno == ETIME) {
|
if (errno == ETIME) {
|
||||||
return ERROR_SOCKET_TIMEOUT;
|
return ERROR_SOCKET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SOCKET_WRITE;
|
return ERROR_SOCKET_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_bytes += *nwrite;
|
send_bytes += *nwrite;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,37 +39,37 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class SimpleSocketStream : public ISrsProtocolReaderWriter
|
class SimpleSocketStream : public ISrsProtocolReaderWriter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int64_t start_time_ms;
|
int64_t start_time_ms;
|
||||||
int64_t recv_timeout;
|
int64_t recv_timeout;
|
||||||
int64_t send_timeout;
|
int64_t send_timeout;
|
||||||
int64_t recv_bytes;
|
int64_t recv_bytes;
|
||||||
int64_t send_bytes;
|
int64_t send_bytes;
|
||||||
int fd;
|
int fd;
|
||||||
public:
|
public:
|
||||||
SimpleSocketStream();
|
SimpleSocketStream();
|
||||||
virtual ~SimpleSocketStream();
|
virtual ~SimpleSocketStream();
|
||||||
public:
|
public:
|
||||||
virtual int create_socket();
|
virtual int create_socket();
|
||||||
virtual int connect(const char* server, int port);
|
virtual int connect(const char* server, int port);
|
||||||
// ISrsBufferReader
|
// ISrsBufferReader
|
||||||
public:
|
public:
|
||||||
virtual int read(const void* buf, size_t size, ssize_t* nread);
|
virtual int read(const void* buf, size_t size, ssize_t* nread);
|
||||||
// ISrsProtocolReader
|
// ISrsProtocolReader
|
||||||
public:
|
public:
|
||||||
virtual void set_recv_timeout(int64_t timeout_us);
|
virtual void set_recv_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_recv_timeout();
|
virtual int64_t get_recv_timeout();
|
||||||
virtual int64_t get_recv_bytes();
|
virtual int64_t get_recv_bytes();
|
||||||
virtual int get_recv_kbps();
|
virtual int get_recv_kbps();
|
||||||
// ISrsProtocolWriter
|
// ISrsProtocolWriter
|
||||||
public:
|
public:
|
||||||
virtual void set_send_timeout(int64_t timeout_us);
|
virtual void set_send_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_send_timeout();
|
virtual int64_t get_send_timeout();
|
||||||
virtual int64_t get_send_bytes();
|
virtual int64_t get_send_bytes();
|
||||||
virtual int get_send_kbps();
|
virtual int get_send_kbps();
|
||||||
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
|
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
|
||||||
// ISrsProtocolReaderWriter
|
// ISrsProtocolReaderWriter
|
||||||
public:
|
public:
|
||||||
virtual bool is_never_timeout(int64_t timeout_us);
|
virtual bool is_never_timeout(int64_t timeout_us);
|
||||||
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
|
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
|
||||||
virtual int write(const void* buf, size_t size, ssize_t* nwrite);
|
virtual int write(const void* buf, size_t size, ssize_t* nwrite);
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,9 +38,9 @@ using namespace std;
|
||||||
|
|
||||||
// if user want to define log, define the folowing macro.
|
// if user want to define log, define the folowing macro.
|
||||||
#ifndef SRS_RTMP_USER_DEFINED_LOG
|
#ifndef SRS_RTMP_USER_DEFINED_LOG
|
||||||
// kernel module.
|
// kernel module.
|
||||||
ISrsLog* _srs_log = new ISrsLog();
|
ISrsLog* _srs_log = new ISrsLog();
|
||||||
ISrsThreadContext* _srs_context = new ISrsThreadContext();
|
ISrsThreadContext* _srs_context = new ISrsThreadContext();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,14 +48,14 @@ using namespace std;
|
||||||
*/
|
*/
|
||||||
struct Context
|
struct Context
|
||||||
{
|
{
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string tcUrl;
|
std::string tcUrl;
|
||||||
std::string host;
|
std::string host;
|
||||||
std::string port;
|
std::string port;
|
||||||
std::string vhost;
|
std::string vhost;
|
||||||
std::string app;
|
std::string app;
|
||||||
std::string stream;
|
std::string stream;
|
||||||
|
|
||||||
SrsRtmpClient* rtmp;
|
SrsRtmpClient* rtmp;
|
||||||
SimpleSocketStream* skt;
|
SimpleSocketStream* skt;
|
||||||
int stream_id;
|
int stream_id;
|
||||||
|
@ -73,68 +73,68 @@ struct Context
|
||||||
|
|
||||||
int srs_librtmp_context_connect(Context* context)
|
int srs_librtmp_context_connect(Context* context)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// parse uri
|
// parse uri
|
||||||
size_t pos = string::npos;
|
size_t pos = string::npos;
|
||||||
string uri = context->url;
|
string uri = context->url;
|
||||||
// tcUrl, stream
|
// tcUrl, stream
|
||||||
if ((pos = uri.rfind("/")) != string::npos) {
|
if ((pos = uri.rfind("/")) != string::npos) {
|
||||||
context->stream = uri.substr(pos + 1);
|
context->stream = uri.substr(pos + 1);
|
||||||
context->tcUrl = uri = uri.substr(0, pos);
|
context->tcUrl = uri = uri.substr(0, pos);
|
||||||
}
|
}
|
||||||
// schema
|
// schema
|
||||||
if ((pos = uri.find("rtmp://")) != string::npos) {
|
if ((pos = uri.find("rtmp://")) != string::npos) {
|
||||||
uri = uri.substr(pos + 7);
|
uri = uri.substr(pos + 7);
|
||||||
}
|
}
|
||||||
// host/vhost/port
|
// host/vhost/port
|
||||||
if ((pos = uri.find(":")) != string::npos) {
|
if ((pos = uri.find(":")) != string::npos) {
|
||||||
context->vhost = context->host = uri.substr(0, pos);
|
context->vhost = context->host = uri.substr(0, pos);
|
||||||
uri = uri.substr(pos + 1);
|
uri = uri.substr(pos + 1);
|
||||||
|
|
||||||
if ((pos = uri.find("/")) != string::npos) {
|
if ((pos = uri.find("/")) != string::npos) {
|
||||||
context->port = uri.substr(0, pos);
|
context->port = uri.substr(0, pos);
|
||||||
uri = uri.substr(pos + 1);
|
uri = uri.substr(pos + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((pos = uri.find("/")) != string::npos) {
|
if ((pos = uri.find("/")) != string::npos) {
|
||||||
context->vhost = context->host = uri.substr(0, pos);
|
context->vhost = context->host = uri.substr(0, pos);
|
||||||
uri = uri.substr(pos + 1);
|
uri = uri.substr(pos + 1);
|
||||||
}
|
}
|
||||||
context->port = RTMP_DEFAULT_PORT;
|
context->port = RTMP_DEFAULT_PORT;
|
||||||
}
|
}
|
||||||
// app
|
// app
|
||||||
context->app = uri;
|
context->app = uri;
|
||||||
// query of app
|
// query of app
|
||||||
if ((pos = uri.find("?")) != string::npos) {
|
if ((pos = uri.find("?")) != string::npos) {
|
||||||
context->app = uri.substr(0, pos);
|
context->app = uri.substr(0, pos);
|
||||||
string query = uri.substr(pos + 1);
|
string query = uri.substr(pos + 1);
|
||||||
if ((pos = query.find("vhost=")) != string::npos) {
|
if ((pos = query.find("vhost=")) != string::npos) {
|
||||||
context->vhost = query.substr(pos + 6);
|
context->vhost = query.substr(pos + 6);
|
||||||
if ((pos = context->vhost.find("&")) != string::npos) {
|
if ((pos = context->vhost.find("&")) != string::npos) {
|
||||||
context->vhost = context->vhost.substr(pos);
|
context->vhost = context->vhost.substr(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
srs_freep(context->skt);
|
srs_freep(context->skt);
|
||||||
context->skt = new SimpleSocketStream();
|
context->skt = new SimpleSocketStream();
|
||||||
|
|
||||||
if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
|
if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect to server:port
|
// connect to server:port
|
||||||
string server = srs_dns_resolve(context->host);
|
string server = srs_dns_resolve(context->host);
|
||||||
if (server.empty()) {
|
if (server.empty()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
|
if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -144,7 +144,7 @@ extern "C"{
|
||||||
srs_rtmp_t srs_rtmp_create(const char* url)
|
srs_rtmp_t srs_rtmp_create(const char* url)
|
||||||
{
|
{
|
||||||
Context* context = new Context();
|
Context* context = new Context();
|
||||||
context->url = url;
|
context->url = url;
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,8 +158,8 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp)
|
||||||
|
|
||||||
int srs_simple_handshake(srs_rtmp_t rtmp)
|
int srs_simple_handshake(srs_rtmp_t rtmp)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
|
@ -167,26 +167,26 @@ int srs_simple_handshake(srs_rtmp_t rtmp)
|
||||||
if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
|
if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple handshake
|
// simple handshake
|
||||||
srs_freep(context->rtmp);
|
srs_freep(context->rtmp);
|
||||||
context->rtmp = new SrsRtmpClient(context->skt);
|
context->rtmp = new SrsRtmpClient(context->skt);
|
||||||
|
|
||||||
if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {
|
if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_complex_handshake(srs_rtmp_t rtmp)
|
int srs_complex_handshake(srs_rtmp_t rtmp)
|
||||||
{
|
{
|
||||||
#ifndef SRS_SSL
|
#ifndef SRS_SSL
|
||||||
return ERROR_RTMP_HS_SSL_REQUIRE;
|
return ERROR_RTMP_HS_SSL_REQUIRE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
|
@ -194,43 +194,43 @@ int srs_complex_handshake(srs_rtmp_t rtmp)
|
||||||
if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
|
if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// complex handshake
|
// complex handshake
|
||||||
srs_freep(context->rtmp);
|
srs_freep(context->rtmp);
|
||||||
context->rtmp = new SrsRtmpClient(context->skt);
|
context->rtmp = new SrsRtmpClient(context->skt);
|
||||||
|
|
||||||
if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {
|
if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_connect_app(srs_rtmp_t rtmp)
|
int srs_connect_app(srs_rtmp_t rtmp)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
string tcUrl = "rtmp://";
|
string tcUrl = "rtmp://";
|
||||||
tcUrl += context->vhost;
|
tcUrl += context->vhost;
|
||||||
tcUrl += ":";
|
tcUrl += ":";
|
||||||
tcUrl += context->port;
|
tcUrl += context->port;
|
||||||
tcUrl += "/";
|
tcUrl += "/";
|
||||||
tcUrl += context->app;
|
tcUrl += context->app;
|
||||||
|
|
||||||
if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {
|
if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_play_stream(srs_rtmp_t rtmp)
|
int srs_play_stream(srs_rtmp_t rtmp)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
|
@ -241,13 +241,13 @@ int srs_play_stream(srs_rtmp_t rtmp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_publish_stream(srs_rtmp_t rtmp)
|
int srs_publish_stream(srs_rtmp_t rtmp)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
|
@ -255,30 +255,30 @@ int srs_publish_stream(srs_rtmp_t rtmp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* srs_type2string(int type)
|
const char* srs_type2string(int type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SRS_RTMP_TYPE_AUDIO: return "Audio";
|
case SRS_RTMP_TYPE_AUDIO: return "Audio";
|
||||||
case SRS_RTMP_TYPE_VIDEO: return "Video";
|
case SRS_RTMP_TYPE_VIDEO: return "Video";
|
||||||
case SRS_RTMP_TYPE_SCRIPT: return "Data";
|
case SRS_RTMP_TYPE_SCRIPT: return "Data";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size)
|
int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size)
|
||||||
{
|
{
|
||||||
*type = 0;
|
*type = 0;
|
||||||
*timestamp = 0;
|
*timestamp = 0;
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
*size = 0;
|
*size = 0;
|
||||||
|
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
|
@ -322,81 +322,81 @@ int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** dat
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size)
|
int srs_write_packet(srs_rtmp_t rtmp, int type, u_int32_t timestamp, char* data, int size)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(rtmp != NULL);
|
srs_assert(rtmp != NULL);
|
||||||
Context* context = (Context*)rtmp;
|
Context* context = (Context*)rtmp;
|
||||||
|
|
||||||
SrsSharedPtrMessage* msg = NULL;
|
SrsSharedPtrMessage* msg = NULL;
|
||||||
|
|
||||||
if (type == SRS_RTMP_TYPE_AUDIO) {
|
if (type == SRS_RTMP_TYPE_AUDIO) {
|
||||||
SrsMessageHeader header;
|
SrsMessageHeader header;
|
||||||
header.initialize_audio(size, timestamp, context->stream_id);
|
header.initialize_audio(size, timestamp, context->stream_id);
|
||||||
|
|
||||||
msg = new SrsSharedPtrMessage();
|
msg = new SrsSharedPtrMessage();
|
||||||
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
|
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
|
||||||
srs_freepa(data);
|
srs_freepa(data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
} else if (type == SRS_RTMP_TYPE_VIDEO) {
|
} else if (type == SRS_RTMP_TYPE_VIDEO) {
|
||||||
SrsMessageHeader header;
|
SrsMessageHeader header;
|
||||||
header.initialize_video(size, timestamp, context->stream_id);
|
header.initialize_video(size, timestamp, context->stream_id);
|
||||||
|
|
||||||
msg = new SrsSharedPtrMessage();
|
msg = new SrsSharedPtrMessage();
|
||||||
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
|
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
|
||||||
srs_freepa(data);
|
srs_freepa(data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
|
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
|
||||||
SrsMessageHeader header;
|
SrsMessageHeader header;
|
||||||
header.initialize_amf0_script(size, context->stream_id);
|
header.initialize_amf0_script(size, context->stream_id);
|
||||||
|
|
||||||
msg = new SrsSharedPtrMessage();
|
msg = new SrsSharedPtrMessage();
|
||||||
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
|
if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) {
|
||||||
srs_freepa(data);
|
srs_freepa(data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg) {
|
if (msg) {
|
||||||
// send out encoded msg.
|
// send out encoded msg.
|
||||||
if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// directly free data if not sent out.
|
// directly free data if not sent out.
|
||||||
srs_freepa(data);
|
srs_freepa(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_ssl_enabled()
|
int srs_ssl_enabled()
|
||||||
{
|
{
|
||||||
#ifndef SRS_SSL
|
#ifndef SRS_SSL
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_version_major()
|
int srs_version_major()
|
||||||
{
|
{
|
||||||
return ::atoi(VERSION_MAJOR);
|
return ::atoi(VERSION_MAJOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_version_minor()
|
int srs_version_minor()
|
||||||
{
|
{
|
||||||
return ::atoi(VERSION_MINOR);
|
return ::atoi(VERSION_MINOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_version_revision()
|
int srs_version_revision()
|
||||||
{
|
{
|
||||||
return ::atoi(VERSION_REVISION);
|
return ::atoi(VERSION_REVISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -48,7 +48,7 @@ typedef void* srs_rtmp_t;
|
||||||
/**
|
/**
|
||||||
* create/destroy a rtmp protocol stack.
|
* create/destroy a rtmp protocol stack.
|
||||||
* @url rtmp url, for example:
|
* @url rtmp url, for example:
|
||||||
* rtmp://127.0.0.1/live/livestream
|
* rtmp://127.0.0.1/live/livestream
|
||||||
* @return a rtmp handler, or NULL if error occured.
|
* @return a rtmp handler, or NULL if error occured.
|
||||||
*/
|
*/
|
||||||
srs_rtmp_t srs_rtmp_create(const char* url);
|
srs_rtmp_t srs_rtmp_create(const char* url);
|
||||||
|
@ -113,23 +113,23 @@ int srs_publish_stream(srs_rtmp_t rtmp);
|
||||||
#define SRS_RTMP_TYPE_SCRIPT 18
|
#define SRS_RTMP_TYPE_SCRIPT 18
|
||||||
/**
|
/**
|
||||||
* convert the flv tag type to string.
|
* convert the flv tag type to string.
|
||||||
* SRS_RTMP_TYPE_AUDIO to "Audio"
|
* SRS_RTMP_TYPE_AUDIO to "Audio"
|
||||||
* SRS_RTMP_TYPE_VIDEO to "Video"
|
* SRS_RTMP_TYPE_VIDEO to "Video"
|
||||||
* SRS_RTMP_TYPE_SCRIPT to "Data"
|
* SRS_RTMP_TYPE_SCRIPT to "Data"
|
||||||
* otherwise, "Unknown"
|
* otherwise, "Unknown"
|
||||||
*/
|
*/
|
||||||
const char* srs_type2string(int type);
|
const char* srs_type2string(int type);
|
||||||
/**
|
/**
|
||||||
* read a audio/video/script-data packet from rtmp stream.
|
* read a audio/video/script-data packet from rtmp stream.
|
||||||
* @param type, output the packet type, macros:
|
* @param type, output the packet type, macros:
|
||||||
* SRS_RTMP_TYPE_AUDIO, FlvTagAudio
|
* SRS_RTMP_TYPE_AUDIO, FlvTagAudio
|
||||||
* SRS_RTMP_TYPE_VIDEO, FlvTagVideo
|
* SRS_RTMP_TYPE_VIDEO, FlvTagVideo
|
||||||
* SRS_RTMP_TYPE_SCRIPT, FlvTagScript
|
* SRS_RTMP_TYPE_SCRIPT, FlvTagScript
|
||||||
* @param timestamp, in ms, overflow in 50days
|
* @param timestamp, in ms, overflow in 50days
|
||||||
* @param data, the packet data, according to type:
|
* @param data, the packet data, according to type:
|
||||||
* FlvTagAudio, @see "E.4.2.1 AUDIODATA"
|
* FlvTagAudio, @see "E.4.2.1 AUDIODATA"
|
||||||
* FlvTagVideo, @see "E.4.3.1 VIDEODATA"
|
* FlvTagVideo, @see "E.4.3.1 VIDEODATA"
|
||||||
* FlvTagScript, @see "E.4.4.1 SCRIPTDATA"
|
* FlvTagScript, @see "E.4.4.1 SCRIPTDATA"
|
||||||
* @param size, size of packet.
|
* @param size, size of packet.
|
||||||
* @return the error code. 0 for success; otherwise, error.
|
* @return the error code. 0 for success; otherwise, error.
|
||||||
*
|
*
|
||||||
|
|
|
@ -158,8 +158,8 @@ public:
|
||||||
private:
|
private:
|
||||||
int connect_server();
|
int connect_server();
|
||||||
private:
|
private:
|
||||||
st_netfd_t stfd;
|
st_netfd_t stfd;
|
||||||
ISrsProtocolReaderWriter* skt;
|
ISrsProtocolReaderWriter* skt;
|
||||||
SrsBandCheckClient* bandCheck_Client;
|
SrsBandCheckClient* bandCheck_Client;
|
||||||
std::string server_address;
|
std::string server_address;
|
||||||
int server_port;
|
int server_port;
|
||||||
|
@ -493,8 +493,8 @@ int SrsBandCheckClient::expect_stop_pub()
|
||||||
this->set_recv_timeout(1000 * 1000);
|
this->set_recv_timeout(1000 * 1000);
|
||||||
this->set_send_timeout(1000 * 1000);
|
this->set_send_timeout(1000 * 1000);
|
||||||
|
|
||||||
SrsCommonMessage* msg;
|
SrsCommonMessage* msg;
|
||||||
SrsBandwidthPacket* pkt;
|
SrsBandwidthPacket* pkt;
|
||||||
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(this->protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(this->protocol, &msg, &pkt)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -641,16 +641,16 @@ int SrsBandCheckClient::send_final()
|
||||||
|
|
||||||
SrsBandCheck::SrsBandCheck()
|
SrsBandCheck::SrsBandCheck()
|
||||||
{
|
{
|
||||||
skt = NULL;
|
skt = NULL;
|
||||||
bandCheck_Client = NULL;
|
bandCheck_Client = NULL;
|
||||||
stfd = NULL;
|
stfd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsBandCheck::~SrsBandCheck()
|
SrsBandCheck::~SrsBandCheck()
|
||||||
{
|
{
|
||||||
srs_freep(bandCheck_Client);
|
srs_freep(bandCheck_Client);
|
||||||
srs_freep(skt);
|
srs_freep(skt);
|
||||||
srs_close_stfd(stfd);
|
srs_close_stfd(stfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsBandCheck::check(const std::string &app, const std::string &tcUrl)
|
int SrsBandCheck::check(const std::string &app, const std::string &tcUrl)
|
||||||
|
@ -709,7 +709,7 @@ int SrsBandCheck::connect_server()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
skt = new SrsSocket(stfd);
|
skt = new SrsSocket(stfd);
|
||||||
bandCheck_Client = new SrsBandCheckClient(skt);
|
bandCheck_Client = new SrsBandCheckClient(skt);
|
||||||
|
|
||||||
// connect to server.
|
// connect to server.
|
||||||
|
@ -757,7 +757,7 @@ int init_st()
|
||||||
void print_help(char** argv)
|
void print_help(char** argv)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"Usage: %s [OPTION]...\n"
|
"Usage: %s [OPTION]...\n"
|
||||||
"test band width from client to rtmp server.\n"
|
"test band width from client to rtmp server.\n"
|
||||||
"Mandatory arguments to long options are mandatory for short options too.\n"
|
"Mandatory arguments to long options are mandatory for short options too.\n"
|
||||||
" -i, --ip the ip or domain that to test\n"
|
" -i, --ip the ip or domain that to test\n"
|
||||||
|
@ -767,8 +767,8 @@ void print_help(char** argv)
|
||||||
" -V, --version output version information and exit \n"
|
" -V, --version output version information and exit \n"
|
||||||
" -h, --help display this help and exit \n"
|
" -h, --help display this help and exit \n"
|
||||||
"\n"
|
"\n"
|
||||||
"For example:\n"
|
"For example:\n"
|
||||||
" %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e"
|
" %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e"
|
||||||
"\n\n"
|
"\n\n"
|
||||||
"Exit status:\n"
|
"Exit status:\n"
|
||||||
"0 if OK,\n"
|
"0 if OK,\n"
|
||||||
|
|
|
@ -38,21 +38,21 @@ SrsServer* _srs_server = new SrsServer();
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef SRS_GPERF_MP
|
#ifdef SRS_GPERF_MP
|
||||||
#include <gperftools/heap-profiler.h>
|
#include <gperftools/heap-profiler.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef SRS_GPERF_CP
|
#ifdef SRS_GPERF_CP
|
||||||
#include <gperftools/profiler.h>
|
#include <gperftools/profiler.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handler(int signo)
|
void handler(int signo)
|
||||||
{
|
{
|
||||||
srs_trace("get a signal, signo=%d", signo);
|
srs_trace("get a signal, signo=%d", signo);
|
||||||
_srs_server->on_signal(signo);
|
_srs_server->on_signal(signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
#ifdef SRS_GPERF_MP
|
#ifdef SRS_GPERF_MP
|
||||||
HeapProfilerStart("gperf.srs.gmp");
|
HeapProfilerStart("gperf.srs.gmp");
|
||||||
|
@ -60,37 +60,37 @@ int main(int argc, char** argv)
|
||||||
#ifdef SRS_GPERF_CP
|
#ifdef SRS_GPERF_CP
|
||||||
ProfilerStart("gperf.srs.gcp");
|
ProfilerStart("gperf.srs.gcp");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
signal(SIGNAL_RELOAD, handler);
|
signal(SIGNAL_RELOAD, handler);
|
||||||
signal(SIGINT, handler);
|
signal(SIGINT, handler);
|
||||||
|
|
||||||
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
|
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SRS_GPERF_MC
|
#ifdef SRS_GPERF_MC
|
||||||
#ifdef SRS_GPERF_MP
|
#ifdef SRS_GPERF_MP
|
||||||
srs_error("option --with-gmc confict with --with-gmp, "
|
srs_error("option --with-gmc confict with --with-gmp, "
|
||||||
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
|
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
|
||||||
"Note that since the heap-checker uses the heap-profiling framework internally, "
|
"Note that since the heap-checker uses the heap-profiling framework internally, "
|
||||||
"it is not possible to run both the heap-checker and heap profiler at the same time");
|
"it is not possible to run both the heap-checker and heap profiler at the same time");
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) {
|
if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create log dir in _srs_config->get_log_dir()
|
// TODO: create log dir in _srs_config->get_log_dir()
|
||||||
|
|
||||||
if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
|
if ((ret = _srs_server->listen()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) {
|
if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,29 +43,29 @@ class __SrsAmf0ObjectEOF;
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// amf0 codec
|
// amf0 codec
|
||||||
// 1. SrsAmf0Any: read any from stream
|
// 1. SrsAmf0Any: read any from stream
|
||||||
// SrsAmf0Any* pany = NULL;
|
// SrsAmf0Any* pany = NULL;
|
||||||
// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) {
|
// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) {
|
||||||
// return ret;
|
// return ret;
|
||||||
// }
|
// }
|
||||||
// srs_assert(pany); // if success, always valid object.
|
// srs_assert(pany); // if success, always valid object.
|
||||||
// 2. SrsAmf0Any: convert to specifid type, for instance, string
|
// 2. SrsAmf0Any: convert to specifid type, for instance, string
|
||||||
// SrsAmf0Any* pany = ...
|
// SrsAmf0Any* pany = ...
|
||||||
// if (pany->is_string()) {
|
// if (pany->is_string()) {
|
||||||
// string v = pany->to_str();
|
// string v = pany->to_str();
|
||||||
// }
|
// }
|
||||||
// 3. SrsAmf0Any: parse specified type to any, for instance, string
|
// 3. SrsAmf0Any: parse specified type to any, for instance, string
|
||||||
// SrsAmf0Any* pany = SrsAmf0Any::str("winlin");
|
// SrsAmf0Any* pany = SrsAmf0Any::str("winlin");
|
||||||
// 4. SrsAmf0Size: get amf0 instance size
|
// 4. SrsAmf0Size: get amf0 instance size
|
||||||
// int size = SrsAmf0Size::str("winlin");
|
// int size = SrsAmf0Size::str("winlin");
|
||||||
// 5. SrsAmf0Object: create the amf0 object.
|
// 5. SrsAmf0Object: create the amf0 object.
|
||||||
// SrsAmf0Object* obj = SrsAmf0Any::object();
|
// SrsAmf0Object* obj = SrsAmf0Any::object();
|
||||||
// 5. SrsAmf0EcmaArray: create the amf0 ecma array.
|
// 5. SrsAmf0EcmaArray: create the amf0 ecma array.
|
||||||
// SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
|
// SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
|
||||||
//
|
//
|
||||||
// please carefully the size and count of amf0 any:
|
// please carefully the size and count of amf0 any:
|
||||||
// 1. total_size(): the total memory size the object wrote to buffer.
|
// 1. total_size(): the total memory size the object wrote to buffer.
|
||||||
// 2. count(): the total element count of object, for instance, the properties
|
// 2. count(): the total element count of object, for instance, the properties
|
||||||
// of amf0 object, used for key_at/value_at loop.
|
// of amf0 object, used for key_at/value_at loop.
|
||||||
//
|
//
|
||||||
// for detail usage, see interfaces of each object.
|
// for detail usage, see interfaces of each object.
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -76,73 +76,73 @@ class __SrsAmf0ObjectEOF;
|
||||||
* any amf0 value.
|
* any amf0 value.
|
||||||
* 2.1 Types Overview
|
* 2.1 Types Overview
|
||||||
* value-type = number-type | boolean-type | string-type | object-type
|
* value-type = number-type | boolean-type | string-type | object-type
|
||||||
* | null-marker | undefined-marker | reference-type | ecma-array-type
|
* | null-marker | undefined-marker | reference-type | ecma-array-type
|
||||||
* | strict-array-type | date-type | long-string-type | xml-document-type
|
* | strict-array-type | date-type | long-string-type | xml-document-type
|
||||||
* | typed-object-type
|
* | typed-object-type
|
||||||
*/
|
*/
|
||||||
class SrsAmf0Any
|
class SrsAmf0Any
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
char marker;
|
char marker;
|
||||||
public:
|
public:
|
||||||
SrsAmf0Any();
|
SrsAmf0Any();
|
||||||
virtual ~SrsAmf0Any();
|
virtual ~SrsAmf0Any();
|
||||||
public:
|
public:
|
||||||
virtual bool is_string();
|
virtual bool is_string();
|
||||||
virtual bool is_boolean();
|
virtual bool is_boolean();
|
||||||
virtual bool is_number();
|
virtual bool is_number();
|
||||||
virtual bool is_null();
|
virtual bool is_null();
|
||||||
virtual bool is_undefined();
|
virtual bool is_undefined();
|
||||||
virtual bool is_object();
|
virtual bool is_object();
|
||||||
virtual bool is_object_eof();
|
virtual bool is_object_eof();
|
||||||
virtual bool is_ecma_array();
|
virtual bool is_ecma_array();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* get the string of any when is_string() indicates true.
|
* get the string of any when is_string() indicates true.
|
||||||
* user must ensure the type is a string, or assert failed.
|
* user must ensure the type is a string, or assert failed.
|
||||||
*/
|
*/
|
||||||
virtual std::string to_str();
|
virtual std::string to_str();
|
||||||
/**
|
/**
|
||||||
* get the boolean of any when is_boolean() indicates true.
|
* get the boolean of any when is_boolean() indicates true.
|
||||||
* user must ensure the type is a boolean, or assert failed.
|
* user must ensure the type is a boolean, or assert failed.
|
||||||
*/
|
*/
|
||||||
virtual bool to_boolean();
|
virtual bool to_boolean();
|
||||||
/**
|
/**
|
||||||
* get the number of any when is_number() indicates true.
|
* get the number of any when is_number() indicates true.
|
||||||
* user must ensure the type is a number, or assert failed.
|
* user must ensure the type is a number, or assert failed.
|
||||||
*/
|
*/
|
||||||
virtual double to_number();
|
virtual double to_number();
|
||||||
/**
|
/**
|
||||||
* get the object of any when is_object() indicates true.
|
* get the object of any when is_object() indicates true.
|
||||||
* user must ensure the type is a object, or assert failed.
|
* user must ensure the type is a object, or assert failed.
|
||||||
*/
|
*/
|
||||||
virtual SrsAmf0Object* to_object();
|
virtual SrsAmf0Object* to_object();
|
||||||
/**
|
/**
|
||||||
* get the ecma array of any when is_ecma_array() indicates true.
|
* get the ecma array of any when is_ecma_array() indicates true.
|
||||||
* user must ensure the type is a ecma array, or assert failed.
|
* user must ensure the type is a ecma array, or assert failed.
|
||||||
*/
|
*/
|
||||||
virtual SrsAmf0EcmaArray* to_ecma_array();
|
virtual SrsAmf0EcmaArray* to_ecma_array();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* get the size of amf0 any, including the marker size.
|
* get the size of amf0 any, including the marker size.
|
||||||
*/
|
*/
|
||||||
virtual int total_size() = 0;
|
virtual int total_size() = 0;
|
||||||
/**
|
/**
|
||||||
* read elem from stream
|
* read elem from stream
|
||||||
*/
|
*/
|
||||||
virtual int read(SrsStream* stream) = 0;
|
virtual int read(SrsStream* stream) = 0;
|
||||||
virtual int write(SrsStream* stream) = 0;
|
virtual int write(SrsStream* stream) = 0;
|
||||||
public:
|
public:
|
||||||
static SrsAmf0Any* str(const char* value = NULL);
|
static SrsAmf0Any* str(const char* value = NULL);
|
||||||
static SrsAmf0Any* boolean(bool value = false);
|
static SrsAmf0Any* boolean(bool value = false);
|
||||||
static SrsAmf0Any* number(double value = 0.0);
|
static SrsAmf0Any* number(double value = 0.0);
|
||||||
static SrsAmf0Any* null();
|
static SrsAmf0Any* null();
|
||||||
static SrsAmf0Any* undefined();
|
static SrsAmf0Any* undefined();
|
||||||
static SrsAmf0Object* object();
|
static SrsAmf0Object* object();
|
||||||
static SrsAmf0Any* object_eof();
|
static SrsAmf0Any* object_eof();
|
||||||
static SrsAmf0EcmaArray* ecma_array();
|
static SrsAmf0EcmaArray* ecma_array();
|
||||||
public:
|
public:
|
||||||
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
|
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,33 +153,33 @@ public:
|
||||||
class SrsAmf0Object : public SrsAmf0Any
|
class SrsAmf0Object : public SrsAmf0Any
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
__SrsUnSortedHashtable* properties;
|
__SrsUnSortedHashtable* properties;
|
||||||
__SrsAmf0ObjectEOF* eof;
|
__SrsAmf0ObjectEOF* eof;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// use SrsAmf0Any::object() to create it.
|
// use SrsAmf0Any::object() to create it.
|
||||||
friend class SrsAmf0Any;
|
friend class SrsAmf0Any;
|
||||||
SrsAmf0Object();
|
SrsAmf0Object();
|
||||||
public:
|
public:
|
||||||
virtual ~SrsAmf0Object();
|
virtual ~SrsAmf0Object();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int total_size();
|
virtual int total_size();
|
||||||
virtual int read(SrsStream* stream);
|
virtual int read(SrsStream* stream);
|
||||||
virtual int write(SrsStream* stream);
|
virtual int write(SrsStream* stream);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int count();
|
virtual int count();
|
||||||
// @remark: max index is count().
|
// @remark: max index is count().
|
||||||
virtual std::string key_at(int index);
|
virtual std::string key_at(int index);
|
||||||
// @remark: max index is count().
|
// @remark: max index is count().
|
||||||
virtual SrsAmf0Any* value_at(int index);
|
virtual SrsAmf0Any* value_at(int index);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void set(std::string key, SrsAmf0Any* value);
|
virtual void set(std::string key, SrsAmf0Any* value);
|
||||||
virtual SrsAmf0Any* get_property(std::string name);
|
virtual SrsAmf0Any* get_property(std::string name);
|
||||||
virtual SrsAmf0Any* ensure_property_string(std::string name);
|
virtual SrsAmf0Any* ensure_property_string(std::string name);
|
||||||
virtual SrsAmf0Any* ensure_property_number(std::string name);
|
virtual SrsAmf0Any* ensure_property_number(std::string name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -191,35 +191,35 @@ public:
|
||||||
class SrsAmf0EcmaArray : public SrsAmf0Any
|
class SrsAmf0EcmaArray : public SrsAmf0Any
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
__SrsUnSortedHashtable* properties;
|
__SrsUnSortedHashtable* properties;
|
||||||
__SrsAmf0ObjectEOF* eof;
|
__SrsAmf0ObjectEOF* eof;
|
||||||
int32_t _count;
|
int32_t _count;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// use SrsAmf0Any::ecma_array() to create it.
|
// use SrsAmf0Any::ecma_array() to create it.
|
||||||
friend class SrsAmf0Any;
|
friend class SrsAmf0Any;
|
||||||
SrsAmf0EcmaArray();
|
SrsAmf0EcmaArray();
|
||||||
public:
|
public:
|
||||||
virtual ~SrsAmf0EcmaArray();
|
virtual ~SrsAmf0EcmaArray();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int total_size();
|
virtual int total_size();
|
||||||
virtual int read(SrsStream* stream);
|
virtual int read(SrsStream* stream);
|
||||||
virtual int write(SrsStream* stream);
|
virtual int write(SrsStream* stream);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
virtual int count();
|
virtual int count();
|
||||||
// @remark: max index is count().
|
// @remark: max index is count().
|
||||||
virtual std::string key_at(int index);
|
virtual std::string key_at(int index);
|
||||||
// @remark: max index is count().
|
// @remark: max index is count().
|
||||||
virtual SrsAmf0Any* value_at(int index);
|
virtual SrsAmf0Any* value_at(int index);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void set(std::string key, SrsAmf0Any* value);
|
virtual void set(std::string key, SrsAmf0Any* value);
|
||||||
virtual SrsAmf0Any* get_property(std::string name);
|
virtual SrsAmf0Any* get_property(std::string name);
|
||||||
virtual SrsAmf0Any* ensure_property_string(std::string name);
|
virtual SrsAmf0Any* ensure_property_string(std::string name);
|
||||||
virtual SrsAmf0Any* ensure_property_number(std::string name);
|
virtual SrsAmf0Any* ensure_property_number(std::string name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -228,22 +228,22 @@ public:
|
||||||
class SrsAmf0Size
|
class SrsAmf0Size
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int utf8(std::string value);
|
static int utf8(std::string value);
|
||||||
static int str(std::string value);
|
static int str(std::string value);
|
||||||
static int number();
|
static int number();
|
||||||
static int null();
|
static int null();
|
||||||
static int undefined();
|
static int undefined();
|
||||||
static int boolean();
|
static int boolean();
|
||||||
static int object(SrsAmf0Object* obj);
|
static int object(SrsAmf0Object* obj);
|
||||||
static int object_eof();
|
static int object_eof();
|
||||||
static int ecma_array(SrsAmf0EcmaArray* arr);
|
static int ecma_array(SrsAmf0EcmaArray* arr);
|
||||||
static int any(SrsAmf0Any* o);
|
static int any(SrsAmf0Any* o);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read anything from stream.
|
* read anything from stream.
|
||||||
* @param ppvalue, the output amf0 any elem.
|
* @param ppvalue, the output amf0 any elem.
|
||||||
* NULL if error; otherwise, never NULL and user must free it.
|
* NULL if error; otherwise, never NULL and user must free it.
|
||||||
*/
|
*/
|
||||||
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);
|
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ extern int srs_amf0_write_string(SrsStream* stream, std::string value);
|
||||||
* read amf0 boolean from stream.
|
* read amf0 boolean from stream.
|
||||||
* 2.4 String Type
|
* 2.4 String Type
|
||||||
* boolean-type = boolean-marker U8
|
* boolean-type = boolean-marker U8
|
||||||
* 0 is false, <> 0 is true
|
* 0 is false, <> 0 is true
|
||||||
*/
|
*/
|
||||||
extern int srs_amf0_read_boolean(SrsStream* stream, bool& value);
|
extern int srs_amf0_read_boolean(SrsStream* stream, bool& value);
|
||||||
extern int srs_amf0_write_boolean(SrsStream* stream, bool value);
|
extern int srs_amf0_write_boolean(SrsStream* stream, bool value);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,17 +39,17 @@ class SrsComplexHandshake;
|
||||||
class SrsSimpleHandshake
|
class SrsSimpleHandshake
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsSimpleHandshake();
|
SrsSimpleHandshake();
|
||||||
virtual ~SrsSimpleHandshake();
|
virtual ~SrsSimpleHandshake();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* simple handshake.
|
* simple handshake.
|
||||||
* @param complex_hs, try complex handshake first,
|
* @param complex_hs, try complex handshake first,
|
||||||
* if NULL, use simple handshake.
|
* if NULL, use simple handshake.
|
||||||
* if failed, rollback to simple handshake.
|
* if failed, rollback to simple handshake.
|
||||||
*/
|
*/
|
||||||
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
|
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
|
||||||
virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
|
virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,20 +60,20 @@ public:
|
||||||
class SrsComplexHandshake
|
class SrsComplexHandshake
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SrsComplexHandshake();
|
SrsComplexHandshake();
|
||||||
virtual ~SrsComplexHandshake();
|
virtual ~SrsComplexHandshake();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* complex hanshake.
|
* complex hanshake.
|
||||||
* @_c1, size of c1 must be 1536.
|
* @_c1, size of c1 must be 1536.
|
||||||
* @remark, user must free the c1.
|
* @remark, user must free the c1.
|
||||||
* @return user must:
|
* @return user must:
|
||||||
* continue connect app if success,
|
* continue connect app if success,
|
||||||
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
|
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
|
||||||
* otherwise, disconnect
|
* otherwise, disconnect
|
||||||
*/
|
*/
|
||||||
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1);
|
virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1);
|
||||||
virtual int handshake_with_server(ISrsProtocolReaderWriter* io);
|
virtual int handshake_with_server(ISrsProtocolReaderWriter* io);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -40,14 +40,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
class ISrsProtocolReader : public ISrsBufferReader
|
class ISrsProtocolReader : public ISrsBufferReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsProtocolReader();
|
ISrsProtocolReader();
|
||||||
virtual ~ISrsProtocolReader();
|
virtual ~ISrsProtocolReader();
|
||||||
// for protocol
|
// for protocol
|
||||||
public:
|
public:
|
||||||
virtual void set_recv_timeout(int64_t timeout_us) = 0;
|
virtual void set_recv_timeout(int64_t timeout_us) = 0;
|
||||||
virtual int64_t get_recv_timeout() = 0;
|
virtual int64_t get_recv_timeout() = 0;
|
||||||
virtual int64_t get_recv_bytes() = 0;
|
virtual int64_t get_recv_bytes() = 0;
|
||||||
virtual int get_recv_kbps() = 0;
|
virtual int get_recv_kbps() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,28 +56,28 @@ public:
|
||||||
class ISrsProtocolWriter
|
class ISrsProtocolWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsProtocolWriter();
|
ISrsProtocolWriter();
|
||||||
virtual ~ISrsProtocolWriter();
|
virtual ~ISrsProtocolWriter();
|
||||||
// for protocol
|
// for protocol
|
||||||
public:
|
public:
|
||||||
virtual void set_send_timeout(int64_t timeout_us) = 0;
|
virtual void set_send_timeout(int64_t timeout_us) = 0;
|
||||||
virtual int64_t get_send_timeout() = 0;
|
virtual int64_t get_send_timeout() = 0;
|
||||||
virtual int64_t get_send_bytes() = 0;
|
virtual int64_t get_send_bytes() = 0;
|
||||||
virtual int get_send_kbps() = 0;
|
virtual int get_send_kbps() = 0;
|
||||||
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite) = 0;
|
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ISrsProtocolReaderWriter : public ISrsProtocolReader, public ISrsProtocolWriter
|
class ISrsProtocolReaderWriter : public ISrsProtocolReader, public ISrsProtocolWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISrsProtocolReaderWriter();
|
ISrsProtocolReaderWriter();
|
||||||
virtual ~ISrsProtocolReaderWriter();
|
virtual ~ISrsProtocolReaderWriter();
|
||||||
// for protocol
|
// for protocol
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* whether the specified timeout_us is never timeout.
|
* whether the specified timeout_us is never timeout.
|
||||||
*/
|
*/
|
||||||
virtual bool is_never_timeout(int64_t timeout_us) = 0;
|
virtual bool is_never_timeout(int64_t timeout_us) = 0;
|
||||||
// for handshake.
|
// for handshake.
|
||||||
public:
|
public:
|
||||||
virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0;
|
virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -48,41 +48,41 @@ class SrsPlayPacket;
|
||||||
*/
|
*/
|
||||||
struct SrsRequest
|
struct SrsRequest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* tcUrl: rtmp://request_vhost:port/app/stream
|
* tcUrl: rtmp://request_vhost:port/app/stream
|
||||||
* support pass vhost in query string, such as:
|
* support pass vhost in query string, such as:
|
||||||
* rtmp://ip:port/app?vhost=request_vhost/stream
|
* rtmp://ip:port/app?vhost=request_vhost/stream
|
||||||
* rtmp://ip:port/app...vhost...request_vhost/stream
|
* rtmp://ip:port/app...vhost...request_vhost/stream
|
||||||
*/
|
*/
|
||||||
std::string tcUrl;
|
std::string tcUrl;
|
||||||
std::string pageUrl;
|
std::string pageUrl;
|
||||||
std::string swfUrl;
|
std::string swfUrl;
|
||||||
double objectEncoding;
|
double objectEncoding;
|
||||||
|
|
||||||
std::string schema;
|
std::string schema;
|
||||||
std::string vhost;
|
std::string vhost;
|
||||||
std::string port;
|
std::string port;
|
||||||
std::string app;
|
std::string app;
|
||||||
std::string stream;
|
std::string stream;
|
||||||
|
|
||||||
SrsRequest();
|
SrsRequest();
|
||||||
virtual ~SrsRequest();
|
virtual ~SrsRequest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deep copy the request, for source to use it to support reload,
|
* deep copy the request, for source to use it to support reload,
|
||||||
* for when initialize the source, the request is valid,
|
* for when initialize the source, the request is valid,
|
||||||
* when reload it, the request maybe invalid, so need to copy it.
|
* when reload it, the request maybe invalid, so need to copy it.
|
||||||
*/
|
*/
|
||||||
virtual SrsRequest* copy();
|
virtual SrsRequest* copy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* disconvery vhost/app from tcUrl.
|
* disconvery vhost/app from tcUrl.
|
||||||
*/
|
*/
|
||||||
virtual int discovery_app();
|
virtual int discovery_app();
|
||||||
virtual std::string get_stream_url();
|
virtual std::string get_stream_url();
|
||||||
virtual void strip();
|
virtual void strip();
|
||||||
private:
|
private:
|
||||||
std::string& trim(std::string& str, std::string chs);
|
std::string& trim(std::string& str, std::string chs);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,10 +90,10 @@ private:
|
||||||
*/
|
*/
|
||||||
struct SrsResponse
|
struct SrsResponse
|
||||||
{
|
{
|
||||||
int stream_id;
|
int stream_id;
|
||||||
|
|
||||||
SrsResponse();
|
SrsResponse();
|
||||||
virtual ~SrsResponse();
|
virtual ~SrsResponse();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,10 +101,10 @@ struct SrsResponse
|
||||||
*/
|
*/
|
||||||
enum SrsClientType
|
enum SrsClientType
|
||||||
{
|
{
|
||||||
SrsClientUnknown,
|
SrsClientUnknown,
|
||||||
SrsClientPlay,
|
SrsClientPlay,
|
||||||
SrsClientFMLEPublish,
|
SrsClientFMLEPublish,
|
||||||
SrsClientFlashPublish,
|
SrsClientFlashPublish,
|
||||||
};
|
};
|
||||||
std::string srs_client_type_string(SrsClientType type);
|
std::string srs_client_type_string(SrsClientType type);
|
||||||
|
|
||||||
|
@ -114,36 +114,36 @@ std::string srs_client_type_string(SrsClientType type);
|
||||||
class SrsRtmpClient
|
class SrsRtmpClient
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
SrsProtocol* protocol;
|
SrsProtocol* protocol;
|
||||||
ISrsProtocolReaderWriter* io;
|
ISrsProtocolReaderWriter* io;
|
||||||
public:
|
public:
|
||||||
SrsRtmpClient(ISrsProtocolReaderWriter* skt);
|
SrsRtmpClient(ISrsProtocolReaderWriter* skt);
|
||||||
virtual ~SrsRtmpClient();
|
virtual ~SrsRtmpClient();
|
||||||
public:
|
public:
|
||||||
virtual void set_recv_timeout(int64_t timeout_us);
|
virtual void set_recv_timeout(int64_t timeout_us);
|
||||||
virtual void set_send_timeout(int64_t timeout_us);
|
virtual void set_send_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_recv_bytes();
|
virtual int64_t get_recv_bytes();
|
||||||
virtual int64_t get_send_bytes();
|
virtual int64_t get_send_bytes();
|
||||||
virtual int get_recv_kbps();
|
virtual int get_recv_kbps();
|
||||||
virtual int get_send_kbps();
|
virtual int get_send_kbps();
|
||||||
virtual int recv_message(SrsCommonMessage** pmsg);
|
virtual int recv_message(SrsCommonMessage** pmsg);
|
||||||
virtual int send_message(ISrsMessage* msg);
|
virtual int send_message(ISrsMessage* msg);
|
||||||
public:
|
public:
|
||||||
// try complex, then simple handshake.
|
// try complex, then simple handshake.
|
||||||
virtual int handshake();
|
virtual int handshake();
|
||||||
// only use simple handshake
|
// only use simple handshake
|
||||||
virtual int simple_handshake();
|
virtual int simple_handshake();
|
||||||
// only use complex handshake
|
// only use complex handshake
|
||||||
virtual int complex_handshake();
|
virtual int complex_handshake();
|
||||||
virtual int connect_app(std::string app, std::string tc_url);
|
virtual int connect_app(std::string app, std::string tc_url);
|
||||||
virtual int create_stream(int& stream_id);
|
virtual int create_stream(int& stream_id);
|
||||||
virtual int play(std::string stream, int stream_id);
|
virtual int play(std::string stream, int stream_id);
|
||||||
// flash publish schema:
|
// flash publish schema:
|
||||||
// connect-app => create-stream => flash-publish
|
// connect-app => create-stream => flash-publish
|
||||||
virtual int publish(std::string stream, int stream_id);
|
virtual int publish(std::string stream, int stream_id);
|
||||||
// FMLE publish schema:
|
// FMLE publish schema:
|
||||||
// connect-app => FMLE publish
|
// connect-app => FMLE publish
|
||||||
virtual int fmle_publish(std::string stream, int& stream_id);
|
virtual int fmle_publish(std::string stream, int& stream_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,93 +155,93 @@ public:
|
||||||
class SrsRtmpServer
|
class SrsRtmpServer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsProtocol* protocol;
|
SrsProtocol* protocol;
|
||||||
ISrsProtocolReaderWriter* io;
|
ISrsProtocolReaderWriter* io;
|
||||||
public:
|
public:
|
||||||
SrsRtmpServer(ISrsProtocolReaderWriter* skt);
|
SrsRtmpServer(ISrsProtocolReaderWriter* skt);
|
||||||
virtual ~SrsRtmpServer();
|
virtual ~SrsRtmpServer();
|
||||||
public:
|
public:
|
||||||
virtual SrsProtocol* get_protocol();
|
virtual SrsProtocol* get_protocol();
|
||||||
virtual void set_recv_timeout(int64_t timeout_us);
|
virtual void set_recv_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_recv_timeout();
|
virtual int64_t get_recv_timeout();
|
||||||
virtual void set_send_timeout(int64_t timeout_us);
|
virtual void set_send_timeout(int64_t timeout_us);
|
||||||
virtual int64_t get_send_timeout();
|
virtual int64_t get_send_timeout();
|
||||||
virtual int64_t get_recv_bytes();
|
virtual int64_t get_recv_bytes();
|
||||||
virtual int64_t get_send_bytes();
|
virtual int64_t get_send_bytes();
|
||||||
virtual int get_recv_kbps();
|
virtual int get_recv_kbps();
|
||||||
virtual int get_send_kbps();
|
virtual int get_send_kbps();
|
||||||
virtual int recv_message(SrsCommonMessage** pmsg);
|
virtual int recv_message(SrsCommonMessage** pmsg);
|
||||||
virtual int send_message(ISrsMessage* msg);
|
virtual int send_message(ISrsMessage* msg);
|
||||||
public:
|
public:
|
||||||
virtual int handshake();
|
virtual int handshake();
|
||||||
virtual int connect_app(SrsRequest* req);
|
virtual int connect_app(SrsRequest* req);
|
||||||
virtual int set_window_ack_size(int ack_size);
|
virtual int set_window_ack_size(int ack_size);
|
||||||
/**
|
/**
|
||||||
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
|
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
|
||||||
* using the Limit type field.
|
* using the Limit type field.
|
||||||
*/
|
*/
|
||||||
virtual int set_peer_bandwidth(int bandwidth, int type);
|
virtual int set_peer_bandwidth(int bandwidth, int type);
|
||||||
/**
|
/**
|
||||||
* @param server_ip the ip of server.
|
* @param server_ip the ip of server.
|
||||||
*/
|
*/
|
||||||
virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL);
|
virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL);
|
||||||
virtual void response_connect_reject(SrsRequest* req, const char* desc);
|
virtual void response_connect_reject(SrsRequest* req, const char* desc);
|
||||||
virtual int on_bw_done();
|
virtual int on_bw_done();
|
||||||
/**
|
/**
|
||||||
* recv some message to identify the client.
|
* recv some message to identify the client.
|
||||||
* @stream_id, client will createStream to play or publish by flash,
|
* @stream_id, client will createStream to play or publish by flash,
|
||||||
* the stream_id used to response the createStream request.
|
* the stream_id used to response the createStream request.
|
||||||
* @type, output the client type.
|
* @type, output the client type.
|
||||||
*/
|
*/
|
||||||
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
|
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
|
||||||
/**
|
/**
|
||||||
* set the chunk size when client type identified.
|
* set the chunk size when client type identified.
|
||||||
*/
|
*/
|
||||||
virtual int set_chunk_size(int chunk_size);
|
virtual int set_chunk_size(int chunk_size);
|
||||||
/**
|
/**
|
||||||
* when client type is play, response with packets:
|
* when client type is play, response with packets:
|
||||||
* StreamBegin,
|
* StreamBegin,
|
||||||
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
|
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
|
||||||
* |RtmpSampleAccess(false, false),
|
* |RtmpSampleAccess(false, false),
|
||||||
* onStatus(NetStream.Data.Start).
|
* onStatus(NetStream.Data.Start).
|
||||||
*/
|
*/
|
||||||
virtual int start_play(int stream_id);
|
virtual int start_play(int stream_id);
|
||||||
/**
|
/**
|
||||||
* when client(type is play) send pause message,
|
* when client(type is play) send pause message,
|
||||||
* if is_pause, response the following packets:
|
* if is_pause, response the following packets:
|
||||||
* onStatus(NetStream.Pause.Notify)
|
* onStatus(NetStream.Pause.Notify)
|
||||||
* StreamEOF
|
* StreamEOF
|
||||||
* if not is_pause, response the following packets:
|
* if not is_pause, response the following packets:
|
||||||
* onStatus(NetStream.Unpause.Notify)
|
* onStatus(NetStream.Unpause.Notify)
|
||||||
* StreamBegin
|
* StreamBegin
|
||||||
*/
|
*/
|
||||||
virtual int on_play_client_pause(int stream_id, bool is_pause);
|
virtual int on_play_client_pause(int stream_id, bool is_pause);
|
||||||
/**
|
/**
|
||||||
* when client type is publish, response with packets:
|
* when client type is publish, response with packets:
|
||||||
* releaseStream response
|
* releaseStream response
|
||||||
* FCPublish
|
* FCPublish
|
||||||
* FCPublish response
|
* FCPublish response
|
||||||
* createStream response
|
* createStream response
|
||||||
* onFCPublish(NetStream.Publish.Start)
|
* onFCPublish(NetStream.Publish.Start)
|
||||||
* onStatus(NetStream.Publish.Start)
|
* onStatus(NetStream.Publish.Start)
|
||||||
*/
|
*/
|
||||||
virtual int start_fmle_publish(int stream_id);
|
virtual int start_fmle_publish(int stream_id);
|
||||||
/**
|
/**
|
||||||
* process the FMLE unpublish event.
|
* process the FMLE unpublish event.
|
||||||
* @unpublish_tid the unpublish request transaction id.
|
* @unpublish_tid the unpublish request transaction id.
|
||||||
*/
|
*/
|
||||||
virtual int fmle_unpublish(int stream_id, double unpublish_tid);
|
virtual int fmle_unpublish(int stream_id, double unpublish_tid);
|
||||||
/**
|
/**
|
||||||
* when client type is publish, response with packets:
|
* when client type is publish, response with packets:
|
||||||
* onStatus(NetStream.Publish.Start)
|
* onStatus(NetStream.Publish.Start)
|
||||||
*/
|
*/
|
||||||
virtual int start_flash_publish(int stream_id);
|
virtual int start_flash_publish(int stream_id);
|
||||||
private:
|
private:
|
||||||
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
|
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
|
||||||
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
|
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
|
||||||
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
|
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
|
||||||
private:
|
private:
|
||||||
virtual int identify_play_client(SrsPlayPacket* req, SrsClientType& type, std::string& stream_name);
|
virtual int identify_play_client(SrsPlayPacket* req, SrsClientType& type, std::string& stream_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -25,24 +25,24 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
void srs_vhost_resolve(std::string& vhost, std::string& app)
|
void srs_vhost_resolve(std::string& vhost, std::string& app)
|
||||||
{
|
{
|
||||||
app = srs_replace(app, "...", "?");
|
app = srs_replace(app, "...", "?");
|
||||||
|
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
if ((pos = app.find("?")) == std::string::npos) {
|
if ((pos = app.find("?")) == std::string::npos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string query = app.substr(pos + 1);
|
std::string query = app.substr(pos + 1);
|
||||||
app = app.substr(0, pos);
|
app = app.substr(0, pos);
|
||||||
|
|
||||||
if ((pos = query.find("vhost?")) != std::string::npos
|
if ((pos = query.find("vhost?")) != std::string::npos
|
||||||
|| (pos = query.find("vhost=")) != std::string::npos
|
|| (pos = query.find("vhost=")) != std::string::npos
|
||||||
|| (pos = query.find("Vhost?")) != std::string::npos
|
|| (pos = query.find("Vhost?")) != std::string::npos
|
||||||
|| (pos = query.find("Vhost=")) != std::string::npos
|
|| (pos = query.find("Vhost=")) != std::string::npos
|
||||||
) {
|
) {
|
||||||
query = query.substr(pos + 6);
|
query = query.substr(pos + 6);
|
||||||
if (!query.empty()) {
|
if (!query.empty()) {
|
||||||
vhost = query;
|
vhost = query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// resolve the vhost in query string
|
// resolve the vhost in query string
|
||||||
// @param app, may contains the vhost in query string format:
|
// @param app, may contains the vhost in query string format:
|
||||||
// app?vhost=request_vhost
|
// app?vhost=request_vhost
|
||||||
// app...vhost...request_vhost
|
// app...vhost...request_vhost
|
||||||
extern void srs_vhost_resolve(std::string& vhost, std::string& app);
|
extern void srs_vhost_resolve(std::string& vhost, std::string& app);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,88 +1,88 @@
|
||||||
file
|
file
|
||||||
main readonly separator,
|
main readonly separator,
|
||||||
..\main\srs_main_server.cpp,
|
..\main\srs_main_server.cpp,
|
||||||
..\main\srs_main_bandcheck.cpp,
|
..\main\srs_main_bandcheck.cpp,
|
||||||
auto readonly separator,
|
auto readonly separator,
|
||||||
..\..\objs\srs_auto_headers.hpp,
|
..\..\objs\srs_auto_headers.hpp,
|
||||||
libs readonly separator,
|
libs readonly separator,
|
||||||
..\libs\srs_librtmp.hpp,
|
..\libs\srs_librtmp.hpp,
|
||||||
..\libs\srs_librtmp.cpp,
|
..\libs\srs_librtmp.cpp,
|
||||||
..\libs\srs_lib_simple_socket.hpp,
|
..\libs\srs_lib_simple_socket.hpp,
|
||||||
..\libs\srs_lib_simple_socket.cpp,
|
..\libs\srs_lib_simple_socket.cpp,
|
||||||
core readonly separator,
|
core readonly separator,
|
||||||
..\core\srs_core.hpp,
|
..\core\srs_core.hpp,
|
||||||
..\core\srs_core.cpp,
|
..\core\srs_core.cpp,
|
||||||
..\core\srs_core_autofree.hpp,
|
..\core\srs_core_autofree.hpp,
|
||||||
..\core\srs_core_autofree.cpp,
|
..\core\srs_core_autofree.cpp,
|
||||||
kernel readonly separator,
|
kernel readonly separator,
|
||||||
..\kernel\srs_kernel_buffer.hpp,
|
..\kernel\srs_kernel_buffer.hpp,
|
||||||
..\kernel\srs_kernel_buffer.cpp,
|
..\kernel\srs_kernel_buffer.cpp,
|
||||||
..\kernel\srs_kernel_error.hpp,
|
..\kernel\srs_kernel_error.hpp,
|
||||||
..\kernel\srs_kernel_error.cpp,
|
..\kernel\srs_kernel_error.cpp,
|
||||||
..\kernel\srs_kernel_log.hpp,
|
..\kernel\srs_kernel_log.hpp,
|
||||||
..\kernel\srs_kernel_log.cpp,
|
..\kernel\srs_kernel_log.cpp,
|
||||||
..\kernel\srs_kernel_stream.hpp,
|
..\kernel\srs_kernel_stream.hpp,
|
||||||
..\kernel\srs_kernel_stream.cpp,
|
..\kernel\srs_kernel_stream.cpp,
|
||||||
rtmp-protocol readonly separator,
|
rtmp-protocol readonly separator,
|
||||||
..\rtmp\srs_protocol_amf0.hpp,
|
..\rtmp\srs_protocol_amf0.hpp,
|
||||||
..\rtmp\srs_protocol_amf0.cpp,
|
..\rtmp\srs_protocol_amf0.cpp,
|
||||||
..\rtmp\srs_protocol_handshake.hpp,
|
..\rtmp\srs_protocol_handshake.hpp,
|
||||||
..\rtmp\srs_protocol_handshake.cpp,
|
..\rtmp\srs_protocol_handshake.cpp,
|
||||||
..\rtmp\srs_protocol_io.hpp,
|
..\rtmp\srs_protocol_io.hpp,
|
||||||
..\rtmp\srs_protocol_io.cpp,
|
..\rtmp\srs_protocol_io.cpp,
|
||||||
..\rtmp\srs_protocol_rtmp.hpp,
|
..\rtmp\srs_protocol_rtmp.hpp,
|
||||||
..\rtmp\srs_protocol_rtmp.cpp,
|
..\rtmp\srs_protocol_rtmp.cpp,
|
||||||
..\rtmp\srs_protocol_rtmp_stack.hpp,
|
..\rtmp\srs_protocol_rtmp_stack.hpp,
|
||||||
..\rtmp\srs_protocol_rtmp_stack.cpp,
|
..\rtmp\srs_protocol_rtmp_stack.cpp,
|
||||||
..\rtmp\srs_protocol_utility.hpp,
|
..\rtmp\srs_protocol_utility.hpp,
|
||||||
..\rtmp\srs_protocol_utility.cpp,
|
..\rtmp\srs_protocol_utility.cpp,
|
||||||
app readonly separator,
|
app readonly separator,
|
||||||
..\app\srs_app_bandwidth.hpp,
|
..\app\srs_app_bandwidth.hpp,
|
||||||
..\app\srs_app_bandwidth.cpp,
|
..\app\srs_app_bandwidth.cpp,
|
||||||
..\app\srs_app_client.hpp,
|
..\app\srs_app_client.hpp,
|
||||||
..\app\srs_app_client.cpp,
|
..\app\srs_app_client.cpp,
|
||||||
..\app\srs_app_codec.hpp,
|
..\app\srs_app_codec.hpp,
|
||||||
..\app\srs_app_codec.cpp,
|
..\app\srs_app_codec.cpp,
|
||||||
..\app\srs_app_conn.hpp,
|
..\app\srs_app_conn.hpp,
|
||||||
..\app\srs_app_conn.cpp,
|
..\app\srs_app_conn.cpp,
|
||||||
..\app\srs_app_config.hpp,
|
..\app\srs_app_config.hpp,
|
||||||
..\app\srs_app_config.cpp,
|
..\app\srs_app_config.cpp,
|
||||||
..\app\srs_app_encoder.hpp,
|
..\app\srs_app_encoder.hpp,
|
||||||
..\app\srs_app_encoder.cpp,
|
..\app\srs_app_encoder.cpp,
|
||||||
..\app\srs_app_forward.hpp,
|
..\app\srs_app_forward.hpp,
|
||||||
..\app\srs_app_forward.cpp,
|
..\app\srs_app_forward.cpp,
|
||||||
..\app\srs_app_hls.hpp,
|
..\app\srs_app_hls.hpp,
|
||||||
..\app\srs_app_hls.cpp,
|
..\app\srs_app_hls.cpp,
|
||||||
..\app\srs_app_http.hpp,
|
..\app\srs_app_http.hpp,
|
||||||
..\app\srs_app_http.cpp,
|
..\app\srs_app_http.cpp,
|
||||||
..\app\srs_app_log.hpp,
|
..\app\srs_app_log.hpp,
|
||||||
..\app\srs_app_log.cpp,
|
..\app\srs_app_log.cpp,
|
||||||
..\app\srs_app_refer.hpp,
|
..\app\srs_app_refer.hpp,
|
||||||
..\app\srs_app_refer.cpp,
|
..\app\srs_app_refer.cpp,
|
||||||
..\app\srs_app_reload.hpp,
|
..\app\srs_app_reload.hpp,
|
||||||
..\app\srs_app_reload.cpp,
|
..\app\srs_app_reload.cpp,
|
||||||
..\app\srs_app_pithy_print.hpp,
|
..\app\srs_app_pithy_print.hpp,
|
||||||
..\app\srs_app_pithy_print.cpp,
|
..\app\srs_app_pithy_print.cpp,
|
||||||
..\app\srs_app_thread.hpp,
|
..\app\srs_app_thread.hpp,
|
||||||
..\app\srs_app_thread.cpp,
|
..\app\srs_app_thread.cpp,
|
||||||
..\app\srs_app_server.hpp,
|
..\app\srs_app_server.hpp,
|
||||||
..\app\srs_app_server.cpp,
|
..\app\srs_app_server.cpp,
|
||||||
..\app\srs_app_st.hpp,
|
..\app\srs_app_st.hpp,
|
||||||
..\app\srs_app_st.cpp,
|
..\app\srs_app_st.cpp,
|
||||||
..\app\srs_app_socket.hpp,
|
..\app\srs_app_socket.hpp,
|
||||||
..\app\srs_app_socket.cpp,
|
..\app\srs_app_socket.cpp,
|
||||||
..\app\srs_app_source.hpp,
|
..\app\srs_app_source.hpp,
|
||||||
..\app\srs_app_source.cpp,
|
..\app\srs_app_source.cpp,
|
||||||
utest readonly separator,
|
utest readonly separator,
|
||||||
..\utest\srs_utest.hpp,
|
..\utest\srs_utest.hpp,
|
||||||
..\utest\srs_utest.cpp,
|
..\utest\srs_utest.cpp,
|
||||||
..\utest\srs_utest_amf0.hpp,
|
..\utest\srs_utest_amf0.hpp,
|
||||||
..\utest\srs_utest_amf0.cpp,
|
..\utest\srs_utest_amf0.cpp,
|
||||||
research readonly separator,
|
research readonly separator,
|
||||||
..\..\research\librtmp\srs_play.c,
|
..\..\research\librtmp\srs_play.c,
|
||||||
..\..\research\librtmp\srs_publish.c,
|
..\..\research\librtmp\srs_publish.c,
|
||||||
..\..\research\hls\ts_info.cc;
|
..\..\research\hls\ts_info.cc;
|
||||||
|
|
||||||
mainconfig
|
mainconfig
|
||||||
"" = "MAIN";
|
"" = "MAIN";
|
||||||
|
|
||||||
|
|
|
@ -39,30 +39,30 @@ SrsServer* _srs_server = NULL;
|
||||||
// basic test and samples.
|
// basic test and samples.
|
||||||
VOID TEST(SampleTest, FastSampleInt64Test)
|
VOID TEST(SampleTest, FastSampleInt64Test)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(1, (int)sizeof(int8_t));
|
EXPECT_EQ(1, (int)sizeof(int8_t));
|
||||||
EXPECT_EQ(2, (int)sizeof(int16_t));
|
EXPECT_EQ(2, (int)sizeof(int16_t));
|
||||||
EXPECT_EQ(4, (int)sizeof(int32_t));
|
EXPECT_EQ(4, (int)sizeof(int32_t));
|
||||||
EXPECT_EQ(8, (int)sizeof(int64_t));
|
EXPECT_EQ(8, (int)sizeof(int64_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID TEST(SampleTest, FastSampleMacrosTest)
|
VOID TEST(SampleTest, FastSampleMacrosTest)
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(1);
|
EXPECT_TRUE(1);
|
||||||
EXPECT_FALSE(0);
|
EXPECT_FALSE(0);
|
||||||
|
|
||||||
EXPECT_EQ(1, 1); // ==
|
EXPECT_EQ(1, 1); // ==
|
||||||
EXPECT_NE(1, 2); // !=
|
EXPECT_NE(1, 2); // !=
|
||||||
EXPECT_LE(1, 2); // <=
|
EXPECT_LE(1, 2); // <=
|
||||||
EXPECT_LT(1, 2); // <
|
EXPECT_LT(1, 2); // <
|
||||||
EXPECT_GE(2, 1); // >=
|
EXPECT_GE(2, 1); // >=
|
||||||
EXPECT_GT(2, 1); // >
|
EXPECT_GT(2, 1); // >
|
||||||
|
|
||||||
EXPECT_STREQ("winlin", "winlin");
|
EXPECT_STREQ("winlin", "winlin");
|
||||||
EXPECT_STRNE("winlin", "srs");
|
EXPECT_STRNE("winlin", "srs");
|
||||||
EXPECT_STRCASEEQ("winlin", "Winlin");
|
EXPECT_STRCASEEQ("winlin", "Winlin");
|
||||||
EXPECT_STRCASENE("winlin", "srs");
|
EXPECT_STRCASENE("winlin", "srs");
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(1.0, 1.000000000000001);
|
EXPECT_FLOAT_EQ(1.0, 1.000000000000001);
|
||||||
EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001);
|
EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001);
|
||||||
EXPECT_NEAR(10, 15, 5);
|
EXPECT_NEAR(10, 15, 5);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue