diff --git a/trunk/src/app/srs_app_bandwidth.cpp b/trunk/src/app/srs_app_bandwidth.cpp index 835f5b45c..c7f756929 100644 --- a/trunk/src/app/srs_app_bandwidth.cpp +++ b/trunk/src/app/srs_app_bandwidth.cpp @@ -45,28 +45,28 @@ SrsBandwidth::~SrsBandwidth() int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServer* _rtmp) { - int ret = ERROR_SUCCESS; - - rtmp = _rtmp; - req = _req; - - if (!_srs_config->get_bw_check_enabled(req->vhost)) { - return ret; - } + int ret = ERROR_SUCCESS; + + rtmp = _rtmp; + req = _req; + + if (!_srs_config->get_bw_check_enabled(req->vhost)) { + return ret; + } - // validate the bandwidth check key - std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost); - if (req->tcUrl.find(key) == std::string::npos) { - ret = ERROR_SYSTEM_BANDWIDTH_KEY; - srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d", - req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret); - return ret; - } - - // shared global last check time, - // to avoid attach by bandwidth check, - // if client request check in the window(specifeid by interval), - // directly reject the request. + // validate the bandwidth check key + std::string key = "key=" + _srs_config->get_bw_check_key(req->vhost); + if (req->tcUrl.find(key) == std::string::npos) { + ret = ERROR_SYSTEM_BANDWIDTH_KEY; + srs_error("check the vhost=%s %s failed, tcUrl=%s, ret=%d", + req->vhost.c_str(), key.c_str(), req->tcUrl.c_str(), ret); + return ret; + } + + // shared global last check time, + // to avoid attach by bandwidth check, + // if client request check in the window(specifeid by interval), + // directly reject the request. static int64_t last_check_time = 0; int interval_ms = _srs_config->get_bw_check_interval_ms(req->vhost); @@ -75,16 +75,16 @@ int SrsBandwidth::bandwidth_test(SrsRequest* _req, st_netfd_t stfd, SrsRtmpServe if (last_check_time > 0 && time_now - last_check_time < interval_ms) { ret = ERROR_SYSTEM_BANDWIDTH_DENIED; srs_trace("bandcheck denied, " - "last_check=%"PRId64", now=%"PRId64", interval=%d", - last_check_time, time_now, interval_ms); - + "last_check=%"PRId64", now=%"PRId64", interval=%d", + last_check_time, time_now, interval_ms); + rtmp->response_connect_reject(req, "bandcheck rejected"); return ret; } // accept and do bandwidth check. - last_check_time = time_now; - + last_check_time = time_now; + char* local_ip = 0; if ((ret = get_local_ip(stfd, local_ip)) != ERROR_SUCCESS) { srs_error("get local ip failed. ret = %d", ret); @@ -137,7 +137,7 @@ int SrsBandwidth::do_bandwidth_check() { int ret = ERROR_SUCCESS; - SrsProtocol* protocol = rtmp->get_protocol(); + SrsProtocol* protocol = rtmp->get_protocol(); int play_duration_ms = 3000; int play_interval_ms = 0; @@ -154,14 +154,14 @@ int SrsBandwidth::do_bandwidth_check() int64_t start_time = srs_get_system_time_ms(); ret = check_play(play_duration_ms, - play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps); + play_interval_ms, play_actual_duration_ms, play_bytes, limit_kbps); if (ret != ERROR_SUCCESS) { srs_error("band width play check failed. ret=%d", ret); return ret; } ret = check_publish(publish_duration_ms, - publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps); + publish_interval_ms, publish_actual_duration_ms, publish_bytes, limit_kbps); if (ret != ERROR_SUCCESS) { srs_error("band width publish check failed. ret=%d", ret); return ret; @@ -188,29 +188,29 @@ int SrsBandwidth::do_bandwidth_check() pkt->data->set("publish_bytes", SrsAmf0Any::number(publish_bytes)); pkt->data->set("publish_time", SrsAmf0Any::number(publish_actual_duration_ms)); - SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); + SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { srs_error("send bandwidth check finish message failed. ret=%d", ret); return ret; } // if flash, we notice the result, and expect a final packet. - while (true) { - SrsCommonMessage* msg = NULL; - SrsBandwidthPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - // info level to ignore and return success. - srs_info("expect final message failed. ret=%d", ret); - return ERROR_SUCCESS; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get final message success."); - - if (pkt->is_flash_final()) { - srs_info("BW check recv flash final response."); - break; - } - } + while (true) { + SrsCommonMessage* msg = NULL; + SrsBandwidthPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + // info level to ignore and return success. + srs_info("expect final message failed. ret=%d", ret); + return ERROR_SUCCESS; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get final message success."); + + if (pkt->is_flash_final()) { + srs_info("BW check recv flash final response."); + break; + } + } srs_info("BW check finished."); @@ -218,44 +218,44 @@ int SrsBandwidth::do_bandwidth_check() } int SrsBandwidth::check_play( - int duration_ms, int interval_ms, int& actual_duration_ms, - int& play_bytes, int max_play_kbps) + int duration_ms, int interval_ms, int& actual_duration_ms, + int& play_bytes, int max_play_kbps) { int ret = ERROR_SUCCESS; - SrsProtocol* protocol = rtmp->get_protocol(); + SrsProtocol* protocol = rtmp->get_protocol(); - if (true) { - // send start play command to client - SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play(); - - pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); - pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); - - SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); - if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send bandwidth check start play message failed. ret=%d", ret); - return ret; - } - srs_info("BW check begin."); - } + if (true) { + // send start play command to client + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_play(); + + pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); + pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); + + SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); + if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send bandwidth check start play message failed. ret=%d", ret); + return ret; + } + srs_info("BW check begin."); + } - while (true) { - // recv client's starting play response - SrsCommonMessage* msg = NULL; - SrsBandwidthPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect bandwidth message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get bandwidth message succes."); - - if (pkt->is_starting_play()) { - srs_info("BW check recv play begin response."); - break; - } - } + while (true) { + // recv client's starting play response + SrsCommonMessage* msg = NULL; + SrsBandwidthPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect bandwidth message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get bandwidth message succes."); + + if (pkt->is_starting_play()) { + srs_info("BW check recv play begin response."); + break; + } + } // send play data to client int64_t current_time = srs_get_system_time_ms(); @@ -280,10 +280,10 @@ int SrsBandwidth::check_play( } data_count += 2; - // TODO: FIXME: get length from the rtmp protocol stack. + // TODO: FIXME: get length from the rtmp protocol stack. play_bytes += pkt->get_payload_length(); - SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); + SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { srs_error("send bandwidth check play messages failed. ret=%d", ret); return ret; @@ -305,81 +305,81 @@ int SrsBandwidth::check_play( actual_duration_ms = srs_get_system_time_ms() - current_time; srs_info("BW check send play bytes over."); - if (true) { - // notify client to stop play - SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play(); - pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); - pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); - pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms)); - pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes)); + if (true) { + // notify client to stop play + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play(); + pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); + pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); + pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms)); + pkt->data->set("bytes_delta", SrsAmf0Any::number(play_bytes)); - SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); + SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send bandwidth check stop play message failed. ret=%d", ret); - return ret; - } - srs_info("BW check stop play bytes."); - } + srs_error("send bandwidth check stop play message failed. ret=%d", ret); + return ret; + } + srs_info("BW check stop play bytes."); + } - while (true) { - // recv client's stop play response. - SrsCommonMessage* msg = NULL; - SrsBandwidthPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect bandwidth message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get bandwidth message succes."); - - if (pkt->is_stopped_play()) { - srs_info("BW check recv stop play response."); - break; - } - } + while (true) { + // recv client's stop play response. + SrsCommonMessage* msg = NULL; + SrsBandwidthPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect bandwidth message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get bandwidth message succes."); + + if (pkt->is_stopped_play()) { + srs_info("BW check recv stop play response."); + break; + } + } return ret; } int SrsBandwidth::check_publish( - int duration_ms, int interval_ms, int& actual_duration_ms, - int& publish_bytes, int max_pub_kbps) + int duration_ms, int interval_ms, int& actual_duration_ms, + int& publish_bytes, int max_pub_kbps) { int ret = ERROR_SUCCESS; - SrsProtocol* protocol = rtmp->get_protocol(); + SrsProtocol* protocol = rtmp->get_protocol(); - if (true) { - // notify client to start publish - SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish(); - - pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); - pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); - - SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); - if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send bandwidth check start publish message failed. ret=%d", ret); - return ret; - } - srs_info("BW check publish begin."); - } + if (true) { + // notify client to start publish + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_start_publish(); + + pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); + pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); + + SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); + if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send bandwidth check start publish message failed. ret=%d", ret); + return ret; + } + srs_info("BW check publish begin."); + } - while (true) { - // read client's notification of starting publish - SrsCommonMessage* msg = NULL; - SrsBandwidthPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect bandwidth message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get bandwidth message succes."); - - if (pkt->is_starting_publish()) { - srs_info("BW check recv publish begin response."); - break; - } - } + while (true) { + // read client's notification of starting publish + SrsCommonMessage* msg = NULL; + SrsBandwidthPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect bandwidth message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get bandwidth message succes."); + + if (pkt->is_starting_publish()) { + srs_info("BW check recv publish begin response."); + break; + } + } // recv publish msgs until @duration_ms ms int64_t current_time = srs_get_system_time_ms(); @@ -393,7 +393,7 @@ int SrsBandwidth::check_publish( } SrsAutoFree(SrsCommonMessage, msg, false); - // TODO: FIXME. + // TODO: FIXME. publish_bytes += msg->header.payload_length; int kbps = 0; @@ -411,21 +411,21 @@ int SrsBandwidth::check_publish( actual_duration_ms = srs_get_system_time_ms() - current_time; srs_info("BW check recv publish data over."); - if (true) { - // notify client to stop publish - SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish(); - pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); - pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); - pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms)); - pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes)); + if (true) { + // notify client to stop publish + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_publish(); + pkt->data->set("duration_ms", SrsAmf0Any::number(duration_ms)); + pkt->data->set("interval_ms", SrsAmf0Any::number(interval_ms)); + pkt->data->set("duration_delta", SrsAmf0Any::number(actual_duration_ms)); + pkt->data->set("bytes_delta", SrsAmf0Any::number(publish_bytes)); - SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); + SrsCommonMessage* msg = (new SrsCommonMessage())->set_packet(pkt, 0); if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send bandwidth check stop publish message failed. ret=%d", ret); - return ret; - } - srs_info("BW check stop publish bytes."); - } + srs_error("send bandwidth check stop publish message failed. ret=%d", ret); + return ret; + } + srs_info("BW check stop publish bytes."); + } // expect client to stop publish // if flash client, we never expect the client stop publish bytes, @@ -433,22 +433,22 @@ int SrsBandwidth::check_publish( // there are many many packets in the queue. // we just ignore the packet and send the bandwidth test data. // TODO: FIXME: check whether flash client. - while (false) { - // recv client's stop publish response. - SrsCommonMessage* msg = NULL; - SrsBandwidthPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect bandwidth message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get bandwidth message succes."); - - if (pkt->is_stopped_publish()) { - srs_info("BW check recv stop publish response."); - break; - } - } + while (false) { + // recv client's stop publish response. + SrsCommonMessage* msg = NULL; + SrsBandwidthPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect bandwidth message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get bandwidth message succes."); + + if (pkt->is_stopped_publish()) { + srs_info("BW check recv stop publish response."); + break; + } + } return ret; } diff --git a/trunk/src/app/srs_app_client.cpp b/trunk/src/app/srs_app_client.cpp index 19c5fcc52..15d3a9b14 100644 --- a/trunk/src/app/srs_app_client.cpp +++ b/trunk/src/app/srs_app_client.cpp @@ -44,603 +44,603 @@ using namespace std; #include SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) - : SrsConnection(srs_server, client_stfd) + : SrsConnection(srs_server, client_stfd) { - ip = NULL; - req = new SrsRequest(); - res = new SrsResponse(); - skt = new SrsSocket(client_stfd); - rtmp = new SrsRtmpServer(skt); - refer = new SrsRefer(); -#ifdef SRS_HTTP_CALLBACK - http_hooks = new SrsHttpHooks(); + ip = NULL; + req = new SrsRequest(); + res = new SrsResponse(); + skt = new SrsSocket(client_stfd); + rtmp = new SrsRtmpServer(skt); + refer = new SrsRefer(); +#ifdef SRS_HTTP_CALLBACK + http_hooks = new SrsHttpHooks(); #endif - bandwidth = new SrsBandwidth(); - - _srs_config->subscribe(this); + bandwidth = new SrsBandwidth(); + + _srs_config->subscribe(this); } SrsClient::~SrsClient() { - _srs_config->unsubscribe(this); - - srs_freepa(ip); - srs_freep(req); - srs_freep(res); - srs_freep(rtmp); - srs_freep(skt); - srs_freep(refer); -#ifdef SRS_HTTP_CALLBACK - srs_freep(http_hooks); + _srs_config->unsubscribe(this); + + srs_freepa(ip); + srs_freep(req); + srs_freep(res); + srs_freep(rtmp); + srs_freep(skt); + srs_freep(refer); +#ifdef SRS_HTTP_CALLBACK + srs_freep(http_hooks); #endif - srs_freep(bandwidth); + srs_freep(bandwidth); } // TODO: return detail message when error for client. int SrsClient::do_cycle() { - int ret = ERROR_SUCCESS; - - if ((ret = get_peer_ip()) != ERROR_SUCCESS) { - srs_error("get peer ip failed. ret=%d", ret); - return ret; - } - srs_trace("get peer ip success. ip=%s, send_to=%"PRId64", recv_to=%"PRId64"", - ip, SRS_SEND_TIMEOUT_US, SRS_RECV_TIMEOUT_US); + int ret = ERROR_SUCCESS; + + if ((ret = get_peer_ip()) != ERROR_SUCCESS) { + srs_error("get peer ip failed. ret=%d", ret); + return ret; + } + srs_trace("get peer ip success. ip=%s, send_to=%"PRId64", recv_to=%"PRId64"", + ip, SRS_SEND_TIMEOUT_US, SRS_RECV_TIMEOUT_US); - rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US); - rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US); - - if ((ret = rtmp->handshake()) != ERROR_SUCCESS) { - srs_error("rtmp handshake failed. ret=%d", ret); - return ret; - } - srs_verbose("rtmp handshake success"); - - if ((ret = rtmp->connect_app(req)) != ERROR_SUCCESS) { - srs_error("rtmp connect vhost/app failed. ret=%d", ret); - return ret; - } - srs_verbose("rtmp connect app success"); - - // discovery vhost, resolve the vhost from config - SrsConfDirective* parsed_vhost = _srs_config->get_vhost(req->vhost); - if (parsed_vhost) { - req->vhost = parsed_vhost->arg0(); - } - - srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", - req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str()); - - if (req->schema.empty() || req->vhost.empty() || req->port.empty() || req->app.empty()) { - ret = ERROR_RTMP_REQ_TCURL; - srs_error("discovery tcUrl failed. " - "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", - req->tcUrl.c_str(), req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str(), ret); - return ret; - } - - // check vhost - if ((ret = check_vhost()) != ERROR_SUCCESS) { - srs_error("check vhost failed. ret=%d", ret); - return ret; - } - srs_verbose("check vhost success."); - - srs_trace("rtmp connect app success. " - "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s", - req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(), - req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), - req->app.c_str()); - - ret = service_cycle(); - on_close(); - - return ret; + rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US); + rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US); + + if ((ret = rtmp->handshake()) != ERROR_SUCCESS) { + srs_error("rtmp handshake failed. ret=%d", ret); + return ret; + } + srs_verbose("rtmp handshake success"); + + if ((ret = rtmp->connect_app(req)) != ERROR_SUCCESS) { + srs_error("rtmp connect vhost/app failed. ret=%d", ret); + return ret; + } + srs_verbose("rtmp connect app success"); + + // discovery vhost, resolve the vhost from config + SrsConfDirective* parsed_vhost = _srs_config->get_vhost(req->vhost); + if (parsed_vhost) { + req->vhost = parsed_vhost->arg0(); + } + + srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", + req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str()); + + if (req->schema.empty() || req->vhost.empty() || req->port.empty() || req->app.empty()) { + ret = ERROR_RTMP_REQ_TCURL; + srs_error("discovery tcUrl failed. " + "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", + req->tcUrl.c_str(), req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str(), ret); + return ret; + } + + // check vhost + if ((ret = check_vhost()) != ERROR_SUCCESS) { + srs_error("check vhost failed. ret=%d", ret); + return ret; + } + srs_verbose("check vhost success."); + + srs_trace("rtmp connect app success. " + "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s", + req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(), + req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), + req->app.c_str()); + + ret = service_cycle(); + on_close(); + + return ret; } int SrsClient::on_reload_vhost_removed(string vhost) { - int ret = ERROR_SUCCESS; - - if (req->vhost != vhost) { - return ret; - } - - // if the vhost connected is removed, disconnect the client. - srs_trace("vhost %s removed/disabled, close client url=%s", - vhost.c_str(), req->get_stream_url().c_str()); - - srs_close_stfd(stfd); - - return ret; + int ret = ERROR_SUCCESS; + + if (req->vhost != vhost) { + return ret; + } + + // if the vhost connected is removed, disconnect the client. + srs_trace("vhost %s removed/disabled, close client url=%s", + vhost.c_str(), req->get_stream_url().c_str()); + + srs_close_stfd(stfd); + + return ret; } - + int SrsClient::service_cycle() -{ - int ret = ERROR_SUCCESS; - - if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) { - srs_error("set window acknowledgement size failed. ret=%d", ret); - return ret; - } - srs_verbose("set window acknowledgement size success"); - - if ((ret = rtmp->set_peer_bandwidth(2.5 * 1000 * 1000, 2)) != ERROR_SUCCESS) { - srs_error("set peer bandwidth failed. ret=%d", ret); - return ret; - } - srs_verbose("set peer bandwidth success"); +{ + int ret = ERROR_SUCCESS; + + if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) { + srs_error("set window acknowledgement size failed. ret=%d", ret); + return ret; + } + srs_verbose("set window acknowledgement size success"); + + if ((ret = rtmp->set_peer_bandwidth(2.5 * 1000 * 1000, 2)) != ERROR_SUCCESS) { + srs_error("set peer bandwidth failed. ret=%d", ret); + return ret; + } + srs_verbose("set peer bandwidth success"); - // do bandwidth test if connect to the vhost which is for bandwidth check. - if (_srs_config->get_bw_check_enabled(req->vhost)) { - return bandwidth->bandwidth_test(req, stfd, rtmp); - } - - if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) { - srs_error("response connect app failed. ret=%d", ret); - return ret; - } - srs_verbose("response connect app success"); - - if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) { - srs_error("on_bw_done failed. ret=%d", ret); - return ret; - } - srs_verbose("on_bw_done success"); - - while (true) { - ret = stream_service_cycle(); - - // stream service must terminated with error, never success. - srs_assert(ret != ERROR_SUCCESS); - - // when not system control error, fatal error, return. - if (!srs_is_system_control_error(ret)) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("stream service cycle failed. ret=%d", ret); - } - return ret; - } - - // for republish, continue service - if (ret == ERROR_CONTROL_REPUBLISH) { - // set timeout to a larger value, wait for encoder to republish. - rtmp->set_send_timeout(SRS_REPUBLISH_RECV_TIMEOUT_US); - rtmp->set_recv_timeout(SRS_REPUBLISH_SEND_TIMEOUT_US); - - srs_trace("control message(unpublish) accept, retry stream service."); - continue; - } - - // for "some" system control error, - // logical accept and retry stream service. - if (ret == ERROR_CONTROL_RTMP_CLOSE) { - // set timeout to a larger value, for user paused. - rtmp->set_recv_timeout(SRS_PAUSED_RECV_TIMEOUT_US); - rtmp->set_send_timeout(SRS_PAUSED_SEND_TIMEOUT_US); - - srs_trace("control message(close) accept, retry stream service."); - continue; - } - - // for other system control message, fatal error. - srs_error("control message(%d) reject as error. ret=%d", ret, ret); - return ret; - } - - return ret; + // do bandwidth test if connect to the vhost which is for bandwidth check. + if (_srs_config->get_bw_check_enabled(req->vhost)) { + return bandwidth->bandwidth_test(req, stfd, rtmp); + } + + if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) { + srs_error("response connect app failed. ret=%d", ret); + return ret; + } + srs_verbose("response connect app success"); + + if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) { + srs_error("on_bw_done failed. ret=%d", ret); + return ret; + } + srs_verbose("on_bw_done success"); + + while (true) { + ret = stream_service_cycle(); + + // stream service must terminated with error, never success. + srs_assert(ret != ERROR_SUCCESS); + + // when not system control error, fatal error, return. + if (!srs_is_system_control_error(ret)) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("stream service cycle failed. ret=%d", ret); + } + return ret; + } + + // for republish, continue service + if (ret == ERROR_CONTROL_REPUBLISH) { + // set timeout to a larger value, wait for encoder to republish. + rtmp->set_send_timeout(SRS_REPUBLISH_RECV_TIMEOUT_US); + rtmp->set_recv_timeout(SRS_REPUBLISH_SEND_TIMEOUT_US); + + srs_trace("control message(unpublish) accept, retry stream service."); + continue; + } + + // for "some" system control error, + // logical accept and retry stream service. + if (ret == ERROR_CONTROL_RTMP_CLOSE) { + // set timeout to a larger value, for user paused. + rtmp->set_recv_timeout(SRS_PAUSED_RECV_TIMEOUT_US); + rtmp->set_send_timeout(SRS_PAUSED_SEND_TIMEOUT_US); + + srs_trace("control message(close) accept, retry stream service."); + continue; + } + + // for other system control message, fatal error. + srs_error("control message(%d) reject as error. ret=%d", ret, ret); + return ret; + } + + return ret; } int SrsClient::stream_service_cycle() { - int ret = ERROR_SUCCESS; - - SrsClientType type; - if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) { - srs_error("identify client failed. ret=%d", ret); - return ret; - } - req->strip(); - srs_trace("identify client success. type=%s, stream_name=%s", - srs_client_type_string(type).c_str(), req->stream.c_str()); + int ret = ERROR_SUCCESS; + + SrsClientType type; + if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) { + srs_error("identify client failed. ret=%d", ret); + return ret; + } + req->strip(); + srs_trace("identify client success. type=%s, stream_name=%s", + srs_client_type_string(type).c_str(), req->stream.c_str()); - // client is identified, set the timeout to service timeout. - rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US); - rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US); - - // set chunk size to larger. + // client is identified, set the timeout to service timeout. + rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US); + rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US); + + // set chunk size to larger. int chunk_size = _srs_config->get_chunk_size(req->vhost); - if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) { - srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret); - return ret; - } - srs_trace("set chunk_size=%d success", chunk_size); - - // find a source to serve. - SrsSource* source = SrsSource::find(req); - srs_assert(source != NULL); - - // check publish available. - if (type != SrsClientPlay && !source->can_publish()) { - ret = ERROR_SYSTEM_STREAM_BUSY; - srs_warn("stream %s is already publishing. ret=%d", - req->get_stream_url().c_str(), ret); - // to delay request - st_usleep(SRS_STREAM_BUSY_SLEEP_US); - return ret; - } - - bool enabled_cache = _srs_config->get_gop_cache(req->vhost); - srs_info("source found, url=%s, enabled_cache=%d", req->get_stream_url().c_str(), enabled_cache); - source->set_cache(enabled_cache); - - switch (type) { - case SrsClientPlay: { - srs_verbose("start to play stream %s.", req->stream.c_str()); - - if ((ret = rtmp->start_play(res->stream_id)) != ERROR_SUCCESS) { - srs_error("start to play stream failed. ret=%d", ret); - return ret; - } - if ((ret = on_play()) != ERROR_SUCCESS) { - srs_error("http hook on_play failed. ret=%d", ret); - return ret; - } - srs_info("start to play stream %s success", req->stream.c_str()); - ret = playing(source); - on_stop(); - return ret; - } - case SrsClientFMLEPublish: { - srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); - - if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) { - srs_error("start to publish stream failed. ret=%d", ret); - return ret; - } - if ((ret = on_publish()) != ERROR_SUCCESS) { - srs_error("http hook on_publish failed. ret=%d", ret); - return ret; - } - srs_info("start to publish stream %s success", req->stream.c_str()); - ret = fmle_publish(source); - source->on_unpublish(); - on_unpublish(); - return ret; - } - case SrsClientFlashPublish: { - srs_verbose("flash start to publish stream %s.", req->stream.c_str()); - - if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) { - srs_error("flash start to publish stream failed. ret=%d", ret); - return ret; - } - if ((ret = on_publish()) != ERROR_SUCCESS) { - srs_error("http hook on_publish failed. ret=%d", ret); - return ret; - } - srs_info("flash start to publish stream %s success", req->stream.c_str()); - ret = flash_publish(source); - source->on_unpublish(); - on_unpublish(); - return ret; - } - default: { - ret = ERROR_SYSTEM_CLIENT_INVALID; - srs_info("invalid client type=%d. ret=%d", type, ret); - return ret; - } - } - - return ret; + if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) { + srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret); + return ret; + } + srs_trace("set chunk_size=%d success", chunk_size); + + // find a source to serve. + SrsSource* source = SrsSource::find(req); + srs_assert(source != NULL); + + // check publish available. + if (type != SrsClientPlay && !source->can_publish()) { + ret = ERROR_SYSTEM_STREAM_BUSY; + srs_warn("stream %s is already publishing. ret=%d", + req->get_stream_url().c_str(), ret); + // to delay request + st_usleep(SRS_STREAM_BUSY_SLEEP_US); + return ret; + } + + bool enabled_cache = _srs_config->get_gop_cache(req->vhost); + srs_info("source found, url=%s, enabled_cache=%d", req->get_stream_url().c_str(), enabled_cache); + source->set_cache(enabled_cache); + + switch (type) { + case SrsClientPlay: { + srs_verbose("start to play stream %s.", req->stream.c_str()); + + if ((ret = rtmp->start_play(res->stream_id)) != ERROR_SUCCESS) { + srs_error("start to play stream failed. ret=%d", ret); + return ret; + } + if ((ret = on_play()) != ERROR_SUCCESS) { + srs_error("http hook on_play failed. ret=%d", ret); + return ret; + } + srs_info("start to play stream %s success", req->stream.c_str()); + ret = playing(source); + on_stop(); + return ret; + } + case SrsClientFMLEPublish: { + srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); + + if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) { + srs_error("start to publish stream failed. ret=%d", ret); + return ret; + } + if ((ret = on_publish()) != ERROR_SUCCESS) { + srs_error("http hook on_publish failed. ret=%d", ret); + return ret; + } + srs_info("start to publish stream %s success", req->stream.c_str()); + ret = fmle_publish(source); + source->on_unpublish(); + on_unpublish(); + return ret; + } + case SrsClientFlashPublish: { + srs_verbose("flash start to publish stream %s.", req->stream.c_str()); + + if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) { + srs_error("flash start to publish stream failed. ret=%d", ret); + return ret; + } + if ((ret = on_publish()) != ERROR_SUCCESS) { + srs_error("http hook on_publish failed. ret=%d", ret); + return ret; + } + srs_info("flash start to publish stream %s success", req->stream.c_str()); + ret = flash_publish(source); + source->on_unpublish(); + on_unpublish(); + return ret; + } + default: { + ret = ERROR_SYSTEM_CLIENT_INVALID; + srs_info("invalid client type=%d. ret=%d", type, ret); + return ret; + } + } + + return ret; } int SrsClient::check_vhost() { - int ret = ERROR_SUCCESS; - - srs_assert(req != NULL); - - SrsConfDirective* vhost = _srs_config->get_vhost(req->vhost); - if (vhost == NULL) { - ret = ERROR_RTMP_VHOST_NOT_FOUND; - srs_error("vhost %s not found. ret=%d", req->vhost.c_str(), ret); - return ret; - } - - if (!_srs_config->get_vhost_enabled(req->vhost)) { - ret = ERROR_RTMP_VHOST_NOT_FOUND; - srs_error("vhost %s disabled. ret=%d", req->vhost.c_str(), ret); - return ret; - } - - if (req->vhost != vhost->arg0()) { - srs_trace("vhost change from %s to %s", req->vhost.c_str(), vhost->arg0().c_str()); - req->vhost = vhost->arg0(); - } - - if ((ret = refer->check(req->pageUrl, _srs_config->get_refer(req->vhost))) != ERROR_SUCCESS) { - srs_error("check refer failed. ret=%d", ret); - return ret; - } - srs_verbose("check refer success."); - - if ((ret = on_connect()) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + srs_assert(req != NULL); + + SrsConfDirective* vhost = _srs_config->get_vhost(req->vhost); + if (vhost == NULL) { + ret = ERROR_RTMP_VHOST_NOT_FOUND; + srs_error("vhost %s not found. ret=%d", req->vhost.c_str(), ret); + return ret; + } + + if (!_srs_config->get_vhost_enabled(req->vhost)) { + ret = ERROR_RTMP_VHOST_NOT_FOUND; + srs_error("vhost %s disabled. ret=%d", req->vhost.c_str(), ret); + return ret; + } + + if (req->vhost != vhost->arg0()) { + srs_trace("vhost change from %s to %s", req->vhost.c_str(), vhost->arg0().c_str()); + req->vhost = vhost->arg0(); + } + + if ((ret = refer->check(req->pageUrl, _srs_config->get_refer(req->vhost))) != ERROR_SUCCESS) { + srs_error("check refer failed. ret=%d", ret); + return ret; + } + srs_verbose("check refer success."); + + if ((ret = on_connect()) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsClient::playing(SrsSource* source) { - int ret = ERROR_SUCCESS; - - if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != ERROR_SUCCESS) { - srs_error("check play_refer failed. ret=%d", ret); - return ret; - } - srs_verbose("check play_refer success."); - - SrsConsumer* consumer = NULL; - if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) { - srs_error("create consumer failed. ret=%d", ret); - return ret; - } - - srs_assert(consumer != NULL); - SrsAutoFree(SrsConsumer, consumer, false); - srs_verbose("consumer created success."); - - rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_US); - - SrsPithyPrint pithy_print(SRS_STAGE_PLAY_USER); + int ret = ERROR_SUCCESS; + + if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != ERROR_SUCCESS) { + srs_error("check play_refer failed. ret=%d", ret); + return ret; + } + srs_verbose("check play_refer success."); + + SrsConsumer* consumer = NULL; + if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) { + srs_error("create consumer failed. ret=%d", ret); + return ret; + } + + srs_assert(consumer != NULL); + SrsAutoFree(SrsConsumer, consumer, false); + srs_verbose("consumer created success."); + + rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_US); + + SrsPithyPrint pithy_print(SRS_STAGE_PLAY_USER); - while (true) { - pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); - - // switch to other st-threads. - st_usleep(0); + while (true) { + pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); + + // switch to other st-threads. + st_usleep(0); - // read from client. - int ctl_msg_ret = ERROR_SUCCESS; - if (true) { - SrsCommonMessage* msg = NULL; - ctl_msg_ret = ret = rtmp->recv_message(&msg); - - srs_verbose("play loop recv message. ret=%d", ret); - if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("recv client control message failed. ret=%d", ret); - } - return ret; - } - if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) { - if (!srs_is_system_control_error(ret)) { - srs_error("process play control message failed. ret=%d", ret); - } - return ret; - } - } - - // get messages from consumer. - SrsSharedPtrMessage** msgs = NULL; - int count = 0; - if ((ret = consumer->get_packets(0, msgs, count)) != ERROR_SUCCESS) { - srs_error("get messages from consumer failed. ret=%d", ret); - return ret; - } + // read from client. + int ctl_msg_ret = ERROR_SUCCESS; + if (true) { + SrsCommonMessage* msg = NULL; + ctl_msg_ret = ret = rtmp->recv_message(&msg); + + srs_verbose("play loop recv message. ret=%d", ret); + if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("recv client control message failed. ret=%d", ret); + } + return ret; + } + if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) { + if (!srs_is_system_control_error(ret)) { + srs_error("process play control message failed. ret=%d", ret); + } + return ret; + } + } + + // get messages from consumer. + SrsSharedPtrMessage** msgs = NULL; + int count = 0; + if ((ret = consumer->get_packets(0, msgs, count)) != ERROR_SUCCESS) { + srs_error("get messages from consumer failed. ret=%d", ret); + return ret; + } - // reportable - if (pithy_print.can_print()) { - srs_trace("-> time=%"PRId64", cmr=%d, msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", - pithy_print.get_age(), ctl_msg_ret, count, rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); - } - - if (count <= 0) { - srs_verbose("no packets in queue."); - continue; - } - SrsAutoFree(SrsSharedPtrMessage*, msgs, true); - - // sendout messages - for (int i = 0; i < count; i++) { - SrsSharedPtrMessage* msg = msgs[i]; - - // the send_message will free the msg, - // so set the msgs[i] to NULL. - msgs[i] = NULL; - - if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send message to client failed. ret=%d", ret); - return ret; - } - } - } - - return ret; + // reportable + if (pithy_print.can_print()) { + srs_trace("-> time=%"PRId64", cmr=%d, msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", + pithy_print.get_age(), ctl_msg_ret, count, rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); + } + + if (count <= 0) { + srs_verbose("no packets in queue."); + continue; + } + SrsAutoFree(SrsSharedPtrMessage*, msgs, true); + + // sendout messages + for (int i = 0; i < count; i++) { + SrsSharedPtrMessage* msg = msgs[i]; + + // the send_message will free the msg, + // so set the msgs[i] to NULL. + msgs[i] = NULL; + + if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send message to client failed. ret=%d", ret); + return ret; + } + } + } + + return ret; } int SrsClient::fmle_publish(SrsSource* source) { - int ret = ERROR_SUCCESS; - - if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { - srs_error("fmle check publish_refer failed. ret=%d", ret); - return ret; - } - srs_verbose("fmle check publish_refer success."); - - SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); - - // notify the hls to prepare when publish start. - if ((ret = source->on_publish(req)) != ERROR_SUCCESS) { - srs_error("fmle hls on_publish failed. ret=%d", ret); - return ret; - } - srs_verbose("fmle hls on_publish success."); - - while (true) { - // switch to other st-threads. - st_usleep(0); - - SrsCommonMessage* msg = NULL; - if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("fmle recv identify client message failed. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { + srs_error("fmle check publish_refer failed. ret=%d", ret); + return ret; + } + srs_verbose("fmle check publish_refer success."); + + SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); + + // notify the hls to prepare when publish start. + if ((ret = source->on_publish(req)) != ERROR_SUCCESS) { + srs_error("fmle hls on_publish failed. ret=%d", ret); + return ret; + } + srs_verbose("fmle hls on_publish success."); + + while (true) { + // switch to other st-threads. + st_usleep(0); + + SrsCommonMessage* msg = NULL; + if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("fmle recv identify client message failed. ret=%d", ret); + return ret; + } - SrsAutoFree(SrsCommonMessage, msg, false); - - pithy_print.set_age(msg->header.timestamp); + SrsAutoFree(SrsCommonMessage, msg, false); + + pithy_print.set_age(msg->header.timestamp); - // reportable - if (pithy_print.can_print()) { - srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", - pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); - } - - // process UnPublish event. - if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) { - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { - srs_error("fmle decode unpublish message failed. ret=%d", ret); - return ret; - } - - SrsPacket* pkt = msg->get_packet(); - if (dynamic_cast(pkt)) { - SrsFMLEStartPacket* unpublish = dynamic_cast(pkt); - if ((ret = rtmp->fmle_unpublish(res->stream_id, unpublish->transaction_id)) != ERROR_SUCCESS) { - return ret; - } - return ERROR_CONTROL_REPUBLISH; - } - - srs_trace("fmle ignore AMF0/AMF3 command message."); - continue; - } + // reportable + if (pithy_print.can_print()) { + srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", + pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); + } + + // process UnPublish event. + if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) { + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { + srs_error("fmle decode unpublish message failed. ret=%d", ret); + return ret; + } + + SrsPacket* pkt = msg->get_packet(); + if (dynamic_cast(pkt)) { + SrsFMLEStartPacket* unpublish = dynamic_cast(pkt); + if ((ret = rtmp->fmle_unpublish(res->stream_id, unpublish->transaction_id)) != ERROR_SUCCESS) { + return ret; + } + return ERROR_CONTROL_REPUBLISH; + } + + srs_trace("fmle ignore AMF0/AMF3 command message."); + continue; + } - // video, audio, data message - if ((ret = process_publish_message(source, msg)) != ERROR_SUCCESS) { - srs_error("fmle process publish message failed. ret=%d", ret); - return ret; - } - } - - return ret; + // video, audio, data message + if ((ret = process_publish_message(source, msg)) != ERROR_SUCCESS) { + srs_error("fmle process publish message failed. ret=%d", ret); + return ret; + } + } + + return ret; } int SrsClient::flash_publish(SrsSource* source) { - int ret = ERROR_SUCCESS; - - if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { - srs_error("flash check publish_refer failed. ret=%d", ret); - return ret; - } - srs_verbose("flash check publish_refer success."); - - SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); - - // notify the hls to prepare when publish start. - if ((ret = source->on_publish(req)) != ERROR_SUCCESS) { - srs_error("flash hls on_publish failed. ret=%d", ret); - return ret; - } - srs_verbose("flash hls on_publish success."); - - while (true) { - // switch to other st-threads. - st_usleep(0); - - SrsCommonMessage* msg = NULL; - if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("flash recv identify client message failed. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) { + srs_error("flash check publish_refer failed. ret=%d", ret); + return ret; + } + srs_verbose("flash check publish_refer success."); + + SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER); + + // notify the hls to prepare when publish start. + if ((ret = source->on_publish(req)) != ERROR_SUCCESS) { + srs_error("flash hls on_publish failed. ret=%d", ret); + return ret; + } + srs_verbose("flash hls on_publish success."); + + while (true) { + // switch to other st-threads. + st_usleep(0); + + SrsCommonMessage* msg = NULL; + if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("flash recv identify client message failed. ret=%d", ret); + return ret; + } - SrsAutoFree(SrsCommonMessage, msg, false); - - pithy_print.set_age(msg->header.timestamp); + SrsAutoFree(SrsCommonMessage, msg, false); + + pithy_print.set_age(msg->header.timestamp); - // reportable - if (pithy_print.can_print()) { - srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", - pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); - } - - // process UnPublish event. - if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) { - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { - srs_error("flash decode unpublish message failed. ret=%d", ret); - return ret; - } - - // flash unpublish. - // TODO: maybe need to support republish. - srs_trace("flash flash publish finished."); - return ERROR_CONTROL_REPUBLISH; - } + // reportable + if (pithy_print.can_print()) { + srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", + pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps()); + } + + // process UnPublish event. + if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) { + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { + srs_error("flash decode unpublish message failed. ret=%d", ret); + return ret; + } + + // flash unpublish. + // TODO: maybe need to support republish. + srs_trace("flash flash publish finished."); + return ERROR_CONTROL_REPUBLISH; + } - // video, audio, data message - if ((ret = process_publish_message(source, msg)) != ERROR_SUCCESS) { - srs_error("flash process publish message failed. ret=%d", ret); - return ret; - } - } - - return ret; + // video, audio, data message + if ((ret = process_publish_message(source, msg)) != ERROR_SUCCESS) { + srs_error("flash process publish message failed. ret=%d", ret); + return ret; + } + } + + return ret; } int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg) { - int ret = ERROR_SUCCESS; - - // process audio packet - if (msg->header.is_audio()) { - if ((ret = source->on_audio(msg)) != ERROR_SUCCESS) { - srs_error("source process audio message failed. ret=%d", ret); - return ret; - } - } - // process video packet - if (msg->header.is_video()) { - if ((ret = source->on_video(msg)) != ERROR_SUCCESS) { - srs_error("source process video message failed. ret=%d", ret); - return ret; - } - } - - // process onMetaData - if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { - srs_error("decode onMetaData message failed. ret=%d", ret); - return ret; - } - - SrsPacket* pkt = msg->get_packet(); - if (dynamic_cast(pkt)) { - SrsOnMetaDataPacket* metadata = dynamic_cast(pkt); - if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) { - srs_error("source process onMetaData message failed. ret=%d", ret); - return ret; - } - srs_trace("process onMetaData message success."); - return ret; - } - - srs_trace("ignore AMF0/AMF3 data message."); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + // process audio packet + if (msg->header.is_audio()) { + if ((ret = source->on_audio(msg)) != ERROR_SUCCESS) { + srs_error("source process audio message failed. ret=%d", ret); + return ret; + } + } + // process video packet + if (msg->header.is_video()) { + if ((ret = source->on_video(msg)) != ERROR_SUCCESS) { + srs_error("source process video message failed. ret=%d", ret); + return ret; + } + } + + // process onMetaData + if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { + srs_error("decode onMetaData message failed. ret=%d", ret); + return ret; + } + + SrsPacket* pkt = msg->get_packet(); + if (dynamic_cast(pkt)) { + SrsOnMetaDataPacket* metadata = dynamic_cast(pkt); + if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) { + srs_error("source process onMetaData message failed. ret=%d", ret); + return ret; + } + srs_trace("process onMetaData message success."); + return ret; + } + + srs_trace("ignore AMF0/AMF3 data message."); + return ret; + } + + return ret; } int SrsClient::get_peer_ip() { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + int fd = st_netfd_fileno(stfd); // discovery client information @@ -674,71 +674,71 @@ int SrsClient::get_peer_ip() int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg) { - int ret = ERROR_SUCCESS; - - if (!msg) { - srs_verbose("ignore all empty message."); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { - srs_info("ignore all message except amf0/amf3 command."); - return ret; - } - - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { - srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret); - return ret; - } - srs_info("decode the amf0/amf3 command packet success."); - - SrsCloseStreamPacket* close = dynamic_cast(msg->get_packet()); - if (close) { - ret = ERROR_CONTROL_RTMP_CLOSE; - srs_trace("system control message: rtmp close stream. ret=%d", ret); - return ret; - } - - SrsPausePacket* pause = dynamic_cast(msg->get_packet()); - if (!pause) { - srs_info("ignore all amf0/amf3 command except pause."); - return ret; - } - - if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) { - srs_error("rtmp process play client pause failed. ret=%d", ret); - return ret; - } - - if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) { - srs_error("consumer process play client pause failed. ret=%d", ret); - return ret; - } - srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms); - + int ret = ERROR_SUCCESS; + + if (!msg) { + srs_verbose("ignore all empty message."); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { + srs_info("ignore all message except amf0/amf3 command."); + return ret; + } + + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) { + srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret); + return ret; + } + srs_info("decode the amf0/amf3 command packet success."); + + SrsCloseStreamPacket* close = dynamic_cast(msg->get_packet()); + if (close) { + ret = ERROR_CONTROL_RTMP_CLOSE; + srs_trace("system control message: rtmp close stream. ret=%d", ret); + return ret; + } + + SrsPausePacket* pause = dynamic_cast(msg->get_packet()); + if (!pause) { + srs_info("ignore all amf0/amf3 command except pause."); + return ret; + } + + if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) { + srs_error("rtmp process play client pause failed. ret=%d", ret); + return ret; + } + + if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) { + srs_error("consumer process play client pause failed. ret=%d", ret); + return ret; + } + srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms); + return ret; } int SrsClient::on_connect() { - int ret = ERROR_SUCCESS; - -#ifdef SRS_HTTP_CALLBACK - // HTTP: on_connect - SrsConfDirective* on_connect = _srs_config->get_vhost_on_connect(req->vhost); - if (!on_connect) { - srs_info("ignore the empty http callback: on_connect"); - return ret; - } - - for (int i = 0; i < (int)on_connect->args.size(); i++) { - std::string url = on_connect->args.at(i); - if ((ret = http_hooks->on_connect(url, connection_id, ip, req)) != ERROR_SUCCESS) { - srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } - } + int ret = ERROR_SUCCESS; + +#ifdef SRS_HTTP_CALLBACK + // HTTP: on_connect + SrsConfDirective* on_connect = _srs_config->get_vhost_on_connect(req->vhost); + if (!on_connect) { + srs_info("ignore the empty http callback: on_connect"); + return ret; + } + + for (int i = 0; i < (int)on_connect->args.size(); i++) { + std::string url = on_connect->args.at(i); + if ((ret = http_hooks->on_connect(url, connection_id, ip, req)) != ERROR_SUCCESS) { + srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); + return ret; + } + } #endif return ret; @@ -747,40 +747,40 @@ int SrsClient::on_connect() void SrsClient::on_close() { #ifdef SRS_HTTP_CALLBACK - // whatever the ret code, notify the api hooks. - // HTTP: on_close - SrsConfDirective* on_close = _srs_config->get_vhost_on_close(req->vhost); - if (!on_close) { - srs_info("ignore the empty http callback: on_close"); - return; - } - - for (int i = 0; i < (int)on_close->args.size(); i++) { - std::string url = on_close->args.at(i); - http_hooks->on_close(url, connection_id, ip, req); - } + // whatever the ret code, notify the api hooks. + // HTTP: on_close + SrsConfDirective* on_close = _srs_config->get_vhost_on_close(req->vhost); + if (!on_close) { + srs_info("ignore the empty http callback: on_close"); + return; + } + + for (int i = 0; i < (int)on_close->args.size(); i++) { + std::string url = on_close->args.at(i); + http_hooks->on_close(url, connection_id, ip, req); + } #endif } int SrsClient::on_publish() { - int ret = ERROR_SUCCESS; - -#ifdef SRS_HTTP_CALLBACK - // HTTP: on_publish - SrsConfDirective* on_publish = _srs_config->get_vhost_on_publish(req->vhost); - if (!on_publish) { - srs_info("ignore the empty http callback: on_publish"); - return ret; - } - - for (int i = 0; i < (int)on_publish->args.size(); i++) { - std::string url = on_publish->args.at(i); - if ((ret = http_hooks->on_publish(url, connection_id, ip, req)) != ERROR_SUCCESS) { - srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } - } + int ret = ERROR_SUCCESS; + +#ifdef SRS_HTTP_CALLBACK + // HTTP: on_publish + SrsConfDirective* on_publish = _srs_config->get_vhost_on_publish(req->vhost); + if (!on_publish) { + srs_info("ignore the empty http callback: on_publish"); + return ret; + } + + for (int i = 0; i < (int)on_publish->args.size(); i++) { + std::string url = on_publish->args.at(i); + if ((ret = http_hooks->on_publish(url, connection_id, ip, req)) != ERROR_SUCCESS) { + srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); + return ret; + } + } #endif return ret; @@ -789,40 +789,40 @@ int SrsClient::on_publish() void SrsClient::on_unpublish() { #ifdef SRS_HTTP_CALLBACK - // whatever the ret code, notify the api hooks. - // HTTP: on_unpublish - SrsConfDirective* on_unpublish = _srs_config->get_vhost_on_unpublish(req->vhost); - if (!on_unpublish) { - srs_info("ignore the empty http callback: on_unpublish"); - return; - } - - for (int i = 0; i < (int)on_unpublish->args.size(); i++) { - std::string url = on_unpublish->args.at(i); - http_hooks->on_unpublish(url, connection_id, ip, req); - } + // whatever the ret code, notify the api hooks. + // HTTP: on_unpublish + SrsConfDirective* on_unpublish = _srs_config->get_vhost_on_unpublish(req->vhost); + if (!on_unpublish) { + srs_info("ignore the empty http callback: on_unpublish"); + return; + } + + for (int i = 0; i < (int)on_unpublish->args.size(); i++) { + std::string url = on_unpublish->args.at(i); + http_hooks->on_unpublish(url, connection_id, ip, req); + } #endif } int SrsClient::on_play() { - int ret = ERROR_SUCCESS; - -#ifdef SRS_HTTP_CALLBACK - // HTTP: on_play - SrsConfDirective* on_play = _srs_config->get_vhost_on_play(req->vhost); - if (!on_play) { - srs_info("ignore the empty http callback: on_play"); - return ret; - } - - for (int i = 0; i < (int)on_play->args.size(); i++) { - std::string url = on_play->args.at(i); - if ((ret = http_hooks->on_play(url, connection_id, ip, req)) != ERROR_SUCCESS) { - srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); - return ret; - } - } + int ret = ERROR_SUCCESS; + +#ifdef SRS_HTTP_CALLBACK + // HTTP: on_play + SrsConfDirective* on_play = _srs_config->get_vhost_on_play(req->vhost); + if (!on_play) { + srs_info("ignore the empty http callback: on_play"); + return ret; + } + + for (int i = 0; i < (int)on_play->args.size(); i++) { + std::string url = on_play->args.at(i); + if ((ret = http_hooks->on_play(url, connection_id, ip, req)) != ERROR_SUCCESS) { + srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); + return ret; + } + } #endif return ret; @@ -831,17 +831,17 @@ int SrsClient::on_play() void SrsClient::on_stop() { #ifdef SRS_HTTP_CALLBACK - // whatever the ret code, notify the api hooks. - // HTTP: on_stop - SrsConfDirective* on_stop = _srs_config->get_vhost_on_stop(req->vhost); - if (!on_stop) { - srs_info("ignore the empty http callback: on_stop"); - return; - } - - for (int i = 0; i < (int)on_stop->args.size(); i++) { - std::string url = on_stop->args.at(i); - http_hooks->on_stop(url, connection_id, ip, req); - } + // whatever the ret code, notify the api hooks. + // HTTP: on_stop + SrsConfDirective* on_stop = _srs_config->get_vhost_on_stop(req->vhost); + if (!on_stop) { + srs_info("ignore the empty http callback: on_stop"); + return; + } + + for (int i = 0; i < (int)on_stop->args.size(); i++) { + std::string url = on_stop->args.at(i); + http_hooks->on_stop(url, connection_id, ip, req); + } #endif } diff --git a/trunk/src/app/srs_app_client.hpp b/trunk/src/app/srs_app_client.hpp index 475219aca..dcdcb1bae 100644 --- a/trunk/src/app/srs_app_client.hpp +++ b/trunk/src/app/srs_app_client.hpp @@ -42,7 +42,7 @@ class SrsRefer; class SrsConsumer; class SrsCommonMessage; class SrsSocket; -#ifdef SRS_HTTP_CALLBACK +#ifdef SRS_HTTP_CALLBACK class SrsHttpHooks; #endif class SrsBandwidth; @@ -53,43 +53,43 @@ class SrsBandwidth; class SrsClient : public SrsConnection, public ISrsReloadHandler { private: - char* ip; - SrsRequest* req; - SrsResponse* res; - SrsSocket* skt; - SrsRtmpServer* rtmp; - SrsRefer* refer; -#ifdef SRS_HTTP_CALLBACK - SrsHttpHooks* http_hooks; + char* ip; + SrsRequest* req; + SrsResponse* res; + SrsSocket* skt; + SrsRtmpServer* rtmp; + SrsRefer* refer; +#ifdef SRS_HTTP_CALLBACK + SrsHttpHooks* http_hooks; #endif - SrsBandwidth* bandwidth; + SrsBandwidth* bandwidth; public: - SrsClient(SrsServer* srs_server, st_netfd_t client_stfd); - virtual ~SrsClient(); + SrsClient(SrsServer* srs_server, st_netfd_t client_stfd); + virtual ~SrsClient(); protected: - virtual int do_cycle(); + virtual int do_cycle(); // interface ISrsReloadHandler public: - virtual int on_reload_vhost_removed(std::string vhost); + virtual int on_reload_vhost_removed(std::string vhost); private: - // when valid and connected to vhost/app, service the client. - virtual int service_cycle(); - // stream(play/publish) service cycle, identify client first. - virtual int stream_service_cycle(); - virtual int check_vhost(); - virtual int playing(SrsSource* source); - virtual int fmle_publish(SrsSource* source); - virtual int flash_publish(SrsSource* source); - virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg); - virtual int get_peer_ip(); - virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); + // when valid and connected to vhost/app, service the client. + virtual int service_cycle(); + // stream(play/publish) service cycle, identify client first. + virtual int stream_service_cycle(); + virtual int check_vhost(); + virtual int playing(SrsSource* source); + virtual int fmle_publish(SrsSource* source); + virtual int flash_publish(SrsSource* source); + virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg); + virtual int get_peer_ip(); + virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); private: - virtual int on_connect(); - virtual void on_close(); - virtual int on_publish(); - virtual void on_unpublish(); - virtual int on_play(); - virtual void on_stop(); + virtual int on_connect(); + virtual void on_close(); + virtual int on_publish(); + virtual void on_unpublish(); + virtual int on_play(); + virtual void on_stop(); }; #endif diff --git a/trunk/src/app/srs_app_codec.cpp b/trunk/src/app/srs_app_codec.cpp index 6552e9b61..1170506c7 100644 --- a/trunk/src/app/srs_app_codec.cpp +++ b/trunk/src/app/srs_app_codec.cpp @@ -33,29 +33,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsCodecBuffer::SrsCodecBuffer() { - size = 0; - bytes = NULL; + size = 0; + bytes = NULL; } void SrsCodecBuffer::append(void* data, int len) { - srs_assert(data); - srs_assert(len > 0); + srs_assert(data); + srs_assert(len > 0); - bytes = (char*)realloc(bytes, size + len); - memcpy(bytes + size, data, len); - size += len; + bytes = (char*)realloc(bytes, size + len); + memcpy(bytes + size, data, len); + size += len; } void SrsCodecBuffer::free() { - size = 0; - srs_freepa(bytes); + size = 0; + srs_freepa(bytes); } SrsCodecSample::SrsCodecSample() { - clear(); + clear(); } SrsCodecSample::~SrsCodecSample() @@ -64,468 +64,468 @@ SrsCodecSample::~SrsCodecSample() void SrsCodecSample::clear() { - is_video = false; - nb_buffers = 0; + is_video = false; + nb_buffers = 0; - cts = 0; - frame_type = SrsCodecVideoAVCFrameReserved; - avc_packet_type = SrsCodecVideoAVCTypeReserved; - - sound_rate = SrsCodecAudioSampleRateReserved; - sound_size = SrsCodecAudioSampleSizeReserved; - sound_type = SrsCodecAudioSoundTypeReserved; - aac_packet_type = SrsCodecAudioTypeReserved; + cts = 0; + frame_type = SrsCodecVideoAVCFrameReserved; + avc_packet_type = SrsCodecVideoAVCTypeReserved; + + sound_rate = SrsCodecAudioSampleRateReserved; + sound_size = SrsCodecAudioSampleSizeReserved; + sound_type = SrsCodecAudioSoundTypeReserved; + aac_packet_type = SrsCodecAudioTypeReserved; } int SrsCodecSample::add_sample(char* bytes, int size) { - int ret = ERROR_SUCCESS; - - if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode samples error, " - "exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret); - return ret; - } - - SrsCodecBuffer* buf = &buffers[nb_buffers++]; - buf->bytes = bytes; - buf->size = size; - - return ret; + int ret = ERROR_SUCCESS; + + if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode samples error, " + "exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret); + return ret; + } + + SrsCodecBuffer* buf = &buffers[nb_buffers++]; + buf->bytes = bytes; + buf->size = size; + + return ret; } SrsCodec::SrsCodec() { - width = 0; - height = 0; - duration = 0; - NAL_unit_length = 0; - frame_rate = 0; - video_data_rate = 0; - video_codec_id = 0; - audio_data_rate = 0; - audio_codec_id = 0; - avc_profile = 0; - avc_level = 0; - aac_profile = 0; - aac_sample_rate = 0; - aac_channels = 0; - avc_extra_size = 0; - avc_extra_data = NULL; - aac_extra_size = 0; - aac_extra_data = NULL; - sequenceParameterSetLength = 0; - sequenceParameterSetNALUnit = NULL; - pictureParameterSetLength = 0; - pictureParameterSetNALUnit = NULL; + width = 0; + height = 0; + duration = 0; + NAL_unit_length = 0; + frame_rate = 0; + video_data_rate = 0; + video_codec_id = 0; + audio_data_rate = 0; + audio_codec_id = 0; + avc_profile = 0; + avc_level = 0; + aac_profile = 0; + aac_sample_rate = 0; + aac_channels = 0; + avc_extra_size = 0; + avc_extra_data = NULL; + aac_extra_size = 0; + aac_extra_data = NULL; + sequenceParameterSetLength = 0; + sequenceParameterSetNALUnit = NULL; + pictureParameterSetLength = 0; + pictureParameterSetNALUnit = NULL; - stream = new SrsStream(); + stream = new SrsStream(); } SrsCodec::~SrsCodec() { - srs_freepa(avc_extra_data); - srs_freepa(aac_extra_data); + srs_freepa(avc_extra_data); + srs_freepa(aac_extra_data); - srs_freep(stream); - srs_freepa(sequenceParameterSetNALUnit); - srs_freepa(pictureParameterSetNALUnit); + srs_freep(stream); + srs_freepa(sequenceParameterSetNALUnit); + srs_freepa(pictureParameterSetNALUnit); } int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) { - int ret = ERROR_SUCCESS; - - sample->is_video = false; - - if (!data || size <= 0) { - srs_trace("no audio present, hls ignore it."); - return ret; - } - - if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { - return ret; - } + int ret = ERROR_SUCCESS; + + sample->is_video = false; + + if (!data || size <= 0) { + srs_trace("no audio present, hls ignore it."); + return ret; + } + + if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { + return ret; + } - // audio decode - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio sound_format failed. ret=%d", ret); - return ret; - } - - int8_t sound_format = stream->read_1bytes(); - - int8_t sound_type = sound_format & 0x01; - int8_t sound_size = (sound_format >> 1) & 0x01; - int8_t sound_rate = (sound_format >> 2) & 0x03; - sound_format = (sound_format >> 4) & 0x0f; - - audio_codec_id = sound_format; - sample->sound_type = (SrsCodecAudioSoundType)sound_type; - sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; - sample->sound_size = (SrsCodecAudioSampleSize)sound_size; - - // reset the sample rate by sequence header + // audio decode + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio sound_format failed. ret=%d", ret); + return ret; + } + + int8_t sound_format = stream->read_1bytes(); + + int8_t sound_type = sound_format & 0x01; + int8_t sound_size = (sound_format >> 1) & 0x01; + int8_t sound_rate = (sound_format >> 2) & 0x03; + sound_format = (sound_format >> 4) & 0x0f; + + audio_codec_id = sound_format; + sample->sound_type = (SrsCodecAudioSoundType)sound_type; + sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate; + sample->sound_size = (SrsCodecAudioSampleSize)sound_size; + + // reset the sample rate by sequence header static int aac_sample_rates[] = { - 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, - 7350, 0, 0, 0 + 96000, 88200, 64000, 48000, + 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, + 7350, 0, 0, 0 }; switch (aac_sample_rates[aac_sample_rate]) { case 11025: - sample->sound_rate = SrsCodecAudioSampleRate11025; - break; + sample->sound_rate = SrsCodecAudioSampleRate11025; + break; case 22050: - sample->sound_rate = SrsCodecAudioSampleRate22050; - break; + sample->sound_rate = SrsCodecAudioSampleRate22050; + break; case 44100: - sample->sound_rate = SrsCodecAudioSampleRate44100; - break; + sample->sound_rate = SrsCodecAudioSampleRate44100; + break; }; - // only support aac - if (audio_codec_id != SrsCodecAudioAAC) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls only support audio aac codec. ret=%d", ret); - return ret; - } + // only support aac + if (audio_codec_id != SrsCodecAudioAAC) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls only support audio aac codec. ret=%d", ret); + return ret; + } - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac_packet_type failed. ret=%d", ret); - return ret; - } - - int8_t aac_packet_type = stream->read_1bytes(); - sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type; - - if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) { - // AudioSpecificConfig - // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. - aac_extra_size = stream->left(); - if (aac_extra_size > 0) { - srs_freepa(aac_extra_data); - aac_extra_data = new char[aac_extra_size]; - memcpy(aac_extra_data, stream->current(), aac_extra_size); - } - - // only need to decode the first 2bytes: - // audioObjectType, aac_profile, 5bits. - // samplingFrequencyIndex, aac_sample_rate, 4bits. - // channelConfiguration, aac_channels, 4bits - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac sequence header failed. ret=%d", ret); - return ret; - } - aac_profile = stream->read_1bytes(); - aac_sample_rate = stream->read_1bytes(); - - aac_channels = (aac_sample_rate >> 3) & 0x0f; - aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); - aac_profile = (aac_profile >> 3) & 0x1f; - - if (aac_profile == 0 || aac_profile == 0x1f) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac sequence header failed, " - "adts object=%d invalid. ret=%d", aac_profile, ret); - return ret; - } - - // aac_profile = audioObjectType - 1 - aac_profile--; - - if (aac_profile > 3) { - // Mark all extended profiles as LC - // to make Android as happy as possible. - // @see: ngx_rtmp_hls_parse_aac_header - aac_profile = 1; - } - } else if (aac_packet_type == SrsCodecAudioTypeRawData) { - // ensure the sequence header demuxed - if (aac_extra_size <= 0 || !aac_extra_data) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret); - return ret; - } - - // Raw AAC frame data in UI8 [] - // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 - if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) { - srs_error("hls add audio sample failed. ret=%d", ret); - return ret; - } - } else { - // ignored. - } - - srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", - sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size); - - return ret; + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac_packet_type failed. ret=%d", ret); + return ret; + } + + int8_t aac_packet_type = stream->read_1bytes(); + sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type; + + if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) { + // AudioSpecificConfig + // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. + aac_extra_size = stream->left(); + if (aac_extra_size > 0) { + srs_freepa(aac_extra_data); + aac_extra_data = new char[aac_extra_size]; + memcpy(aac_extra_data, stream->current(), aac_extra_size); + } + + // only need to decode the first 2bytes: + // audioObjectType, aac_profile, 5bits. + // samplingFrequencyIndex, aac_sample_rate, 4bits. + // channelConfiguration, aac_channels, 4bits + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac sequence header failed. ret=%d", ret); + return ret; + } + aac_profile = stream->read_1bytes(); + aac_sample_rate = stream->read_1bytes(); + + aac_channels = (aac_sample_rate >> 3) & 0x0f; + aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); + aac_profile = (aac_profile >> 3) & 0x1f; + + if (aac_profile == 0 || aac_profile == 0x1f) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac sequence header failed, " + "adts object=%d invalid. ret=%d", aac_profile, ret); + return ret; + } + + // aac_profile = audioObjectType - 1 + aac_profile--; + + if (aac_profile > 3) { + // Mark all extended profiles as LC + // to make Android as happy as possible. + // @see: ngx_rtmp_hls_parse_aac_header + aac_profile = 1; + } + } else if (aac_packet_type == SrsCodecAudioTypeRawData) { + // ensure the sequence header demuxed + if (aac_extra_size <= 0 || !aac_extra_data) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret); + return ret; + } + + // Raw AAC frame data in UI8 [] + // 6.3 Raw Data, aac-iso-13818-7.pdf, page 28 + if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) { + srs_error("hls add audio sample failed. ret=%d", ret); + return ret; + } + } else { + // ignored. + } + + srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d", + sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size); + + return ret; } int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample) { - int ret = ERROR_SUCCESS; - - sample->is_video = true; - - if (!data || size <= 0) { - srs_trace("no video present, hls ignore it."); - return ret; - } - - if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { - return ret; - } + int ret = ERROR_SUCCESS; + + sample->is_video = true; + + if (!data || size <= 0) { + srs_trace("no video present, hls ignore it."); + return ret; + } + + if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) { + return ret; + } - // video decode - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video frame_type failed. ret=%d", ret); - return ret; - } - - int8_t frame_type = stream->read_1bytes(); - int8_t codec_id = frame_type & 0x0f; - frame_type = (frame_type >> 4) & 0x0f; - - sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; - - // only support h.264/avc - if (codec_id != SrsCodecVideoAVC) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls only support video h.264/avc codec. ret=%d", ret); - return ret; - } - video_codec_id = codec_id; - - if (!stream->require(4)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc_packet_type failed. ret=%d", ret); - return ret; - } - int8_t avc_packet_type = stream->read_1bytes(); - int32_t composition_time = stream->read_3bytes(); - - // pts = dts + cts. - sample->cts = composition_time; - sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; - - if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { - // AVCDecoderConfigurationRecord - // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 - avc_extra_size = stream->left(); - if (avc_extra_size > 0) { - srs_freepa(avc_extra_data); - avc_extra_data = new char[avc_extra_size]; - memcpy(avc_extra_data, stream->current(), avc_extra_size); - } - - if (!stream->require(6)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header failed. ret=%d", ret); - return ret; - } - //int8_t configurationVersion = stream->read_1bytes(); - //int8_t AVCProfileIndication = stream->read_1bytes(); - //int8_t profile_compatibility = stream->read_1bytes(); - //int8_t AVCLevelIndication = stream->read_1bytes(); - stream->skip(4); - // parse the NALU size. - int8_t lengthSizeMinusOne = stream->read_1bytes(); - lengthSizeMinusOne &= 0x03; - NAL_unit_length = lengthSizeMinusOne; - - // 1 sps - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); - return ret; - } - int8_t numOfSequenceParameterSets = stream->read_1bytes(); - numOfSequenceParameterSets &= 0x1f; - if (numOfSequenceParameterSets != 1) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); - return ret; - } - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); - return ret; - } - sequenceParameterSetLength = stream->read_2bytes(); - if (!stream->require(sequenceParameterSetLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); - return ret; - } - if (sequenceParameterSetLength > 0) { - srs_freepa(sequenceParameterSetNALUnit); - sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; - memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength); - stream->skip(sequenceParameterSetLength); - } - // 1 pps - if (!stream->require(1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); - return ret; - } - int8_t numOfPictureParameterSets = stream->read_1bytes(); - numOfPictureParameterSets &= 0x1f; - if (numOfPictureParameterSets != 1) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); - return ret; - } - if (!stream->require(2)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); - return ret; - } - pictureParameterSetLength = stream->read_2bytes(); - if (!stream->require(pictureParameterSetLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); - return ret; - } - if (pictureParameterSetLength > 0) { - srs_freepa(pictureParameterSetNALUnit); - pictureParameterSetNALUnit = new char[pictureParameterSetLength]; - memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength); - stream->skip(pictureParameterSetLength); - } - } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ - // ensure the sequence header demuxed - if (avc_extra_size <= 0 || !avc_extra_data) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret); - return ret; - } - - // One or more NALUs (Full frames are required) - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 - int PictureLength = stream->left(); - for (int i = 0; i < PictureLength;) { - if (!stream->require(NAL_unit_length + 1)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc NALU size failed. ret=%d", ret); - return ret; - } - int32_t NALUnitLength = 0; - if (NAL_unit_length == 3) { - NALUnitLength = stream->read_4bytes(); - } else if (NALUnitLength == 2) { - NALUnitLength = stream->read_3bytes(); - } else if (NALUnitLength == 1) { - NALUnitLength = stream->read_2bytes(); - } else { - NALUnitLength = stream->read_1bytes(); - } - // NALUnit - if (!stream->require(NALUnitLength)) { - ret = ERROR_HLS_DECODE_ERROR; - srs_error("hls decode video avc NALU data failed. ret=%d", ret); - return ret; - } - // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. - if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) { - srs_error("hls add video sample failed. ret=%d", ret); - return ret; - } - stream->skip(NALUnitLength); - - i += NAL_unit_length + 1 + NALUnitLength; - } - } else { - // ignored. - } - - srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d", - frame_type, video_codec_id, avc_packet_type, composition_time, size); - - return ret; + // video decode + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video frame_type failed. ret=%d", ret); + return ret; + } + + int8_t frame_type = stream->read_1bytes(); + int8_t codec_id = frame_type & 0x0f; + frame_type = (frame_type >> 4) & 0x0f; + + sample->frame_type = (SrsCodecVideoAVCFrame)frame_type; + + // only support h.264/avc + if (codec_id != SrsCodecVideoAVC) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls only support video h.264/avc codec. ret=%d", ret); + return ret; + } + video_codec_id = codec_id; + + if (!stream->require(4)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc_packet_type failed. ret=%d", ret); + return ret; + } + int8_t avc_packet_type = stream->read_1bytes(); + int32_t composition_time = stream->read_3bytes(); + + // pts = dts + cts. + sample->cts = composition_time; + sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type; + + if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { + // AVCDecoderConfigurationRecord + // 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + avc_extra_size = stream->left(); + if (avc_extra_size > 0) { + srs_freepa(avc_extra_data); + avc_extra_data = new char[avc_extra_size]; + memcpy(avc_extra_data, stream->current(), avc_extra_size); + } + + if (!stream->require(6)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header failed. ret=%d", ret); + return ret; + } + //int8_t configurationVersion = stream->read_1bytes(); + //int8_t AVCProfileIndication = stream->read_1bytes(); + //int8_t profile_compatibility = stream->read_1bytes(); + //int8_t AVCLevelIndication = stream->read_1bytes(); + stream->skip(4); + // parse the NALU size. + int8_t lengthSizeMinusOne = stream->read_1bytes(); + lengthSizeMinusOne &= 0x03; + NAL_unit_length = lengthSizeMinusOne; + + // 1 sps + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); + return ret; + } + int8_t numOfSequenceParameterSets = stream->read_1bytes(); + numOfSequenceParameterSets &= 0x1f; + if (numOfSequenceParameterSets != 1) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret); + return ret; + } + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret); + return ret; + } + sequenceParameterSetLength = stream->read_2bytes(); + if (!stream->require(sequenceParameterSetLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret); + return ret; + } + if (sequenceParameterSetLength > 0) { + srs_freepa(sequenceParameterSetNALUnit); + sequenceParameterSetNALUnit = new char[sequenceParameterSetLength]; + memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength); + stream->skip(sequenceParameterSetLength); + } + // 1 pps + if (!stream->require(1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); + return ret; + } + int8_t numOfPictureParameterSets = stream->read_1bytes(); + numOfPictureParameterSets &= 0x1f; + if (numOfPictureParameterSets != 1) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret); + return ret; + } + if (!stream->require(2)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret); + return ret; + } + pictureParameterSetLength = stream->read_2bytes(); + if (!stream->require(pictureParameterSetLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret); + return ret; + } + if (pictureParameterSetLength > 0) { + srs_freepa(pictureParameterSetNALUnit); + pictureParameterSetNALUnit = new char[pictureParameterSetLength]; + memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength); + stream->skip(pictureParameterSetLength); + } + } else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){ + // ensure the sequence header demuxed + if (avc_extra_size <= 0 || !avc_extra_data) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret); + return ret; + } + + // One or more NALUs (Full frames are required) + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20 + int PictureLength = stream->left(); + for (int i = 0; i < PictureLength;) { + if (!stream->require(NAL_unit_length + 1)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc NALU size failed. ret=%d", ret); + return ret; + } + int32_t NALUnitLength = 0; + if (NAL_unit_length == 3) { + NALUnitLength = stream->read_4bytes(); + } else if (NALUnitLength == 2) { + NALUnitLength = stream->read_3bytes(); + } else if (NALUnitLength == 1) { + NALUnitLength = stream->read_2bytes(); + } else { + NALUnitLength = stream->read_1bytes(); + } + // NALUnit + if (!stream->require(NALUnitLength)) { + ret = ERROR_HLS_DECODE_ERROR; + srs_error("hls decode video avc NALU data failed. ret=%d", ret); + return ret; + } + // 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44. + if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) { + srs_error("hls add video sample failed. ret=%d", ret); + return ret; + } + stream->skip(NALUnitLength); + + i += NAL_unit_length + 1 + NALUnitLength; + } + } else { + // ignored. + } + + srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d", + frame_type, video_codec_id, avc_packet_type, composition_time, size); + + return ret; } bool SrsCodec::video_is_keyframe(int8_t* data, int size) { - // 2bytes required. - if (size < 1) { - return false; - } + // 2bytes required. + if (size < 1) { + return false; + } - char frame_type = *(char*)data; - frame_type = (frame_type >> 4) & 0x0F; - - return frame_type == SrsCodecVideoAVCFrameKeyFrame; + char frame_type = *(char*)data; + frame_type = (frame_type >> 4) & 0x0F; + + return frame_type == SrsCodecVideoAVCFrameKeyFrame; } bool SrsCodec::video_is_sequence_header(int8_t* data, int size) { - // sequence header only for h264 - if (!video_is_h264(data, size)) { - return false; - } - - // 2bytes required. - if (size < 2) { - return false; - } + // sequence header only for h264 + if (!video_is_h264(data, size)) { + return false; + } + + // 2bytes required. + if (size < 2) { + return false; + } - char frame_type = *(char*)data; - frame_type = (frame_type >> 4) & 0x0F; + char frame_type = *(char*)data; + frame_type = (frame_type >> 4) & 0x0F; - char avc_packet_type = *(char*)(data + 1); - - return frame_type == SrsCodecVideoAVCFrameKeyFrame - && avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader; + char avc_packet_type = *(char*)(data + 1); + + return frame_type == SrsCodecVideoAVCFrameKeyFrame + && avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader; } bool SrsCodec::audio_is_sequence_header(int8_t* data, int size) { - // sequence header only for aac - if (!audio_is_aac(data, size)) { - return false; - } - - // 2bytes required. - if (size < 2) { - return false; - } - - char aac_packet_type = *(char*)(data + 1); - - return aac_packet_type == SrsCodecAudioTypeSequenceHeader; + // sequence header only for aac + if (!audio_is_aac(data, size)) { + return false; + } + + // 2bytes required. + if (size < 2) { + return false; + } + + char aac_packet_type = *(char*)(data + 1); + + return aac_packet_type == SrsCodecAudioTypeSequenceHeader; } bool SrsCodec::video_is_h264(int8_t* data, int size) { - // 1bytes required. - if (size < 1) { - return false; - } + // 1bytes required. + if (size < 1) { + return false; + } - char codec_id = *(char*)data; - codec_id = codec_id & 0x0F; - - return codec_id == SrsCodecVideoAVC; + char codec_id = *(char*)data; + codec_id = codec_id & 0x0F; + + return codec_id == SrsCodecVideoAVC; } bool SrsCodec::audio_is_aac(int8_t* data, int size) { - // 1bytes required. - if (size < 1) { - return false; - } - - char sound_format = *(char*)data; - sound_format = (sound_format >> 4) & 0x0F; - - return sound_format == SrsCodecAudioAAC; + // 1bytes required. + if (size < 1) { + return false; + } + + char sound_format = *(char*)data; + sound_format = (sound_format >> 4) & 0x0F; + + return sound_format == SrsCodecAudioAAC; } diff --git a/trunk/src/app/srs_app_codec.hpp b/trunk/src/app/srs_app_codec.hpp index a31456d1f..aef90b202 100644 --- a/trunk/src/app/srs_app_codec.hpp +++ b/trunk/src/app/srs_app_codec.hpp @@ -37,104 +37,104 @@ class SrsStream; // E.4.3.1 VIDEODATA // CodecID UB [4] // Codec Identifier. The following values are defined: -// 2 = Sorenson H.263 -// 3 = Screen video -// 4 = On2 VP6 -// 5 = On2 VP6 with alpha channel -// 6 = Screen video version 2 -// 7 = AVC +// 2 = Sorenson H.263 +// 3 = Screen video +// 4 = On2 VP6 +// 5 = On2 VP6 with alpha channel +// 6 = Screen video version 2 +// 7 = AVC enum SrsCodecVideo { - SrsCodecVideoReserved = 0, - - SrsCodecVideoSorensonH263 = 2, - SrsCodecVideoScreenVideo = 3, - SrsCodecVideoOn2VP6 = 4, - SrsCodecVideoOn2VP6WithAlphaChannel = 5, - SrsCodecVideoScreenVideoVersion2 = 6, - SrsCodecVideoAVC = 7, + SrsCodecVideoReserved = 0, + + SrsCodecVideoSorensonH263 = 2, + SrsCodecVideoScreenVideo = 3, + SrsCodecVideoOn2VP6 = 4, + SrsCodecVideoOn2VP6WithAlphaChannel = 5, + SrsCodecVideoScreenVideoVersion2 = 6, + SrsCodecVideoAVC = 7, }; // E.4.3.1 VIDEODATA // Frame Type UB [4] // Type of video frame. The following values are defined: -// 1 = key frame (for AVC, a seekable frame) -// 2 = inter frame (for AVC, a non-seekable frame) -// 3 = disposable inter frame (H.263 only) -// 4 = generated key frame (reserved for server use only) -// 5 = video info/command frame +// 1 = key frame (for AVC, a seekable frame) +// 2 = inter frame (for AVC, a non-seekable frame) +// 3 = disposable inter frame (H.263 only) +// 4 = generated key frame (reserved for server use only) +// 5 = video info/command frame enum SrsCodecVideoAVCFrame { - SrsCodecVideoAVCFrameReserved = 0, - - SrsCodecVideoAVCFrameKeyFrame = 1, - SrsCodecVideoAVCFrameInterFrame = 2, - SrsCodecVideoAVCFrameDisposableInterFrame = 3, - SrsCodecVideoAVCFrameGeneratedKeyFrame = 4, - SrsCodecVideoAVCFrameVideoInfoFrame = 5, + SrsCodecVideoAVCFrameReserved = 0, + + SrsCodecVideoAVCFrameKeyFrame = 1, + SrsCodecVideoAVCFrameInterFrame = 2, + SrsCodecVideoAVCFrameDisposableInterFrame = 3, + SrsCodecVideoAVCFrameGeneratedKeyFrame = 4, + SrsCodecVideoAVCFrameVideoInfoFrame = 5, }; // AVCPacketType IF CodecID == 7 UI8 // The following values are defined: -// 0 = AVC sequence header -// 1 = AVC NALU -// 2 = AVC end of sequence (lower level NALU sequence ender is -// not required or supported) +// 0 = AVC sequence header +// 1 = AVC NALU +// 2 = AVC end of sequence (lower level NALU sequence ender is +// not required or supported) enum SrsCodecVideoAVCType { - SrsCodecVideoAVCTypeReserved = -1, - - SrsCodecVideoAVCTypeSequenceHeader = 0, - SrsCodecVideoAVCTypeNALU = 1, - SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, + SrsCodecVideoAVCTypeReserved = -1, + + SrsCodecVideoAVCTypeSequenceHeader = 0, + SrsCodecVideoAVCTypeNALU = 1, + SrsCodecVideoAVCTypeSequenceHeaderEOF = 2, }; // SoundFormat UB [4] // Format of SoundData. The following values are defined: -// 0 = Linear PCM, platform endian -// 1 = ADPCM -// 2 = MP3 -// 3 = Linear PCM, little endian -// 4 = Nellymoser 16 kHz mono -// 5 = Nellymoser 8 kHz mono -// 6 = Nellymoser -// 7 = G.711 A-law logarithmic PCM -// 8 = G.711 mu-law logarithmic PCM -// 9 = reserved -// 10 = AAC -// 11 = Speex -// 14 = MP3 8 kHz -// 15 = Device-specific sound +// 0 = Linear PCM, platform endian +// 1 = ADPCM +// 2 = MP3 +// 3 = Linear PCM, little endian +// 4 = Nellymoser 16 kHz mono +// 5 = Nellymoser 8 kHz mono +// 6 = Nellymoser +// 7 = G.711 A-law logarithmic PCM +// 8 = G.711 mu-law logarithmic PCM +// 9 = reserved +// 10 = AAC +// 11 = Speex +// 14 = MP3 8 kHz +// 15 = Device-specific sound // Formats 7, 8, 14, and 15 are reserved. // AAC is supported in Flash Player 9,0,115,0 and higher. // Speex is supported in Flash Player 10 and higher. enum SrsCodecAudio { - SrsCodecAudioLinearPCMPlatformEndian = 0, - SrsCodecAudioADPCM = 1, - SrsCodecAudioMP3 = 2, - SrsCodecAudioLinearPCMLittleEndian = 3, - SrsCodecAudioNellymoser16kHzMono = 4, - SrsCodecAudioNellymoser8kHzMono = 5, - SrsCodecAudioNellymoser = 6, - SrsCodecAudioReservedG711AlawLogarithmicPCM = 7, - SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8, - SrsCodecAudioReserved = 9, - SrsCodecAudioAAC = 10, - SrsCodecAudioSpeex = 11, - SrsCodecAudioReservedMP3_8kHz = 14, - SrsCodecAudioReservedDeviceSpecificSound = 15, + SrsCodecAudioLinearPCMPlatformEndian = 0, + SrsCodecAudioADPCM = 1, + SrsCodecAudioMP3 = 2, + SrsCodecAudioLinearPCMLittleEndian = 3, + SrsCodecAudioNellymoser16kHzMono = 4, + SrsCodecAudioNellymoser8kHzMono = 5, + SrsCodecAudioNellymoser = 6, + SrsCodecAudioReservedG711AlawLogarithmicPCM = 7, + SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8, + SrsCodecAudioReserved = 9, + SrsCodecAudioAAC = 10, + SrsCodecAudioSpeex = 11, + SrsCodecAudioReservedMP3_8kHz = 14, + SrsCodecAudioReservedDeviceSpecificSound = 15, }; // AACPacketType IF SoundFormat == 10 UI8 // The following values are defined: -// 0 = AAC sequence header -// 1 = AAC raw +// 0 = AAC sequence header +// 1 = AAC raw enum SrsCodecAudioType { - SrsCodecAudioTypeReserved = -1, - SrsCodecAudioTypeSequenceHeader = 0, - SrsCodecAudioTypeRawData = 1, + SrsCodecAudioTypeReserved = -1, + SrsCodecAudioTypeSequenceHeader = 0, + SrsCodecAudioTypeRawData = 1, }; // Sampling rate. The following values are defined: @@ -144,12 +144,12 @@ enum SrsCodecAudioType // 3 = 44 kHz = 44100 Hz enum SrsCodecAudioSampleRate { - SrsCodecAudioSampleRateReserved = -1, - - SrsCodecAudioSampleRate5512 = 0, - SrsCodecAudioSampleRate11025 = 1, - SrsCodecAudioSampleRate22050 = 2, - SrsCodecAudioSampleRate44100 = 3, + SrsCodecAudioSampleRateReserved = -1, + + SrsCodecAudioSampleRate5512 = 0, + SrsCodecAudioSampleRate11025 = 1, + SrsCodecAudioSampleRate22050 = 2, + SrsCodecAudioSampleRate44100 = 3, }; // Size of each audio sample. This parameter only pertains to @@ -159,10 +159,10 @@ enum SrsCodecAudioSampleRate // 1 = 16-bit samples enum SrsCodecAudioSampleSize { - SrsCodecAudioSampleSizeReserved = -1, - - SrsCodecAudioSampleSize8bit = 0, - SrsCodecAudioSampleSize16bit = 1, + SrsCodecAudioSampleSizeReserved = -1, + + SrsCodecAudioSampleSize8bit = 0, + SrsCodecAudioSampleSize16bit = 1, }; // Mono or stereo sound @@ -170,10 +170,10 @@ enum SrsCodecAudioSampleSize // 1 = Stereo sound enum SrsCodecAudioSoundType { - SrsCodecAudioSoundTypeReserved = -1, - - SrsCodecAudioSoundTypeMono = 0, - SrsCodecAudioSoundTypeStereo = 1, + SrsCodecAudioSoundTypeReserved = -1, + + SrsCodecAudioSoundTypeMono = 0, + SrsCodecAudioSoundTypeStereo = 1, }; /** @@ -181,21 +181,21 @@ enum SrsCodecAudioSoundType */ struct SrsCodecBuffer { - /** - * @remark user must manage the bytes. - */ - int size; - char* bytes; - - SrsCodecBuffer(); - void append(void* data, int len); - - /** - * free the bytes, - * user can invoke it to free the bytes, - * the SrsCodecBuffer never free automatically. - */ - void free(); + /** + * @remark user must manage the bytes. + */ + int size; + char* bytes; + + SrsCodecBuffer(); + void append(void* data, int len); + + /** + * free the bytes, + * user can invoke it to free the bytes, + * the SrsCodecBuffer never free automatically. + */ + void free(); }; /** @@ -204,26 +204,26 @@ struct SrsCodecBuffer class SrsCodecSample { public: - int nb_buffers; - SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; + int nb_buffers; + SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE]; public: - bool is_video; - // video specified - SrsCodecVideoAVCFrame frame_type; - SrsCodecVideoAVCType avc_packet_type; - // CompositionTime, video_file_format_spec_v10_1.pdf, page 78. - // cts = pts - dts, where dts = flvheader->timestamp. - int32_t cts; - // audio specified - SrsCodecAudioSampleRate sound_rate; - SrsCodecAudioSampleSize sound_size; - SrsCodecAudioSoundType sound_type; - SrsCodecAudioType aac_packet_type; + bool is_video; + // video specified + SrsCodecVideoAVCFrame frame_type; + SrsCodecVideoAVCType avc_packet_type; + // CompositionTime, video_file_format_spec_v10_1.pdf, page 78. + // cts = pts - dts, where dts = flvheader->timestamp. + int32_t cts; + // audio specified + SrsCodecAudioSampleRate sound_rate; + SrsCodecAudioSampleSize sound_size; + SrsCodecAudioSoundType sound_type; + SrsCodecAudioType aac_packet_type; public: - SrsCodecSample(); - virtual ~SrsCodecSample(); - void clear(); - int add_sample(char* bytes, int size); + SrsCodecSample(); + virtual ~SrsCodecSample(); + void clear(); + int add_sample(char* bytes, int size); }; /** @@ -232,81 +232,81 @@ public: class SrsCodec { private: - SrsStream* stream; + SrsStream* stream; public: - /** - * video specified - */ - // @see: SrsCodecVideo - int video_codec_id; - // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. - u_int8_t avc_profile; - // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. - u_int8_t avc_level; - int width; - int height; - int video_data_rate; // in bps - int frame_rate; - int duration; - // lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 - int8_t NAL_unit_length; - u_int16_t sequenceParameterSetLength; - char* sequenceParameterSetNALUnit; - u_int16_t pictureParameterSetLength; - char* pictureParameterSetNALUnit; - /** - * audio specified - */ - // @see: SrsCodecAudioType - int audio_codec_id; - int audio_data_rate; // in bps - // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. - // audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40. - u_int8_t aac_profile; - // samplingFrequencyIndex - u_int8_t aac_sample_rate; - // channelConfiguration - u_int8_t aac_channels; - // the avc extra data, the AVC sequence header, - // without the flv codec header, - // @see: ffmpeg, AVCodecContext::extradata - int avc_extra_size; - char* avc_extra_data; - // the aac extra data, the AAC sequence header, - // without the flv codec header, - // @see: ffmpeg, AVCodecContext::extradata - int aac_extra_size; - char* aac_extra_data; + /** + * video specified + */ + // @see: SrsCodecVideo + int video_codec_id; + // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. + u_int8_t avc_profile; + // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. + u_int8_t avc_level; + int width; + int height; + int video_data_rate; // in bps + int frame_rate; + int duration; + // lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 + int8_t NAL_unit_length; + u_int16_t sequenceParameterSetLength; + char* sequenceParameterSetNALUnit; + u_int16_t pictureParameterSetLength; + char* pictureParameterSetNALUnit; + /** + * audio specified + */ + // @see: SrsCodecAudioType + int audio_codec_id; + int audio_data_rate; // in bps + // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33. + // audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40. + u_int8_t aac_profile; + // samplingFrequencyIndex + u_int8_t aac_sample_rate; + // channelConfiguration + u_int8_t aac_channels; + // the avc extra data, the AVC sequence header, + // without the flv codec header, + // @see: ffmpeg, AVCodecContext::extradata + int avc_extra_size; + char* avc_extra_data; + // the aac extra data, the AAC sequence header, + // without the flv codec header, + // @see: ffmpeg, AVCodecContext::extradata + int aac_extra_size; + char* aac_extra_data; public: - SrsCodec(); - virtual ~SrsCodec(); + SrsCodec(); + virtual ~SrsCodec(); // the following function used for hls to build the codec info. public: - virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample); - virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample); + virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample); + virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample); // the following function used to finger out the flv/rtmp packet detail. public: - /** - * only check the frame_type, not check the codec type. - */ - static bool video_is_keyframe(int8_t* data, int size); - /** - * check codec h264, keyframe, sequence header - */ - static bool video_is_sequence_header(int8_t* data, int size); - /** - * check codec aac, sequence header - */ - static bool audio_is_sequence_header(int8_t* data, int size); - /** - * check codec h264. - */ - static bool video_is_h264(int8_t* data, int size); + /** + * only check the frame_type, not check the codec type. + */ + static bool video_is_keyframe(int8_t* data, int size); + /** + * check codec h264, keyframe, sequence header + */ + static bool video_is_sequence_header(int8_t* data, int size); + /** + * check codec aac, sequence header + */ + static bool audio_is_sequence_header(int8_t* data, int size); + /** + * check codec h264. + */ + static bool video_is_h264(int8_t* data, int size); private: - /** - * check codec aac. - */ - static bool audio_is_aac(int8_t* data, int size); + /** + * check codec aac. + */ + static bool audio_is_aac(int8_t* data, int size); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 44df9b976..93a5e619f 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -46,10 +46,10 @@ using namespace std; int64_t FILE_SIZE(int fd) { - int64_t pre = FILE_OFFSET(fd); - int64_t pos = lseek(fd, 0, SEEK_END); - lseek(fd, pre, SEEK_SET); - return pos; + int64_t pre = FILE_OFFSET(fd); + int64_t pos = lseek(fd, 0, SEEK_END); + lseek(fd, pre, SEEK_SET); + return pos; } #define LF (char)0x0a @@ -57,87 +57,87 @@ int64_t FILE_SIZE(int fd) bool is_common_space(char ch) { - return (ch == ' ' || ch == '\t' || ch == CR || ch == LF); + return (ch == ' ' || ch == '\t' || ch == CR || ch == LF); } class SrsFileBuffer { private: - // last available position. - char* last; - // end of buffer. - char* end; - // start of buffer. - char* start; + // last available position. + char* last; + // end of buffer. + char* end; + // start of buffer. + char* start; public: - // current consumed position. - char* pos; - // current parsed line. - int line; - - SrsFileBuffer(); - virtual ~SrsFileBuffer(); - virtual int fullfill(const char* filename); - virtual bool empty(); + // current consumed position. + char* pos; + // current parsed line. + int line; + + SrsFileBuffer(); + virtual ~SrsFileBuffer(); + virtual int fullfill(const char* filename); + virtual bool empty(); }; SrsFileBuffer::SrsFileBuffer() { - line = 0; + line = 0; - pos = last = start = NULL; - end = start; + pos = last = start = NULL; + end = start; } SrsFileBuffer::~SrsFileBuffer() { - srs_freepa(start); + srs_freepa(start); } int SrsFileBuffer::fullfill(const char* filename) { - int ret = ERROR_SUCCESS; - - int fd = -1; - int nread = 0; - int filesize = 0; - - if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("open conf file error. ret=%d", ret); - goto finish; - } - - if ((filesize = FILE_SIZE(fd) - FILE_OFFSET(fd)) <= 0) { - ret = ERROR_SYSTEM_CONFIG_EOF; - srs_error("read conf file error. ret=%d", ret); - goto finish; - } + int ret = ERROR_SUCCESS; + + int fd = -1; + int nread = 0; + int filesize = 0; + + if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("open conf file error. ret=%d", ret); + goto finish; + } + + if ((filesize = FILE_SIZE(fd) - FILE_OFFSET(fd)) <= 0) { + ret = ERROR_SYSTEM_CONFIG_EOF; + srs_error("read conf file error. ret=%d", ret); + goto finish; + } - srs_freepa(start); - pos = last = start = new char[filesize]; - end = start + filesize; - - if ((nread = read(fd, start, filesize)) != filesize) { - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("read file read error. expect %d, actual %d bytes, ret=%d", - filesize, nread, ret); - goto finish; - } - - line = 1; - + srs_freepa(start); + pos = last = start = new char[filesize]; + end = start + filesize; + + if ((nread = read(fd, start, filesize)) != filesize) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("read file read error. expect %d, actual %d bytes, ret=%d", + filesize, nread, ret); + goto finish; + } + + line = 1; + finish: - if (fd > 0) { - ::close(fd); - } - - return ret; + if (fd > 0) { + ::close(fd); + } + + return ret; } bool SrsFileBuffer::empty() { - return pos >= end; + return pos >= end; } SrsConfDirective::SrsConfDirective() @@ -146,1297 +146,1297 @@ SrsConfDirective::SrsConfDirective() SrsConfDirective::~SrsConfDirective() { - std::vector::iterator it; - for (it = directives.begin(); it != directives.end(); ++it) { - SrsConfDirective* directive = *it; - srs_freep(directive); - } - directives.clear(); + std::vector::iterator it; + for (it = directives.begin(); it != directives.end(); ++it) { + SrsConfDirective* directive = *it; + srs_freep(directive); + } + directives.clear(); } string SrsConfDirective::arg0() { - if (args.size() > 0) { - return args.at(0); - } - - return ""; + if (args.size() > 0) { + return args.at(0); + } + + return ""; } string SrsConfDirective::arg1() { - if (args.size() > 1) { - return args.at(1); - } - - return ""; + if (args.size() > 1) { + return args.at(1); + } + + return ""; } string SrsConfDirective::arg2() { - if (args.size() > 2) { - return args.at(2); - } - - return ""; + if (args.size() > 2) { + return args.at(2); + } + + return ""; } SrsConfDirective* SrsConfDirective::at(int index) { - return directives.at(index); + return directives.at(index); } SrsConfDirective* SrsConfDirective::get(string _name) { - std::vector::iterator it; - for (it = directives.begin(); it != directives.end(); ++it) { - SrsConfDirective* directive = *it; - if (directive->name == _name) { - return directive; - } - } - - return NULL; + std::vector::iterator it; + for (it = directives.begin(); it != directives.end(); ++it) { + SrsConfDirective* directive = *it; + if (directive->name == _name) { + return directive; + } + } + + return NULL; } SrsConfDirective* SrsConfDirective::get(string _name, string _arg0) { - std::vector::iterator it; - for (it = directives.begin(); it != directives.end(); ++it) { - SrsConfDirective* directive = *it; - if (directive->name == _name && directive->arg0() == _arg0) { - return directive; - } - } - - return NULL; + std::vector::iterator it; + for (it = directives.begin(); it != directives.end(); ++it) { + SrsConfDirective* directive = *it; + if (directive->name == _name && directive->arg0() == _arg0) { + return directive; + } + } + + return NULL; } int SrsConfDirective::parse(const char* filename) { - int ret = ERROR_SUCCESS; - - SrsFileBuffer buffer; - - if ((ret = buffer.fullfill(filename)) != ERROR_SUCCESS) { - return ret; - } - - return parse_conf(&buffer, parse_file); + int ret = ERROR_SUCCESS; + + SrsFileBuffer buffer; + + if ((ret = buffer.fullfill(filename)) != ERROR_SUCCESS) { + return ret; + } + + return parse_conf(&buffer, parse_file); } // see: ngx_conf_parse int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type) { - int ret = ERROR_SUCCESS; - - while (true) { - std::vector args; - ret = read_token(buffer, args); - - /** - * ret maybe: - * ERROR_SYSTEM_CONFIG_INVALID error. - * ERROR_SYSTEM_CONFIG_DIRECTIVE directive terminated by ';' found - * ERROR_SYSTEM_CONFIG_BLOCK_START token terminated by '{' found - * ERROR_SYSTEM_CONFIG_BLOCK_END the '}' found - * ERROR_SYSTEM_CONFIG_EOF the config file is done - */ - if (ret == ERROR_SYSTEM_CONFIG_INVALID) { - return ret; - } - if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) { - if (type != parse_block) { - srs_error("line %d: unexpected \"}\"", buffer->line); - return ret; - } - return ERROR_SUCCESS; - } - if (ret == ERROR_SYSTEM_CONFIG_EOF) { - if (type == parse_block) { - srs_error("line %d: unexpected end of file, expecting \"}\"", buffer->line); - return ret; - } - return ERROR_SUCCESS; - } - - if (args.empty()) { - srs_error("line %d: empty directive.", buffer->line); - return ret; - } - - // build directive tree. - SrsConfDirective* directive = new SrsConfDirective(); + int ret = ERROR_SUCCESS; + + while (true) { + std::vector args; + ret = read_token(buffer, args); + + /** + * ret maybe: + * ERROR_SYSTEM_CONFIG_INVALID error. + * ERROR_SYSTEM_CONFIG_DIRECTIVE directive terminated by ';' found + * ERROR_SYSTEM_CONFIG_BLOCK_START token terminated by '{' found + * ERROR_SYSTEM_CONFIG_BLOCK_END the '}' found + * ERROR_SYSTEM_CONFIG_EOF the config file is done + */ + if (ret == ERROR_SYSTEM_CONFIG_INVALID) { + return ret; + } + if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) { + if (type != parse_block) { + srs_error("line %d: unexpected \"}\"", buffer->line); + return ret; + } + return ERROR_SUCCESS; + } + if (ret == ERROR_SYSTEM_CONFIG_EOF) { + if (type == parse_block) { + srs_error("line %d: unexpected end of file, expecting \"}\"", buffer->line); + return ret; + } + return ERROR_SUCCESS; + } + + if (args.empty()) { + srs_error("line %d: empty directive.", buffer->line); + return ret; + } + + // build directive tree. + SrsConfDirective* directive = new SrsConfDirective(); - directive->conf_line = buffer->line; - directive->name = args[0]; - args.erase(args.begin()); - directive->args.swap(args); - - directives.push_back(directive); - - if (ret == ERROR_SYSTEM_CONFIG_BLOCK_START) { - if ((ret = directive->parse_conf(buffer, parse_block)) != ERROR_SUCCESS) { - return ret; - } - } - } - - return ret; + directive->conf_line = buffer->line; + directive->name = args[0]; + args.erase(args.begin()); + directive->args.swap(args); + + directives.push_back(directive); + + if (ret == ERROR_SYSTEM_CONFIG_BLOCK_START) { + if ((ret = directive->parse_conf(buffer, parse_block)) != ERROR_SUCCESS) { + return ret; + } + } + } + + return ret; } // see: ngx_conf_read_token int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector& args) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - char* pstart = buffer->pos; + char* pstart = buffer->pos; - bool sharp_comment = false; - - bool d_quoted = false; - bool s_quoted = false; - - bool need_space = false; - bool last_space = true; - - while (true) { - if (buffer->empty()) { - ret = ERROR_SYSTEM_CONFIG_EOF; - - if (!args.empty() || !last_space) { - srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line); - return ERROR_SYSTEM_CONFIG_INVALID; - } + bool sharp_comment = false; + + bool d_quoted = false; + bool s_quoted = false; + + bool need_space = false; + bool last_space = true; + + while (true) { + if (buffer->empty()) { + ret = ERROR_SYSTEM_CONFIG_EOF; + + if (!args.empty() || !last_space) { + srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line); + return ERROR_SYSTEM_CONFIG_INVALID; + } srs_trace("end of file. ret=%d", ret); - - return ret; - } - - char ch = *buffer->pos++; - - if (ch == LF) { - buffer->line++; - sharp_comment = false; - } - - if (sharp_comment) { - continue; - } - - if (need_space) { - if (is_common_space(ch)) { - last_space = true; - need_space = false; - continue; - } - if (ch == ';') { - return ERROR_SYSTEM_CONFIG_DIRECTIVE; - } - if (ch == '{') { - return ERROR_SYSTEM_CONFIG_BLOCK_START; - } - srs_error("line %d: unexpected '%c'", buffer->line, ch); - return ERROR_SYSTEM_CONFIG_INVALID; - } - - // last charecter is space. - if (last_space) { - if (is_common_space(ch)) { - continue; - } - pstart = buffer->pos - 1; - switch (ch) { - case ';': - if (args.size() == 0) { - srs_error("line %d: unexpected ';'", buffer->line); - return ERROR_SYSTEM_CONFIG_INVALID; - } - return ERROR_SYSTEM_CONFIG_DIRECTIVE; - case '{': - if (args.size() == 0) { - srs_error("line %d: unexpected '{'", buffer->line); - return ERROR_SYSTEM_CONFIG_INVALID; - } - return ERROR_SYSTEM_CONFIG_BLOCK_START; - case '}': - if (args.size() != 0) { - srs_error("line %d: unexpected '}'", buffer->line); - return ERROR_SYSTEM_CONFIG_INVALID; - } - return ERROR_SYSTEM_CONFIG_BLOCK_END; - case '#': - sharp_comment = 1; - continue; - case '"': - pstart++; - d_quoted = true; - last_space = 0; - continue; - case '\'': - pstart++; - s_quoted = true; - last_space = 0; - continue; - default: - last_space = 0; - continue; - } - } else { - // last charecter is not space - bool found = false; - if (d_quoted) { - if (ch == '"') { - d_quoted = false; - need_space = true; - found = true; - } - } else if (s_quoted) { - if (ch == '\'') { - s_quoted = false; - need_space = true; - found = true; - } - } else if (is_common_space(ch) || ch == ';' || ch == '{') { - last_space = true; - found = 1; - } - - if (found) { - int len = buffer->pos - pstart; - char* word = new char[len]; - memcpy(word, pstart, len); - word[len - 1] = 0; - - string word_str = word; - if (!word_str.empty()) { - args.push_back(word_str); - } - srs_freepa(word); - - if (ch == ';') { - return ERROR_SYSTEM_CONFIG_DIRECTIVE; - } - if (ch == '{') { - return ERROR_SYSTEM_CONFIG_BLOCK_START; - } - } - } - } - - return ret; + + return ret; + } + + char ch = *buffer->pos++; + + if (ch == LF) { + buffer->line++; + sharp_comment = false; + } + + if (sharp_comment) { + continue; + } + + if (need_space) { + if (is_common_space(ch)) { + last_space = true; + need_space = false; + continue; + } + if (ch == ';') { + return ERROR_SYSTEM_CONFIG_DIRECTIVE; + } + if (ch == '{') { + return ERROR_SYSTEM_CONFIG_BLOCK_START; + } + srs_error("line %d: unexpected '%c'", buffer->line, ch); + return ERROR_SYSTEM_CONFIG_INVALID; + } + + // last charecter is space. + if (last_space) { + if (is_common_space(ch)) { + continue; + } + pstart = buffer->pos - 1; + switch (ch) { + case ';': + if (args.size() == 0) { + srs_error("line %d: unexpected ';'", buffer->line); + return ERROR_SYSTEM_CONFIG_INVALID; + } + return ERROR_SYSTEM_CONFIG_DIRECTIVE; + case '{': + if (args.size() == 0) { + srs_error("line %d: unexpected '{'", buffer->line); + return ERROR_SYSTEM_CONFIG_INVALID; + } + return ERROR_SYSTEM_CONFIG_BLOCK_START; + case '}': + if (args.size() != 0) { + srs_error("line %d: unexpected '}'", buffer->line); + return ERROR_SYSTEM_CONFIG_INVALID; + } + return ERROR_SYSTEM_CONFIG_BLOCK_END; + case '#': + sharp_comment = 1; + continue; + case '"': + pstart++; + d_quoted = true; + last_space = 0; + continue; + case '\'': + pstart++; + s_quoted = true; + last_space = 0; + continue; + default: + last_space = 0; + continue; + } + } else { + // last charecter is not space + bool found = false; + if (d_quoted) { + if (ch == '"') { + d_quoted = false; + need_space = true; + found = true; + } + } else if (s_quoted) { + if (ch == '\'') { + s_quoted = false; + need_space = true; + found = true; + } + } else if (is_common_space(ch) || ch == ';' || ch == '{') { + last_space = true; + found = 1; + } + + if (found) { + int len = buffer->pos - pstart; + char* word = new char[len]; + memcpy(word, pstart, len); + word[len - 1] = 0; + + string word_str = word; + if (!word_str.empty()) { + args.push_back(word_str); + } + srs_freepa(word); + + if (ch == ';') { + return ERROR_SYSTEM_CONFIG_DIRECTIVE; + } + if (ch == '{') { + return ERROR_SYSTEM_CONFIG_BLOCK_START; + } + } + } + } + + return ret; } SrsConfig::SrsConfig() { - show_help = false; - show_version = false; - - root = new SrsConfDirective(); - root->conf_line = 0; - root->name = "root"; + show_help = false; + show_version = false; + + root = new SrsConfDirective(); + root->conf_line = 0; + root->name = "root"; } SrsConfig::~SrsConfig() { - srs_freep(root); + srs_freep(root); } int SrsConfig::reload() { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - SrsConfig conf; - if ((ret = conf.parse_file(config_file.c_str())) != ERROR_SUCCESS) { - srs_error("config reloader parse file failed. ret=%d", ret); - return ret; - } - srs_info("config reloader parse file success."); - - // store current root to old_root, - // and reap the root from conf to current root. - SrsConfDirective* old_root = root; - SrsAutoFree(SrsConfDirective, old_root, false); - - root = conf.root; - conf.root = NULL; - - // merge config. - std::vector::iterator it; + SrsConfig conf; + if ((ret = conf.parse_file(config_file.c_str())) != ERROR_SUCCESS) { + srs_error("config reloader parse file failed. ret=%d", ret); + return ret; + } + srs_info("config reloader parse file success."); + + // store current root to old_root, + // and reap the root from conf to current root. + SrsConfDirective* old_root = root; + SrsAutoFree(SrsConfDirective, old_root, false); + + root = conf.root; + conf.root = NULL; + + // merge config. + std::vector::iterator it; - // merge config: listen - if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) { - srs_error("notify subscribes reload listen failed. ret=%d", ret); - return ret; - } - } - srs_trace("reload listen success."); - } - - // merge config: pithy_print - if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) { - srs_error("notify subscribes pithy_print listen failed. ret=%d", ret); - return ret; - } - } - srs_trace("reload pithy_print success."); - } + // merge config: listen + if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) { + srs_error("notify subscribes reload listen failed. ret=%d", ret); + return ret; + } + } + srs_trace("reload listen success."); + } + + // merge config: pithy_print + if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) { + srs_error("notify subscribes pithy_print listen failed. ret=%d", ret); + return ret; + } + } + srs_trace("reload pithy_print success."); + } - // merge config: vhost added, directly supported. - - // merge config: vhost removed/disabled/modified. - for (int i = 0; i < (int)old_root->directives.size(); i++) { - SrsConfDirective* old_vhost = old_root->at(i); - // only process vhost directives. - if (old_vhost->name != "vhost") { - continue; - } - - std::string vhost = old_vhost->arg0(); + // merge config: vhost added, directly supported. + + // merge config: vhost removed/disabled/modified. + for (int i = 0; i < (int)old_root->directives.size(); i++) { + SrsConfDirective* old_vhost = old_root->at(i); + // only process vhost directives. + if (old_vhost->name != "vhost") { + continue; + } + + std::string vhost = old_vhost->arg0(); - SrsConfDirective* new_vhost = root->get("vhost", vhost); - // ignore if absolutely equal - if (new_vhost && srs_directive_equals(old_vhost, new_vhost)) { - srs_trace("vhost %s absolutely equal, ignore.", vhost.c_str()); - continue; - } - // ignore if enable the new vhost when old vhost is disabled. - if (get_vhost_enabled(new_vhost) && !get_vhost_enabled(old_vhost)) { - srs_trace("vhost %s disabled=>enabled, ignore.", vhost.c_str()); - continue; - } - // ignore if both old and new vhost are disabled. - if (!get_vhost_enabled(new_vhost) && !get_vhost_enabled(old_vhost)) { - srs_trace("vhost %s disabled=>disabled, ignore.", vhost.c_str()); - continue; - } + SrsConfDirective* new_vhost = root->get("vhost", vhost); + // ignore if absolutely equal + if (new_vhost && srs_directive_equals(old_vhost, new_vhost)) { + srs_trace("vhost %s absolutely equal, ignore.", vhost.c_str()); + continue; + } + // ignore if enable the new vhost when old vhost is disabled. + if (get_vhost_enabled(new_vhost) && !get_vhost_enabled(old_vhost)) { + srs_trace("vhost %s disabled=>enabled, ignore.", vhost.c_str()); + continue; + } + // ignore if both old and new vhost are disabled. + if (!get_vhost_enabled(new_vhost) && !get_vhost_enabled(old_vhost)) { + srs_trace("vhost %s disabled=>disabled, ignore.", vhost.c_str()); + continue; + } - // merge config: vhost removed/disabled. - if (!get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { - srs_trace("vhost %s disabled, reload it.", vhost.c_str()); - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_vhost_removed(vhost)) != ERROR_SUCCESS) { - srs_error("notify subscribes pithy_print remove " - "vhost %s failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("reload remove vhost %s success.", vhost.c_str()); - } - - // merge config: vhost modified. - srs_trace("vhost %s modified, reload its detail.", vhost.c_str()); - if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { - // gop_cache - if (!srs_directive_equals(new_vhost->get("gop_cache"), old_vhost->get("gop_cache"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_gop_cache(vhost)) != ERROR_SUCCESS) { - srs_error("vhost %s notify subscribes gop_cache failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("vhost %s reload gop_cache success.", vhost.c_str()); - } - // queue_length - if (!srs_directive_equals(new_vhost->get("queue_length"), old_vhost->get("queue_length"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_queue_length(vhost)) != ERROR_SUCCESS) { - srs_error("vhost %s notify subscribes queue_length failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("vhost %s reload queue_length success.", vhost.c_str()); - } - // forward - if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_forward(vhost)) != ERROR_SUCCESS) { - srs_error("vhost %s notify subscribes forward failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("vhost %s reload forward success.", vhost.c_str()); - } - // hls - if (!srs_directive_equals(new_vhost->get("hls"), old_vhost->get("hls"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_hls(vhost)) != ERROR_SUCCESS) { - srs_error("vhost %s notify subscribes hls failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("vhost %s reload hls success.", vhost.c_str()); - } - // transcode - if (!srs_directive_equals(new_vhost->get("transcode"), old_vhost->get("transcode"))) { - for (it = subscribes.begin(); it != subscribes.end(); ++it) { - ISrsReloadHandler* subscribe = *it; - if ((ret = subscribe->on_reload_transcode(vhost)) != ERROR_SUCCESS) { - srs_error("vhost %s notify subscribes transcode failed. ret=%d", vhost.c_str(), ret); - return ret; - } - } - srs_trace("vhost %s reload transcode success.", vhost.c_str()); - } - // TODO: suppor reload hls/forward/ffmpeg/http - continue; - } - srs_warn("invalid reload path, enabled old: %d, new: %d", - get_vhost_enabled(old_vhost), get_vhost_enabled(new_vhost)); - } - - return ret; + // merge config: vhost removed/disabled. + if (!get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { + srs_trace("vhost %s disabled, reload it.", vhost.c_str()); + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_vhost_removed(vhost)) != ERROR_SUCCESS) { + srs_error("notify subscribes pithy_print remove " + "vhost %s failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("reload remove vhost %s success.", vhost.c_str()); + } + + // merge config: vhost modified. + srs_trace("vhost %s modified, reload its detail.", vhost.c_str()); + if (get_vhost_enabled(new_vhost) && get_vhost_enabled(old_vhost)) { + // gop_cache + if (!srs_directive_equals(new_vhost->get("gop_cache"), old_vhost->get("gop_cache"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_gop_cache(vhost)) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes gop_cache failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload gop_cache success.", vhost.c_str()); + } + // queue_length + if (!srs_directive_equals(new_vhost->get("queue_length"), old_vhost->get("queue_length"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_queue_length(vhost)) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes queue_length failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload queue_length success.", vhost.c_str()); + } + // forward + if (!srs_directive_equals(new_vhost->get("forward"), old_vhost->get("forward"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_forward(vhost)) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes forward failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload forward success.", vhost.c_str()); + } + // hls + if (!srs_directive_equals(new_vhost->get("hls"), old_vhost->get("hls"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_hls(vhost)) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes hls failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload hls success.", vhost.c_str()); + } + // transcode + if (!srs_directive_equals(new_vhost->get("transcode"), old_vhost->get("transcode"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_transcode(vhost)) != ERROR_SUCCESS) { + srs_error("vhost %s notify subscribes transcode failed. ret=%d", vhost.c_str(), ret); + return ret; + } + } + srs_trace("vhost %s reload transcode success.", vhost.c_str()); + } + // TODO: suppor reload hls/forward/ffmpeg/http + continue; + } + srs_warn("invalid reload path, enabled old: %d, new: %d", + get_vhost_enabled(old_vhost), get_vhost_enabled(new_vhost)); + } + + return ret; } void SrsConfig::subscribe(ISrsReloadHandler* handler) { - std::vector::iterator it; - - it = std::find(subscribes.begin(), subscribes.end(), handler); - if (it != subscribes.end()) { - return; - } - - subscribes.push_back(handler); + std::vector::iterator it; + + it = std::find(subscribes.begin(), subscribes.end(), handler); + if (it != subscribes.end()) { + return; + } + + subscribes.push_back(handler); } void SrsConfig::unsubscribe(ISrsReloadHandler* handler) { - std::vector::iterator it; - - it = std::find(subscribes.begin(), subscribes.end(), handler); - if (it == subscribes.end()) { - return; - } - - subscribes.erase(it); + std::vector::iterator it; + + it = std::find(subscribes.begin(), subscribes.end(), handler); + if (it == subscribes.end()) { + return; + } + + subscribes.erase(it); } // see: ngx_get_options int SrsConfig::parse_options(int argc, char** argv) { - int ret = ERROR_SUCCESS; - - for (int i = 1; i < argc; i++) { - if ((ret = parse_argv(i, argv)) != ERROR_SUCCESS) { - return ret; - } - } - - if (show_help) { - print_help(argv); - } - - if (show_version) { - printf("%s\n", RTMP_SIG_SRS_VERSION); - } - - if (show_help || show_version) { - exit(0); - } - - if (config_file.empty()) { - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("config file not specified, see help: %s -h, ret=%d", argv[0], ret); - return ret; - } + int ret = ERROR_SUCCESS; + + for (int i = 1; i < argc; i++) { + if ((ret = parse_argv(i, argv)) != ERROR_SUCCESS) { + return ret; + } + } + + if (show_help) { + print_help(argv); + } + + if (show_version) { + printf("%s\n", RTMP_SIG_SRS_VERSION); + } + + if (show_help || show_version) { + exit(0); + } + + if (config_file.empty()) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("config file not specified, see help: %s -h, ret=%d", argv[0], ret); + return ret; + } - return parse_file(config_file.c_str()); + return parse_file(config_file.c_str()); } int SrsConfig::parse_file(const char* filename) { - int ret = ERROR_SUCCESS; - - config_file = filename; - - if (config_file.empty()) { - return ERROR_SYSTEM_CONFIG_INVALID; - } - - if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) { - return ret; - } - - SrsConfDirective* conf = NULL; - if ((conf = get_listen()) == NULL || conf->args.size() == 0) { - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("line %d: conf error, " - "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret); - return ret; - } - - // TODO: check the hls. - // TODO: check forward. - // TODO: check ffmpeg. - // TODO: check http. - - return ret; + int ret = ERROR_SUCCESS; + + config_file = filename; + + if (config_file.empty()) { + return ERROR_SYSTEM_CONFIG_INVALID; + } + + if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) { + return ret; + } + + SrsConfDirective* conf = NULL; + if ((conf = get_listen()) == NULL || conf->args.size() == 0) { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("line %d: conf error, " + "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret); + return ret; + } + + // TODO: check the hls. + // TODO: check forward. + // TODO: check ffmpeg. + // TODO: check http. + + return ret; } int SrsConfig::parse_argv(int& i, char** argv) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - char* p = argv[i]; - - if (*p++ != '-') { - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("invalid options(index=%d, value=%s), " - "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret); - return ret; - } - - while (*p) { - switch (*p++) { - case '?': - case 'h': - show_help = true; - break; - case 'v': - case 'V': - show_version = true; - break; - case 'c': - if (*p) { - config_file = p; - return ret; - } - if (argv[++i]) { - config_file = argv[i]; - return ret; - } - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("option \"-c\" requires parameter, ret=%d", ret); - return ret; - default: - ret = ERROR_SYSTEM_CONFIG_INVALID; - srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret); - return ret; - } - } - - return ret; + char* p = argv[i]; + + if (*p++ != '-') { + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("invalid options(index=%d, value=%s), " + "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret); + return ret; + } + + while (*p) { + switch (*p++) { + case '?': + case 'h': + show_help = true; + break; + case 'v': + case 'V': + show_version = true; + break; + case 'c': + if (*p) { + config_file = p; + return ret; + } + if (argv[++i]) { + config_file = argv[i]; + return ret; + } + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("option \"-c\" requires parameter, ret=%d", ret); + return ret; + default: + ret = ERROR_SYSTEM_CONFIG_INVALID; + srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret); + return ret; + } + } + + return ret; } void SrsConfig::print_help(char** argv) { - printf( - RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION" "RTMP_SIG_SRS_COPYRIGHT"\n" - "Primary Authors: "RTMP_SIG_SRS_PRIMARY_AUTHROS"\n" - "Build: "SRS_BUILD_DATE" Configuration:"SRS_CONFIGURE"\n" - "Usage: %s [-h?vV] [-c ]\n" - "\n" - "Options:\n" - " -?-h : show help\n" - " -v-V : show version and exit\n" - " -c filename : set configuration file\n" - "\n" - RTMP_SIG_SRS_WEB"\n" - RTMP_SIG_SRS_URL"\n" - "Email: "RTMP_SIG_SRS_EMAIL"\n" - "\n", - argv[0]); + printf( + RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION" "RTMP_SIG_SRS_COPYRIGHT"\n" + "Primary Authors: "RTMP_SIG_SRS_PRIMARY_AUTHROS"\n" + "Build: "SRS_BUILD_DATE" Configuration:"SRS_CONFIGURE"\n" + "Usage: %s [-h?vV] [-c ]\n" + "\n" + "Options:\n" + " -?-h : show help\n" + " -v-V : show version and exit\n" + " -c filename : set configuration file\n" + "\n" + RTMP_SIG_SRS_WEB"\n" + RTMP_SIG_SRS_URL"\n" + "Email: "RTMP_SIG_SRS_EMAIL"\n" + "\n", + argv[0]); } SrsConfDirective* SrsConfig::get_vhost(string vhost) { - srs_assert(root); - - for (int i = 0; i < (int)root->directives.size(); i++) { - SrsConfDirective* conf = root->at(i); - - if (conf->name != "vhost") { - continue; - } - - if (conf->arg0() == vhost) { - return conf; - } - } - - if (vhost != RTMP_VHOST_DEFAULT) { - return get_vhost(RTMP_VHOST_DEFAULT); - } - - return NULL; + srs_assert(root); + + for (int i = 0; i < (int)root->directives.size(); i++) { + SrsConfDirective* conf = root->at(i); + + if (conf->name != "vhost") { + continue; + } + + if (conf->arg0() == vhost) { + return conf; + } + } + + if (vhost != RTMP_VHOST_DEFAULT) { + return get_vhost(RTMP_VHOST_DEFAULT); + } + + return NULL; } SrsConfDirective* SrsConfig::get_vhost_on_connect(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - conf = conf->get("http_hooks"); - if (!conf) { - return NULL; - } - - SrsConfDirective* enabled = conf->get("enabled"); - if (!enabled || enabled->arg0() != "on") { - return NULL; - } - - return conf->get("on_connect"); + if (!conf) { + return NULL; + } + + conf = conf->get("http_hooks"); + if (!conf) { + return NULL; + } + + SrsConfDirective* enabled = conf->get("enabled"); + if (!enabled || enabled->arg0() != "on") { + return NULL; + } + + return conf->get("on_connect"); } SrsConfDirective* SrsConfig::get_vhost_on_close(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - conf = conf->get("http_hooks"); - if (!conf) { - return NULL; - } - - SrsConfDirective* enabled = conf->get("enabled"); - if (!enabled || enabled->arg0() != "on") { - return NULL; - } - - return conf->get("on_close"); + if (!conf) { + return NULL; + } + + conf = conf->get("http_hooks"); + if (!conf) { + return NULL; + } + + SrsConfDirective* enabled = conf->get("enabled"); + if (!enabled || enabled->arg0() != "on") { + return NULL; + } + + return conf->get("on_close"); } SrsConfDirective* SrsConfig::get_vhost_on_publish(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - conf = conf->get("http_hooks"); - if (!conf) { - return NULL; - } - - SrsConfDirective* enabled = conf->get("enabled"); - if (!enabled || enabled->arg0() != "on") { - return NULL; - } - - return conf->get("on_publish"); + if (!conf) { + return NULL; + } + + conf = conf->get("http_hooks"); + if (!conf) { + return NULL; + } + + SrsConfDirective* enabled = conf->get("enabled"); + if (!enabled || enabled->arg0() != "on") { + return NULL; + } + + return conf->get("on_publish"); } SrsConfDirective* SrsConfig::get_vhost_on_unpublish(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - conf = conf->get("http_hooks"); - if (!conf) { - return NULL; - } - - SrsConfDirective* enabled = conf->get("enabled"); - if (!enabled || enabled->arg0() != "on") { - return NULL; - } - - return conf->get("on_unpublish"); + if (!conf) { + return NULL; + } + + conf = conf->get("http_hooks"); + if (!conf) { + return NULL; + } + + SrsConfDirective* enabled = conf->get("enabled"); + if (!enabled || enabled->arg0() != "on") { + return NULL; + } + + return conf->get("on_unpublish"); } SrsConfDirective* SrsConfig::get_vhost_on_play(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - conf = conf->get("http_hooks"); - if (!conf) { - return NULL; - } - - SrsConfDirective* enabled = conf->get("enabled"); - if (!enabled || enabled->arg0() != "on") { - return NULL; - } - - return conf->get("on_play"); + if (!conf) { + return NULL; + } + + conf = conf->get("http_hooks"); + if (!conf) { + return NULL; + } + + SrsConfDirective* enabled = conf->get("enabled"); + if (!enabled || enabled->arg0() != "on") { + return NULL; + } + + return conf->get("on_play"); } SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - conf = conf->get("http_hooks"); - if (!conf) { - return NULL; - } - - SrsConfDirective* enabled = conf->get("enabled"); - if (!enabled || enabled->arg0() != "on") { - return NULL; - } - - return conf->get("on_stop"); + if (!conf) { + return NULL; + } + + conf = conf->get("http_hooks"); + if (!conf) { + return NULL; + } + + SrsConfDirective* enabled = conf->get("enabled"); + if (!enabled || enabled->arg0() != "on") { + return NULL; + } + + return conf->get("on_stop"); } bool SrsConfig::get_vhost_enabled(string vhost) { - SrsConfDirective* vhost_conf = get_vhost(vhost); - - return get_vhost_enabled(vhost_conf); + SrsConfDirective* vhost_conf = get_vhost(vhost); + + return get_vhost_enabled(vhost_conf); } bool SrsConfig::get_vhost_enabled(SrsConfDirective* vhost) { - if (!vhost) { - return false; - } - - SrsConfDirective* conf = vhost->get("enabled"); - if (!conf) { - return true; - } - - if (conf->arg0() == "off") { - return false; - } - - return true; + if (!vhost) { + return false; + } + + SrsConfDirective* conf = vhost->get("enabled"); + if (!conf) { + return true; + } + + if (conf->arg0() == "off") { + return false; + } + + return true; } SrsConfDirective* SrsConfig::get_transcode(string vhost, string scope) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - SrsConfDirective* transcode = conf->get("transcode"); - if (!transcode) { - return NULL; - } - - if (transcode->arg0() == scope) { - return transcode; - } - - return NULL; + if (!conf) { + return NULL; + } + + SrsConfDirective* transcode = conf->get("transcode"); + if (!transcode) { + return NULL; + } + + if (transcode->arg0() == scope) { + return transcode; + } + + return NULL; } bool SrsConfig::get_transcode_enabled(SrsConfDirective* transcode) { - if (!transcode) { - return false; - } - - SrsConfDirective* conf = transcode->get("enabled"); - if (!conf || conf->arg0() != "on") { - return false; - } - - return true; + if (!transcode) { + return false; + } + + SrsConfDirective* conf = transcode->get("enabled"); + if (!conf || conf->arg0() != "on") { + return false; + } + + return true; } string SrsConfig::get_transcode_ffmpeg(SrsConfDirective* transcode) { - if (!transcode) { - return ""; - } - - SrsConfDirective* conf = transcode->get("ffmpeg"); - if (!conf) { - return ""; - } - - return conf->arg0(); + if (!transcode) { + return ""; + } + + SrsConfDirective* conf = transcode->get("ffmpeg"); + if (!conf) { + return ""; + } + + return conf->arg0(); } void SrsConfig::get_transcode_engines(SrsConfDirective* transcode, std::vector& engines) { - if (!transcode) { - return; - } - - for (int i = 0; i < (int)transcode->directives.size(); i++) { - SrsConfDirective* conf = transcode->directives[i]; - - if (conf->name == "engine") { - engines.push_back(conf); - } - } - - return; + if (!transcode) { + return; + } + + for (int i = 0; i < (int)transcode->directives.size(); i++) { + SrsConfDirective* conf = transcode->directives[i]; + + if (conf->name == "engine") { + engines.push_back(conf); + } + } + + return; } bool SrsConfig::get_engine_enabled(SrsConfDirective* engine) { - if (!engine) { - return false; - } - - SrsConfDirective* conf = engine->get("enabled"); - if (!conf || conf->arg0() != "on") { - return false; - } - - return true; + if (!engine) { + return false; + } + + SrsConfDirective* conf = engine->get("enabled"); + if (!conf || conf->arg0() != "on") { + return false; + } + + return true; } string SrsConfig::get_engine_vcodec(SrsConfDirective* engine) { - if (!engine) { - return ""; - } - - SrsConfDirective* conf = engine->get("vcodec"); - if (!conf) { - return ""; - } - - return conf->arg0(); + if (!engine) { + return ""; + } + + SrsConfDirective* conf = engine->get("vcodec"); + if (!conf) { + return ""; + } + + return conf->arg0(); } int SrsConfig::get_engine_vbitrate(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("vbitrate"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("vbitrate"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } double SrsConfig::get_engine_vfps(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("vfps"); - if (!conf) { - return 0; - } - - return ::atof(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("vfps"); + if (!conf) { + return 0; + } + + return ::atof(conf->arg0().c_str()); } int SrsConfig::get_engine_vwidth(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("vwidth"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("vwidth"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } int SrsConfig::get_engine_vheight(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("vheight"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("vheight"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } int SrsConfig::get_engine_vthreads(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("vthreads"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("vthreads"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } string SrsConfig::get_engine_vprofile(SrsConfDirective* engine) { - if (!engine) { - return ""; - } - - SrsConfDirective* conf = engine->get("vprofile"); - if (!conf) { - return ""; - } - - return conf->arg0(); + if (!engine) { + return ""; + } + + SrsConfDirective* conf = engine->get("vprofile"); + if (!conf) { + return ""; + } + + return conf->arg0(); } string SrsConfig::get_engine_vpreset(SrsConfDirective* engine) { - if (!engine) { - return ""; - } - - SrsConfDirective* conf = engine->get("vpreset"); - if (!conf) { - return ""; - } - - return conf->arg0(); + if (!engine) { + return ""; + } + + SrsConfDirective* conf = engine->get("vpreset"); + if (!conf) { + return ""; + } + + return conf->arg0(); } void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector& vparams) { - if (!engine) { - return; - } - - SrsConfDirective* conf = engine->get("vparams"); - if (!conf) { - return; - } - - for (int i = 0; i < (int)conf->directives.size(); i++) { - SrsConfDirective* p = conf->directives[i]; - if (!p) { - continue; - } - - vparams.push_back("-" + p->name); - vparams.push_back(p->arg0()); - } + if (!engine) { + return; + } + + SrsConfDirective* conf = engine->get("vparams"); + if (!conf) { + return; + } + + for (int i = 0; i < (int)conf->directives.size(); i++) { + SrsConfDirective* p = conf->directives[i]; + if (!p) { + continue; + } + + vparams.push_back("-" + p->name); + vparams.push_back(p->arg0()); + } } void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector& vfilter) { - if (!engine) { - return; - } - - SrsConfDirective* conf = engine->get("vfilter"); - if (!conf) { - return; - } - - for (int i = 0; i < (int)conf->directives.size(); i++) { - SrsConfDirective* p = conf->directives[i]; - if (!p) { - continue; - } - - vfilter.push_back("-" + p->name); - vfilter.push_back(p->arg0()); - } + if (!engine) { + return; + } + + SrsConfDirective* conf = engine->get("vfilter"); + if (!conf) { + return; + } + + for (int i = 0; i < (int)conf->directives.size(); i++) { + SrsConfDirective* p = conf->directives[i]; + if (!p) { + continue; + } + + vfilter.push_back("-" + p->name); + vfilter.push_back(p->arg0()); + } } string SrsConfig::get_engine_acodec(SrsConfDirective* engine) { - if (!engine) { - return ""; - } - - SrsConfDirective* conf = engine->get("acodec"); - if (!conf) { - return ""; - } - - return conf->arg0(); + if (!engine) { + return ""; + } + + SrsConfDirective* conf = engine->get("acodec"); + if (!conf) { + return ""; + } + + return conf->arg0(); } int SrsConfig::get_engine_abitrate(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("abitrate"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("abitrate"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } int SrsConfig::get_engine_asample_rate(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("asample_rate"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("asample_rate"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } int SrsConfig::get_engine_achannels(SrsConfDirective* engine) { - if (!engine) { - return 0; - } - - SrsConfDirective* conf = engine->get("achannels"); - if (!conf) { - return 0; - } - - return ::atoi(conf->arg0().c_str()); + if (!engine) { + return 0; + } + + SrsConfDirective* conf = engine->get("achannels"); + if (!conf) { + return 0; + } + + return ::atoi(conf->arg0().c_str()); } void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector& aparams) { - if (!engine) { - return; - } - - SrsConfDirective* conf = engine->get("aparams"); - if (!conf) { - return; - } - - for (int i = 0; i < (int)conf->directives.size(); i++) { - SrsConfDirective* p = conf->directives[i]; - if (!p) { - continue; - } - - aparams.push_back("-" + p->name); - aparams.push_back(p->arg0()); - } + if (!engine) { + return; + } + + SrsConfDirective* conf = engine->get("aparams"); + if (!conf) { + return; + } + + for (int i = 0; i < (int)conf->directives.size(); i++) { + SrsConfDirective* p = conf->directives[i]; + if (!p) { + continue; + } + + aparams.push_back("-" + p->name); + aparams.push_back(p->arg0()); + } } string SrsConfig::get_engine_output(SrsConfDirective* engine) { - if (!engine) { - return ""; - } - - SrsConfDirective* conf = engine->get("output"); - if (!conf) { - return ""; - } - - return conf->arg0(); + if (!engine) { + return ""; + } + + SrsConfDirective* conf = engine->get("output"); + if (!conf) { + return ""; + } + + return conf->arg0(); } string SrsConfig::get_log_dir() { - srs_assert(root); - - SrsConfDirective* conf = root->get("log_dir"); - if (!conf || conf->arg0().empty()) { - return "./objs/logs"; - } - - return conf->arg0(); + srs_assert(root); + + SrsConfDirective* conf = root->get("log_dir"); + if (!conf || conf->arg0().empty()) { + return "./objs/logs"; + } + + return conf->arg0(); } int SrsConfig::get_max_connections() { - srs_assert(root); - - SrsConfDirective* conf = root->get("max_connections"); - if (!conf || conf->arg0().empty()) { - return 2000; - } - - return ::atoi(conf->arg0().c_str()); + srs_assert(root); + + SrsConfDirective* conf = root->get("max_connections"); + if (!conf || conf->arg0().empty()) { + return 2000; + } + + return ::atoi(conf->arg0().c_str()); } bool SrsConfig::get_gop_cache(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return true; - } - - conf = conf->get("gop_cache"); - if (conf && conf->arg0() == "off") { - return false; - } - - return true; + if (!conf) { + return true; + } + + conf = conf->get("gop_cache"); + if (conf && conf->arg0() == "off") { + return false; + } + + return true; } double SrsConfig::get_queue_length(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return SRS_CONF_DEFAULT_QUEUE_LENGTH; - } - - conf = conf->get("queue_length"); - if (!conf || conf->arg0().empty()) { - return SRS_CONF_DEFAULT_QUEUE_LENGTH; - } - - return ::atoi(conf->arg0().c_str()); + if (!conf) { + return SRS_CONF_DEFAULT_QUEUE_LENGTH; + } + + conf = conf->get("queue_length"); + if (!conf || conf->arg0().empty()) { + return SRS_CONF_DEFAULT_QUEUE_LENGTH; + } + + return ::atoi(conf->arg0().c_str()); } SrsConfDirective* SrsConfig::get_forward(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - return conf->get("forward"); + if (!conf) { + return NULL; + } + + return conf->get("forward"); } SrsConfDirective* SrsConfig::get_hls(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - return conf->get("hls"); + if (!conf) { + return NULL; + } + + return conf->get("hls"); } bool SrsConfig::get_hls_enabled(string vhost) { - SrsConfDirective* hls = get_hls(vhost); - - if (!hls) { - return false; - } - - SrsConfDirective* conf = hls->get("enabled"); - - if (!conf) { - return false; - } - - if (conf->arg0() == "on") { - return true; - } - - return false; + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return false; + } + + SrsConfDirective* conf = hls->get("enabled"); + + if (!conf) { + return false; + } + + if (conf->arg0() == "on") { + return true; + } + + return false; } string SrsConfig::get_hls_path(string vhost) { - SrsConfDirective* hls = get_hls(vhost); - - if (!hls) { - return SRS_CONF_DEFAULT_HLS_PATH; - } - - SrsConfDirective* conf = hls->get("hls_path"); - - if (!conf) { - return SRS_CONF_DEFAULT_HLS_PATH; - } + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return SRS_CONF_DEFAULT_HLS_PATH; + } + + SrsConfDirective* conf = hls->get("hls_path"); + + if (!conf) { + return SRS_CONF_DEFAULT_HLS_PATH; + } - return conf->arg0(); + return conf->arg0(); } double SrsConfig::get_hls_fragment(string vhost) { - SrsConfDirective* hls = get_hls(vhost); - - if (!hls) { - return SRS_CONF_DEFAULT_HLS_FRAGMENT; - } - - SrsConfDirective* conf = hls->get("hls_fragment"); - - if (!conf) { - return SRS_CONF_DEFAULT_HLS_FRAGMENT; - } + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return SRS_CONF_DEFAULT_HLS_FRAGMENT; + } + + SrsConfDirective* conf = hls->get("hls_fragment"); + + if (!conf) { + return SRS_CONF_DEFAULT_HLS_FRAGMENT; + } - return ::atof(conf->arg0().c_str()); + return ::atof(conf->arg0().c_str()); } double SrsConfig::get_hls_window(string vhost) { - SrsConfDirective* hls = get_hls(vhost); - - if (!hls) { - return SRS_CONF_DEFAULT_HLS_WINDOW; - } - - SrsConfDirective* conf = hls->get("hls_window"); - - if (!conf) { - return SRS_CONF_DEFAULT_HLS_WINDOW; - } + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return SRS_CONF_DEFAULT_HLS_WINDOW; + } + + SrsConfDirective* conf = hls->get("hls_window"); + + if (!conf) { + return SRS_CONF_DEFAULT_HLS_WINDOW; + } - return ::atof(conf->arg0().c_str()); + return ::atof(conf->arg0().c_str()); } SrsConfDirective* SrsConfig::get_refer(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - return conf->get("refer"); + if (!conf) { + return NULL; + } + + return conf->get("refer"); } SrsConfDirective* SrsConfig::get_refer_play(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - return conf->get("refer_play"); + if (!conf) { + return NULL; + } + + return conf->get("refer_play"); } SrsConfDirective* SrsConfig::get_refer_publish(string vhost) { - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = get_vhost(vhost); - if (!conf) { - return NULL; - } - - return conf->get("refer_publish"); + if (!conf) { + return NULL; + } + + return conf->get("refer_publish"); } SrsConfDirective* SrsConfig::get_listen() { - return root->get("listen"); + return root->get("listen"); } int SrsConfig::get_chunk_size(const std::string &vhost) @@ -1444,19 +1444,19 @@ int SrsConfig::get_chunk_size(const std::string &vhost) SrsConfDirective* conf = get_vhost(vhost); if (!conf) { - return SRS_CONF_DEFAULT_CHUNK_SIZE; + return SRS_CONF_DEFAULT_CHUNK_SIZE; } conf = conf->get("chunk_size"); if (!conf) { // vhost does not specify the chunk size, // use the global instead. - conf = root->get("chunk_size"); - if (!conf) { - return SRS_CONF_DEFAULT_CHUNK_SIZE; - } - - return ::atoi(conf->arg0().c_str()); + conf = root->get("chunk_size"); + if (!conf) { + return SRS_CONF_DEFAULT_CHUNK_SIZE; + } + + return ::atoi(conf->arg0().c_str()); } return ::atoi(conf->arg0().c_str()); @@ -1464,47 +1464,47 @@ int SrsConfig::get_chunk_size(const std::string &vhost) int SrsConfig::get_pithy_print_publish() { - SrsConfDirective* pithy = root->get("pithy_print"); - if (!pithy) { - return SRS_STAGE_PUBLISH_USER_INTERVAL_MS; - } - - pithy = pithy->get("publish"); - if (!pithy) { - return SRS_STAGE_PUBLISH_USER_INTERVAL_MS; - } - - return ::atoi(pithy->arg0().c_str()); + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return SRS_STAGE_PUBLISH_USER_INTERVAL_MS; + } + + pithy = pithy->get("publish"); + if (!pithy) { + return SRS_STAGE_PUBLISH_USER_INTERVAL_MS; + } + + return ::atoi(pithy->arg0().c_str()); } int SrsConfig::get_pithy_print_forwarder() { - SrsConfDirective* pithy = root->get("pithy_print"); - if (!pithy) { - return SRS_STAGE_FORWARDER_INTERVAL_MS; - } - - pithy = pithy->get("forwarder"); - if (!pithy) { - return SRS_STAGE_FORWARDER_INTERVAL_MS; - } - - return ::atoi(pithy->arg0().c_str()); + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return SRS_STAGE_FORWARDER_INTERVAL_MS; + } + + pithy = pithy->get("forwarder"); + if (!pithy) { + return SRS_STAGE_FORWARDER_INTERVAL_MS; + } + + return ::atoi(pithy->arg0().c_str()); } int SrsConfig::get_pithy_print_hls() { - SrsConfDirective* pithy = root->get("pithy_print"); - if (!pithy) { - return SRS_STAGE_HLS_INTERVAL_MS; - } - - pithy = pithy->get("hls"); - if (!pithy) { - return SRS_STAGE_HLS_INTERVAL_MS; - } - - return ::atoi(pithy->arg0().c_str()); + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return SRS_STAGE_HLS_INTERVAL_MS; + } + + pithy = pithy->get("hls"); + if (!pithy) { + return SRS_STAGE_HLS_INTERVAL_MS; + } + + return ::atoi(pithy->arg0().c_str()); } bool SrsConfig::get_bw_check_enabled(const string &vhost) @@ -1593,71 +1593,71 @@ int SrsConfig::get_bw_check_limit_kbps(const string &vhost) int SrsConfig::get_pithy_print_encoder() { - SrsConfDirective* pithy = root->get("encoder"); - if (!pithy) { - return SRS_STAGE_ENCODER_INTERVAL_MS; - } - - pithy = pithy->get("forwarder"); - if (!pithy) { - return SRS_STAGE_ENCODER_INTERVAL_MS; - } - - return ::atoi(pithy->arg0().c_str()); + SrsConfDirective* pithy = root->get("encoder"); + if (!pithy) { + return SRS_STAGE_ENCODER_INTERVAL_MS; + } + + pithy = pithy->get("forwarder"); + if (!pithy) { + return SRS_STAGE_ENCODER_INTERVAL_MS; + } + + return ::atoi(pithy->arg0().c_str()); } int SrsConfig::get_pithy_print_play() { - SrsConfDirective* pithy = root->get("pithy_print"); - if (!pithy) { - return SRS_STAGE_PLAY_USER_INTERVAL_MS; - } - - pithy = pithy->get("play"); - if (!pithy) { - return SRS_STAGE_PLAY_USER_INTERVAL_MS; - } - - return ::atoi(pithy->arg0().c_str()); + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return SRS_STAGE_PLAY_USER_INTERVAL_MS; + } + + pithy = pithy->get("play"); + if (!pithy) { + return SRS_STAGE_PLAY_USER_INTERVAL_MS; + } + + return ::atoi(pithy->arg0().c_str()); } bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b) { - // both NULL, equal. - if (!a && !b) { - return true; - } - - if (!a || !b) { - return false; - } - - if (a->name != b->name) { - return false; - } - - if (a->args.size() != b->args.size()) { - return false; - } - - for (int i = 0; i < (int)a->args.size(); i++) { - if (a->args.at(i) != b->args.at(i)) { - return false; - } - } - - if (a->directives.size() != b->directives.size()) { - return false; - } - - for (int i = 0; i < (int)a->directives.size(); i++) { - SrsConfDirective* a0 = a->at(i); - SrsConfDirective* b0 = b->at(i); - - if (!srs_directive_equals(a0, b0)) { - return false; - } - } - - return true; + // both NULL, equal. + if (!a && !b) { + return true; + } + + if (!a || !b) { + return false; + } + + if (a->name != b->name) { + return false; + } + + if (a->args.size() != b->args.size()) { + return false; + } + + for (int i = 0; i < (int)a->args.size(); i++) { + if (a->args.at(i) != b->args.at(i)) { + return false; + } + } + + if (a->directives.size() != b->directives.size()) { + return false; + } + + for (int i = 0; i < (int)a->directives.size(); i++) { + SrsConfDirective* a0 = a->at(i); + SrsConfDirective* b0 = b->at(i); + + if (!srs_directive_equals(a0, b0)) { + return false; + } + } + + return true; } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 16bcd025e..8129e4eba 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -66,25 +66,25 @@ class SrsFileBuffer; class SrsConfDirective { public: - int conf_line; - std::string name; - std::vector args; - std::vector directives; + int conf_line; + std::string name; + std::vector args; + std::vector directives; public: - SrsConfDirective(); - virtual ~SrsConfDirective(); - std::string arg0(); - std::string arg1(); - std::string arg2(); - SrsConfDirective* at(int index); - SrsConfDirective* get(std::string _name); - SrsConfDirective* get(std::string _name, std::string _arg0); + SrsConfDirective(); + virtual ~SrsConfDirective(); + std::string arg0(); + std::string arg1(); + std::string arg2(); + SrsConfDirective* at(int index); + SrsConfDirective* get(std::string _name); + SrsConfDirective* get(std::string _name, std::string _arg0); public: - virtual int parse(const char* filename); + virtual int parse(const char* filename); public: - enum SrsDirectiveType{parse_file, parse_block}; - virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type); - virtual int read_token(SrsFileBuffer* buffer, std::vector& args); + enum SrsDirectiveType{parse_file, parse_block}; + virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type); + virtual int read_token(SrsFileBuffer* buffer, std::vector& args); }; /** @@ -97,81 +97,81 @@ public: class SrsConfig { private: - bool show_help; - bool show_version; - std::string config_file; - SrsConfDirective* root; - std::vector subscribes; + bool show_help; + bool show_version; + std::string config_file; + SrsConfDirective* root; + std::vector subscribes; public: - SrsConfig(); - virtual ~SrsConfig(); + SrsConfig(); + virtual ~SrsConfig(); public: - virtual int reload(); - virtual void subscribe(ISrsReloadHandler* handler); - virtual void unsubscribe(ISrsReloadHandler* handler); + virtual int reload(); + virtual void subscribe(ISrsReloadHandler* handler); + virtual void unsubscribe(ISrsReloadHandler* handler); public: - virtual int parse_options(int argc, char** argv); + virtual int parse_options(int argc, char** argv); private: - virtual int parse_file(const char* filename); - virtual int parse_argv(int& i, char** argv); - virtual void print_help(char** argv); + virtual int parse_file(const char* filename); + virtual int parse_argv(int& i, char** argv); + virtual void print_help(char** argv); public: - virtual SrsConfDirective* get_vhost(std::string vhost); - virtual bool get_vhost_enabled(std::string vhost); - virtual bool get_vhost_enabled(SrsConfDirective* vhost); - virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); - virtual SrsConfDirective* get_vhost_on_close(std::string vhost); - virtual SrsConfDirective* get_vhost_on_publish(std::string vhost); - virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); - virtual SrsConfDirective* get_vhost_on_play(std::string vhost); - virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); - virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); - virtual bool get_transcode_enabled(SrsConfDirective* transcode); - virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); - virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector& engines); - virtual bool get_engine_enabled(SrsConfDirective* engine); - virtual std::string get_engine_vcodec(SrsConfDirective* engine); - virtual int get_engine_vbitrate(SrsConfDirective* engine); - virtual double get_engine_vfps(SrsConfDirective* engine); - virtual int get_engine_vwidth(SrsConfDirective* engine); - virtual int get_engine_vheight(SrsConfDirective* engine); - virtual int get_engine_vthreads(SrsConfDirective* engine); - virtual std::string get_engine_vprofile(SrsConfDirective* engine); - virtual std::string get_engine_vpreset(SrsConfDirective* engine); - virtual void get_engine_vparams(SrsConfDirective* engine, std::vector& vparams); - virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector& vfilter); - virtual std::string get_engine_acodec(SrsConfDirective* engine); - virtual int get_engine_abitrate(SrsConfDirective* engine); - virtual int get_engine_asample_rate(SrsConfDirective* engine); - virtual int get_engine_achannels(SrsConfDirective* engine); - virtual void get_engine_aparams(SrsConfDirective* engine, std::vector& aparams); - virtual std::string get_engine_output(SrsConfDirective* engine); - virtual std::string get_log_dir(); - virtual int get_max_connections(); - virtual bool get_gop_cache(std::string vhost); - virtual double get_queue_length(std::string vhost); - virtual SrsConfDirective* get_forward(std::string vhost); + virtual SrsConfDirective* get_vhost(std::string vhost); + virtual bool get_vhost_enabled(std::string vhost); + virtual bool get_vhost_enabled(SrsConfDirective* vhost); + virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); + virtual SrsConfDirective* get_vhost_on_close(std::string vhost); + virtual SrsConfDirective* get_vhost_on_publish(std::string vhost); + virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); + virtual SrsConfDirective* get_vhost_on_play(std::string vhost); + virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); + virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); + virtual bool get_transcode_enabled(SrsConfDirective* transcode); + virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); + virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector& engines); + virtual bool get_engine_enabled(SrsConfDirective* engine); + virtual std::string get_engine_vcodec(SrsConfDirective* engine); + virtual int get_engine_vbitrate(SrsConfDirective* engine); + virtual double get_engine_vfps(SrsConfDirective* engine); + virtual int get_engine_vwidth(SrsConfDirective* engine); + virtual int get_engine_vheight(SrsConfDirective* engine); + virtual int get_engine_vthreads(SrsConfDirective* engine); + virtual std::string get_engine_vprofile(SrsConfDirective* engine); + virtual std::string get_engine_vpreset(SrsConfDirective* engine); + virtual void get_engine_vparams(SrsConfDirective* engine, std::vector& vparams); + virtual void get_engine_vfilter(SrsConfDirective* engine, std::vector& vfilter); + virtual std::string get_engine_acodec(SrsConfDirective* engine); + virtual int get_engine_abitrate(SrsConfDirective* engine); + virtual int get_engine_asample_rate(SrsConfDirective* engine); + virtual int get_engine_achannels(SrsConfDirective* engine); + virtual void get_engine_aparams(SrsConfDirective* engine, std::vector& aparams); + virtual std::string get_engine_output(SrsConfDirective* engine); + virtual std::string get_log_dir(); + virtual int get_max_connections(); + virtual bool get_gop_cache(std::string vhost); + virtual double get_queue_length(std::string vhost); + virtual SrsConfDirective* get_forward(std::string vhost); private: - virtual SrsConfDirective* get_hls(std::string vhost); + virtual SrsConfDirective* get_hls(std::string vhost); public: - virtual bool get_hls_enabled(std::string vhost); - virtual std::string get_hls_path(std::string vhost); - virtual double get_hls_fragment(std::string vhost); - virtual double get_hls_window(std::string vhost); - virtual SrsConfDirective* get_refer(std::string vhost); - virtual SrsConfDirective* get_refer_play(std::string vhost); - virtual SrsConfDirective* get_refer_publish(std::string vhost); - virtual SrsConfDirective* get_listen(); - virtual int get_chunk_size(const std::string& vhost); - virtual int get_pithy_print_publish(); - virtual int get_pithy_print_forwarder(); - virtual int get_pithy_print_encoder(); - virtual int get_pithy_print_hls(); - virtual int get_pithy_print_play(); + virtual bool get_hls_enabled(std::string vhost); + virtual std::string get_hls_path(std::string vhost); + virtual double get_hls_fragment(std::string vhost); + virtual double get_hls_window(std::string vhost); + virtual SrsConfDirective* get_refer(std::string vhost); + virtual SrsConfDirective* get_refer_play(std::string vhost); + virtual SrsConfDirective* get_refer_publish(std::string vhost); + virtual SrsConfDirective* get_listen(); + virtual int get_chunk_size(const std::string& vhost); + virtual int get_pithy_print_publish(); + virtual int get_pithy_print_forwarder(); + virtual int get_pithy_print_encoder(); + virtual int get_pithy_print_hls(); + virtual int get_pithy_print_play(); virtual bool get_bw_check_enabled(const std::string& vhost); - virtual std::string get_bw_check_key(const std::string& vhost); - virtual int get_bw_check_interval_ms(const std::string& vhost); - virtual int get_bw_check_limit_kbps(const std::string& vhost); + virtual std::string get_bw_check_key(const std::string& vhost); + virtual int get_bw_check_interval_ms(const std::string& vhost); + virtual int get_bw_check_limit_kbps(const std::string& vhost); }; /** diff --git a/trunk/src/app/srs_app_conn.cpp b/trunk/src/app/srs_app_conn.cpp index db2491888..2395a0d96 100644 --- a/trunk/src/app/srs_app_conn.cpp +++ b/trunk/src/app/srs_app_conn.cpp @@ -29,19 +29,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) { - server = srs_server; - stfd = client_stfd; - connection_id = 0; + server = srs_server; + stfd = client_stfd; + connection_id = 0; } SrsConnection::~SrsConnection() { - srs_close_stfd(stfd); + srs_close_stfd(stfd); } int SrsConnection::start() { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; if (st_thread_create(cycle_thread, this, 0, 0) == NULL) { ret = ERROR_ST_CREATE_CYCLE_THREAD; @@ -49,44 +49,44 @@ int SrsConnection::start() return ret; } srs_verbose("create st conn cycle thread success."); - - return ret; + + return ret; } void SrsConnection::cycle() { - int ret = ERROR_SUCCESS; - - _srs_context->generate_id(); - connection_id = _srs_context->get_id(); - - ret = do_cycle(); - - // if socket io error, set to closed. - if (srs_is_client_gracefully_close(ret)) { - ret = ERROR_SOCKET_CLOSED; - } + int ret = ERROR_SUCCESS; - // success. - if (ret == ERROR_SUCCESS) { - srs_trace("client process normally finished. ret=%d", ret); - } - - // client close peer. - if (ret == ERROR_SOCKET_CLOSED) { - srs_warn("client disconnect peer. ret=%d", ret); - } - - server->remove(this); + _srs_context->generate_id(); + connection_id = _srs_context->get_id(); + + ret = do_cycle(); + + // if socket io error, set to closed. + if (srs_is_client_gracefully_close(ret)) { + ret = ERROR_SOCKET_CLOSED; + } + + // success. + if (ret == ERROR_SUCCESS) { + srs_trace("client process normally finished. ret=%d", ret); + } + + // client close peer. + if (ret == ERROR_SOCKET_CLOSED) { + srs_warn("client disconnect peer. ret=%d", ret); + } + + server->remove(this); } void* SrsConnection::cycle_thread(void* arg) { - SrsConnection* conn = (SrsConnection*)arg; - srs_assert(conn != NULL); - - conn->cycle(); - - return NULL; + SrsConnection* conn = (SrsConnection*)arg; + srs_assert(conn != NULL); + + conn->cycle(); + + return NULL; } diff --git a/trunk/src/app/srs_app_conn.hpp b/trunk/src/app/srs_app_conn.hpp index f6ae638cc..c2d528329 100644 --- a/trunk/src/app/srs_app_conn.hpp +++ b/trunk/src/app/srs_app_conn.hpp @@ -36,19 +36,19 @@ class SrsServer; class SrsConnection { protected: - SrsServer* server; - st_netfd_t stfd; - int connection_id; + SrsServer* server; + st_netfd_t stfd; + int connection_id; public: - SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd); - virtual ~SrsConnection(); + SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd); + virtual ~SrsConnection(); public: - virtual int start(); + virtual int start(); protected: - virtual int do_cycle() = 0; + virtual int do_cycle() = 0; private: - virtual void cycle(); - static void* cycle_thread(void* arg); + virtual void cycle(); + static void* cycle_thread(void* arg); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_encoder.cpp b/trunk/src/app/srs_app_encoder.cpp index 324420ee2..9524b0772 100644 --- a/trunk/src/app/srs_app_encoder.cpp +++ b/trunk/src/app/srs_app_encoder.cpp @@ -41,474 +41,474 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef SRS_FFMPEG -#define SRS_ENCODER_COPY "copy" -#define SRS_ENCODER_VCODEC "libx264" -#define SRS_ENCODER_ACODEC "libaacplus" +#define SRS_ENCODER_COPY "copy" +#define SRS_ENCODER_VCODEC "libx264" +#define SRS_ENCODER_ACODEC "libaacplus" // for encoder to detect the dead loop static std::vector _transcoded_url; SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin) { - started = false; - pid = -1; - ffmpeg = ffmpeg_bin; - - vbitrate = 0; - vfps = 0; - vwidth = 0; - vheight = 0; - vthreads = 0; - abitrate = 0; - asample_rate = 0; - achannels = 0; - - log_fd = -1; + started = false; + pid = -1; + ffmpeg = ffmpeg_bin; + + vbitrate = 0; + vfps = 0; + vwidth = 0; + vheight = 0; + vthreads = 0; + abitrate = 0; + asample_rate = 0; + achannels = 0; + + log_fd = -1; } SrsFFMPEG::~SrsFFMPEG() { - stop(); + stop(); } int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine) { - int ret = ERROR_SUCCESS; - - _srs_config->get_engine_vfilter(engine, vfilter); - vcodec = _srs_config->get_engine_vcodec(engine); - vbitrate = _srs_config->get_engine_vbitrate(engine); - vfps = _srs_config->get_engine_vfps(engine); - vwidth = _srs_config->get_engine_vwidth(engine); - vheight = _srs_config->get_engine_vheight(engine); - vthreads = _srs_config->get_engine_vthreads(engine); - vprofile = _srs_config->get_engine_vprofile(engine); - vpreset = _srs_config->get_engine_vpreset(engine); - _srs_config->get_engine_vparams(engine, vparams); - acodec = _srs_config->get_engine_acodec(engine); - abitrate = _srs_config->get_engine_abitrate(engine); - asample_rate = _srs_config->get_engine_asample_rate(engine); - achannels = _srs_config->get_engine_achannels(engine); - _srs_config->get_engine_aparams(engine, aparams); - output = _srs_config->get_engine_output(engine); - - // ensure the size is even. - vwidth -= vwidth % 2; - vheight -= vheight % 2; + int ret = ERROR_SUCCESS; + + _srs_config->get_engine_vfilter(engine, vfilter); + vcodec = _srs_config->get_engine_vcodec(engine); + vbitrate = _srs_config->get_engine_vbitrate(engine); + vfps = _srs_config->get_engine_vfps(engine); + vwidth = _srs_config->get_engine_vwidth(engine); + vheight = _srs_config->get_engine_vheight(engine); + vthreads = _srs_config->get_engine_vthreads(engine); + vprofile = _srs_config->get_engine_vprofile(engine); + vpreset = _srs_config->get_engine_vpreset(engine); + _srs_config->get_engine_vparams(engine, vparams); + acodec = _srs_config->get_engine_acodec(engine); + abitrate = _srs_config->get_engine_abitrate(engine); + asample_rate = _srs_config->get_engine_asample_rate(engine); + achannels = _srs_config->get_engine_achannels(engine); + _srs_config->get_engine_aparams(engine, aparams); + output = _srs_config->get_engine_output(engine); + + // ensure the size is even. + vwidth -= vwidth % 2; + vheight -= vheight % 2; - // input stream, from local. - // ie. rtmp://127.0.0.1:1935/live/livestream - input = "rtmp://127.0.0.1:"; - input += req->port; - input += "/"; - input += req->app; - input += "?vhost="; - input += req->vhost; - input += "/"; - input += req->stream; - - // output stream, to other/self server - // ie. rtmp://127.0.0.1:1935/live/livestream_sd - output = srs_replace(output, "[vhost]", req->vhost); - output = srs_replace(output, "[port]", req->port); - output = srs_replace(output, "[app]", req->app); - output = srs_replace(output, "[stream]", req->stream); - output = srs_replace(output, "[engine]", engine->arg0()); - - // write ffmpeg info to log file. - log_file = _srs_config->get_log_dir(); - log_file += "/"; - log_file += "encoder"; - log_file += "-"; - log_file += req->vhost; - log_file += "-"; - log_file += req->app; - log_file += "-"; - log_file += req->stream; - log_file += ".log"; + // input stream, from local. + // ie. rtmp://127.0.0.1:1935/live/livestream + input = "rtmp://127.0.0.1:"; + input += req->port; + input += "/"; + input += req->app; + input += "?vhost="; + input += req->vhost; + input += "/"; + input += req->stream; + + // output stream, to other/self server + // ie. rtmp://127.0.0.1:1935/live/livestream_sd + output = srs_replace(output, "[vhost]", req->vhost); + output = srs_replace(output, "[port]", req->port); + output = srs_replace(output, "[app]", req->app); + output = srs_replace(output, "[stream]", req->stream); + output = srs_replace(output, "[engine]", engine->arg0()); + + // write ffmpeg info to log file. + log_file = _srs_config->get_log_dir(); + log_file += "/"; + log_file += "encoder"; + log_file += "-"; + log_file += req->vhost; + log_file += "-"; + log_file += req->app; + log_file += "-"; + log_file += req->stream; + log_file += ".log"; - // important: loop check, donot transcode again. - std::vector::iterator it; - it = std::find(_transcoded_url.begin(), _transcoded_url.end(), input); - if (it != _transcoded_url.end()) { - ret = ERROR_ENCODER_LOOP; - srs_info("detect a loop cycle, input=%s, output=%s, ignore it. ret=%d", - input.c_str(), output.c_str(), ret); - return ret; - } - _transcoded_url.push_back(output); - - if (vcodec != SRS_ENCODER_COPY) { - if (vcodec != SRS_ENCODER_VCODEC) { - ret = ERROR_ENCODER_VCODEC; - srs_error("invalid vcodec, must be %s, actual %s, ret=%d", - SRS_ENCODER_VCODEC, vcodec.c_str(), ret); - return ret; - } - if (vbitrate <= 0) { - ret = ERROR_ENCODER_VBITRATE; - srs_error("invalid vbitrate: %d, ret=%d", vbitrate, ret); - return ret; - } - if (vfps <= 0) { - ret = ERROR_ENCODER_VFPS; - srs_error("invalid vfps: %.2f, ret=%d", vfps, ret); - return ret; - } - if (vwidth <= 0) { - ret = ERROR_ENCODER_VWIDTH; - srs_error("invalid vwidth: %d, ret=%d", vwidth, ret); - return ret; - } - if (vheight <= 0) { - ret = ERROR_ENCODER_VHEIGHT; - srs_error("invalid vheight: %d, ret=%d", vheight, ret); - return ret; - } - if (vthreads < 0) { - ret = ERROR_ENCODER_VTHREADS; - srs_error("invalid vthreads: %d, ret=%d", vthreads, ret); - return ret; - } - if (vprofile.empty()) { - ret = ERROR_ENCODER_VPROFILE; - srs_error("invalid vprofile: %s, ret=%d", vprofile.c_str(), ret); - return ret; - } - if (vpreset.empty()) { - ret = ERROR_ENCODER_VPRESET; - srs_error("invalid vpreset: %s, ret=%d", vpreset.c_str(), ret); - return ret; - } - } - - if (acodec != SRS_ENCODER_COPY) { - if (acodec != SRS_ENCODER_ACODEC) { - ret = ERROR_ENCODER_ACODEC; - srs_error("invalid acodec, must be %s, actual %s, ret=%d", - SRS_ENCODER_ACODEC, acodec.c_str(), ret); - return ret; - } - if (abitrate <= 0) { - ret = ERROR_ENCODER_ABITRATE; - srs_error("invalid abitrate: %d, ret=%d", - abitrate, ret); - return ret; - } - if (asample_rate <= 0) { - ret = ERROR_ENCODER_ASAMPLE_RATE; - srs_error("invalid sample rate: %d, ret=%d", - asample_rate, ret); - return ret; - } - if (achannels != 1 && achannels != 2) { - ret = ERROR_ENCODER_ACHANNELS; - srs_error("invalid achannels, must be 1 or 2, actual %d, ret=%d", - achannels, ret); - return ret; - } - } - if (output.empty()) { - ret = ERROR_ENCODER_OUTPUT; - srs_error("invalid empty output, ret=%d", ret); - return ret; - } - - return ret; + // important: loop check, donot transcode again. + std::vector::iterator it; + it = std::find(_transcoded_url.begin(), _transcoded_url.end(), input); + if (it != _transcoded_url.end()) { + ret = ERROR_ENCODER_LOOP; + srs_info("detect a loop cycle, input=%s, output=%s, ignore it. ret=%d", + input.c_str(), output.c_str(), ret); + return ret; + } + _transcoded_url.push_back(output); + + if (vcodec != SRS_ENCODER_COPY) { + if (vcodec != SRS_ENCODER_VCODEC) { + ret = ERROR_ENCODER_VCODEC; + srs_error("invalid vcodec, must be %s, actual %s, ret=%d", + SRS_ENCODER_VCODEC, vcodec.c_str(), ret); + return ret; + } + if (vbitrate <= 0) { + ret = ERROR_ENCODER_VBITRATE; + srs_error("invalid vbitrate: %d, ret=%d", vbitrate, ret); + return ret; + } + if (vfps <= 0) { + ret = ERROR_ENCODER_VFPS; + srs_error("invalid vfps: %.2f, ret=%d", vfps, ret); + return ret; + } + if (vwidth <= 0) { + ret = ERROR_ENCODER_VWIDTH; + srs_error("invalid vwidth: %d, ret=%d", vwidth, ret); + return ret; + } + if (vheight <= 0) { + ret = ERROR_ENCODER_VHEIGHT; + srs_error("invalid vheight: %d, ret=%d", vheight, ret); + return ret; + } + if (vthreads < 0) { + ret = ERROR_ENCODER_VTHREADS; + srs_error("invalid vthreads: %d, ret=%d", vthreads, ret); + return ret; + } + if (vprofile.empty()) { + ret = ERROR_ENCODER_VPROFILE; + srs_error("invalid vprofile: %s, ret=%d", vprofile.c_str(), ret); + return ret; + } + if (vpreset.empty()) { + ret = ERROR_ENCODER_VPRESET; + srs_error("invalid vpreset: %s, ret=%d", vpreset.c_str(), ret); + return ret; + } + } + + if (acodec != SRS_ENCODER_COPY) { + if (acodec != SRS_ENCODER_ACODEC) { + ret = ERROR_ENCODER_ACODEC; + srs_error("invalid acodec, must be %s, actual %s, ret=%d", + SRS_ENCODER_ACODEC, acodec.c_str(), ret); + return ret; + } + if (abitrate <= 0) { + ret = ERROR_ENCODER_ABITRATE; + srs_error("invalid abitrate: %d, ret=%d", + abitrate, ret); + return ret; + } + if (asample_rate <= 0) { + ret = ERROR_ENCODER_ASAMPLE_RATE; + srs_error("invalid sample rate: %d, ret=%d", + asample_rate, ret); + return ret; + } + if (achannels != 1 && achannels != 2) { + ret = ERROR_ENCODER_ACHANNELS; + srs_error("invalid achannels, must be 1 or 2, actual %d, ret=%d", + achannels, ret); + return ret; + } + } + if (output.empty()) { + ret = ERROR_ENCODER_OUTPUT; + srs_error("invalid empty output, ret=%d", ret); + return ret; + } + + return ret; } int SrsFFMPEG::start() { - int ret = ERROR_SUCCESS; - - if (started) { - return ret; - } - - // prepare exec params - char tmp[256]; - std::vector params; - - // argv[0], set to ffmpeg bin. - // The execv() and execvp() functions .... - // The first argument, by convention, should point to - // the filename associated with the file being executed. - params.push_back(ffmpeg); - - // input. - params.push_back("-f"); - params.push_back("flv"); - - params.push_back("-i"); - params.push_back(input); - - // build the filter - if (!vfilter.empty()) { - std::vector::iterator it; - for (it = vfilter.begin(); it != vfilter.end(); ++it) { - std::string p = *it; - if (!p.empty()) { - params.push_back(p); - } - } - } - - // video specified. - params.push_back("-vcodec"); - params.push_back(vcodec); - - // the codec params is disabled when copy - if (vcodec != SRS_ENCODER_COPY) { - params.push_back("-b:v"); - snprintf(tmp, sizeof(tmp), "%d", vbitrate * 1000); - params.push_back(tmp); - - params.push_back("-r"); - snprintf(tmp, sizeof(tmp), "%.2f", vfps); - params.push_back(tmp); - - params.push_back("-s"); - snprintf(tmp, sizeof(tmp), "%dx%d", vwidth, vheight); - params.push_back(tmp); - - // TODO: add aspect if needed. - params.push_back("-aspect"); - snprintf(tmp, sizeof(tmp), "%d:%d", vwidth, vheight); - params.push_back(tmp); - - params.push_back("-threads"); - snprintf(tmp, sizeof(tmp), "%d", vthreads); - params.push_back(tmp); - - params.push_back("-profile:v"); - params.push_back(vprofile); - - params.push_back("-preset"); - params.push_back(vpreset); - - // vparams - if (!vparams.empty()) { - std::vector::iterator it; - for (it = vparams.begin(); it != vparams.end(); ++it) { - std::string p = *it; - if (!p.empty()) { - params.push_back(p); - } - } - } - } - - // audio specified. - params.push_back("-acodec"); - params.push_back(acodec); - - // the codec params is disabled when copy - if (acodec != SRS_ENCODER_COPY) { - params.push_back("-b:a"); - snprintf(tmp, sizeof(tmp), "%d", abitrate * 1000); - params.push_back(tmp); - - params.push_back("-ar"); - snprintf(tmp, sizeof(tmp), "%d", asample_rate); - params.push_back(tmp); - - params.push_back("-ac"); - snprintf(tmp, sizeof(tmp), "%d", achannels); - params.push_back(tmp); - - // aparams - if (!aparams.empty()) { - std::vector::iterator it; - for (it = aparams.begin(); it != aparams.end(); ++it) { - std::string p = *it; - if (!p.empty()) { - params.push_back(p); - } - } - } - } + int ret = ERROR_SUCCESS; + + if (started) { + return ret; + } + + // prepare exec params + char tmp[256]; + std::vector params; + + // argv[0], set to ffmpeg bin. + // The execv() and execvp() functions .... + // The first argument, by convention, should point to + // the filename associated with the file being executed. + params.push_back(ffmpeg); + + // input. + params.push_back("-f"); + params.push_back("flv"); + + params.push_back("-i"); + params.push_back(input); + + // build the filter + if (!vfilter.empty()) { + std::vector::iterator it; + for (it = vfilter.begin(); it != vfilter.end(); ++it) { + std::string p = *it; + if (!p.empty()) { + params.push_back(p); + } + } + } + + // video specified. + params.push_back("-vcodec"); + params.push_back(vcodec); + + // the codec params is disabled when copy + if (vcodec != SRS_ENCODER_COPY) { + params.push_back("-b:v"); + snprintf(tmp, sizeof(tmp), "%d", vbitrate * 1000); + params.push_back(tmp); + + params.push_back("-r"); + snprintf(tmp, sizeof(tmp), "%.2f", vfps); + params.push_back(tmp); + + params.push_back("-s"); + snprintf(tmp, sizeof(tmp), "%dx%d", vwidth, vheight); + params.push_back(tmp); + + // TODO: add aspect if needed. + params.push_back("-aspect"); + snprintf(tmp, sizeof(tmp), "%d:%d", vwidth, vheight); + params.push_back(tmp); + + params.push_back("-threads"); + snprintf(tmp, sizeof(tmp), "%d", vthreads); + params.push_back(tmp); + + params.push_back("-profile:v"); + params.push_back(vprofile); + + params.push_back("-preset"); + params.push_back(vpreset); + + // vparams + if (!vparams.empty()) { + std::vector::iterator it; + for (it = vparams.begin(); it != vparams.end(); ++it) { + std::string p = *it; + if (!p.empty()) { + params.push_back(p); + } + } + } + } + + // audio specified. + params.push_back("-acodec"); + params.push_back(acodec); + + // the codec params is disabled when copy + if (acodec != SRS_ENCODER_COPY) { + params.push_back("-b:a"); + snprintf(tmp, sizeof(tmp), "%d", abitrate * 1000); + params.push_back(tmp); + + params.push_back("-ar"); + snprintf(tmp, sizeof(tmp), "%d", asample_rate); + params.push_back(tmp); + + params.push_back("-ac"); + snprintf(tmp, sizeof(tmp), "%d", achannels); + params.push_back(tmp); + + // aparams + if (!aparams.empty()) { + std::vector::iterator it; + for (it = aparams.begin(); it != aparams.end(); ++it) { + std::string p = *it; + if (!p.empty()) { + params.push_back(p); + } + } + } + } - // output - params.push_back("-f"); - params.push_back("flv"); - - params.push_back("-y"); - params.push_back(output); + // output + params.push_back("-f"); + params.push_back("flv"); + + params.push_back("-y"); + params.push_back(output); - if (true) { - int pparam_size = 8 * 1024; - char* pparam = new char[pparam_size]; - char* p = pparam; - char* last = pparam + pparam_size; - for (int i = 0; i < (int)params.size(); i++) { - std::string ffp = params[i]; - snprintf(p, last - p, "%s ", ffp.c_str()); - p += ffp.length() + 1; - } - srs_trace("start transcoder, log: %s, params: %s", - log_file.c_str(), pparam); - srs_freepa(pparam); - } - - // TODO: fork or vfork? - if ((pid = fork()) < 0) { - ret = ERROR_ENCODER_FORK; - srs_error("vfork process failed. ret=%d", ret); - return ret; - } - - // child process: ffmpeg encoder engine. - if (pid == 0) { - // redirect logs to file. - int flags = O_CREAT|O_WRONLY|O_APPEND; - mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; - if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) { - ret = ERROR_ENCODER_OPEN; - srs_error("open encoder file %s failed. ret=%d", log_file.c_str(), ret); - return ret; - } - if (dup2(log_fd, STDOUT_FILENO) < 0) { - ret = ERROR_ENCODER_DUP2; - srs_error("dup2 encoder file failed. ret=%d", ret); - return ret; - } - if (dup2(log_fd, STDERR_FILENO) < 0) { - ret = ERROR_ENCODER_DUP2; - srs_error("dup2 encoder file failed. ret=%d", ret); - return ret; - } - // close other fds - // TODO: do in right way. - for (int i = 3; i < 1024; i++) { - ::close(i); - } - - // memory leak in child process, it's ok. - char** charpv_params = new char*[params.size() + 1]; - for (int i = 0; i < (int)params.size(); i++) { - std::string p = params[i]; - charpv_params[i] = (char*)p.c_str(); - } - // EOF: NULL - charpv_params[params.size()] = NULL; - - // TODO: execv or execvp - ret = execv(ffmpeg.c_str(), charpv_params); - if (ret < 0) { - fprintf(stderr, "fork ffmpeg failed, errno=%d(%s)", - errno, strerror(errno)); - } - exit(ret); - } + if (true) { + int pparam_size = 8 * 1024; + char* pparam = new char[pparam_size]; + char* p = pparam; + char* last = pparam + pparam_size; + for (int i = 0; i < (int)params.size(); i++) { + std::string ffp = params[i]; + snprintf(p, last - p, "%s ", ffp.c_str()); + p += ffp.length() + 1; + } + srs_trace("start transcoder, log: %s, params: %s", + log_file.c_str(), pparam); + srs_freepa(pparam); + } + + // TODO: fork or vfork? + if ((pid = fork()) < 0) { + ret = ERROR_ENCODER_FORK; + srs_error("vfork process failed. ret=%d", ret); + return ret; + } + + // child process: ffmpeg encoder engine. + if (pid == 0) { + // redirect logs to file. + int flags = O_CREAT|O_WRONLY|O_APPEND; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; + if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) { + ret = ERROR_ENCODER_OPEN; + srs_error("open encoder file %s failed. ret=%d", log_file.c_str(), ret); + return ret; + } + if (dup2(log_fd, STDOUT_FILENO) < 0) { + ret = ERROR_ENCODER_DUP2; + srs_error("dup2 encoder file failed. ret=%d", ret); + return ret; + } + if (dup2(log_fd, STDERR_FILENO) < 0) { + ret = ERROR_ENCODER_DUP2; + srs_error("dup2 encoder file failed. ret=%d", ret); + return ret; + } + // close other fds + // TODO: do in right way. + for (int i = 3; i < 1024; i++) { + ::close(i); + } + + // memory leak in child process, it's ok. + char** charpv_params = new char*[params.size() + 1]; + for (int i = 0; i < (int)params.size(); i++) { + std::string p = params[i]; + charpv_params[i] = (char*)p.c_str(); + } + // EOF: NULL + charpv_params[params.size()] = NULL; + + // TODO: execv or execvp + ret = execv(ffmpeg.c_str(), charpv_params); + if (ret < 0) { + fprintf(stderr, "fork ffmpeg failed, errno=%d(%s)", + errno, strerror(errno)); + } + exit(ret); + } - // parent. - if (pid > 0) { - started = true; - srs_trace("vfored ffmpeg encoder engine, pid=%d", pid); - return ret; - } - - return ret; + // parent. + if (pid > 0) { + started = true; + srs_trace("vfored ffmpeg encoder engine, pid=%d", pid); + return ret; + } + + return ret; } int SrsFFMPEG::cycle() { - int ret = ERROR_SUCCESS; - - if (!started) { - return ret; - } - - int status = 0; - pid_t p = waitpid(pid, &status, WNOHANG); - - if (p < 0) { - ret = ERROR_SYSTEM_WAITPID; - srs_error("transcode waitpid failed, pid=%d, ret=%d", pid, ret); - return ret; - } - - if (p == 0) { - srs_info("transcode process pid=%d is running.", pid); - return ret; - } - - srs_trace("transcode process pid=%d terminate, restart it.", pid); - started = false; - - return ret; + int ret = ERROR_SUCCESS; + + if (!started) { + return ret; + } + + int status = 0; + pid_t p = waitpid(pid, &status, WNOHANG); + + if (p < 0) { + ret = ERROR_SYSTEM_WAITPID; + srs_error("transcode waitpid failed, pid=%d, ret=%d", pid, ret); + return ret; + } + + if (p == 0) { + srs_info("transcode process pid=%d is running.", pid); + return ret; + } + + srs_trace("transcode process pid=%d terminate, restart it.", pid); + started = false; + + return ret; } void SrsFFMPEG::stop() { - if (log_fd > 0) { - ::close(log_fd); - log_fd = -1; - } - - if (!started) { - return; - } - - // kill the ffmpeg, - // when rewind, upstream will stop publish(unpublish), - // unpublish event will stop all ffmpeg encoders, - // then publish will start all ffmpeg encoders. - if (pid > 0) { - if (kill(pid, SIGKILL) < 0) { - srs_warn("kill the encoder failed, ignored. pid=%d", pid); - } - - // wait for the ffmpeg to quit. - // ffmpeg will gracefully quit if signal is: - // 1) SIGHUP 2) SIGINT 3) SIGQUIT - // other signals, directly exit(123), for example: - // 9) SIGKILL 15) SIGTERM - int status = 0; - if (waitpid(pid, &status, 0) < 0) { - srs_warn("wait the encoder quit failed, ignored. pid=%d", pid); - } - - srs_trace("stop the encoder success. pid=%d", pid); - pid = -1; - } - - std::vector::iterator it; - it = std::find(_transcoded_url.begin(), _transcoded_url.end(), output); - if (it != _transcoded_url.end()) { - _transcoded_url.erase(it); - } + if (log_fd > 0) { + ::close(log_fd); + log_fd = -1; + } + + if (!started) { + return; + } + + // kill the ffmpeg, + // when rewind, upstream will stop publish(unpublish), + // unpublish event will stop all ffmpeg encoders, + // then publish will start all ffmpeg encoders. + if (pid > 0) { + if (kill(pid, SIGKILL) < 0) { + srs_warn("kill the encoder failed, ignored. pid=%d", pid); + } + + // wait for the ffmpeg to quit. + // ffmpeg will gracefully quit if signal is: + // 1) SIGHUP 2) SIGINT 3) SIGQUIT + // other signals, directly exit(123), for example: + // 9) SIGKILL 15) SIGTERM + int status = 0; + if (waitpid(pid, &status, 0) < 0) { + srs_warn("wait the encoder quit failed, ignored. pid=%d", pid); + } + + srs_trace("stop the encoder success. pid=%d", pid); + pid = -1; + } + + std::vector::iterator it; + it = std::find(_transcoded_url.begin(), _transcoded_url.end(), output); + if (it != _transcoded_url.end()) { + _transcoded_url.erase(it); + } } SrsEncoder::SrsEncoder() { - pthread = new SrsThread(this, SRS_ENCODER_SLEEP_US); - pithy_print = new SrsPithyPrint(SRS_STAGE_ENCODER); + pthread = new SrsThread(this, SRS_ENCODER_SLEEP_US); + pithy_print = new SrsPithyPrint(SRS_STAGE_ENCODER); } SrsEncoder::~SrsEncoder() { - on_unpublish(); - - srs_freep(pthread); + on_unpublish(); + + srs_freep(pthread); } int SrsEncoder::on_publish(SrsRequest* req) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - ret = parse_scope_engines(req); - - // ignore the loop encoder - if (ret == ERROR_ENCODER_LOOP) { - clear_engines(); - ret = ERROR_SUCCESS; - } - - // return for error or no engine. - if (ret != ERROR_SUCCESS || ffmpegs.empty()) { - return ret; - } + ret = parse_scope_engines(req); + + // ignore the loop encoder + if (ret == ERROR_ENCODER_LOOP) { + clear_engines(); + ret = ERROR_SUCCESS; + } + + // return for error or no engine. + if (ret != ERROR_SUCCESS || ffmpegs.empty()) { + return ret; + } // start thread to run all encoding engines. if ((ret = pthread->start()) != ERROR_SUCCESS) { @@ -516,177 +516,177 @@ int SrsEncoder::on_publish(SrsRequest* req) return ret; } - return ret; + return ret; } void SrsEncoder::on_unpublish() { - pthread->stop(); - clear_engines(); + pthread->stop(); + clear_engines(); } int SrsEncoder::cycle() { - int ret = ERROR_SUCCESS; - - std::vector::iterator it; - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { - SrsFFMPEG* ffmpeg = *it; - - // start all ffmpegs. - if ((ret = ffmpeg->start()) != ERROR_SUCCESS) { - srs_error("ffmpeg start failed. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + std::vector::iterator it; + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { + SrsFFMPEG* ffmpeg = *it; + + // start all ffmpegs. + if ((ret = ffmpeg->start()) != ERROR_SUCCESS) { + srs_error("ffmpeg start failed. ret=%d", ret); + return ret; + } - // check ffmpeg status. - if ((ret = ffmpeg->cycle()) != ERROR_SUCCESS) { - srs_error("ffmpeg cycle failed. ret=%d", ret); - return ret; - } - } + // check ffmpeg status. + if ((ret = ffmpeg->cycle()) != ERROR_SUCCESS) { + srs_error("ffmpeg cycle failed. ret=%d", ret); + return ret; + } + } - // pithy print - encoder(); - pithy_print->elapse(SRS_ENCODER_SLEEP_US / 1000); - - return ret; + // pithy print + encoder(); + pithy_print->elapse(SRS_ENCODER_SLEEP_US / 1000); + + return ret; } void SrsEncoder::on_leave_loop() { - // kill ffmpeg when finished and it alive - std::vector::iterator it; + // kill ffmpeg when finished and it alive + std::vector::iterator it; - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { - SrsFFMPEG* ffmpeg = *it; - ffmpeg->stop(); - } + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { + SrsFFMPEG* ffmpeg = *it; + ffmpeg->stop(); + } } void SrsEncoder::clear_engines() { - std::vector::iterator it; - - for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { - SrsFFMPEG* ffmpeg = *it; - srs_freep(ffmpeg); - } + std::vector::iterator it; + + for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { + SrsFFMPEG* ffmpeg = *it; + srs_freep(ffmpeg); + } - ffmpegs.clear(); + ffmpegs.clear(); } SrsFFMPEG* SrsEncoder::at(int index) { - return ffmpegs[index]; + return ffmpegs[index]; } int SrsEncoder::parse_scope_engines(SrsRequest* req) { - int ret = ERROR_SUCCESS; - - // parse all transcode engines. - SrsConfDirective* conf = NULL; - - // parse vhost scope engines - std::string scope = ""; - if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { - srs_error("parse vhost scope=%s transcode engines failed. " - "ret=%d", scope.c_str(), ret); - return ret; - } - } - // parse app scope engines - scope = req->app; - if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { - srs_error("parse app scope=%s transcode engines failed. " - "ret=%d", scope.c_str(), ret); - return ret; - } - } - // parse stream scope engines - scope += "/"; - scope += req->stream; - if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { - if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { - srs_error("parse stream scope=%s transcode engines failed. " - "ret=%d", scope.c_str(), ret); - return ret; - } - } - - return ret; + int ret = ERROR_SUCCESS; + + // parse all transcode engines. + SrsConfDirective* conf = NULL; + + // parse vhost scope engines + std::string scope = ""; + if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { + srs_error("parse vhost scope=%s transcode engines failed. " + "ret=%d", scope.c_str(), ret); + return ret; + } + } + // parse app scope engines + scope = req->app; + if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { + srs_error("parse app scope=%s transcode engines failed. " + "ret=%d", scope.c_str(), ret); + return ret; + } + } + // parse stream scope engines + scope += "/"; + scope += req->stream; + if ((conf = _srs_config->get_transcode(req->vhost, scope)) != NULL) { + if ((ret = parse_transcode(req, conf)) != ERROR_SUCCESS) { + srs_error("parse stream scope=%s transcode engines failed. " + "ret=%d", scope.c_str(), ret); + return ret; + } + } + + return ret; } int SrsEncoder::parse_transcode(SrsRequest* req, SrsConfDirective* conf) { - int ret = ERROR_SUCCESS; - - srs_assert(conf); - - // enabled - if (!_srs_config->get_transcode_enabled(conf)) { - srs_trace("ignore the disabled transcode: %s", - conf->arg0().c_str()); - return ret; - } - - // ffmpeg - std::string ffmpeg_bin = _srs_config->get_transcode_ffmpeg(conf); - if (ffmpeg_bin.empty()) { - srs_trace("ignore the empty ffmpeg transcode: %s", - conf->arg0().c_str()); - return ret; - } - - // get all engines. - std::vector engines; - _srs_config->get_transcode_engines(conf, engines); - if (engines.empty()) { - srs_trace("ignore the empty transcode engine: %s", - conf->arg0().c_str()); - return ret; - } - - // create engine - for (int i = 0; i < (int)engines.size(); i++) { - SrsConfDirective* engine = engines[i]; - if (!_srs_config->get_engine_enabled(engine)) { - srs_trace("ignore the diabled transcode engine: %s %s", - conf->arg0().c_str(), engine->arg0().c_str()); - continue; - } - - SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); - - if ((ret = ffmpeg->initialize(req, engine)) != ERROR_SUCCESS) { - srs_freep(ffmpeg); - - // if got a loop, donot transcode the whole stream. - if (ret == ERROR_ENCODER_LOOP) { - break; - } - - srs_error("invalid transcode engine: %s %s", - conf->arg0().c_str(), engine->arg0().c_str()); - return ret; - } + int ret = ERROR_SUCCESS; + + srs_assert(conf); + + // enabled + if (!_srs_config->get_transcode_enabled(conf)) { + srs_trace("ignore the disabled transcode: %s", + conf->arg0().c_str()); + return ret; + } + + // ffmpeg + std::string ffmpeg_bin = _srs_config->get_transcode_ffmpeg(conf); + if (ffmpeg_bin.empty()) { + srs_trace("ignore the empty ffmpeg transcode: %s", + conf->arg0().c_str()); + return ret; + } + + // get all engines. + std::vector engines; + _srs_config->get_transcode_engines(conf, engines); + if (engines.empty()) { + srs_trace("ignore the empty transcode engine: %s", + conf->arg0().c_str()); + return ret; + } + + // create engine + for (int i = 0; i < (int)engines.size(); i++) { + SrsConfDirective* engine = engines[i]; + if (!_srs_config->get_engine_enabled(engine)) { + srs_trace("ignore the diabled transcode engine: %s %s", + conf->arg0().c_str(), engine->arg0().c_str()); + continue; + } + + SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); + + if ((ret = ffmpeg->initialize(req, engine)) != ERROR_SUCCESS) { + srs_freep(ffmpeg); + + // if got a loop, donot transcode the whole stream. + if (ret == ERROR_ENCODER_LOOP) { + break; + } + + srs_error("invalid transcode engine: %s %s", + conf->arg0().c_str(), engine->arg0().c_str()); + return ret; + } - ffmpegs.push_back(ffmpeg); - } - - return ret; + ffmpegs.push_back(ffmpeg); + } + + return ret; } void SrsEncoder::encoder() { - // reportable - if (pithy_print->can_print()) { - // TODO: FIXME: show more info. - srs_trace("-> time=%"PRId64", encoders=%d", pithy_print->get_age(), (int)ffmpegs.size()); - } + // reportable + if (pithy_print->can_print()) { + // TODO: FIXME: show more info. + srs_trace("-> time=%"PRId64", encoders=%d", pithy_print->get_age(), (int)ffmpegs.size()); + } } #endif diff --git a/trunk/src/app/srs_app_encoder.hpp b/trunk/src/app/srs_app_encoder.hpp index 6d8f028f7..27cdbfc0c 100644 --- a/trunk/src/app/srs_app_encoder.hpp +++ b/trunk/src/app/srs_app_encoder.hpp @@ -47,38 +47,38 @@ class SrsPithyPrint; class SrsFFMPEG { private: - bool started; - pid_t pid; + bool started; + pid_t pid; private: - std::string log_file; - int log_fd; + std::string log_file; + int log_fd; private: - std::string ffmpeg; - std::vector vfilter; - std::string vcodec; - int vbitrate; - double vfps; - int vwidth; - int vheight; - int vthreads; - std::string vprofile; - std::string vpreset; - std::vector vparams; - std::string acodec; - int abitrate; - int asample_rate; - int achannels; - std::vector aparams; - std::string output; - std::string input; + std::string ffmpeg; + std::vector vfilter; + std::string vcodec; + int vbitrate; + double vfps; + int vwidth; + int vheight; + int vthreads; + std::string vprofile; + std::string vpreset; + std::vector vparams; + std::string acodec; + int abitrate; + int asample_rate; + int achannels; + std::vector aparams; + std::string output; + std::string input; public: - SrsFFMPEG(std::string ffmpeg_bin); - virtual ~SrsFFMPEG(); + SrsFFMPEG(std::string ffmpeg_bin); + virtual ~SrsFFMPEG(); public: - virtual int initialize(SrsRequest* req, SrsConfDirective* engine); - virtual int start(); - virtual int cycle(); - virtual void stop(); + virtual int initialize(SrsRequest* req, SrsConfDirective* engine); + virtual int start(); + virtual int cycle(); + virtual void stop(); }; /** @@ -88,26 +88,26 @@ public: class SrsEncoder : public ISrsThreadHandler { private: - std::vector ffmpegs; + std::vector ffmpegs; private: - SrsThread* pthread; - SrsPithyPrint* pithy_print; + SrsThread* pthread; + SrsPithyPrint* pithy_print; public: - SrsEncoder(); - virtual ~SrsEncoder(); + SrsEncoder(); + virtual ~SrsEncoder(); public: - virtual int on_publish(SrsRequest* req); - virtual void on_unpublish(); + virtual int on_publish(SrsRequest* req); + virtual void on_unpublish(); // interface ISrsThreadHandler. public: - virtual int cycle(); - virtual void on_leave_loop(); + virtual int cycle(); + virtual void on_leave_loop(); private: - virtual void clear_engines(); - virtual SrsFFMPEG* at(int index); - virtual int parse_scope_engines(SrsRequest* req); - virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); - virtual void encoder(); + virtual void clear_engines(); + virtual SrsFFMPEG* at(int index); + virtual int parse_scope_engines(SrsRequest* req); + virtual int parse_transcode(SrsRequest* req, SrsConfDirective* conf); + virtual void encoder(); }; #endif diff --git a/trunk/src/app/srs_app_forward.cpp b/trunk/src/app/srs_app_forward.cpp index e5e827489..6989ac962 100644 --- a/trunk/src/app/srs_app_forward.cpp +++ b/trunk/src/app/srs_app_forward.cpp @@ -42,203 +42,203 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsForwarder::SrsForwarder(SrsSource* _source) { - source = _source; - - io = NULL; - client = NULL; - stfd = NULL; - stream_id = 0; + source = _source; + + io = NULL; + client = NULL; + stfd = NULL; + stream_id = 0; - pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US); - queue = new SrsMessageQueue(); - jitter = new SrsRtmpJitter(); + pthread = new SrsThread(this, SRS_FORWARDER_SLEEP_US); + queue = new SrsMessageQueue(); + jitter = new SrsRtmpJitter(); } SrsForwarder::~SrsForwarder() { - on_unpublish(); - - srs_freep(pthread); - srs_freep(queue); - srs_freep(jitter); + on_unpublish(); + + srs_freep(pthread); + srs_freep(queue); + srs_freep(jitter); } void SrsForwarder::set_queue_size(double queue_size) { - queue->set_queue_size(queue_size); + queue->set_queue_size(queue_size); } int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) { - int ret = ERROR_SUCCESS; - - // forward app - app = req->app; - - stream_name = req->stream; - server = forward_server; - std::string s_port = RTMP_DEFAULT_PORT; - port = ::atoi(RTMP_DEFAULT_PORT); - - size_t pos = forward_server.find(":"); - if (pos != std::string::npos) { - s_port = forward_server.substr(pos + 1); - server = forward_server.substr(0, pos); - } - // discovery vhost - std::string vhost = req->vhost; - srs_vhost_resolve(vhost, s_port); - port = ::atoi(s_port.c_str()); - - // generate tcUrl - tc_url = "rtmp://"; - tc_url += vhost; - tc_url += "/"; - tc_url += req->app; - - // dead loop check - std::string source_ep = req->vhost; - source_ep += ":"; - source_ep += req->port; - - std::string dest_ep = vhost; - dest_ep += ":"; - dest_ep += s_port; - - if (source_ep == dest_ep) { - ret = ERROR_SYSTEM_FORWARD_LOOP; - srs_warn("farder loop detected. src=%s, dest=%s, ret=%d", - source_ep.c_str(), dest_ep.c_str(), ret); - return ret; - } - srs_trace("start forward %s to %s, stream: %s/%s", - source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), - stream_name.c_str()); - - if ((ret = pthread->start()) != ERROR_SUCCESS) { + int ret = ERROR_SUCCESS; + + // forward app + app = req->app; + + stream_name = req->stream; + server = forward_server; + std::string s_port = RTMP_DEFAULT_PORT; + port = ::atoi(RTMP_DEFAULT_PORT); + + size_t pos = forward_server.find(":"); + if (pos != std::string::npos) { + s_port = forward_server.substr(pos + 1); + server = forward_server.substr(0, pos); + } + // discovery vhost + std::string vhost = req->vhost; + srs_vhost_resolve(vhost, s_port); + port = ::atoi(s_port.c_str()); + + // generate tcUrl + tc_url = "rtmp://"; + tc_url += vhost; + tc_url += "/"; + tc_url += req->app; + + // dead loop check + std::string source_ep = req->vhost; + source_ep += ":"; + source_ep += req->port; + + std::string dest_ep = vhost; + dest_ep += ":"; + dest_ep += s_port; + + if (source_ep == dest_ep) { + ret = ERROR_SYSTEM_FORWARD_LOOP; + srs_warn("farder loop detected. src=%s, dest=%s, ret=%d", + source_ep.c_str(), dest_ep.c_str(), ret); + return ret; + } + srs_trace("start forward %s to %s, stream: %s/%s", + source_ep.c_str(), dest_ep.c_str(), tc_url.c_str(), + stream_name.c_str()); + + if ((ret = pthread->start()) != ERROR_SUCCESS) { srs_error("start srs thread failed. ret=%d", ret); return ret; - } - - return ret; + } + + return ret; } void SrsForwarder::on_unpublish() { - pthread->stop(); - - close_underlayer_socket(); - - srs_freep(client); - srs_freep(io); + pthread->stop(); + + close_underlayer_socket(); + + srs_freep(client); + srs_freep(io); } int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata) { - int ret = ERROR_SUCCESS; - - if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) { - srs_freep(metadata); - return ret; - } - - if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = jitter->correct(metadata, 0, 0)) != ERROR_SUCCESS) { + srs_freep(metadata); + return ret; + } + + if ((ret = queue->enqueue(metadata)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsForwarder::on_audio(SrsSharedPtrMessage* msg) { - int ret = ERROR_SUCCESS; - - if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { - srs_freep(msg); - return ret; - } - - if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { + srs_freep(msg); + return ret; + } + + if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsForwarder::on_video(SrsSharedPtrMessage* msg) { - int ret = ERROR_SUCCESS; - - if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { - srs_freep(msg); - return ret; - } - - if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = jitter->correct(msg, 0, 0)) != ERROR_SUCCESS) { + srs_freep(msg); + return ret; + } + + if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsForwarder::cycle() { - int ret = ERROR_SUCCESS; - - if ((ret = connect_server()) != ERROR_SUCCESS) { - return ret; - } - srs_assert(client); + int ret = ERROR_SUCCESS; + + if ((ret = connect_server()) != ERROR_SUCCESS) { + return ret; + } + srs_assert(client); - client->set_recv_timeout(SRS_RECV_TIMEOUT_US); - client->set_send_timeout(SRS_SEND_TIMEOUT_US); - - if ((ret = client->handshake()) != ERROR_SUCCESS) { - srs_error("handshake with server failed. ret=%d", ret); - return ret; - } - if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { - srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); - return ret; - } - if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { - srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); - return ret; - } - - if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { - srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", - stream_name.c_str(), stream_id, ret); - return ret; - } - - if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) { - srs_error("callback the source to feed the sequence header failed. ret=%d", ret); - return ret; - } - - if ((ret = forward()) != ERROR_SUCCESS) { - return ret; - } - - return ret; + client->set_recv_timeout(SRS_RECV_TIMEOUT_US); + client->set_send_timeout(SRS_SEND_TIMEOUT_US); + + if ((ret = client->handshake()) != ERROR_SUCCESS) { + srs_error("handshake with server failed. ret=%d", ret); + return ret; + } + if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) { + srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret); + return ret; + } + if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) { + srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret); + return ret; + } + + if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) { + srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d", + stream_name.c_str(), stream_id, ret); + return ret; + } + + if ((ret = source->on_forwarder_start(this)) != ERROR_SUCCESS) { + srs_error("callback the source to feed the sequence header failed. ret=%d", ret); + return ret; + } + + if ((ret = forward()) != ERROR_SUCCESS) { + return ret; + } + + return ret; } void SrsForwarder::close_underlayer_socket() { - srs_close_stfd(stfd); + srs_close_stfd(stfd); } int SrsForwarder::connect_server() { - int ret = ERROR_SUCCESS; - - // reopen - close_underlayer_socket(); - - // open socket. - srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", - stream_name.c_str(), tc_url.c_str(), server.c_str(), port); + int ret = ERROR_SUCCESS; + + // reopen + close_underlayer_socket(); + + // open socket. + srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d", + stream_name.c_str(), tc_url.c_str(), server.c_str(), port); int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1){ @@ -255,20 +255,20 @@ int SrsForwarder::connect_server() return ret; } - srs_freep(client); - srs_freep(io); - - io = new SrsSocket(stfd); - client = new SrsRtmpClient(io); - - // connect to server. - std::string ip = srs_dns_resolve(server); - if (ip.empty()) { - ret = ERROR_SYSTEM_IP_INVALID; - srs_error("dns resolve server error, ip empty. ret=%d", ret); - return ret; - } - + srs_freep(client); + srs_freep(io); + + io = new SrsSocket(stfd); + client = new SrsRtmpClient(io); + + // connect to server. + std::string ip = srs_dns_resolve(server); + if (ip.empty()) { + ret = ERROR_SYSTEM_IP_INVALID; + srs_error("dns resolve server error, ip empty. ret=%d", ret); + return ret; + } + sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); @@ -281,69 +281,69 @@ int SrsForwarder::connect_server() } srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port); - return ret; + return ret; } int SrsForwarder::forward() { - int ret = ERROR_SUCCESS; - - client->set_recv_timeout(SRS_PULSE_TIMEOUT_US); - - SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); + int ret = ERROR_SUCCESS; + + client->set_recv_timeout(SRS_PULSE_TIMEOUT_US); + + SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); - while (pthread->can_loop()) { - // switch to other st-threads. - st_usleep(0); + while (pthread->can_loop()) { + // switch to other st-threads. + st_usleep(0); - // read from client. - if (true) { - SrsCommonMessage* msg = NULL; - ret = client->recv_message(&msg); - - srs_verbose("play loop recv message. ret=%d", ret); - if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { - srs_error("recv server control message failed. ret=%d", ret); - return ret; - } - } - - // forward all messages. - int count = 0; - SrsSharedPtrMessage** msgs = NULL; - if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) { - srs_error("get message to forward failed. ret=%d", ret); - return ret; - } - - // ignore when no messages. - if (count <= 0) { - srs_verbose("no packets to forward."); - continue; - } - SrsAutoFree(SrsSharedPtrMessage*, msgs, true); + // read from client. + if (true) { + SrsCommonMessage* msg = NULL; + ret = client->recv_message(&msg); + + srs_verbose("play loop recv message. ret=%d", ret); + if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { + srs_error("recv server control message failed. ret=%d", ret); + return ret; + } + } + + // forward all messages. + int count = 0; + SrsSharedPtrMessage** msgs = NULL; + if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) { + srs_error("get message to forward failed. ret=%d", ret); + return ret; + } + + // ignore when no messages. + if (count <= 0) { + srs_verbose("no packets to forward."); + continue; + } + SrsAutoFree(SrsSharedPtrMessage*, msgs, true); - // pithy print - pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); - if (pithy_print.can_print()) { - srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", - pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); - } - - // all msgs to forward. - for (int i = 0; i < count; i++) { - SrsSharedPtrMessage* msg = msgs[i]; - - srs_assert(msg); - msgs[i] = NULL; - - if ((ret = client->send_message(msg)) != ERROR_SUCCESS) { - srs_error("forwarder send message to server failed. ret=%d", ret); - return ret; - } - } - } - - return ret; + // pithy print + pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); + if (pithy_print.can_print()) { + srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", + pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); + } + + // all msgs to forward. + for (int i = 0; i < count; i++) { + SrsSharedPtrMessage* msg = msgs[i]; + + srs_assert(msg); + msgs[i] = NULL; + + if ((ret = client->send_message(msg)) != ERROR_SUCCESS) { + srs_error("forwarder send message to server failed. ret=%d", ret); + return ret; + } + } + } + + return ret; } diff --git a/trunk/src/app/srs_app_forward.hpp b/trunk/src/app/srs_app_forward.hpp index 7e93ff7dc..6907022cd 100644 --- a/trunk/src/app/srs_app_forward.hpp +++ b/trunk/src/app/srs_app_forward.hpp @@ -49,39 +49,39 @@ class SrsSource; class SrsForwarder : public ISrsThreadHandler { private: - std::string app; - std::string tc_url; - std::string stream_name; - int stream_id; - std::string server; - int port; + std::string app; + std::string tc_url; + std::string stream_name; + int stream_id; + std::string server; + int port; private: - st_netfd_t stfd; - SrsThread* pthread; + st_netfd_t stfd; + SrsThread* pthread; private: - SrsSource* source; - ISrsProtocolReaderWriter* io; - SrsRtmpClient* client; - SrsRtmpJitter* jitter; - SrsMessageQueue* queue; + SrsSource* source; + ISrsProtocolReaderWriter* io; + SrsRtmpClient* client; + SrsRtmpJitter* jitter; + SrsMessageQueue* queue; public: - SrsForwarder(SrsSource* _source); - virtual ~SrsForwarder(); + SrsForwarder(SrsSource* _source); + virtual ~SrsForwarder(); public: - virtual void set_queue_size(double queue_size); + virtual void set_queue_size(double queue_size); public: - virtual int on_publish(SrsRequest* req, std::string forward_server); - virtual void on_unpublish(); - virtual int on_meta_data(SrsSharedPtrMessage* metadata); - virtual int on_audio(SrsSharedPtrMessage* msg); - virtual int on_video(SrsSharedPtrMessage* msg); + virtual int on_publish(SrsRequest* req, std::string forward_server); + virtual void on_unpublish(); + virtual int on_meta_data(SrsSharedPtrMessage* metadata); + virtual int on_audio(SrsSharedPtrMessage* msg); + virtual int on_video(SrsSharedPtrMessage* msg); // interface ISrsThreadHandler. public: - virtual int cycle(); + virtual int cycle(); private: - virtual void close_underlayer_socket(); - virtual int connect_server(); - virtual int forward(); + virtual void close_underlayer_socket(); + virtual int connect_server(); + virtual int forward(); }; #endif diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index a0fda8ee1..eaf9e1bfb 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -123,12 +123,12 @@ u_int8_t mpegts_header[] = { // @see: ngx_rtmp_SrsMpegtsFrame_t struct SrsMpegtsFrame { - int64_t pts; - int64_t dts; - int pid; - int sid; - int cc; - bool key; + int64_t pts; + int64_t dts; + int pid; + int sid; + int cc; + bool key; SrsMpegtsFrame() { @@ -143,214 +143,214 @@ struct SrsMpegtsFrame class SrsMpegtsWriter { public: - static int write_header(int fd) - { - int ret = ERROR_SUCCESS; - - if (::write(fd, mpegts_header, sizeof(mpegts_header)) != sizeof(mpegts_header)) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write ts file header failed. ret=%d", ret); - return ret; - } + static int write_header(int fd) + { + int ret = ERROR_SUCCESS; + + if (::write(fd, mpegts_header, sizeof(mpegts_header)) != sizeof(mpegts_header)) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write ts file header failed. ret=%d", ret); + return ret; + } - return ret; - } - static int write_frame(int fd, SrsMpegtsFrame* frame, SrsCodecBuffer* buffer) - { - int ret = ERROR_SUCCESS; - - if (!buffer->bytes || buffer->size <= 0) { - return ret; - } - - char* last = buffer->bytes + buffer->size; - char* pos = buffer->bytes; - - bool first = true; - while (pos < last) { - static char packet[188]; - char* p = packet; - - frame->cc++; - - // sync_byte; //8bits - *p++ = 0x47; - // pid; //13bits - *p++ = (frame->pid >> 8) & 0x1f; - // payload_unit_start_indicator; //1bit - if (first) { - p[-1] |= 0x40; - } - *p++ = frame->pid; - - // transport_scrambling_control; //2bits - // adaption_field_control; //2bits, 0x01: PayloadOnly - // continuity_counter; //4bits - *p++ = 0x10 | (frame->cc & 0x0f); - - if (first) { - first = false; - if (frame->key) { - p[-1] |= 0x20; // Both Adaption and Payload - *p++ = 7; // size - *p++ = 0x50; // random access + PCR - p = write_pcr(p, frame->dts - SRS_HLS_DELAY); - } - - // PES header - // packet_start_code_prefix; //24bits, '00 00 01' - *p++ = 0x00; - *p++ = 0x00; - *p++ = 0x01; - //8bits - *p++ = frame->sid; - - // pts(33bits) need 5bytes. - u_int8_t header_size = 5; - u_int8_t flags = 0x80; // pts - - // dts(33bits) need 5bytes also - if (frame->dts != frame->pts) { - header_size += 5; - flags |= 0x40; // dts - } - - // 3bytes: flag fields from PES_packet_length to PES_header_data_length - int pes_size = (last - pos) + header_size + 3; - if (pes_size > 0xffff) { - /** - * when actual packet length > 0xffff(65535), - * which exceed the max u_int16_t packet length, - * use 0 packet length, the next unit start indicates the end of packet. - */ - pes_size = 0; - } - - // PES_packet_length; //16bits - *p++ = (pes_size >> 8); - *p++ = pes_size; - - // PES_scrambling_control; //2bits, '10' - // PES_priority; //1bit - // data_alignment_indicator; //1bit - // copyright; //1bit - // original_or_copy; //1bit - *p++ = 0x80; /* H222 */ - - // PTS_DTS_flags; //2bits - // ESCR_flag; //1bit - // ES_rate_flag; //1bit - // DSM_trick_mode_flag; //1bit - // additional_copy_info_flag; //1bit - // PES_CRC_flag; //1bit - // PES_extension_flag; //1bit - *p++ = flags; - - // PES_header_data_length; //8bits - *p++ = header_size; + return ret; + } + static int write_frame(int fd, SrsMpegtsFrame* frame, SrsCodecBuffer* buffer) + { + int ret = ERROR_SUCCESS; + + if (!buffer->bytes || buffer->size <= 0) { + return ret; + } + + char* last = buffer->bytes + buffer->size; + char* pos = buffer->bytes; + + bool first = true; + while (pos < last) { + static char packet[188]; + char* p = packet; + + frame->cc++; + + // sync_byte; //8bits + *p++ = 0x47; + // pid; //13bits + *p++ = (frame->pid >> 8) & 0x1f; + // payload_unit_start_indicator; //1bit + if (first) { + p[-1] |= 0x40; + } + *p++ = frame->pid; + + // transport_scrambling_control; //2bits + // adaption_field_control; //2bits, 0x01: PayloadOnly + // continuity_counter; //4bits + *p++ = 0x10 | (frame->cc & 0x0f); + + if (first) { + first = false; + if (frame->key) { + p[-1] |= 0x20; // Both Adaption and Payload + *p++ = 7; // size + *p++ = 0x50; // random access + PCR + p = write_pcr(p, frame->dts - SRS_HLS_DELAY); + } + + // PES header + // packet_start_code_prefix; //24bits, '00 00 01' + *p++ = 0x00; + *p++ = 0x00; + *p++ = 0x01; + //8bits + *p++ = frame->sid; + + // pts(33bits) need 5bytes. + u_int8_t header_size = 5; + u_int8_t flags = 0x80; // pts + + // dts(33bits) need 5bytes also + if (frame->dts != frame->pts) { + header_size += 5; + flags |= 0x40; // dts + } + + // 3bytes: flag fields from PES_packet_length to PES_header_data_length + int pes_size = (last - pos) + header_size + 3; + if (pes_size > 0xffff) { + /** + * when actual packet length > 0xffff(65535), + * which exceed the max u_int16_t packet length, + * use 0 packet length, the next unit start indicates the end of packet. + */ + pes_size = 0; + } + + // PES_packet_length; //16bits + *p++ = (pes_size >> 8); + *p++ = pes_size; + + // PES_scrambling_control; //2bits, '10' + // PES_priority; //1bit + // data_alignment_indicator; //1bit + // copyright; //1bit + // original_or_copy; //1bit + *p++ = 0x80; /* H222 */ + + // PTS_DTS_flags; //2bits + // ESCR_flag; //1bit + // ES_rate_flag; //1bit + // DSM_trick_mode_flag; //1bit + // additional_copy_info_flag; //1bit + // PES_CRC_flag; //1bit + // PES_extension_flag; //1bit + *p++ = flags; + + // PES_header_data_length; //8bits + *p++ = header_size; - // pts; // 33bits - p = write_pts(p, flags >> 6, frame->pts + SRS_HLS_DELAY); - - // dts; // 33bits - if (frame->dts != frame->pts) { - p = write_pts(p, 1, frame->dts + SRS_HLS_DELAY); - } - } - - int body_size = sizeof(packet) - (p - packet); - int in_size = last - pos; - - if (body_size <= in_size) { - memcpy(p, pos, body_size); - pos += body_size; - } else { - p = fill_stuff(p, packet, body_size, in_size); - memcpy(p, pos, in_size); - pos = last; - } - - // write ts packet - if (::write(fd, packet, sizeof(packet)) != sizeof(packet)) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write ts file failed. ret=%d", ret); - return ret; - } - } - - return ret; - } + // pts; // 33bits + p = write_pts(p, flags >> 6, frame->pts + SRS_HLS_DELAY); + + // dts; // 33bits + if (frame->dts != frame->pts) { + p = write_pts(p, 1, frame->dts + SRS_HLS_DELAY); + } + } + + int body_size = sizeof(packet) - (p - packet); + int in_size = last - pos; + + if (body_size <= in_size) { + memcpy(p, pos, body_size); + pos += body_size; + } else { + p = fill_stuff(p, packet, body_size, in_size); + memcpy(p, pos, in_size); + pos = last; + } + + // write ts packet + if (::write(fd, packet, sizeof(packet)) != sizeof(packet)) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write ts file failed. ret=%d", ret); + return ret; + } + } + + return ret; + } private: - static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size) - { - char* p = pes_body_end; - - // insert the stuff bytes before PES body - int stuff_size = (body_size - in_size); - - // adaption_field_control; //2bits - if (packet[3] & 0x20) { - // has adaptation - // packet[4]: adaption_field_length - // packet[5]: adaption field data - // base: start of PES body - char* base = &packet[5] + packet[4]; - int len = p - base; - p = (char*)memmove(base + stuff_size, base, len) + len; - // increase the adaption field size. - packet[4] += stuff_size; - - return p; - } + static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size) + { + char* p = pes_body_end; + + // insert the stuff bytes before PES body + int stuff_size = (body_size - in_size); + + // adaption_field_control; //2bits + if (packet[3] & 0x20) { + // has adaptation + // packet[4]: adaption_field_length + // packet[5]: adaption field data + // base: start of PES body + char* base = &packet[5] + packet[4]; + int len = p - base; + p = (char*)memmove(base + stuff_size, base, len) + len; + // increase the adaption field size. + packet[4] += stuff_size; + + return p; + } - // create adaption field. - // adaption_field_control; //2bits - packet[3] |= 0x20; - // base: start of PES body - char* base = &packet[4]; - int len = p - base; - p = (char*)memmove(base + stuff_size, base, len) + len; - // adaption_field_length; //8bits - packet[4] = (stuff_size - 1); - if (stuff_size >= 2) { - // adaption field flags. - packet[5] = 0; - // adaption data. - if (stuff_size > 2) { - memset(&packet[6], 0xff, stuff_size - 2); - } - } - - return p; - } - static char* write_pcr(char* p, int64_t pcr) - { - *p++ = (char) (pcr >> 25); - *p++ = (char) (pcr >> 17); - *p++ = (char) (pcr >> 9); - *p++ = (char) (pcr >> 1); - *p++ = (char) (pcr << 7 | 0x7e); - *p++ = 0; - - return p; - } - static char* write_pts(char* p, u_int8_t fb, int64_t pts) - { - int32_t val; - - val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; - *p++ = val; - - val = (((pts >> 15) & 0x7fff) << 1) | 1; - *p++ = (val >> 8); - *p++ = val; - - val = (((pts) & 0x7fff) << 1) | 1; - *p++ = (val >> 8); - *p++ = val; - - return p; - } + // create adaption field. + // adaption_field_control; //2bits + packet[3] |= 0x20; + // base: start of PES body + char* base = &packet[4]; + int len = p - base; + p = (char*)memmove(base + stuff_size, base, len) + len; + // adaption_field_length; //8bits + packet[4] = (stuff_size - 1); + if (stuff_size >= 2) { + // adaption field flags. + packet[5] = 0; + // adaption data. + if (stuff_size > 2) { + memset(&packet[6], 0xff, stuff_size - 2); + } + } + + return p; + } + static char* write_pcr(char* p, int64_t pcr) + { + *p++ = (char) (pcr >> 25); + *p++ = (char) (pcr >> 17); + *p++ = (char) (pcr >> 9); + *p++ = (char) (pcr >> 1); + *p++ = (char) (pcr << 7 | 0x7e); + *p++ = 0; + + return p; + } + static char* write_pts(char* p, u_int8_t fb, int64_t pts) + { + int32_t val; + + val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; + *p++ = val; + + val = (((pts >> 15) & 0x7fff) << 1) | 1; + *p++ = (val >> 8); + *p++ = val; + + val = (((pts) & 0x7fff) << 1) | 1; + *p++ = (val >> 8); + *p++ = val; + + return p; + } }; SrsHlsAacJitter::~SrsHlsAacJitter() @@ -359,39 +359,39 @@ SrsHlsAacJitter::~SrsHlsAacJitter() int64_t SrsHlsAacJitter::on_buffer_start(int64_t flv_pts, int sample_rate) { - // 0 = 5.5 kHz = 5512 Hz - // 1 = 11 kHz = 11025 Hz - // 2 = 22 kHz = 22050 Hz - // 3 = 44 kHz = 44100 Hz - static int flv_sample_rates[] = {5512, 11025, 22050, 44100}; - int flv_sample_rate = flv_sample_rates[sample_rate & 0x03]; + // 0 = 5.5 kHz = 5512 Hz + // 1 = 11 kHz = 11025 Hz + // 2 = 22 kHz = 22050 Hz + // 3 = 44 kHz = 44100 Hz + static int flv_sample_rates[] = {5512, 11025, 22050, 44100}; + int flv_sample_rate = flv_sample_rates[sample_rate & 0x03]; - // sync time set to 0, donot adjust the aac timestamp. - if (!sync_ms) { - return flv_pts; - } - - // @see: ngx_rtmp_hls_audio + // sync time set to 0, donot adjust the aac timestamp. + if (!sync_ms) { + return flv_pts; + } + + // @see: ngx_rtmp_hls_audio /* TODO: We assume here AAC frame size is 1024 * Need to handle AAC frames with frame size of 960 */ - int64_t est_pts = base_pts + nb_samples * 90000LL * 1024LL / flv_sample_rate; - int64_t dpts = (int64_t) (est_pts - flv_pts); + int64_t est_pts = base_pts + nb_samples * 90000LL * 1024LL / flv_sample_rate; + int64_t dpts = (int64_t) (est_pts - flv_pts); if (dpts <= (int64_t) sync_ms * 90 && dpts >= (int64_t) sync_ms * -90) { srs_info("HLS correct aac pts " - "from %"PRId64" to %"PRId64", base=%"PRId64", nb_samples=%d, sample_rate=%d", - flv_pts, est_pts, nb_samples, flv_sample_rate, base_pts); + "from %"PRId64" to %"PRId64", base=%"PRId64", nb_samples=%d, sample_rate=%d", + flv_pts, est_pts, nb_samples, flv_sample_rate, base_pts); - nb_samples++; - - return est_pts; + nb_samples++; + + return est_pts; } // resync - srs_trace("HLS aac resync, dpts=%"PRId64", pts=%"PRId64 - ", base=%"PRId64", nb_samples=%"PRId64", sample_rate=%d", - dpts, flv_pts, base_pts, nb_samples, flv_sample_rate); - + srs_trace("HLS aac resync, dpts=%"PRId64", pts=%"PRId64 + ", base=%"PRId64", nb_samples=%"PRId64", sample_rate=%d", + dpts, flv_pts, base_pts, nb_samples, flv_sample_rate); + base_pts = flv_pts; nb_samples = 1; @@ -400,951 +400,951 @@ int64_t SrsHlsAacJitter::on_buffer_start(int64_t flv_pts, int sample_rate) void SrsHlsAacJitter::on_buffer_continue() { - nb_samples++; + nb_samples++; } SrsTSMuxer::SrsTSMuxer() { - fd = -1; + fd = -1; } SrsTSMuxer::~SrsTSMuxer() { - close(); + close(); } int SrsTSMuxer::open(std::string _path) { - int ret = ERROR_SUCCESS; - - path = _path; - - close(); - - int flags = O_CREAT|O_WRONLY|O_TRUNC; - mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; - if ((fd = ::open(path.c_str(), flags, mode)) < 0) { - ret = ERROR_HLS_OPEN_FAILED; - srs_error("open ts file %s failed. ret=%d", path.c_str(), ret); - return ret; - } + int ret = ERROR_SUCCESS; + + path = _path; + + close(); + + int flags = O_CREAT|O_WRONLY|O_TRUNC; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; + if ((fd = ::open(path.c_str(), flags, mode)) < 0) { + ret = ERROR_HLS_OPEN_FAILED; + srs_error("open ts file %s failed. ret=%d", path.c_str(), ret); + return ret; + } - // write mpegts header - if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + // write mpegts header + if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) { - int ret = ERROR_SUCCESS; - - if ((ret = SrsMpegtsWriter::write_frame(fd, af, ab)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = SrsMpegtsWriter::write_frame(fd, af, ab)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb) { - int ret = ERROR_SUCCESS; - - if ((ret = SrsMpegtsWriter::write_frame(fd, vf, vb)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = SrsMpegtsWriter::write_frame(fd, vf, vb)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } void SrsTSMuxer::close() { - if (fd > 0) { - ::close(fd); - fd = -1; - } + if (fd > 0) { + ::close(fd); + fd = -1; + } } SrsM3u8Segment::SrsM3u8Segment() { - duration = 0; - sequence_no = 0; - muxer = new SrsTSMuxer(); - segment_start_dts = 0; + duration = 0; + sequence_no = 0; + muxer = new SrsTSMuxer(); + segment_start_dts = 0; } SrsM3u8Segment::~SrsM3u8Segment() { - srs_freep(muxer); + srs_freep(muxer); } double SrsM3u8Segment::update_duration(int64_t video_stream_dts) { - duration = (video_stream_dts - segment_start_dts) / 90000.0; - srs_assert(duration >= 0); - - return duration; + duration = (video_stream_dts - segment_start_dts) / 90000.0; + srs_assert(duration >= 0); + + return duration; } SrsHlsAacJitter::SrsHlsAacJitter() { - base_pts = 0; - nb_samples = 0; + base_pts = 0; + nb_samples = 0; - // TODO: config it, 0 means no adjust - sync_ms = SRS_CONF_DEFAULT_AAC_SYNC; + // TODO: config it, 0 means no adjust + sync_ms = SRS_CONF_DEFAULT_AAC_SYNC; } SrsM3u8Muxer::SrsM3u8Muxer() { - hls_fragment = hls_window = 0; - video_stream_dts = 0; - file_index = 0; - current = NULL; + hls_fragment = hls_window = 0; + video_stream_dts = 0; + file_index = 0; + current = NULL; } SrsM3u8Muxer::~SrsM3u8Muxer() { - std::vector::iterator it; - for (it = segments.begin(); it != segments.end(); ++it) { - SrsM3u8Segment* segment = *it; - srs_freep(segment); - } - segments.clear(); - - srs_freep(current); + std::vector::iterator it; + for (it = segments.begin(); it != segments.end(); ++it) { + SrsM3u8Segment* segment = *it; + srs_freep(segment); + } + segments.clear(); + + srs_freep(current); } int SrsM3u8Muxer::update_config( - std::string _app, std::string _stream, - std::string path, int fragment, int window + std::string _app, std::string _stream, + std::string path, int fragment, int window ) { - int ret = ERROR_SUCCESS; - - app = _app; - stream = _stream; - hls_path = path; - hls_fragment = fragment; - hls_window = window; - - return ret; + int ret = ERROR_SUCCESS; + + app = _app; + stream = _stream; + hls_path = path; + hls_fragment = fragment; + hls_window = window; + + return ret; } int SrsM3u8Muxer::segment_open() { - int ret = ERROR_SUCCESS; - - if (current) { - srs_warn("ignore the segment open, for segment is already open."); - return ret; - } - - // TODO: create all parents dirs. - // create dir for app. - if ((ret = create_dir()) != ERROR_SUCCESS) { - return ret; - } - - // when segment open, the current segment must be NULL. - srs_assert(!current); - - // new segment. - current = new SrsM3u8Segment(); - current->sequence_no = file_index++; - current->segment_start_dts = video_stream_dts; - - // generate filename. - char filename[128]; - snprintf(filename, sizeof(filename), - "%s-%d.ts", stream.c_str(), current->sequence_no); - - // TODO: use temp file and rename it. - current->full_path = hls_path; - current->full_path += "/"; - current->full_path += app; - current->full_path += "/"; - current->full_path += filename; - - // TODO: support base url, and so on. - current->uri = filename; - - if ((ret = current->muxer->open(current->full_path)) != ERROR_SUCCESS) { - srs_error("open hls muxer failed. ret=%d", ret); - return ret; - } - srs_info("open HLS muxer success. vhost=%s, path=%s", - vhost.c_str(), current->full_path.c_str()); - - return ret; + int ret = ERROR_SUCCESS; + + if (current) { + srs_warn("ignore the segment open, for segment is already open."); + return ret; + } + + // TODO: create all parents dirs. + // create dir for app. + if ((ret = create_dir()) != ERROR_SUCCESS) { + return ret; + } + + // when segment open, the current segment must be NULL. + srs_assert(!current); + + // new segment. + current = new SrsM3u8Segment(); + current->sequence_no = file_index++; + current->segment_start_dts = video_stream_dts; + + // generate filename. + char filename[128]; + snprintf(filename, sizeof(filename), + "%s-%d.ts", stream.c_str(), current->sequence_no); + + // TODO: use temp file and rename it. + current->full_path = hls_path; + current->full_path += "/"; + current->full_path += app; + current->full_path += "/"; + current->full_path += filename; + + // TODO: support base url, and so on. + current->uri = filename; + + if ((ret = current->muxer->open(current->full_path)) != ERROR_SUCCESS) { + srs_error("open hls muxer failed. ret=%d", ret); + return ret; + } + srs_info("open HLS muxer success. vhost=%s, path=%s", + vhost.c_str(), current->full_path.c_str()); + + return ret; } int SrsM3u8Muxer::flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - // if current is NULL, segment is not open, ignore the flush event. - if (!current) { - srs_warn("flush audio ignored, for segment is not open."); - return ret; - } - - if (ab->size <= 0) { - return ret; - } - - if ((ret = current->muxer->write_audio(af, ab)) != ERROR_SUCCESS) { - return ret; - } - - // write success, clear and free the buffer - ab->free(); + // if current is NULL, segment is not open, ignore the flush event. + if (!current) { + srs_warn("flush audio ignored, for segment is not open."); + return ret; + } + + if (ab->size <= 0) { + return ret; + } + + if ((ret = current->muxer->write_audio(af, ab)) != ERROR_SUCCESS) { + return ret; + } + + // write success, clear and free the buffer + ab->free(); - return ret; + return ret; } int SrsM3u8Muxer::flush_video( - SrsMpegtsFrame* af, SrsCodecBuffer* ab, - SrsMpegtsFrame* vf, SrsCodecBuffer* vb) + SrsMpegtsFrame* af, SrsCodecBuffer* ab, + SrsMpegtsFrame* vf, SrsCodecBuffer* vb) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - // if current is NULL, segment is not open, ignore the flush event. - if (!current) { - srs_warn("flush video ignored, for segment is not open."); - return ret; - } - - video_stream_dts = vf->dts; - - srs_assert(current); - // reopen the muxer for a gop - if (vf->key && current->duration >= hls_fragment) { - // TODO: flush audio before or after segment? - /* - if ((ret = flush_audio(af, ab)) != ERROR_SUCCESS) { - srs_error("m3u8 muxer flush audio failed. ret=%d", ret); - return ret; - } - */ - - if ((ret = segment_close()) != ERROR_SUCCESS) { - srs_error("m3u8 muxer close segment failed. ret=%d", ret); - return ret; - } - - if ((ret = segment_open()) != ERROR_SUCCESS) { - srs_error("m3u8 muxer open segment failed. ret=%d", ret); - return ret; - } - - // TODO: flush audio before or after segment? - // segment open, flush the audio. - // @see: ngx_rtmp_hls_open_fragment - /* start fragment with audio to make iPhone happy */ - if ((ret = flush_audio(af, ab)) != ERROR_SUCCESS) { - srs_error("m3u8 muxer flush audio failed. ret=%d", ret); - return ret; - } - } - - // update the duration of segment. - current->update_duration(video_stream_dts); - - if ((ret = current->muxer->write_video(vf, vb)) != ERROR_SUCCESS) { - return ret; - } - - // write success, clear and free the buffer - vb->free(); - - return ret; + // if current is NULL, segment is not open, ignore the flush event. + if (!current) { + srs_warn("flush video ignored, for segment is not open."); + return ret; + } + + video_stream_dts = vf->dts; + + srs_assert(current); + // reopen the muxer for a gop + if (vf->key && current->duration >= hls_fragment) { + // TODO: flush audio before or after segment? + /* + if ((ret = flush_audio(af, ab)) != ERROR_SUCCESS) { + srs_error("m3u8 muxer flush audio failed. ret=%d", ret); + return ret; + } + */ + + if ((ret = segment_close()) != ERROR_SUCCESS) { + srs_error("m3u8 muxer close segment failed. ret=%d", ret); + return ret; + } + + if ((ret = segment_open()) != ERROR_SUCCESS) { + srs_error("m3u8 muxer open segment failed. ret=%d", ret); + return ret; + } + + // TODO: flush audio before or after segment? + // segment open, flush the audio. + // @see: ngx_rtmp_hls_open_fragment + /* start fragment with audio to make iPhone happy */ + if ((ret = flush_audio(af, ab)) != ERROR_SUCCESS) { + srs_error("m3u8 muxer flush audio failed. ret=%d", ret); + return ret; + } + } + + // update the duration of segment. + current->update_duration(video_stream_dts); + + if ((ret = current->muxer->write_video(vf, vb)) != ERROR_SUCCESS) { + return ret; + } + + // write success, clear and free the buffer + vb->free(); + + return ret; } int SrsM3u8Muxer::segment_close() { - int ret = ERROR_SUCCESS; - - if (!current) { - srs_warn("ignore the segment close, for segment is not open."); - return ret; - } - - // when close current segment, the current segment must not be NULL. - srs_assert(current); + int ret = ERROR_SUCCESS; + + if (!current) { + srs_warn("ignore the segment close, for segment is not open."); + return ret; + } + + // when close current segment, the current segment must not be NULL. + srs_assert(current); - // assert segment duplicate. - std::vector::iterator it; - it = std::find(segments.begin(), segments.end(), current); - srs_assert(it == segments.end()); + // assert segment duplicate. + std::vector::iterator it; + it = std::find(segments.begin(), segments.end(), current); + srs_assert(it == segments.end()); - // valid, add to segments. - segments.push_back(current); - - srs_trace("reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64"", - current->sequence_no, current->uri.c_str(), current->duration, - current->segment_start_dts); - - // close the muxer of finished segment. - srs_freep(current->muxer); - current = NULL; - - // the segments to remove - std::vector segment_to_remove; - - // shrink the segments. - double duration = 0; - int remove_index = -1; - for (int i = segments.size() - 1; i >= 0; i--) { - SrsM3u8Segment* segment = segments[i]; - duration += segment->duration; - - if ((int)duration > hls_window) { - remove_index = i; - break; - } - } - for (int i = 0; i < remove_index && !segments.empty(); i++) { - SrsM3u8Segment* segment = *segments.begin(); - segments.erase(segments.begin()); - segment_to_remove.push_back(segment); - } - - // refresh the m3u8, donot contains the removed ts - ret = refresh_m3u8(); + // valid, add to segments. + segments.push_back(current); + + srs_trace("reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"PRId64"", + current->sequence_no, current->uri.c_str(), current->duration, + current->segment_start_dts); + + // close the muxer of finished segment. + srs_freep(current->muxer); + current = NULL; + + // the segments to remove + std::vector segment_to_remove; + + // shrink the segments. + double duration = 0; + int remove_index = -1; + for (int i = segments.size() - 1; i >= 0; i--) { + SrsM3u8Segment* segment = segments[i]; + duration += segment->duration; + + if ((int)duration > hls_window) { + remove_index = i; + break; + } + } + for (int i = 0; i < remove_index && !segments.empty(); i++) { + SrsM3u8Segment* segment = *segments.begin(); + segments.erase(segments.begin()); + segment_to_remove.push_back(segment); + } + + // refresh the m3u8, donot contains the removed ts + ret = refresh_m3u8(); - // remove the ts file. - for (int i = 0; i < (int)segment_to_remove.size(); i++) { - SrsM3u8Segment* segment = segment_to_remove[i]; - unlink(segment->full_path.c_str()); - srs_freep(segment); - } - segment_to_remove.clear(); - - // check ret of refresh m3u8 - if (ret != ERROR_SUCCESS) { - srs_error("refresh m3u8 failed. ret=%d", ret); - return ret; - } - - return ret; + // remove the ts file. + for (int i = 0; i < (int)segment_to_remove.size(); i++) { + SrsM3u8Segment* segment = segment_to_remove[i]; + unlink(segment->full_path.c_str()); + srs_freep(segment); + } + segment_to_remove.clear(); + + // check ret of refresh m3u8 + if (ret != ERROR_SUCCESS) { + srs_error("refresh m3u8 failed. ret=%d", ret); + return ret; + } + + return ret; } int SrsM3u8Muxer::refresh_m3u8() { - int ret = ERROR_SUCCESS; - - std::string m3u8_file = hls_path; - m3u8_file += "/"; - m3u8_file += app; - m3u8_file += "/"; - m3u8_file += stream; - m3u8_file += ".m3u8"; - - m3u8 = m3u8_file; - m3u8_file += ".temp"; - - int fd = -1; - ret = _refresh_m3u8(fd, m3u8_file); - if (fd >= 0) { - close(fd); - if (rename(m3u8_file.c_str(), m3u8.c_str()) < 0) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("rename m3u8 file failed. ret=%d", ret); - } - } - - // remove the temp file. - unlink(m3u8_file.c_str()); - - return ret; + int ret = ERROR_SUCCESS; + + std::string m3u8_file = hls_path; + m3u8_file += "/"; + m3u8_file += app; + m3u8_file += "/"; + m3u8_file += stream; + m3u8_file += ".m3u8"; + + m3u8 = m3u8_file; + m3u8_file += ".temp"; + + int fd = -1; + ret = _refresh_m3u8(fd, m3u8_file); + if (fd >= 0) { + close(fd); + if (rename(m3u8_file.c_str(), m3u8.c_str()) < 0) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("rename m3u8 file failed. ret=%d", ret); + } + } + + // remove the temp file. + unlink(m3u8_file.c_str()); + + return ret; } int SrsM3u8Muxer::_refresh_m3u8(int& fd, std::string m3u8_file) { - int ret = ERROR_SUCCESS; - - // no segments, return. - if (segments.size() == 0) { - return ret; - } - - int flags = O_CREAT|O_WRONLY|O_TRUNC; - mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; - if ((fd = ::open(m3u8_file.c_str(), flags, mode)) < 0) { - ret = ERROR_HLS_OPEN_FAILED; - srs_error("open m3u8 file %s failed. ret=%d", m3u8_file.c_str(), ret); - return ret; - } - srs_info("open m3u8 file %s success.", m3u8_file.c_str()); - - // #EXTM3U\n#EXT-X-VERSION:3\n - char header[] = { - // #EXTM3U\n - 0x23, 0x45, 0x58, 0x54, 0x4d, 0x33, 0x55, 0xa, - // #EXT-X-VERSION:3\n - 0x23, 0x45, 0x58, 0x54, 0x2d, 0x58, 0x2d, 0x56, 0x45, 0x52, - 0x53, 0x49, 0x4f, 0x4e, 0x3a, 0x33, 0xa - }; - if (::write(fd, header, sizeof(header)) != sizeof(header)) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write m3u8 header failed. ret=%d", ret); - return ret; - } - srs_verbose("write m3u8 header success."); - - // #EXT-X-MEDIA-SEQUENCE:4294967295\n - SrsM3u8Segment* first = *segments.begin(); - char sequence[34] = {}; - int len = snprintf(sequence, sizeof(sequence), "#EXT-X-MEDIA-SEQUENCE:%d\n", first->sequence_no); - if (::write(fd, sequence, len) != len) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write m3u8 sequence failed. ret=%d", ret); - return ret; - } - srs_verbose("write m3u8 sequence success."); - - // #EXT-X-TARGETDURATION:4294967295\n - int target_duration = 0; - std::vector::iterator it; - for (it = segments.begin(); it != segments.end(); ++it) { - SrsM3u8Segment* segment = *it; - target_duration = srs_max(target_duration, (int)segment->duration); - } - // TODO: maybe need to take an around value - target_duration += 1; - char duration[34]; - len = snprintf(duration, sizeof(duration), "#EXT-X-TARGETDURATION:%d\n", target_duration); - if (::write(fd, duration, len) != len) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write m3u8 duration failed. ret=%d", ret); - return ret; - } - srs_verbose("write m3u8 duration success."); - - // write all segments - for (it = segments.begin(); it != segments.end(); ++it) { - SrsM3u8Segment* segment = *it; - - // "#EXTINF:4294967295.208,\n" - char ext_info[25]; - len = snprintf(ext_info, sizeof(ext_info), "#EXTINF:%.3f\n", segment->duration); - if (::write(fd, ext_info, len) != len) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write m3u8 segment failed. ret=%d", ret); - return ret; - } - srs_verbose("write m3u8 segment success."); - - // file name - std::string filename = segment->uri; - filename += "\n"; - if (::write(fd, filename.c_str(), filename.length()) != (int)filename.length()) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write m3u8 segment uri failed. ret=%d", ret); - return ret; - } - srs_verbose("write m3u8 segment uri success."); - } - srs_info("write m3u8 %s success.", m3u8_file.c_str()); - - return ret; + int ret = ERROR_SUCCESS; + + // no segments, return. + if (segments.size() == 0) { + return ret; + } + + int flags = O_CREAT|O_WRONLY|O_TRUNC; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; + if ((fd = ::open(m3u8_file.c_str(), flags, mode)) < 0) { + ret = ERROR_HLS_OPEN_FAILED; + srs_error("open m3u8 file %s failed. ret=%d", m3u8_file.c_str(), ret); + return ret; + } + srs_info("open m3u8 file %s success.", m3u8_file.c_str()); + + // #EXTM3U\n#EXT-X-VERSION:3\n + char header[] = { + // #EXTM3U\n + 0x23, 0x45, 0x58, 0x54, 0x4d, 0x33, 0x55, 0xa, + // #EXT-X-VERSION:3\n + 0x23, 0x45, 0x58, 0x54, 0x2d, 0x58, 0x2d, 0x56, 0x45, 0x52, + 0x53, 0x49, 0x4f, 0x4e, 0x3a, 0x33, 0xa + }; + if (::write(fd, header, sizeof(header)) != sizeof(header)) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write m3u8 header failed. ret=%d", ret); + return ret; + } + srs_verbose("write m3u8 header success."); + + // #EXT-X-MEDIA-SEQUENCE:4294967295\n + SrsM3u8Segment* first = *segments.begin(); + char sequence[34] = {}; + int len = snprintf(sequence, sizeof(sequence), "#EXT-X-MEDIA-SEQUENCE:%d\n", first->sequence_no); + if (::write(fd, sequence, len) != len) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write m3u8 sequence failed. ret=%d", ret); + return ret; + } + srs_verbose("write m3u8 sequence success."); + + // #EXT-X-TARGETDURATION:4294967295\n + int target_duration = 0; + std::vector::iterator it; + for (it = segments.begin(); it != segments.end(); ++it) { + SrsM3u8Segment* segment = *it; + target_duration = srs_max(target_duration, (int)segment->duration); + } + // TODO: maybe need to take an around value + target_duration += 1; + char duration[34]; + len = snprintf(duration, sizeof(duration), "#EXT-X-TARGETDURATION:%d\n", target_duration); + if (::write(fd, duration, len) != len) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write m3u8 duration failed. ret=%d", ret); + return ret; + } + srs_verbose("write m3u8 duration success."); + + // write all segments + for (it = segments.begin(); it != segments.end(); ++it) { + SrsM3u8Segment* segment = *it; + + // "#EXTINF:4294967295.208,\n" + char ext_info[25]; + len = snprintf(ext_info, sizeof(ext_info), "#EXTINF:%.3f\n", segment->duration); + if (::write(fd, ext_info, len) != len) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write m3u8 segment failed. ret=%d", ret); + return ret; + } + srs_verbose("write m3u8 segment success."); + + // file name + std::string filename = segment->uri; + filename += "\n"; + if (::write(fd, filename.c_str(), filename.length()) != (int)filename.length()) { + ret = ERROR_HLS_WRITE_FAILED; + srs_error("write m3u8 segment uri failed. ret=%d", ret); + return ret; + } + srs_verbose("write m3u8 segment uri success."); + } + srs_info("write m3u8 %s success.", m3u8_file.c_str()); + + return ret; } int SrsM3u8Muxer::create_dir() { - int ret = ERROR_SUCCESS; - - std::string app_dir = hls_path; - app_dir += "/"; - app_dir += app; - - // TODO: cleanup the dir when startup. + int ret = ERROR_SUCCESS; + + std::string app_dir = hls_path; + app_dir += "/"; + app_dir += app; + + // TODO: cleanup the dir when startup. - mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH; - if (::mkdir(app_dir.c_str(), mode) < 0) { - if (errno != EEXIST) { - ret = ERROR_HLS_CREATE_DIR; - srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret); - return ret; - } - } - srs_info("create app dir %s success.", app_dir.c_str()); + mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH; + if (::mkdir(app_dir.c_str(), mode) < 0) { + if (errno != EEXIST) { + ret = ERROR_HLS_CREATE_DIR; + srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret); + return ret; + } + } + srs_info("create app dir %s success.", app_dir.c_str()); - return ret; + return ret; } SrsTSCache::SrsTSCache() { - aac_jitter = new SrsHlsAacJitter(); - - ab = new SrsCodecBuffer(); - vb = new SrsCodecBuffer(); - - af = new SrsMpegtsFrame(); - vf = new SrsMpegtsFrame(); + aac_jitter = new SrsHlsAacJitter(); + + ab = new SrsCodecBuffer(); + vb = new SrsCodecBuffer(); + + af = new SrsMpegtsFrame(); + vf = new SrsMpegtsFrame(); } SrsTSCache::~SrsTSCache() { - srs_freep(aac_jitter); - - ab->free(); - vb->free(); - - srs_freep(ab); - srs_freep(vb); - - srs_freep(af); - srs_freep(vf); + srs_freep(aac_jitter); + + ab->free(); + vb->free(); + + srs_freep(ab); + srs_freep(vb); + + srs_freep(af); + srs_freep(vf); } - + int SrsTSCache::write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample) { - int ret = ERROR_SUCCESS; - - // start buffer, set the af - if (ab->size == 0) { - pts = aac_jitter->on_buffer_start(pts, sample->sound_rate); - - af->dts = af->pts = audio_buffer_start_pts = pts; - af->pid = TS_AUDIO_PID; - af->sid = TS_AUDIO_AAC; - } else { - aac_jitter->on_buffer_continue(); - } - - // write audio to cache. - if ((ret = cache_audio(codec, sample)) != ERROR_SUCCESS) { - return ret; - } - - // flush if buffer exceed max size. - if (ab->size > SRS_HLS_AUDIO_CACHE_SIZE) { - if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { - return ret; - } - } - // TODO: config it. - // in ms, audio delay to flush the audios. - int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; - // flush if audio delay exceed - if (pts - audio_buffer_start_pts > audio_delay * 90) { - if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { - return ret; - } - } - - return ret; + int ret = ERROR_SUCCESS; + + // start buffer, set the af + if (ab->size == 0) { + pts = aac_jitter->on_buffer_start(pts, sample->sound_rate); + + af->dts = af->pts = audio_buffer_start_pts = pts; + af->pid = TS_AUDIO_PID; + af->sid = TS_AUDIO_AAC; + } else { + aac_jitter->on_buffer_continue(); + } + + // write audio to cache. + if ((ret = cache_audio(codec, sample)) != ERROR_SUCCESS) { + return ret; + } + + // flush if buffer exceed max size. + if (ab->size > SRS_HLS_AUDIO_CACHE_SIZE) { + if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { + return ret; + } + } + // TODO: config it. + // in ms, audio delay to flush the audios. + int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; + // flush if audio delay exceed + if (pts - audio_buffer_start_pts > audio_delay * 90) { + if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { + return ret; + } + } + + return ret; } - + int SrsTSCache::write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample) { - int ret = ERROR_SUCCESS; - - // write video to cache. - if ((ret = cache_video(codec, sample)) != ERROR_SUCCESS) { - return ret; - } - - vf->dts = dts; - vf->pts = vf->dts + sample->cts * 90; - vf->pid = TS_VIDEO_PID; - vf->sid = TS_VIDEO_AVC; - vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; - - // flush video when got one - if ((ret = muxer->flush_video(af, ab, vf, vb)) != ERROR_SUCCESS) { - srs_error("m3u8 muxer flush video failed. ret=%d", ret); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + // write video to cache. + if ((ret = cache_video(codec, sample)) != ERROR_SUCCESS) { + return ret; + } + + vf->dts = dts; + vf->pts = vf->dts + sample->cts * 90; + vf->pid = TS_VIDEO_PID; + vf->sid = TS_VIDEO_AVC; + vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; + + // flush video when got one + if ((ret = muxer->flush_video(af, ab, vf, vb)) != ERROR_SUCCESS) { + srs_error("m3u8 muxer flush video failed. ret=%d", ret); + return ret; + } + + return ret; } int SrsTSCache::flush_audio(SrsM3u8Muxer* muxer) { - int ret = ERROR_SUCCESS; - - if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { - srs_error("m3u8 muxer flush audio failed. ret=%d", ret); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { + srs_error("m3u8 muxer flush audio failed. ret=%d", ret); + return ret; + } + + return ret; } int SrsTSCache::cache_audio(SrsCodec* codec, SrsCodecSample* sample) { - int ret = ERROR_SUCCESS; - - for (int i = 0; i < sample->nb_buffers; i++) { - SrsCodecBuffer* buf = &sample->buffers[i]; - int32_t size = buf->size; - - if (!buf->bytes || size <= 0 || size > 0x1fff) { - ret = ERROR_HLS_AAC_FRAME_LENGTH; - srs_error("invalid aac frame length=%d, ret=%d", size, ret); - return ret; - } - - // the frame length is the AAC raw data plus the adts header size. - int32_t frame_length = size + 7; - - // AAC-ADTS - // 6.2 Audio Data Transport Stream, ADTS - // in aac-iso-13818-7.pdf, page 26. - // fixed 7bytes header - static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc}; - /* - // adts_fixed_header - // 2B, 16bits - int16_t syncword; //12bits, '1111 1111 1111' - int8_t ID; //1bit, '0' - int8_t layer; //2bits, '00' - int8_t protection_absent; //1bit, can be '1' - // 12bits - int8_t profile; //2bit, 7.1 Profiles, page 40 - TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46 - int8_t private_bit; //1bit, can be '0' - int8_t channel_configuration; //3bits, Table 8 - int8_t original_or_copy; //1bit, can be '0' - int8_t home; //1bit, can be '0' - - // adts_variable_header - // 28bits - int8_t copyright_identification_bit; //1bit, can be '0' - int8_t copyright_identification_start; //1bit, can be '0' - int16_t frame_length; //13bits - int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream. - int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block() - */ - // profile, 2bits - adts_header[2] = (codec->aac_profile << 6) & 0xc0; - // sampling_frequency_index 4bits - adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c; - // channel_configuration 3bits - adts_header[2] |= (codec->aac_channels >> 2) & 0x01; - adts_header[3] = (codec->aac_channels << 6) & 0xc0; - // frame_length 13bits - adts_header[3] |= (frame_length >> 11) & 0x03; - adts_header[4] = (frame_length >> 3) & 0xff; - adts_header[5] = ((frame_length << 5) & 0xe0); - // adts_buffer_fullness; //11bits - adts_header[5] |= 0x1f; + int ret = ERROR_SUCCESS; + + for (int i = 0; i < sample->nb_buffers; i++) { + SrsCodecBuffer* buf = &sample->buffers[i]; + int32_t size = buf->size; + + if (!buf->bytes || size <= 0 || size > 0x1fff) { + ret = ERROR_HLS_AAC_FRAME_LENGTH; + srs_error("invalid aac frame length=%d, ret=%d", size, ret); + return ret; + } + + // the frame length is the AAC raw data plus the adts header size. + int32_t frame_length = size + 7; + + // AAC-ADTS + // 6.2 Audio Data Transport Stream, ADTS + // in aac-iso-13818-7.pdf, page 26. + // fixed 7bytes header + static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc}; + /* + // adts_fixed_header + // 2B, 16bits + int16_t syncword; //12bits, '1111 1111 1111' + int8_t ID; //1bit, '0' + int8_t layer; //2bits, '00' + int8_t protection_absent; //1bit, can be '1' + // 12bits + int8_t profile; //2bit, 7.1 Profiles, page 40 + TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46 + int8_t private_bit; //1bit, can be '0' + int8_t channel_configuration; //3bits, Table 8 + int8_t original_or_copy; //1bit, can be '0' + int8_t home; //1bit, can be '0' + + // adts_variable_header + // 28bits + int8_t copyright_identification_bit; //1bit, can be '0' + int8_t copyright_identification_start; //1bit, can be '0' + int16_t frame_length; //13bits + int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream. + int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block() + */ + // profile, 2bits + adts_header[2] = (codec->aac_profile << 6) & 0xc0; + // sampling_frequency_index 4bits + adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c; + // channel_configuration 3bits + adts_header[2] |= (codec->aac_channels >> 2) & 0x01; + adts_header[3] = (codec->aac_channels << 6) & 0xc0; + // frame_length 13bits + adts_header[3] |= (frame_length >> 11) & 0x03; + adts_header[4] = (frame_length >> 3) & 0xff; + adts_header[5] = ((frame_length << 5) & 0xe0); + // adts_buffer_fullness; //11bits + adts_header[5] |= 0x1f; - // copy to audio buffer - ab->append(adts_header, sizeof(adts_header)); - ab->append(buf->bytes, buf->size); - } - - return ret; + // copy to audio buffer + ab->append(adts_header, sizeof(adts_header)); + ab->append(buf->bytes, buf->size); + } + + return ret; } int SrsTSCache::cache_video(SrsCodec* codec, SrsCodecSample* sample) { - int ret = ERROR_SUCCESS; - - static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; - vb->append(aud_nal, sizeof(aud_nal)); - - bool sps_pps_sent = false; - for (int i = 0; i < sample->nb_buffers; i++) { - SrsCodecBuffer* buf = &sample->buffers[i]; - int32_t size = buf->size; - - if (!buf->bytes || size <= 0) { - ret = ERROR_HLS_AVC_SAMPLE_SIZE; - srs_error("invalid avc sample length=%d, ret=%d", size, ret); - return ret; - } - - // 5bits, 7.3.1 NAL unit syntax, - // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. - u_int8_t nal_unit_type; - nal_unit_type = *buf->bytes; - nal_unit_type &= 0x1f; - - // Table 7-1 – NAL unit type codes, page 61 - // 1: Coded slice - if (nal_unit_type == 1) { - sps_pps_sent = false; - } - // 5: Coded slice of an IDR picture. - // insert sps/pps before IDR or key frame is ok. - if (nal_unit_type == 5 && !sps_pps_sent) { - //if (vf->key && !sps_pps_sent) { - sps_pps_sent = true; - - // ngx_rtmp_hls_append_sps_pps - if (codec->sequenceParameterSetLength > 0) { - // AnnexB prefix - vb->append(aud_nal, 4); - // sps - vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); - } - if (codec->pictureParameterSetLength > 0) { - // AnnexB prefix - vb->append(aud_nal, 4); - // pps - vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); - } - } - - // sample start prefix, '00 00 00 01' or '00 00 01' - u_int8_t* p = aud_nal + 1; - u_int8_t* end = p + 3; - - // first AnnexB prefix is long (4 bytes) - if (i == 0) { - p = aud_nal; - } - vb->append(p, end - p); - - // sample data - vb->append(buf->bytes, buf->size); - } - - return ret; + int ret = ERROR_SUCCESS; + + static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; + vb->append(aud_nal, sizeof(aud_nal)); + + bool sps_pps_sent = false; + for (int i = 0; i < sample->nb_buffers; i++) { + SrsCodecBuffer* buf = &sample->buffers[i]; + int32_t size = buf->size; + + if (!buf->bytes || size <= 0) { + ret = ERROR_HLS_AVC_SAMPLE_SIZE; + srs_error("invalid avc sample length=%d, ret=%d", size, ret); + return ret; + } + + // 5bits, 7.3.1 NAL unit syntax, + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. + u_int8_t nal_unit_type; + nal_unit_type = *buf->bytes; + nal_unit_type &= 0x1f; + + // Table 7-1 – NAL unit type codes, page 61 + // 1: Coded slice + if (nal_unit_type == 1) { + sps_pps_sent = false; + } + // 5: Coded slice of an IDR picture. + // insert sps/pps before IDR or key frame is ok. + if (nal_unit_type == 5 && !sps_pps_sent) { + //if (vf->key && !sps_pps_sent) { + sps_pps_sent = true; + + // ngx_rtmp_hls_append_sps_pps + if (codec->sequenceParameterSetLength > 0) { + // AnnexB prefix + vb->append(aud_nal, 4); + // sps + vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); + } + if (codec->pictureParameterSetLength > 0) { + // AnnexB prefix + vb->append(aud_nal, 4); + // pps + vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); + } + } + + // sample start prefix, '00 00 00 01' or '00 00 01' + u_int8_t* p = aud_nal + 1; + u_int8_t* end = p + 3; + + // first AnnexB prefix is long (4 bytes) + if (i == 0) { + p = aud_nal; + } + vb->append(p, end - p); + + // sample data + vb->append(buf->bytes, buf->size); + } + + return ret; } SrsHls::SrsHls(SrsSource* _source) { - hls_enabled = false; - - source = _source; - codec = new SrsCodec(); - sample = new SrsCodecSample(); - jitter = new SrsRtmpJitter(); - - muxer = new SrsM3u8Muxer(); - ts_cache = new SrsTSCache(); + hls_enabled = false; + + source = _source; + codec = new SrsCodec(); + sample = new SrsCodecSample(); + jitter = new SrsRtmpJitter(); + + muxer = new SrsM3u8Muxer(); + ts_cache = new SrsTSCache(); - pithy_print = new SrsPithyPrint(SRS_STAGE_HLS); + pithy_print = new SrsPithyPrint(SRS_STAGE_HLS); } SrsHls::~SrsHls() { - srs_freep(codec); - srs_freep(sample); - srs_freep(jitter); - - srs_freep(muxer); - srs_freep(ts_cache); - - srs_freep(pithy_print); + srs_freep(codec); + srs_freep(sample); + srs_freep(jitter); + + srs_freep(muxer); + srs_freep(ts_cache); + + srs_freep(pithy_print); } int SrsHls::on_publish(SrsRequest* req) { - int ret = ERROR_SUCCESS; - - // support multiple publish. - if (hls_enabled) { - return ret; - } + int ret = ERROR_SUCCESS; + + // support multiple publish. + if (hls_enabled) { + return ret; + } - std::string vhost = req->vhost; - std::string stream = req->stream; - std::string app = req->app; - - if (!_srs_config->get_hls_enabled(vhost)) { - return ret; - } - - // if enabled, open the muxer. - hls_enabled = true; - - int hls_fragment = _srs_config->get_hls_fragment(vhost); - int hls_window = _srs_config->get_hls_window(vhost); - - // get the hls path config - std::string hls_path = _srs_config->get_hls_path(vhost); - - // open muxer - if ((ret = muxer->update_config(app, stream, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) { - srs_error("m3u8 muxer update config failed. ret=%d", ret); - return ret; - } - - if ((ret = muxer->segment_open()) != ERROR_SUCCESS) { - srs_error("m3u8 muxer open segment failed. ret=%d", ret); - return ret; - } - - // notice the source to get the cached sequence header. - if ((ret = source->on_hls_start()) != ERROR_SUCCESS) { - srs_error("callback source hls start failed. ret=%d", ret); - return ret; - } + std::string vhost = req->vhost; + std::string stream = req->stream; + std::string app = req->app; + + if (!_srs_config->get_hls_enabled(vhost)) { + return ret; + } + + // if enabled, open the muxer. + hls_enabled = true; + + int hls_fragment = _srs_config->get_hls_fragment(vhost); + int hls_window = _srs_config->get_hls_window(vhost); + + // get the hls path config + std::string hls_path = _srs_config->get_hls_path(vhost); + + // open muxer + if ((ret = muxer->update_config(app, stream, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) { + srs_error("m3u8 muxer update config failed. ret=%d", ret); + return ret; + } + + if ((ret = muxer->segment_open()) != ERROR_SUCCESS) { + srs_error("m3u8 muxer open segment failed. ret=%d", ret); + return ret; + } + + // notice the source to get the cached sequence header. + if ((ret = source->on_hls_start()) != ERROR_SUCCESS) { + srs_error("callback source hls start failed. ret=%d", ret); + return ret; + } - return ret; + return ret; } void SrsHls::on_unpublish() { - int ret = ERROR_SUCCESS; - - // support multiple unpublish. - if (!hls_enabled) { - return; - } - - // close muxer when unpublish. - ret = ts_cache->flush_audio(muxer); - ret += muxer->segment_close(); + int ret = ERROR_SUCCESS; + + // support multiple unpublish. + if (!hls_enabled) { + return; + } + + // close muxer when unpublish. + ret = ts_cache->flush_audio(muxer); + ret += muxer->segment_close(); - if (ret != ERROR_SUCCESS) { - srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret); - } - - hls_enabled = false; + if (ret != ERROR_SUCCESS) { + srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret); + } + + hls_enabled = false; } int SrsHls::on_meta_data(SrsAmf0Object* metadata) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if (!metadata) { - srs_trace("no metadata persent, hls ignored it."); - return ret; - } - - SrsAmf0Object* obj = metadata; - if (obj->count() <= 0) { - srs_trace("no metadata persent, hls ignored it."); - return ret; - } - - // finger out the codec info from metadata if possible. - SrsAmf0Any* prop = NULL; + if (!metadata) { + srs_trace("no metadata persent, hls ignored it."); + return ret; + } + + SrsAmf0Object* obj = metadata; + if (obj->count() <= 0) { + srs_trace("no metadata persent, hls ignored it."); + return ret; + } + + // finger out the codec info from metadata if possible. + SrsAmf0Any* prop = NULL; - if ((prop = obj->get_property("duration")) != NULL && prop->is_number()) { - codec->duration = (int)prop->to_number(); - } - if ((prop = obj->get_property("width")) != NULL && prop->is_number()) { - codec->width = (int)prop->to_number(); - } - if ((prop = obj->get_property("height")) != NULL && prop->is_number()) { - codec->height = (int)prop->to_number(); - } - if ((prop = obj->get_property("framerate")) != NULL && prop->is_number()) { - codec->frame_rate = (int)prop->to_number(); - } - if ((prop = obj->get_property("videocodecid")) != NULL && prop->is_number()) { - codec->video_codec_id = (int)prop->to_number(); - } - if ((prop = obj->get_property("videodatarate")) != NULL && prop->is_number()) { - codec->video_data_rate = (int)(1000 * prop->to_number()); - } - - if ((prop = obj->get_property("audiocodecid")) != NULL && prop->is_number()) { - codec->audio_codec_id = (int)prop->to_number(); - } - if ((prop = obj->get_property("audiodatarate")) != NULL && prop->is_number()) { - codec->audio_data_rate = (int)(1000 * prop->to_number()); - } - - // ignore the following, for each flv/rtmp packet contains them: - // audiosamplerate, sample->sound_rate - // audiosamplesize, sample->sound_size - // stereo, sample->sound_type - - return ret; + if ((prop = obj->get_property("duration")) != NULL && prop->is_number()) { + codec->duration = (int)prop->to_number(); + } + if ((prop = obj->get_property("width")) != NULL && prop->is_number()) { + codec->width = (int)prop->to_number(); + } + if ((prop = obj->get_property("height")) != NULL && prop->is_number()) { + codec->height = (int)prop->to_number(); + } + if ((prop = obj->get_property("framerate")) != NULL && prop->is_number()) { + codec->frame_rate = (int)prop->to_number(); + } + if ((prop = obj->get_property("videocodecid")) != NULL && prop->is_number()) { + codec->video_codec_id = (int)prop->to_number(); + } + if ((prop = obj->get_property("videodatarate")) != NULL && prop->is_number()) { + codec->video_data_rate = (int)(1000 * prop->to_number()); + } + + if ((prop = obj->get_property("audiocodecid")) != NULL && prop->is_number()) { + codec->audio_codec_id = (int)prop->to_number(); + } + if ((prop = obj->get_property("audiodatarate")) != NULL && prop->is_number()) { + codec->audio_data_rate = (int)(1000 * prop->to_number()); + } + + // ignore the following, for each flv/rtmp packet contains them: + // audiosamplerate, sample->sound_rate + // audiosamplesize, sample->sound_size + // stereo, sample->sound_type + + return ret; } int SrsHls::on_audio(SrsSharedPtrMessage* audio) { - int ret = ERROR_SUCCESS; - - SrsAutoFree(SrsSharedPtrMessage, audio, false); - - if (!hls_enabled) { - return ret; - } - - sample->clear(); - if ((ret = codec->audio_aac_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { - srs_error("codec demux audio failed. ret=%d", ret); - return ret; - } - - if (codec->audio_codec_id != SrsCodecAudioAAC) { - return ret; - } - - // ignore sequence header - if (sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) { - return ret; - } - - if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { - srs_error("rtmp jitter correct audio failed. ret=%d", ret); - return ret; - } - - // the pts calc from rtmp/flv header. - int64_t pts = audio->header.timestamp * 90; - - if ((ret = ts_cache->write_audio(codec, muxer, pts, sample)) != ERROR_SUCCESS) { - srs_error("ts cache write audio failed. ret=%d", ret); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + SrsAutoFree(SrsSharedPtrMessage, audio, false); + + if (!hls_enabled) { + return ret; + } + + sample->clear(); + if ((ret = codec->audio_aac_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { + srs_error("codec demux audio failed. ret=%d", ret); + return ret; + } + + if (codec->audio_codec_id != SrsCodecAudioAAC) { + return ret; + } + + // ignore sequence header + if (sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) { + return ret; + } + + if ((ret = jitter->correct(audio, 0, 0)) != ERROR_SUCCESS) { + srs_error("rtmp jitter correct audio failed. ret=%d", ret); + return ret; + } + + // the pts calc from rtmp/flv header. + int64_t pts = audio->header.timestamp * 90; + + if ((ret = ts_cache->write_audio(codec, muxer, pts, sample)) != ERROR_SUCCESS) { + srs_error("ts cache write audio failed. ret=%d", ret); + return ret; + } + + return ret; } int SrsHls::on_video(SrsSharedPtrMessage* video) { - int ret = ERROR_SUCCESS; - - SrsAutoFree(SrsSharedPtrMessage, video, false); - - if (!hls_enabled) { - return ret; - } - - sample->clear(); - if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) { - srs_error("codec demux video failed. ret=%d", ret); - return ret; - } - - if (codec->video_codec_id != SrsCodecVideoAVC) { - return ret; - } - - // ignore sequence header - if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame - && sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { - return ret; - } - - if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { - srs_error("rtmp jitter correct video failed. ret=%d", ret); - return ret; - } - - int64_t dts = video->header.timestamp * 90; - if ((ret = ts_cache->write_video(codec, muxer, dts, sample)) != ERROR_SUCCESS) { - srs_error("ts cache write video failed. ret=%d", ret); - return ret; - } - - hls_mux(); - - return ret; + int ret = ERROR_SUCCESS; + + SrsAutoFree(SrsSharedPtrMessage, video, false); + + if (!hls_enabled) { + return ret; + } + + sample->clear(); + if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) { + srs_error("codec demux video failed. ret=%d", ret); + return ret; + } + + if (codec->video_codec_id != SrsCodecVideoAVC) { + return ret; + } + + // ignore sequence header + if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame + && sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { + return ret; + } + + if ((ret = jitter->correct(video, 0, 0)) != ERROR_SUCCESS) { + srs_error("rtmp jitter correct video failed. ret=%d", ret); + return ret; + } + + int64_t dts = video->header.timestamp * 90; + if ((ret = ts_cache->write_video(codec, muxer, dts, sample)) != ERROR_SUCCESS) { + srs_error("ts cache write video failed. ret=%d", ret); + return ret; + } + + hls_mux(); + + return ret; } void SrsHls::hls_mux() { - // reportable - if (pithy_print->can_print()) { - srs_trace("-> time=%"PRId64"", pithy_print->get_age()); - } - - pithy_print->elapse(sample->cts); + // reportable + if (pithy_print->can_print()) { + srs_trace("-> time=%"PRId64"", pithy_print->get_age()); + } + + pithy_print->elapse(sample->cts); } #endif diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 9c09ca3d6..eb0e1ef35 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -56,40 +56,40 @@ class SrsSource; class SrsHlsAacJitter { private: - int64_t base_pts; - int64_t nb_samples; - int sync_ms; + int64_t base_pts; + int64_t nb_samples; + int sync_ms; public: - SrsHlsAacJitter(); - virtual ~SrsHlsAacJitter(); - /** - * when buffer start, calc the "correct" pts for ts, - * @param flv_pts, the flv pts calc from flv header timestamp, - * @return the calc correct pts. - */ - virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate); - /** - * when buffer continue, muxer donot write to file, - * the audio buffer continue grow and donot need a pts, - * for the ts audio PES packet only has one pts at the first time. - */ - virtual void on_buffer_continue(); + SrsHlsAacJitter(); + virtual ~SrsHlsAacJitter(); + /** + * when buffer start, calc the "correct" pts for ts, + * @param flv_pts, the flv pts calc from flv header timestamp, + * @return the calc correct pts. + */ + virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate); + /** + * when buffer continue, muxer donot write to file, + * the audio buffer continue grow and donot need a pts, + * for the ts audio PES packet only has one pts at the first time. + */ + virtual void on_buffer_continue(); }; //TODO: refine the ts muxer, do more jobs. class SrsTSMuxer { private: - int fd; - std::string path; + int fd; + std::string path; public: - SrsTSMuxer(); - virtual ~SrsTSMuxer(); + SrsTSMuxer(); + virtual ~SrsTSMuxer(); public: - virtual int open(std::string _path); - virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); - virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb); - virtual void close(); + virtual int open(std::string _path); + virtual int write_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); + virtual int write_video(SrsMpegtsFrame* vf, SrsCodecBuffer* vb); + virtual void close(); }; /** @@ -98,26 +98,26 @@ public: */ struct SrsM3u8Segment { - // duration in seconds in m3u8. - double duration; - // sequence number in m3u8. - int sequence_no; - // ts uri in m3u8. - std::string uri; - // ts full file to write. - std::string full_path; - // the muxer to write ts. - SrsTSMuxer* muxer; - // current segment start dts for m3u8 - int64_t segment_start_dts; - - SrsM3u8Segment(); - virtual ~SrsM3u8Segment(); - - /** - * update the segment duration. - */ - virtual double update_duration(int64_t video_stream_dts); + // duration in seconds in m3u8. + double duration; + // sequence number in m3u8. + int sequence_no; + // ts uri in m3u8. + std::string uri; + // ts full file to write. + std::string full_path; + // the muxer to write ts. + SrsTSMuxer* muxer; + // current segment start dts for m3u8 + int64_t segment_start_dts; + + SrsM3u8Segment(); + virtual ~SrsM3u8Segment(); + + /** + * update the segment duration. + */ + virtual double update_duration(int64_t video_stream_dts); }; /** @@ -126,39 +126,39 @@ struct SrsM3u8Segment class SrsM3u8Muxer { private: - std::string app; - std::string stream; + std::string app; + std::string stream; private: - std::string hls_path; - int hls_fragment; - int hls_window; + std::string hls_path; + int hls_fragment; + int hls_window; private: - int file_index; - std::string m3u8; + int file_index; + std::string m3u8; private: - /** - * m3u8 segments. - */ - std::vector segments; - /** - * current writing segment. - */ - SrsM3u8Segment* current; - // last known dts - int64_t video_stream_dts; + /** + * m3u8 segments. + */ + std::vector segments; + /** + * current writing segment. + */ + SrsM3u8Segment* current; + // last known dts + int64_t video_stream_dts; public: - SrsM3u8Muxer(); - virtual ~SrsM3u8Muxer(); + SrsM3u8Muxer(); + virtual ~SrsM3u8Muxer(); public: - virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window); - virtual int segment_open(); - virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); - virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb); - virtual int segment_close(); + virtual int update_config(std::string _app, std::string _stream, std::string path, int fragment, int window); + virtual int segment_open(); + virtual int flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab); + virtual int flush_video(SrsMpegtsFrame* af, SrsCodecBuffer* ab, SrsMpegtsFrame* vf, SrsCodecBuffer* vb); + virtual int segment_close(); private: - virtual int refresh_m3u8(); - virtual int _refresh_m3u8(int& fd, std::string m3u8_file); - virtual int create_dir(); + virtual int refresh_m3u8(); + virtual int _refresh_m3u8(int& fd, std::string m3u8_file); + virtual int create_dir(); }; /** @@ -167,35 +167,35 @@ private: class SrsTSCache { private: - // current frame and buffer - SrsMpegtsFrame* af; - SrsCodecBuffer* ab; - SrsMpegtsFrame* vf; - SrsCodecBuffer* vb; + // current frame and buffer + SrsMpegtsFrame* af; + SrsCodecBuffer* ab; + SrsMpegtsFrame* vf; + SrsCodecBuffer* vb; private: - // the audio cache buffer start pts, to flush audio if full. - int64_t audio_buffer_start_pts; - // time jitter for aac - SrsHlsAacJitter* aac_jitter; + // the audio cache buffer start pts, to flush audio if full. + int64_t audio_buffer_start_pts; + // time jitter for aac + SrsHlsAacJitter* aac_jitter; public: - SrsTSCache(); - virtual ~SrsTSCache(); + SrsTSCache(); + virtual ~SrsTSCache(); public: - /** - * write audio to cache, if need to flush, flush to muxer. - */ - virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample); - /** - * write video to muxer. - */ - virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample); - /** - * flush audio in cache to muxer. - */ - virtual int flush_audio(SrsM3u8Muxer* muxer); + /** + * write audio to cache, if need to flush, flush to muxer. + */ + virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample); + /** + * write video to muxer. + */ + virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample); + /** + * flush audio in cache to muxer. + */ + virtual int flush_audio(SrsM3u8Muxer* muxer); private: - virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample); - virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample); + virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample); + virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample); }; /** @@ -204,43 +204,43 @@ private: class SrsHls { private: - SrsM3u8Muxer* muxer; - SrsTSCache* ts_cache; + SrsM3u8Muxer* muxer; + SrsTSCache* ts_cache; private: - bool hls_enabled; - SrsSource* source; - SrsCodec* codec; - SrsCodecSample* sample; - SrsRtmpJitter* jitter; - SrsPithyPrint* pithy_print; + bool hls_enabled; + SrsSource* source; + SrsCodec* codec; + SrsCodecSample* sample; + SrsRtmpJitter* jitter; + SrsPithyPrint* pithy_print; public: - SrsHls(SrsSource* _source); - virtual ~SrsHls(); + SrsHls(SrsSource* _source); + virtual ~SrsHls(); public: - /** - * publish stream event, continue to write the m3u8, - * for the muxer object not destroyed. - */ - virtual int on_publish(SrsRequest* req); - /** - * the unpublish event, only close the muxer, donot destroy the - * muxer, for when we continue to publish, the m3u8 will continue. - */ - virtual void on_unpublish(); - /** - * get some information from metadata, it's optinal. - */ - virtual int on_meta_data(SrsAmf0Object* metadata); - /** - * mux the audio packets to ts. - */ - virtual int on_audio(SrsSharedPtrMessage* audio); - /** - * mux the video packets to ts. - */ - virtual int on_video(SrsSharedPtrMessage* video); + /** + * publish stream event, continue to write the m3u8, + * for the muxer object not destroyed. + */ + virtual int on_publish(SrsRequest* req); + /** + * the unpublish event, only close the muxer, donot destroy the + * muxer, for when we continue to publish, the m3u8 will continue. + */ + virtual void on_unpublish(); + /** + * get some information from metadata, it's optinal. + */ + virtual int on_meta_data(SrsAmf0Object* metadata); + /** + * mux the audio packets to ts. + */ + virtual int on_audio(SrsSharedPtrMessage* audio); + /** + * mux the video packets to ts. + */ + virtual int on_video(SrsSharedPtrMessage* video); private: - virtual void hls_mux(); + virtual void hls_mux(); }; #endif diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index fd640c02b..83af8e4df 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsHttpUri::SrsHttpUri() { - port = SRS_DEFAULT_HTTP_PORT; + port = SRS_DEFAULT_HTTP_PORT; } SrsHttpUri::~SrsHttpUri() @@ -51,7 +51,7 @@ SrsHttpUri::~SrsHttpUri() int SrsHttpUri::initialize(std::string _url) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; url = _url; const char* purl = url.c_str(); @@ -65,7 +65,7 @@ int SrsHttpUri::initialize(std::string _url) return ret; } - std::string field = get_uri_field(url, &hp_u, UF_SCHEMA); + std::string field = get_uri_field(url, &hp_u, UF_SCHEMA); if(!field.empty()){ schema = field; } @@ -80,7 +80,7 @@ int SrsHttpUri::initialize(std::string _url) path = get_uri_field(url, &hp_u, UF_PATH); srs_info("parse url %s success", purl); - return ret; + return ret; } const char* SrsHttpUri::get_url() @@ -128,24 +128,24 @@ std::string SrsHttpUri::get_uri_field(std::string uri, http_parser_url* hp_u, ht SrsHttpClient::SrsHttpClient() { - connected = false; - stfd = NULL; + connected = false; + stfd = NULL; } SrsHttpClient::~SrsHttpClient() { - disconnect(); + disconnect(); } int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res) { - int ret = ERROR_SUCCESS; - - if ((ret = connect(uri)) != ERROR_SUCCESS) { - srs_error("http connect server failed. ret=%d", ret); - return ret; - } - + int ret = ERROR_SUCCESS; + + if ((ret = connect(uri)) != ERROR_SUCCESS) { + srs_error("http connect server failed. ret=%d", ret); + return ret; + } + // send POST request to uri // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s std::stringstream ss; @@ -176,33 +176,33 @@ int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res) return ret; } srs_info("parse http post response success."); - - return ret; + + return ret; } void SrsHttpClient::disconnect() { - connected = false; - - srs_close_stfd(stfd); + connected = false; + + srs_close_stfd(stfd); } int SrsHttpClient::connect(SrsHttpUri* uri) { - int ret = ERROR_SUCCESS; - - if (connected) { - return ret; - } - - disconnect(); - - std::string ip = srs_dns_resolve(uri->get_host()); - if (ip.empty()) { - ret = ERROR_SYSTEM_IP_INVALID; - srs_error("dns resolve server error, ip empty. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + if (connected) { + return ret; + } + + disconnect(); + + std::string ip = srs_dns_resolve(uri->get_host()); + if (ip.empty()) { + ret = ERROR_SYSTEM_IP_INVALID; + srs_error("dns resolve server error, ip empty. ret=%d", ret); + return ret; + } int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1){ @@ -217,7 +217,7 @@ int SrsHttpClient::connect(SrsHttpUri* uri) srs_error("st_netfd_open_socket failed. ret=%d", ret); return ret; } - + sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(uri->get_port()); @@ -226,16 +226,16 @@ int SrsHttpClient::connect(SrsHttpUri* uri) if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){ ret = ERROR_ST_CONNECT; srs_error("connect to server error. " - "ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret); + "ip=%s, port=%d, ret=%d", ip.c_str(), uri->get_port(), ret); return ret; } srs_info("connect to server success. " - "http url=%s, server=%s, ip=%s, port=%d", - uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port()); + "http url=%s, server=%s, ip=%s, port=%d", + uri->get_url(), uri->get_host(), ip.c_str(), uri->get_port()); connected = true; - return ret; + return ret; } int SrsHttpClient::parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response) @@ -327,17 +327,17 @@ int SrsHttpClient::parse_response_body(SrsHttpUri* uri, SrsSocket* skt, std::str char buf[SRS_HTTP_BODY_BUFFER]; return parse_response_body_data( - uri, skt, response, (size_t)body_left, - (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER + uri, skt, response, (size_t)body_left, + (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER ); } else { // if ignore response, use shared fast memory. static char buf[SRS_HTTP_BODY_BUFFER]; return parse_response_body_data( - uri, skt, response, (size_t)body_left, - (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER - ); + uri, skt, response, (size_t)body_left, + (const void*)buf, (size_t)SRS_HTTP_BODY_BUFFER + ); } return ret; @@ -351,7 +351,7 @@ int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std while (body_left > 0) { ssize_t nread; - int size_to_read = srs_min(size, body_left); + int size_to_read = srs_min(size, body_left); if ((ret = skt->read(buf, size_to_read, &nread)) != ERROR_SUCCESS) { srs_error("read header from server failed. ret=%d", ret); return ret; @@ -394,424 +394,424 @@ SrsHttpHooks::~SrsHttpHooks() int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_connect url failed. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - - /** - { - "action": "on_connect", - "client_id": 1985, - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", - "pageUrl": "http://www.test.com/live.html" - } + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_error("http uri parse on_connect url failed. " + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); + return ret; + } + + /** + { + "action": "on_connect", + "client_id": 1985, + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", + "pageUrl": "http://www.test.com/live.html" + } */ - std::stringstream ss; - ss << "{" - // action - << '"' << "action" << '"' << ':' - << '"' << "on_connect" << '"' - << ',' - // client_id - << '"' << "client_id" << '"' << ':' - << std::dec << client_id - << ',' - // ip - << '"' << "ip" << '"' << ':' - << '"' << ip << '"' - << ',' - // vhost - << '"' << "vhost" << '"' << ':' - << '"' << req->vhost << '"' - << ',' - // app - << '"' << "app" << '"' << ':' - << '"' << req->app << '"' - << ',' - // pageUrl - << '"' << "pageUrl" << '"' << ':' - << '"' << req->pageUrl << '"' - //<< ',' - << "}"; - std::string data = ss.str(); - std::string res; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { - srs_error("http post on_connect uri failed. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_error("http hook on_connect validate failed. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); - return ret; - } - - srs_trace("http hook on_connect success. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - - return ret; + std::stringstream ss; + ss << "{" + // action + << '"' << "action" << '"' << ':' + << '"' << "on_connect" << '"' + << ',' + // client_id + << '"' << "client_id" << '"' << ':' + << std::dec << client_id + << ',' + // ip + << '"' << "ip" << '"' << ':' + << '"' << ip << '"' + << ',' + // vhost + << '"' << "vhost" << '"' << ':' + << '"' << req->vhost << '"' + << ',' + // app + << '"' << "app" << '"' << ':' + << '"' << req->app << '"' + << ',' + // pageUrl + << '"' << "pageUrl" << '"' << ':' + << '"' << req->pageUrl << '"' + //<< ',' + << "}"; + std::string data = ss.str(); + std::string res; + + SrsHttpClient http; + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { + srs_error("http post on_connect uri failed. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + return ret; + } + + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + ret = ERROR_HTTP_DATA_INVLIAD; + srs_error("http hook on_connect validate failed. " + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + return ret; + } + + srs_trace("http hook on_connect success. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + + return ret; } void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_warn("http uri parse on_close url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return; - } - - /** - { - "action": "on_close", - "client_id": 1985, - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", - "stream": "livestream" - } + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_warn("http uri parse on_close url failed, ignored. " + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); + return; + } + + /** + { + "action": "on_close", + "client_id": 1985, + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", + "stream": "livestream" + } */ - std::stringstream ss; - ss << "{" - // action - << '"' << "action" << '"' << ':' - << '"' << "on_close" << '"' - << ',' - // client_id - << '"' << "client_id" << '"' << ':' - << std::dec << client_id - << ',' - // ip - << '"' << "ip" << '"' << ':' - << '"' << ip << '"' - << ',' - // vhost - << '"' << "vhost" << '"' << ':' - << '"' << req->vhost << '"' - << ',' - // app - << '"' << "app" << '"' << ':' - << '"' << req->app << '"' - //<< ',' - << "}"; - std::string data = ss.str(); - std::string res; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { - srs_warn("http post on_close uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_close validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); - return; - } - - srs_trace("http hook on_close success. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - - return; + std::stringstream ss; + ss << "{" + // action + << '"' << "action" << '"' << ':' + << '"' << "on_close" << '"' + << ',' + // client_id + << '"' << "client_id" << '"' << ':' + << std::dec << client_id + << ',' + // ip + << '"' << "ip" << '"' << ':' + << '"' << ip << '"' + << ',' + // vhost + << '"' << "vhost" << '"' << ':' + << '"' << req->vhost << '"' + << ',' + // app + << '"' << "app" << '"' << ':' + << '"' << req->app << '"' + //<< ',' + << "}"; + std::string data = ss.str(); + std::string res; + + SrsHttpClient http; + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { + srs_warn("http post on_close uri failed, ignored. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + return; + } + + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + ret = ERROR_HTTP_DATA_INVLIAD; + srs_warn("http hook on_close validate failed, ignored. " + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + return; + } + + srs_trace("http hook on_close success. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + + return; } int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_publish url failed. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - - /** - { - "action": "on_publish", - "client_id": 1985, - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", - "stream": "livestream" - } + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_error("http uri parse on_publish url failed. " + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); + return ret; + } + + /** + { + "action": "on_publish", + "client_id": 1985, + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", + "stream": "livestream" + } */ - std::stringstream ss; - ss << "{" - // action - << '"' << "action" << '"' << ':' - << '"' << "on_publish" << '"' - << ',' - // client_id - << '"' << "client_id" << '"' << ':' - << std::dec << client_id - << ',' - // ip - << '"' << "ip" << '"' << ':' - << '"' << ip << '"' - << ',' - // vhost - << '"' << "vhost" << '"' << ':' - << '"' << req->vhost << '"' - << ',' - // app - << '"' << "app" << '"' << ':' - << '"' << req->app << '"' - << ',' - // stream - << '"' << "stream" << '"' << ':' - << '"' << req->stream << '"' - //<< ',' - << "}"; - std::string data = ss.str(); - std::string res; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { - srs_error("http post on_publish uri failed. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_error("http hook on_publish validate failed. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); - return ret; - } - - srs_trace("http hook on_publish success. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - - return ret; + std::stringstream ss; + ss << "{" + // action + << '"' << "action" << '"' << ':' + << '"' << "on_publish" << '"' + << ',' + // client_id + << '"' << "client_id" << '"' << ':' + << std::dec << client_id + << ',' + // ip + << '"' << "ip" << '"' << ':' + << '"' << ip << '"' + << ',' + // vhost + << '"' << "vhost" << '"' << ':' + << '"' << req->vhost << '"' + << ',' + // app + << '"' << "app" << '"' << ':' + << '"' << req->app << '"' + << ',' + // stream + << '"' << "stream" << '"' << ':' + << '"' << req->stream << '"' + //<< ',' + << "}"; + std::string data = ss.str(); + std::string res; + + SrsHttpClient http; + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { + srs_error("http post on_publish uri failed. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + return ret; + } + + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + ret = ERROR_HTTP_DATA_INVLIAD; + srs_error("http hook on_publish validate failed. " + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + return ret; + } + + srs_trace("http hook on_publish success. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + + return ret; } void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_warn("http uri parse on_unpublish url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return; - } - - /** - { - "action": "on_unpublish", - "client_id": 1985, - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", - "stream": "livestream" - } + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_warn("http uri parse on_unpublish url failed, ignored. " + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); + return; + } + + /** + { + "action": "on_unpublish", + "client_id": 1985, + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", + "stream": "livestream" + } */ - std::stringstream ss; - ss << "{" - // action - << '"' << "action" << '"' << ':' - << '"' << "on_unpublish" << '"' - << ',' - // client_id - << '"' << "client_id" << '"' << ':' - << std::dec << client_id - << ',' - // ip - << '"' << "ip" << '"' << ':' - << '"' << ip << '"' - << ',' - // vhost - << '"' << "vhost" << '"' << ':' - << '"' << req->vhost << '"' - << ',' - // app - << '"' << "app" << '"' << ':' - << '"' << req->app << '"' - << ',' - // stream - << '"' << "stream" << '"' << ':' - << '"' << req->stream << '"' - //<< ',' - << "}"; - std::string data = ss.str(); - std::string res; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { - srs_warn("http post on_unpublish uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_unpublish validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); - return; - } - - srs_trace("http hook on_unpublish success. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - - return; + std::stringstream ss; + ss << "{" + // action + << '"' << "action" << '"' << ':' + << '"' << "on_unpublish" << '"' + << ',' + // client_id + << '"' << "client_id" << '"' << ':' + << std::dec << client_id + << ',' + // ip + << '"' << "ip" << '"' << ':' + << '"' << ip << '"' + << ',' + // vhost + << '"' << "vhost" << '"' << ':' + << '"' << req->vhost << '"' + << ',' + // app + << '"' << "app" << '"' << ':' + << '"' << req->app << '"' + << ',' + // stream + << '"' << "stream" << '"' << ':' + << '"' << req->stream << '"' + //<< ',' + << "}"; + std::string data = ss.str(); + std::string res; + + SrsHttpClient http; + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { + srs_warn("http post on_unpublish uri failed, ignored. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + return; + } + + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + ret = ERROR_HTTP_DATA_INVLIAD; + srs_warn("http hook on_unpublish validate failed, ignored. " + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + return; + } + + srs_trace("http hook on_unpublish success. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + + return; } int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_error("http uri parse on_play url failed. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return ret; - } - - /** - { - "action": "on_play", - "client_id": 1985, - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", - "stream": "livestream" - } + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_error("http uri parse on_play url failed. " + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); + return ret; + } + + /** + { + "action": "on_play", + "client_id": 1985, + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", + "stream": "livestream" + } */ - std::stringstream ss; - ss << "{" - // action - << '"' << "action" << '"' << ':' - << '"' << "on_play" << '"' - << ',' - // client_id - << '"' << "client_id" << '"' << ':' - << std::dec << client_id - << ',' - // ip - << '"' << "ip" << '"' << ':' - << '"' << ip << '"' - << ',' - // vhost - << '"' << "vhost" << '"' << ':' - << '"' << req->vhost << '"' - << ',' - // app - << '"' << "app" << '"' << ':' - << '"' << req->app << '"' - << ',' - // stream - << '"' << "stream" << '"' << ':' - << '"' << req->stream << '"' - //<< ',' - << "}"; - std::string data = ss.str(); - std::string res; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { - srs_error("http post on_play uri failed. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return ret; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_error("http hook on_play validate failed. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); - return ret; - } - - srs_trace("http hook on_play success. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - - return ret; + std::stringstream ss; + ss << "{" + // action + << '"' << "action" << '"' << ':' + << '"' << "on_play" << '"' + << ',' + // client_id + << '"' << "client_id" << '"' << ':' + << std::dec << client_id + << ',' + // ip + << '"' << "ip" << '"' << ':' + << '"' << ip << '"' + << ',' + // vhost + << '"' << "vhost" << '"' << ':' + << '"' << req->vhost << '"' + << ',' + // app + << '"' << "app" << '"' << ':' + << '"' << req->app << '"' + << ',' + // stream + << '"' << "stream" << '"' << ':' + << '"' << req->stream << '"' + //<< ',' + << "}"; + std::string data = ss.str(); + std::string res; + + SrsHttpClient http; + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { + srs_error("http post on_play uri failed. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + return ret; + } + + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + ret = ERROR_HTTP_DATA_INVLIAD; + srs_error("http hook on_play validate failed. " + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + return ret; + } + + srs_trace("http hook on_play success. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + + return ret; } void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsHttpUri uri; - if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { - srs_warn("http uri parse on_stop url failed, ignored. " - "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); - return; - } - - /** - { - "action": "on_stop", - "client_id": 1985, - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", - "stream": "livestream" - } + int ret = ERROR_SUCCESS; + + SrsHttpUri uri; + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { + srs_warn("http uri parse on_stop url failed, ignored. " + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); + return; + } + + /** + { + "action": "on_stop", + "client_id": 1985, + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", + "stream": "livestream" + } */ - std::stringstream ss; - ss << "{" - // action - << '"' << "action" << '"' << ':' - << '"' << "on_stop" << '"' - << ',' - // client_id - << '"' << "client_id" << '"' << ':' - << std::dec << client_id - << ',' - // ip - << '"' << "ip" << '"' << ':' - << '"' << ip << '"' - << ',' - // vhost - << '"' << "vhost" << '"' << ':' - << '"' << req->vhost << '"' - << ',' - // app - << '"' << "app" << '"' << ':' - << '"' << req->app << '"' - << ',' - // stream - << '"' << "stream" << '"' << ':' - << '"' << req->stream << '"' - //<< ',' - << "}"; - std::string data = ss.str(); - std::string res; - - SrsHttpClient http; - if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { - srs_warn("http post on_stop uri failed, ignored. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - return; - } - - if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { - ret = ERROR_HTTP_DATA_INVLIAD; - srs_warn("http hook on_stop validate failed, ignored. " - "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); - return; - } - - srs_trace("http hook on_stop success. " - "client_id=%d, url=%s, request=%s, response=%s, ret=%d", - client_id, url.c_str(), data.c_str(), res.c_str(), ret); - - return; + std::stringstream ss; + ss << "{" + // action + << '"' << "action" << '"' << ':' + << '"' << "on_stop" << '"' + << ',' + // client_id + << '"' << "client_id" << '"' << ':' + << std::dec << client_id + << ',' + // ip + << '"' << "ip" << '"' << ':' + << '"' << ip << '"' + << ',' + // vhost + << '"' << "vhost" << '"' << ':' + << '"' << req->vhost << '"' + << ',' + // app + << '"' << "app" << '"' << ':' + << '"' << req->app << '"' + << ',' + // stream + << '"' << "stream" << '"' << ':' + << '"' << req->stream << '"' + //<< ',' + << "}"; + std::string data = ss.str(); + std::string res; + + SrsHttpClient http; + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { + srs_warn("http post on_stop uri failed, ignored. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + return; + } + + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { + ret = ERROR_HTTP_DATA_INVLIAD; + srs_warn("http hook on_stop validate failed, ignored. " + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); + return; + } + + srs_trace("http hook on_stop success. " + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", + client_id, url.c_str(), data.c_str(), res.c_str(), ret); + + return; } #endif diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index 357911254..795907f8f 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -40,8 +40,8 @@ class SrsSocket; #include -#define SRS_HTTP_HEADER_BUFFER 1024 -#define SRS_HTTP_BODY_BUFFER 32 * 1024 +#define SRS_HTTP_HEADER_BUFFER 1024 +#define SRS_HTTP_BODY_BUFFER 32 * 1024 /** * used to resolve the http uri. @@ -55,13 +55,13 @@ private: int port; std::string path; public: - SrsHttpUri(); - virtual ~SrsHttpUri(); + SrsHttpUri(); + virtual ~SrsHttpUri(); public: - /** - * initialize the http uri. - */ - virtual int initialize(std::string _url); + /** + * initialize the http uri. + */ + virtual int initialize(std::string _url); public: virtual const char* get_url(); virtual const char* get_schema(); @@ -82,23 +82,23 @@ private: class SrsHttpClient { private: - bool connected; - st_netfd_t stfd; + bool connected; + st_netfd_t stfd; private: http_parser http_header; public: - SrsHttpClient(); - virtual ~SrsHttpClient(); + SrsHttpClient(); + virtual ~SrsHttpClient(); public: - /** - * to post data to the uri. - * @param req the data post to uri. - * @param res the response data from server. - */ - virtual int post(SrsHttpUri* uri, std::string req, std::string& res); + /** + * to post data to the uri. + * @param req the data post to uri. + * @param res the response data from server. + */ + virtual int post(SrsHttpUri* uri, std::string req, std::string& res); private: - virtual void disconnect(); - virtual int connect(SrsHttpUri* uri); + virtual void disconnect(); + virtual int connect(SrsHttpUri* uri); private: virtual int parse_response(SrsHttpUri* uri, SrsSocket* skt, std::string* response); virtual int parse_response_header(SrsSocket* skt, std::string* response, int& body_received); @@ -117,54 +117,54 @@ private: class SrsHttpHooks { public: - SrsHttpHooks(); - virtual ~SrsHttpHooks(); + SrsHttpHooks(); + virtual ~SrsHttpHooks(); public: - /** - * on_connect hook, when client connect to srs. - * @param client_id the id of client on server. - * @param url the api server url, to valid the client. - * ignore if empty. - * @return valid failed or connect to the url failed. - */ - virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req); - /** - * on_close hook, when client disconnect to srs, where client is valid by on_connect. - * @param client_id the id of client on server. - * @param url the api server url, to process the event. - * ignore if empty. - */ - virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req); - /** - * on_publish hook, when client(encoder) start to publish stream - * @param client_id the id of client on server. - * @param url the api server url, to valid the client. - * ignore if empty. - * @return valid failed or connect to the url failed. - */ - virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req); - /** - * on_unpublish hook, when client(encoder) stop publish stream. - * @param client_id the id of client on server. - * @param url the api server url, to process the event. - * ignore if empty. - */ - virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req); - /** - * on_play hook, when client start to play stream. - * @param client_id the id of client on server. - * @param url the api server url, to valid the client. - * ignore if empty. - * @return valid failed or connect to the url failed. - */ - virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req); - /** - * on_stop hook, when client stop to play the stream. - * @param client_id the id of client on server. - * @param url the api server url, to process the event. - * ignore if empty. - */ - virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req); + /** + * on_connect hook, when client connect to srs. + * @param client_id the id of client on server. + * @param url the api server url, to valid the client. + * ignore if empty. + * @return valid failed or connect to the url failed. + */ + virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req); + /** + * on_close hook, when client disconnect to srs, where client is valid by on_connect. + * @param client_id the id of client on server. + * @param url the api server url, to process the event. + * ignore if empty. + */ + virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req); + /** + * on_publish hook, when client(encoder) start to publish stream + * @param client_id the id of client on server. + * @param url the api server url, to valid the client. + * ignore if empty. + * @return valid failed or connect to the url failed. + */ + virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req); + /** + * on_unpublish hook, when client(encoder) stop publish stream. + * @param client_id the id of client on server. + * @param url the api server url, to process the event. + * ignore if empty. + */ + virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req); + /** + * on_play hook, when client start to play stream. + * @param client_id the id of client on server. + * @param url the api server url, to valid the client. + * ignore if empty. + * @return valid failed or connect to the url failed. + */ + virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req); + /** + * on_stop hook, when client stop to play the stream. + * @param client_id the id of client on server. + * @param url the api server url, to process the event. + * ignore if empty. + */ + virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req); }; #endif diff --git a/trunk/src/app/srs_app_log.cpp b/trunk/src/app/srs_app_log.cpp index 3de374f4e..2c877e52a 100644 --- a/trunk/src/app/srs_app_log.cpp +++ b/trunk/src/app/srs_app_log.cpp @@ -36,7 +36,7 @@ SrsThreadContext::~SrsThreadContext() void SrsThreadContext::generate_id() { - static int id = 1; + static int id = 1; cache[st_thread_self()] = id++; } @@ -55,7 +55,7 @@ int SrsThreadContext::get_id() SrsFastLog::SrsFastLog() { - level = SrsLogLevel::Trace; + level = SrsLogLevel::Trace; log_data = new char[LOG_MAX_SIZE]; } @@ -185,15 +185,15 @@ bool SrsFastLog::generate_header(const char* tag, int context_id, const char* le int log_header_size = -1; if (tag) { - log_header_size = snprintf(log_data, LOG_MAX_SIZE, - "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ", - 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), - level_name, tag, context_id, errno); + log_header_size = snprintf(log_data, LOG_MAX_SIZE, + "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%s][%d][%d] ", + 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), + level_name, tag, context_id, errno); } else { - log_header_size = snprintf(log_data, LOG_MAX_SIZE, - "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ", - 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), - level_name, context_id, errno); + log_header_size = snprintf(log_data, LOG_MAX_SIZE, + "[%d-%02d-%02d %02d:%02d:%02d.%03d][%s][%d][%d] ", + 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(tv.tv_usec / 1000), + level_name, context_id, errno); } if (log_header_size == -1) { diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index 134cbb115..6438021d8 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -35,132 +35,132 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. struct SrsStageInfo : public ISrsReloadHandler { - int stage_id; - int pithy_print_time_ms; - int nb_clients; - - SrsStageInfo(int _stage_id) - { - stage_id = _stage_id; - nb_clients = 0; - - update_print_time(); - - _srs_config->subscribe(this); - } - virtual ~SrsStageInfo() - { - _srs_config->unsubscribe(this); - } - void update_print_time() - { - switch (stage_id) { - case SRS_STAGE_PLAY_USER: { - pithy_print_time_ms = _srs_config->get_pithy_print_play(); - break; - } - case SRS_STAGE_PUBLISH_USER: { - pithy_print_time_ms = _srs_config->get_pithy_print_publish(); - break; - } - case SRS_STAGE_FORWARDER: { - pithy_print_time_ms = _srs_config->get_pithy_print_forwarder(); - break; - } - case SRS_STAGE_ENCODER: { - pithy_print_time_ms = _srs_config->get_pithy_print_encoder(); - break; - } - case SRS_STAGE_HLS: { - pithy_print_time_ms = _srs_config->get_pithy_print_hls(); - break; - } - default: { - pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS; - break; - } - } - } + int stage_id; + int pithy_print_time_ms; + int nb_clients; + + SrsStageInfo(int _stage_id) + { + stage_id = _stage_id; + nb_clients = 0; + + update_print_time(); + + _srs_config->subscribe(this); + } + virtual ~SrsStageInfo() + { + _srs_config->unsubscribe(this); + } + void update_print_time() + { + switch (stage_id) { + case SRS_STAGE_PLAY_USER: { + pithy_print_time_ms = _srs_config->get_pithy_print_play(); + break; + } + case SRS_STAGE_PUBLISH_USER: { + pithy_print_time_ms = _srs_config->get_pithy_print_publish(); + break; + } + case SRS_STAGE_FORWARDER: { + pithy_print_time_ms = _srs_config->get_pithy_print_forwarder(); + break; + } + case SRS_STAGE_ENCODER: { + pithy_print_time_ms = _srs_config->get_pithy_print_encoder(); + break; + } + case SRS_STAGE_HLS: { + pithy_print_time_ms = _srs_config->get_pithy_print_hls(); + break; + } + default: { + pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS; + break; + } + } + } public: - virtual int on_reload_pithy_print() - { - update_print_time(); - return ERROR_SUCCESS; - } + virtual int on_reload_pithy_print() + { + update_print_time(); + return ERROR_SUCCESS; + } }; static std::map _srs_stages; SrsPithyPrint::SrsPithyPrint(int _stage_id) { - stage_id = _stage_id; - client_id = enter_stage(); - printed_age = age = 0; + stage_id = _stage_id; + client_id = enter_stage(); + printed_age = age = 0; } SrsPithyPrint::~SrsPithyPrint() { - leave_stage(); + leave_stage(); } int SrsPithyPrint::enter_stage() { - SrsStageInfo* stage = NULL; - - std::map::iterator it = _srs_stages.find(stage_id); - if (it == _srs_stages.end()) { - stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id); - } else { - stage = it->second; - } - - srs_assert(stage != NULL); - client_id = stage->nb_clients++; + SrsStageInfo* stage = NULL; + + std::map::iterator it = _srs_stages.find(stage_id); + if (it == _srs_stages.end()) { + stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id); + } else { + stage = it->second; + } + + srs_assert(stage != NULL); + client_id = stage->nb_clients++; - srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", - stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms); - - return client_id; + srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", + stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms); + + return client_id; } void SrsPithyPrint::leave_stage() { - SrsStageInfo* stage = _srs_stages[stage_id]; - srs_assert(stage != NULL); - - stage->nb_clients--; + SrsStageInfo* stage = _srs_stages[stage_id]; + srs_assert(stage != NULL); + + stage->nb_clients--; - srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", - stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms); + srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", + stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms); } void SrsPithyPrint::elapse(int64_t time_ms) { - age += time_ms; + age += time_ms; } bool SrsPithyPrint::can_print() { - SrsStageInfo* stage = _srs_stages[stage_id]; - srs_assert(stage != NULL); - - int64_t alive_age = age - printed_age; - int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms; - - bool can_print = alive_age >= can_print_age; - if (can_print) { - printed_age = age; - } - - return can_print; + SrsStageInfo* stage = _srs_stages[stage_id]; + srs_assert(stage != NULL); + + int64_t alive_age = age - printed_age; + int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms; + + bool can_print = alive_age >= can_print_age; + if (can_print) { + printed_age = age; + } + + return can_print; } int64_t SrsPithyPrint::get_age() { - return age; + return age; } void SrsPithyPrint::set_age(int64_t _age) { - age = _age; + age = _age; } diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index f93b0acfc..d15f65aa5 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -50,39 +50,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsPithyPrint { private: - int client_id; - int stage_id; - int64_t age; - int64_t printed_age; + int client_id; + int stage_id; + int64_t age; + int64_t printed_age; public: - /** - * @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER. - */ - SrsPithyPrint(int _stage_id); - virtual ~SrsPithyPrint(); + /** + * @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER. + */ + SrsPithyPrint(int _stage_id); + virtual ~SrsPithyPrint(); private: - /** - * enter the specified stage, return the client id. - */ - virtual int enter_stage(); - /** - * leave the specified stage, release the client id. - */ - virtual void leave_stage(); + /** + * enter the specified stage, return the client id. + */ + virtual int enter_stage(); + /** + * leave the specified stage, release the client id. + */ + virtual void leave_stage(); public: - /** - * specified client elapse some time. - */ - virtual void elapse(int64_t time_ms); - /** - * whether current client can print. - */ - virtual bool can_print(); - /** - * get the elapsed time in ms. - */ - virtual int64_t get_age(); - virtual void set_age(int64_t _age); + /** + * specified client elapse some time. + */ + virtual void elapse(int64_t time_ms); + /** + * whether current client can print. + */ + virtual bool can_print(); + /** + * get the elapsed time in ms. + */ + virtual int64_t get_age(); + virtual void set_age(int64_t _age); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_refer.cpp b/trunk/src/app/srs_app_refer.cpp index 1b157f015..ecf897d3e 100644 --- a/trunk/src/app/srs_app_refer.cpp +++ b/trunk/src/app/srs_app_refer.cpp @@ -29,60 +29,60 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. int SrsRefer::check(std::string page_url, SrsConfDirective* refer) { - int ret = ERROR_SUCCESS; - - if (!refer) { - srs_verbose("ignore refer check for page_url=%s", page_url.c_str()); - return ret; - } - - for (int i = 0; i < (int)refer->args.size(); i++) { - if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) { - srs_verbose("check refer success. page_url=%s, refer=%s", - page_url.c_str(), refer->args.at(i).c_str()); - return ret; - } - } - - ret = ERROR_RTMP_ACCESS_DENIED; - srs_error("check refer failed. ret=%d", ret); - - return ret; + int ret = ERROR_SUCCESS; + + if (!refer) { + srs_verbose("ignore refer check for page_url=%s", page_url.c_str()); + return ret; + } + + for (int i = 0; i < (int)refer->args.size(); i++) { + if ((ret = check_single_refer(page_url, refer->args.at(i))) == ERROR_SUCCESS) { + srs_verbose("check refer success. page_url=%s, refer=%s", + page_url.c_str(), refer->args.at(i).c_str()); + return ret; + } + } + + ret = ERROR_RTMP_ACCESS_DENIED; + srs_error("check refer failed. ret=%d", ret); + + return ret; } int SrsRefer::check_single_refer(std::string page_url, std::string refer) { - int ret = ERROR_SUCCESS; - - size_t pos = std::string::npos; - - std::string domain_name = page_url; - if ((pos = domain_name.find("://")) != std::string::npos) { - domain_name = domain_name.substr(pos + 3); - } - - if ((pos = domain_name.find("/")) != std::string::npos) { - domain_name = domain_name.substr(0, pos); - } - - if ((pos = domain_name.find(":")) != std::string::npos) { - domain_name = domain_name.substr(0, pos); - } - - pos = domain_name.find(refer); - if (pos == std::string::npos) { - ret = ERROR_RTMP_ACCESS_DENIED; - } - // match primary domain. - if (pos != domain_name.length() - refer.length()) { - ret = ERROR_RTMP_ACCESS_DENIED; - } - - if (ret != ERROR_SUCCESS) { - srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d", - page_url.c_str(), domain_name.c_str(), refer.c_str(), ret); - } - - return ret; + int ret = ERROR_SUCCESS; + + size_t pos = std::string::npos; + + std::string domain_name = page_url; + if ((pos = domain_name.find("://")) != std::string::npos) { + domain_name = domain_name.substr(pos + 3); + } + + if ((pos = domain_name.find("/")) != std::string::npos) { + domain_name = domain_name.substr(0, pos); + } + + if ((pos = domain_name.find(":")) != std::string::npos) { + domain_name = domain_name.substr(0, pos); + } + + pos = domain_name.find(refer); + if (pos == std::string::npos) { + ret = ERROR_RTMP_ACCESS_DENIED; + } + // match primary domain. + if (pos != domain_name.length() - refer.length()) { + ret = ERROR_RTMP_ACCESS_DENIED; + } + + if (ret != ERROR_SUCCESS) { + srs_verbose("access denied, page_url=%s, domain_name=%s, refer=%s, ret=%d", + page_url.c_str(), domain_name.c_str(), refer.c_str(), ret); + } + + return ret; } diff --git a/trunk/src/app/srs_app_refer.hpp b/trunk/src/app/srs_app_refer.hpp index 7e26b6188..9e327beb7 100644 --- a/trunk/src/app/srs_app_refer.hpp +++ b/trunk/src/app/srs_app_refer.hpp @@ -36,14 +36,14 @@ class SrsConfDirective; class SrsRefer { public: - /** - * to check the refer. - * @param page_url the client page url. - * @param refer the refer in config. - */ - virtual int check(std::string page_url, SrsConfDirective* refer); + /** + * to check the refer. + * @param page_url the client page url. + * @param refer the refer in config. + */ + virtual int check(std::string page_url, SrsConfDirective* refer); private: - virtual int check_single_refer(std::string page_url, std::string refer); + virtual int check_single_refer(std::string page_url, std::string refer); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index f69d24a3f..58a945df6 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -37,41 +37,41 @@ ISrsReloadHandler::~ISrsReloadHandler() int ISrsReloadHandler::on_reload_listen() { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_pithy_print() { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_vhost_removed(string /*vhost*/) { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_gop_cache(string /*vhost*/) { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_queue_length(string /*vhost*/) { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_forward(string /*vhost*/) { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_hls(string /*vhost*/) { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } int ISrsReloadHandler::on_reload_transcode(string /*vhost*/) { - return ERROR_SUCCESS; + return ERROR_SUCCESS; } diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index 1e2c64a90..de4cddf11 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -37,17 +37,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class ISrsReloadHandler { public: - ISrsReloadHandler(); - virtual ~ISrsReloadHandler(); + ISrsReloadHandler(); + virtual ~ISrsReloadHandler(); public: - virtual int on_reload_listen(); - virtual int on_reload_pithy_print(); - virtual int on_reload_vhost_removed(std::string vhost); - virtual int on_reload_gop_cache(std::string vhost); - virtual int on_reload_queue_length(std::string vhost); - virtual int on_reload_forward(std::string vhost); - virtual int on_reload_hls(std::string vhost); - virtual int on_reload_transcode(std::string vhost); + virtual int on_reload_listen(); + virtual int on_reload_pithy_print(); + virtual int on_reload_vhost_removed(std::string vhost); + virtual int on_reload_gop_cache(std::string vhost); + virtual int on_reload_queue_length(std::string vhost); + virtual int on_reload_forward(std::string vhost); + virtual int on_reload_hls(std::string vhost); + virtual int on_reload_transcode(std::string vhost); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index b10f364eb..5ae8640c0 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -40,40 +40,40 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsListener::SrsListener(SrsServer* _server, SrsListenerType _type) { - fd = -1; - stfd = NULL; - - port = 0; - server = _server; - type = _type; + fd = -1; + stfd = NULL; + + port = 0; + server = _server; + type = _type; - pthread = new SrsThread(this, 0); + pthread = new SrsThread(this, 0); } SrsListener::~SrsListener() { - srs_close_stfd(stfd); - - pthread->stop(); - srs_freep(pthread); - - // st does not close it sometimes, - // close it manually. - close(fd); + srs_close_stfd(stfd); + + pthread->stop(); + srs_freep(pthread); + + // st does not close it sometimes, + // close it manually. + close(fd); } int SrsListener::listen(int _port) { - int ret = ERROR_SUCCESS; - - port = _port; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + int ret = ERROR_SUCCESS; + + port = _port; + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { ret = ERROR_SOCKET_CREATE; srs_error("create linux socket error. ret=%d", ret); return ret; - } - srs_verbose("create linux socket success. fd=%d", fd); + } + srs_verbose("create linux socket success. fd=%d", fd); int reuse_socket = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) { @@ -115,19 +115,19 @@ int SrsListener::listen(int _port) srs_verbose("create st listen thread success."); srs_trace("server started, listen at port=%d, fd=%d", port, fd); - - return ret; + + return ret; } void SrsListener::on_enter_loop() { - srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); + srs_trace("listen cycle start, port=%d, type=%d, fd=%d", port, type, fd); } int SrsListener::cycle() { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); if(client_stfd == NULL){ @@ -136,45 +136,45 @@ int SrsListener::cycle() return ret; } srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); - - if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { - srs_warn("accept client error. ret=%d", ret); - return ret; - } - - srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); - - return ret; + + if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { + srs_warn("accept client error. ret=%d", ret); + return ret; + } + + srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); + + return ret; } SrsServer::SrsServer() { - signal_reload = false; - signal_gmc_stop = false; - - srs_assert(_srs_config); - _srs_config->subscribe(this); + signal_reload = false; + signal_gmc_stop = false; + + srs_assert(_srs_config); + _srs_config->subscribe(this); } SrsServer::~SrsServer() { - _srs_config->unsubscribe(this); - - if (true) { - std::vector::iterator it; - for (it = conns.begin(); it != conns.end(); ++it) { - SrsConnection* conn = *it; - srs_freep(conn); - } - conns.clear(); - } - - close_listeners(); + _srs_config->unsubscribe(this); + + if (true) { + std::vector::iterator it; + for (it = conns.begin(); it != conns.end(); ++it) { + SrsConnection* conn = *it; + srs_freep(conn); + } + conns.clear(); + } + + close_listeners(); } int SrsServer::initialize() { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; // use linux epoll. if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) { @@ -190,159 +190,159 @@ int SrsServer::initialize() return ret; } srs_verbose("st_init success"); - - // set current log id. - _srs_context->generate_id(); - srs_info("log set id success"); - - return ret; + + // set current log id. + _srs_context->generate_id(); + srs_info("log set id success"); + + return ret; } int SrsServer::listen() { - int ret = ERROR_SUCCESS; - - SrsConfDirective* conf = NULL; - - // stream service port. - conf = _srs_config->get_listen(); - srs_assert(conf); - - close_listeners(); - - for (int i = 0; i < (int)conf->args.size(); i++) { - SrsListener* listener = new SrsListener(this, SrsListenerStream); - listeners.push_back(listener); - - int port = ::atoi(conf->args.at(i).c_str()); - if ((ret = listener->listen(port)) != ERROR_SUCCESS) { - srs_error("listen at port %d failed. ret=%d", port, ret); - return ret; - } - } - - return ret; + int ret = ERROR_SUCCESS; + + SrsConfDirective* conf = NULL; + + // stream service port. + conf = _srs_config->get_listen(); + srs_assert(conf); + + close_listeners(); + + for (int i = 0; i < (int)conf->args.size(); i++) { + SrsListener* listener = new SrsListener(this, SrsListenerStream); + listeners.push_back(listener); + + int port = ::atoi(conf->args.at(i).c_str()); + if ((ret = listener->listen(port)) != ERROR_SUCCESS) { + srs_error("listen at port %d failed. ret=%d", port, ret); + return ret; + } + } + + return ret; } int SrsServer::cycle() { - int ret = ERROR_SUCCESS; - - // the deamon thread, update the time cache - while (true) { - st_usleep(SRS_TIME_RESOLUTION_MS * 1000); - srs_update_system_time_ms(); - + int ret = ERROR_SUCCESS; + + // the deamon thread, update the time cache + while (true) { + st_usleep(SRS_TIME_RESOLUTION_MS * 1000); + srs_update_system_time_ms(); + // for gperf heap checker, // @see: research/gperftools/heap-checker/heap_checker.cc // if user interrupt the program, exit to check mem leak. // but, if gperf, use reload to ensure main return normally, // because directly exit will cause core-dump. #ifdef SRS_GPERF_MC - if (signal_gmc_stop) { - break; - } + if (signal_gmc_stop) { + break; + } #endif - - if (signal_reload) { - signal_reload = false; - srs_info("get signal reload, to reload the config."); - - if ((ret = _srs_config->reload()) != ERROR_SUCCESS) { - srs_error("reload config failed. ret=%d", ret); - return ret; - } - srs_trace("reload config success."); - } - } - - return ret; + + if (signal_reload) { + signal_reload = false; + srs_info("get signal reload, to reload the config."); + + if ((ret = _srs_config->reload()) != ERROR_SUCCESS) { + srs_error("reload config failed. ret=%d", ret); + return ret; + } + srs_trace("reload config success."); + } + } + + return ret; } void SrsServer::remove(SrsConnection* conn) { - std::vector::iterator it = std::find(conns.begin(), conns.end(), conn); - - if (it != conns.end()) { - conns.erase(it); - } - - srs_info("conn removed. conns=%d", (int)conns.size()); - - // all connections are created by server, - // so we free it here. - srs_freep(conn); + std::vector::iterator it = std::find(conns.begin(), conns.end(), conn); + + if (it != conns.end()) { + conns.erase(it); + } + + srs_info("conn removed. conns=%d", (int)conns.size()); + + // all connections are created by server, + // so we free it here. + srs_freep(conn); } void SrsServer::on_signal(int signo) { - if (signo == SIGNAL_RELOAD) { - signal_reload = true; - return; - } - - if (signo == SIGINT) { + if (signo == SIGNAL_RELOAD) { + signal_reload = true; + return; + } + + if (signo == SIGINT) { #ifdef SRS_GPERF_MC - srs_trace("gmc is on, main cycle will terminate normally."); - signal_gmc_stop = true; + srs_trace("gmc is on, main cycle will terminate normally."); + signal_gmc_stop = true; #else - srs_trace("user terminate program"); - exit(0); + srs_trace("user terminate program"); + exit(0); #endif - return; - } + return; + } - // TODO: handle the SIGINT, SIGTERM. + // TODO: handle the SIGINT, SIGTERM. } void SrsServer::close_listeners() { - std::vector::iterator it; - for (it = listeners.begin(); it != listeners.end(); ++it) { - SrsListener* listener = *it; - srs_freep(listener); - } - listeners.clear(); + std::vector::iterator it; + for (it = listeners.begin(); it != listeners.end(); ++it) { + SrsListener* listener = *it; + srs_freep(listener); + } + listeners.clear(); } int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd) { - int ret = ERROR_SUCCESS; - - int max_connections = _srs_config->get_max_connections(); - if ((int)conns.size() >= max_connections) { - int fd = st_netfd_fileno(client_stfd); - - srs_error("exceed the max connections, drop client: " - "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); - - srs_close_stfd(client_stfd); - - return ret; - } - - SrsConnection* conn = NULL; - if (type == SrsListenerStream) { - conn = new SrsClient(this, client_stfd); - } else { - // handler others - } - srs_assert(conn); - - // directly enqueue, the cycle thread will remove the client. - conns.push_back(conn); - srs_verbose("add conn from port %d to vector. conns=%d", port, (int)conns.size()); - - // cycle will start process thread and when finished remove the client. - if ((ret = conn->start()) != ERROR_SUCCESS) { - return ret; - } - srs_verbose("conn start finished. ret=%d", ret); + int ret = ERROR_SUCCESS; - return ret; + int max_connections = _srs_config->get_max_connections(); + if ((int)conns.size() >= max_connections) { + int fd = st_netfd_fileno(client_stfd); + + srs_error("exceed the max connections, drop client: " + "clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd); + + srs_close_stfd(client_stfd); + + return ret; + } + + SrsConnection* conn = NULL; + if (type == SrsListenerStream) { + conn = new SrsClient(this, client_stfd); + } else { + // handler others + } + srs_assert(conn); + + // directly enqueue, the cycle thread will remove the client. + conns.push_back(conn); + srs_verbose("add conn from port %d to vector. conns=%d", port, (int)conns.size()); + + // cycle will start process thread and when finished remove the client. + if ((ret = conn->start()) != ERROR_SUCCESS) { + return ret; + } + srs_verbose("conn start finished. ret=%d", ret); + + return ret; } int SrsServer::on_reload_listen() { - return listen(); + return listen(); } diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index 4819e6fc5..1e7f0a59d 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -41,53 +41,53 @@ class SrsConnection; enum SrsListenerType { - SrsListenerStream = 0, - SrsListenerApi + SrsListenerStream = 0, + SrsListenerApi }; class SrsListener : public ISrsThreadHandler { public: - SrsListenerType type; + SrsListenerType type; private: - int fd; - st_netfd_t stfd; - int port; - SrsServer* server; - SrsThread* pthread; + int fd; + st_netfd_t stfd; + int port; + SrsServer* server; + SrsThread* pthread; public: - SrsListener(SrsServer* _server, SrsListenerType _type); - virtual ~SrsListener(); + SrsListener(SrsServer* _server, SrsListenerType _type); + virtual ~SrsListener(); public: - virtual int listen(int port); + virtual int listen(int port); // interface ISrsThreadHandler. public: - virtual void on_enter_loop(); - virtual int cycle(); + virtual void on_enter_loop(); + virtual int cycle(); }; class SrsServer : public ISrsReloadHandler { - friend class SrsListener; + friend class SrsListener; private: - std::vector conns; - std::vector listeners; - bool signal_reload; - bool signal_gmc_stop; + std::vector conns; + std::vector listeners; + bool signal_reload; + bool signal_gmc_stop; public: - SrsServer(); - virtual ~SrsServer(); + SrsServer(); + virtual ~SrsServer(); public: - virtual int initialize(); - virtual int listen(); - virtual int cycle(); - virtual void remove(SrsConnection* conn); - virtual void on_signal(int signo); + virtual int initialize(); + virtual int listen(); + virtual int cycle(); + virtual void remove(SrsConnection* conn); + virtual void on_signal(int signo); private: - virtual void close_listeners(); - virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); + virtual void close_listeners(); + virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); public: - virtual int on_reload_listen(); + virtual int on_reload_listen(); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_socket.cpp b/trunk/src/app/srs_app_socket.cpp index b36c6ad74..f5038b7b7 100644 --- a/trunk/src/app/srs_app_socket.cpp +++ b/trunk/src/app/srs_app_socket.cpp @@ -28,9 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsSocket::SrsSocket(st_netfd_t client_stfd) { stfd = client_stfd; - send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; - recv_bytes = send_bytes = 0; - start_time_ms = srs_get_system_time_ms(); + send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; + recv_bytes = send_bytes = 0; + start_time_ms = srs_get_system_time_ms(); } SrsSocket::~SrsSocket() @@ -39,59 +39,59 @@ SrsSocket::~SrsSocket() bool SrsSocket::is_never_timeout(int64_t timeout_us) { - return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; + return timeout_us == (int64_t)ST_UTIME_NO_TIMEOUT; } void SrsSocket::set_recv_timeout(int64_t timeout_us) { - recv_timeout = timeout_us; + recv_timeout = timeout_us; } int64_t SrsSocket::get_recv_timeout() { - return recv_timeout; + return recv_timeout; } void SrsSocket::set_send_timeout(int64_t timeout_us) { - send_timeout = timeout_us; + send_timeout = timeout_us; } int64_t SrsSocket::get_send_timeout() { - return send_timeout; + return send_timeout; } int64_t SrsSocket::get_recv_bytes() { - return recv_bytes; + return recv_bytes; } int64_t SrsSocket::get_send_bytes() { - return send_bytes; + return send_bytes; } int SrsSocket::get_recv_kbps() { - int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; - - if (diff_ms <= 0) { - return 0; - } - - return recv_bytes * 8 / diff_ms; + int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; + + if (diff_ms <= 0) { + return 0; + } + + return recv_bytes * 8 / diff_ms; } int SrsSocket::get_send_kbps() { - int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; - - if (diff_ms <= 0) { - return 0; - } - - return send_bytes * 8 / diff_ms; + int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; + + if (diff_ms <= 0) { + return 0; + } + + return send_bytes * 8 / diff_ms; } int SrsSocket::read(const void* buf, size_t size, ssize_t* nread) @@ -103,10 +103,10 @@ int SrsSocket::read(const void* buf, size_t size, ssize_t* nread) // On success a non-negative integer indicating the number of bytes actually read is returned // (a value of 0 means the network connection is closed or end of file is reached). if (*nread <= 0) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + if (*nread == 0) { errno = ECONNRESET; } @@ -128,10 +128,10 @@ int SrsSocket::read_fully(const void* buf, size_t size, ssize_t* nread) // On success a non-negative integer indicating the number of bytes actually read is returned // (a value less than nbyte means the network connection is closed or end of file is reached) if (*nread != (ssize_t)size) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + if (*nread >= 0) { errno = ECONNRESET; } @@ -151,10 +151,10 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite) *nwrite = st_write(stfd, (void*)buf, size, send_timeout); if (*nwrite <= 0) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + return ERROR_SOCKET_WRITE; } @@ -170,10 +170,10 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite) *nwrite = st_writev(stfd, iov, iov_size, send_timeout); if (*nwrite <= 0) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + return ERROR_SOCKET_WRITE; } diff --git a/trunk/src/app/srs_app_socket.hpp b/trunk/src/app/srs_app_socket.hpp index bba5b1dfd..63e914fac 100644 --- a/trunk/src/app/srs_app_socket.hpp +++ b/trunk/src/app/srs_app_socket.hpp @@ -40,25 +40,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsSocket : public ISrsProtocolReaderWriter { private: - int64_t recv_timeout; - int64_t send_timeout; - int64_t recv_bytes; - int64_t send_bytes; - int64_t start_time_ms; + int64_t recv_timeout; + int64_t send_timeout; + int64_t recv_bytes; + int64_t send_bytes; + int64_t start_time_ms; st_netfd_t stfd; public: SrsSocket(st_netfd_t client_stfd); virtual ~SrsSocket(); public: - virtual bool is_never_timeout(int64_t timeout_us); - virtual void set_recv_timeout(int64_t timeout_us); - virtual int64_t get_recv_timeout(); - virtual void set_send_timeout(int64_t timeout_us); - virtual int64_t get_send_timeout(); - virtual int64_t get_recv_bytes(); - virtual int64_t get_send_bytes(); - virtual int get_recv_kbps(); - virtual int get_send_kbps(); + virtual bool is_never_timeout(int64_t timeout_us); + virtual void set_recv_timeout(int64_t timeout_us); + virtual int64_t get_recv_timeout(); + virtual void set_send_timeout(int64_t timeout_us); + virtual int64_t get_send_timeout(); + virtual int64_t get_recv_bytes(); + virtual int64_t get_send_bytes(); + virtual int get_recv_kbps(); + virtual int get_send_kbps(); public: virtual int read(const void* buf, size_t size, ssize_t* nread); virtual int read_fully(const void* buf, size_t size, ssize_t* nread); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 54566e6d2..45a852060 100644 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -37,12 +37,12 @@ using namespace std; #include #include -#define CONST_MAX_JITTER_MS 500 -#define DEFAULT_FRAME_TIME_MS 40 +#define CONST_MAX_JITTER_MS 500 +#define DEFAULT_FRAME_TIME_MS 40 SrsRtmpJitter::SrsRtmpJitter() { - last_pkt_correct_time = last_pkt_time = 0; + last_pkt_correct_time = last_pkt_time = 0; } SrsRtmpJitter::~SrsRtmpJitter() @@ -51,945 +51,945 @@ SrsRtmpJitter::~SrsRtmpJitter() int SrsRtmpJitter::correct(SrsSharedPtrMessage* msg, int tba, int tbv) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - // set to 0 for metadata. - if (!msg->header.is_video() && !msg->header.is_audio()) { - msg->header.timestamp = 0; - return ret; - } - - int sample_rate = tba; - int frame_rate = tbv; - - /** - * we use a very simple time jitter detect/correct algorithm: - * 1. delta: ensure the delta is positive and valid, - * we set the delta to DEFAULT_FRAME_TIME_MS, - * if the delta of time is nagative or greater than CONST_MAX_JITTER_MS. - * 2. last_pkt_time: specifies the original packet time, - * is used to detect next jitter. - * 3. last_pkt_correct_time: simply add the positive delta, - * and enforce the time monotonically. - */ - int64_t time = msg->header.timestamp; - int64_t delta = time - last_pkt_time; + // set to 0 for metadata. + if (!msg->header.is_video() && !msg->header.is_audio()) { + msg->header.timestamp = 0; + return ret; + } + + int sample_rate = tba; + int frame_rate = tbv; + + /** + * we use a very simple time jitter detect/correct algorithm: + * 1. delta: ensure the delta is positive and valid, + * we set the delta to DEFAULT_FRAME_TIME_MS, + * if the delta of time is nagative or greater than CONST_MAX_JITTER_MS. + * 2. last_pkt_time: specifies the original packet time, + * is used to detect next jitter. + * 3. last_pkt_correct_time: simply add the positive delta, + * and enforce the time monotonically. + */ + int64_t time = msg->header.timestamp; + int64_t delta = time - last_pkt_time; - // if jitter detected, reset the delta. - if (delta < 0 || delta > CONST_MAX_JITTER_MS) { - // calc the right diff by audio sample rate - if (msg->header.is_audio() && sample_rate > 0) { - delta = (int64_t)(delta * 1000.0 / sample_rate); - } else if (msg->header.is_video() && frame_rate > 0) { - delta = (int64_t)(delta * 1.0 / frame_rate); - } else { - delta = DEFAULT_FRAME_TIME_MS; - } + // if jitter detected, reset the delta. + if (delta < 0 || delta > CONST_MAX_JITTER_MS) { + // calc the right diff by audio sample rate + if (msg->header.is_audio() && sample_rate > 0) { + delta = (int64_t)(delta * 1000.0 / sample_rate); + } else if (msg->header.is_video() && frame_rate > 0) { + delta = (int64_t)(delta * 1.0 / frame_rate); + } else { + delta = DEFAULT_FRAME_TIME_MS; + } - // sometimes, the time is absolute time, so correct it again. - if (delta < 0 || delta > CONST_MAX_JITTER_MS) { - delta = DEFAULT_FRAME_TIME_MS; - } - - srs_info("jitter detected, last_pts=%"PRId64", pts=%"PRId64", diff=%"PRId64", last_time=%"PRId64", time=%"PRId64", diff=%"PRId64"", - last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta); - } else { - srs_verbose("timestamp no jitter. time=%"PRId64", last_pkt=%"PRId64", correct_to=%"PRId64"", - time, last_pkt_time, last_pkt_correct_time + delta); - } - - last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); - - msg->header.timestamp = last_pkt_correct_time; - last_pkt_time = time; - - return ret; + // sometimes, the time is absolute time, so correct it again. + if (delta < 0 || delta > CONST_MAX_JITTER_MS) { + delta = DEFAULT_FRAME_TIME_MS; + } + + srs_info("jitter detected, last_pts=%"PRId64", pts=%"PRId64", diff=%"PRId64", last_time=%"PRId64", time=%"PRId64", diff=%"PRId64"", + last_pkt_time, time, time - last_pkt_time, last_pkt_correct_time, last_pkt_correct_time + delta, delta); + } else { + srs_verbose("timestamp no jitter. time=%"PRId64", last_pkt=%"PRId64", correct_to=%"PRId64"", + time, last_pkt_time, last_pkt_correct_time + delta); + } + + last_pkt_correct_time = srs_max(0, last_pkt_correct_time + delta); + + msg->header.timestamp = last_pkt_correct_time; + last_pkt_time = time; + + return ret; } int SrsRtmpJitter::get_time() { - return (int)last_pkt_correct_time; + return (int)last_pkt_correct_time; } SrsMessageQueue::SrsMessageQueue() { - queue_size_ms = 0; - av_start_time = av_end_time = -1; + queue_size_ms = 0; + av_start_time = av_end_time = -1; } SrsMessageQueue::~SrsMessageQueue() { - clear(); + clear(); } void SrsMessageQueue::set_queue_size(double queue_size) { - queue_size_ms = (int)(queue_size * 1000); + queue_size_ms = (int)(queue_size * 1000); } int SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg) { - int ret = ERROR_SUCCESS; - - if (msg->header.is_video() || msg->header.is_audio()) { - if (av_start_time == -1) { - av_start_time = msg->header.timestamp; - } - - av_end_time = msg->header.timestamp; - } - - msgs.push_back(msg); + int ret = ERROR_SUCCESS; + + if (msg->header.is_video() || msg->header.is_audio()) { + if (av_start_time == -1) { + av_start_time = msg->header.timestamp; + } + + av_end_time = msg->header.timestamp; + } + + msgs.push_back(msg); - while (av_end_time - av_start_time > queue_size_ms) { - shrink(); - } - - return ret; + while (av_end_time - av_start_time > queue_size_ms) { + shrink(); + } + + return ret; } int SrsMessageQueue::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count) { - int ret = ERROR_SUCCESS; - - if (msgs.empty()) { - return ret; - } - - if (max_count == 0) { - count = (int)msgs.size(); - } else { - count = srs_min(max_count, (int)msgs.size()); - } + int ret = ERROR_SUCCESS; + + if (msgs.empty()) { + return ret; + } + + if (max_count == 0) { + count = (int)msgs.size(); + } else { + count = srs_min(max_count, (int)msgs.size()); + } - if (count <= 0) { - return ret; - } - - pmsgs = new SrsSharedPtrMessage*[count]; - - for (int i = 0; i < count; i++) { - pmsgs[i] = msgs[i]; - } - - SrsSharedPtrMessage* last = msgs[count - 1]; - av_start_time = last->header.timestamp; - - if (count == (int)msgs.size()) { - msgs.clear(); - } else { - msgs.erase(msgs.begin(), msgs.begin() + count); - } - - return ret; + if (count <= 0) { + return ret; + } + + pmsgs = new SrsSharedPtrMessage*[count]; + + for (int i = 0; i < count; i++) { + pmsgs[i] = msgs[i]; + } + + SrsSharedPtrMessage* last = msgs[count - 1]; + av_start_time = last->header.timestamp; + + if (count == (int)msgs.size()) { + msgs.clear(); + } else { + msgs.erase(msgs.begin(), msgs.begin() + count); + } + + return ret; } void SrsMessageQueue::shrink() { - int iframe_index = -1; - - // issue the first iframe. - // skip the first frame, whatever the type of it, - // for when we shrinked, the first is the iframe, - // we will directly remove the gop next time. - for (int i = 1; i < (int)msgs.size(); i++) { - SrsSharedPtrMessage* msg = msgs[i]; - - if (msg->header.is_video()) { - if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) { - // the max frame index to remove. - iframe_index = i; - - // set the start time, we will remove until this frame. - av_start_time = msg->header.timestamp; - - break; - } - } - } - - // no iframe, clear the queue. - if (iframe_index < 0) { - clear(); - return; - } - - srs_trace("shrink the cache queue, size=%d, removed=%d, max=%.2f", - (int)msgs.size(), iframe_index, queue_size_ms / 1000.0); - - // remove the first gop from the front - for (int i = 0; i < iframe_index; i++) { - SrsSharedPtrMessage* msg = msgs[i]; - srs_freep(msg); - } - msgs.erase(msgs.begin(), msgs.begin() + iframe_index); + int iframe_index = -1; + + // issue the first iframe. + // skip the first frame, whatever the type of it, + // for when we shrinked, the first is the iframe, + // we will directly remove the gop next time. + for (int i = 1; i < (int)msgs.size(); i++) { + SrsSharedPtrMessage* msg = msgs[i]; + + if (msg->header.is_video()) { + if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) { + // the max frame index to remove. + iframe_index = i; + + // set the start time, we will remove until this frame. + av_start_time = msg->header.timestamp; + + break; + } + } + } + + // no iframe, clear the queue. + if (iframe_index < 0) { + clear(); + return; + } + + srs_trace("shrink the cache queue, size=%d, removed=%d, max=%.2f", + (int)msgs.size(), iframe_index, queue_size_ms / 1000.0); + + // remove the first gop from the front + for (int i = 0; i < iframe_index; i++) { + SrsSharedPtrMessage* msg = msgs[i]; + srs_freep(msg); + } + msgs.erase(msgs.begin(), msgs.begin() + iframe_index); } void SrsMessageQueue::clear() { - std::vector::iterator it; + std::vector::iterator it; - for (it = msgs.begin(); it != msgs.end(); ++it) { - SrsSharedPtrMessage* msg = *it; - srs_freep(msg); - } + for (it = msgs.begin(); it != msgs.end(); ++it) { + SrsSharedPtrMessage* msg = *it; + srs_freep(msg); + } - msgs.clear(); - - av_start_time = av_end_time = -1; + msgs.clear(); + + av_start_time = av_end_time = -1; } SrsConsumer::SrsConsumer(SrsSource* _source) { - source = _source; - paused = false; - jitter = new SrsRtmpJitter(); - queue = new SrsMessageQueue(); + source = _source; + paused = false; + jitter = new SrsRtmpJitter(); + queue = new SrsMessageQueue(); } SrsConsumer::~SrsConsumer() { - source->on_consumer_destroy(this); - srs_freep(jitter); - srs_freep(queue); + source->on_consumer_destroy(this); + srs_freep(jitter); + srs_freep(queue); } void SrsConsumer::set_queue_size(double queue_size) { - queue->set_queue_size(queue_size); + queue->set_queue_size(queue_size); } int SrsConsumer::get_time() { - return jitter->get_time(); + return jitter->get_time(); } int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, int tba, int tbv) { - int ret = ERROR_SUCCESS; - - if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { - srs_freep(msg); - return ret; - } - - if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = jitter->correct(msg, tba, tbv)) != ERROR_SUCCESS) { + srs_freep(msg); + return ret; + } + + if ((ret = queue->enqueue(msg)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count) { - // paused, return nothing. - if (paused) { - return ERROR_SUCCESS; - } - - return queue->get_packets(max_count, pmsgs, count); + // paused, return nothing. + if (paused) { + return ERROR_SUCCESS; + } + + return queue->get_packets(max_count, pmsgs, count); } int SrsConsumer::on_play_client_pause(bool is_pause) { - int ret = ERROR_SUCCESS; - - srs_trace("stream consumer change pause state %d=>%d", paused, is_pause); - paused = is_pause; - - return ret; + int ret = ERROR_SUCCESS; + + srs_trace("stream consumer change pause state %d=>%d", paused, is_pause); + paused = is_pause; + + return ret; } SrsGopCache::SrsGopCache() { - cached_video_count = 0; - enable_gop_cache = true; + cached_video_count = 0; + enable_gop_cache = true; } SrsGopCache::~SrsGopCache() { - clear(); + clear(); } void SrsGopCache::set(bool enabled) { - enable_gop_cache = enabled; - - if (!enabled) { - srs_info("disable gop cache, clear %d packets.", (int)gop_cache.size()); - clear(); - return; - } - - srs_info("enable gop cache"); + enable_gop_cache = enabled; + + if (!enabled) { + srs_info("disable gop cache, clear %d packets.", (int)gop_cache.size()); + clear(); + return; + } + + srs_info("enable gop cache"); } int SrsGopCache::cache(SrsSharedPtrMessage* msg) { - int ret = ERROR_SUCCESS; - - if (!enable_gop_cache) { - srs_verbose("gop cache is disabled."); - return ret; - } - - // got video, update the video count if acceptable - if (msg->header.is_video()) { - cached_video_count++; - } - - // no acceptable video or pure audio, disable the cache. - if (cached_video_count == 0) { - srs_verbose("ignore any frame util got a h264 video frame."); - return ret; - } - - // clear gop cache when got key frame - if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) { - srs_info("clear gop cache when got keyframe. vcount=%d, count=%d", - cached_video_count, (int)gop_cache.size()); - - clear(); - - // curent msg is video frame, so we set to 1. - cached_video_count = 1; - } - - // cache the frame. - gop_cache.push_back(msg->copy()); - - return ret; + int ret = ERROR_SUCCESS; + + if (!enable_gop_cache) { + srs_verbose("gop cache is disabled."); + return ret; + } + + // got video, update the video count if acceptable + if (msg->header.is_video()) { + cached_video_count++; + } + + // no acceptable video or pure audio, disable the cache. + if (cached_video_count == 0) { + srs_verbose("ignore any frame util got a h264 video frame."); + return ret; + } + + // clear gop cache when got key frame + if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) { + srs_info("clear gop cache when got keyframe. vcount=%d, count=%d", + cached_video_count, (int)gop_cache.size()); + + clear(); + + // curent msg is video frame, so we set to 1. + cached_video_count = 1; + } + + // cache the frame. + gop_cache.push_back(msg->copy()); + + return ret; } void SrsGopCache::clear() { - std::vector::iterator it; - for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { - SrsSharedPtrMessage* msg = *it; - srs_freep(msg); - } - gop_cache.clear(); + std::vector::iterator it; + for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { + SrsSharedPtrMessage* msg = *it; + srs_freep(msg); + } + gop_cache.clear(); - cached_video_count = 0; + cached_video_count = 0; } - + int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) { - int ret = ERROR_SUCCESS; - - std::vector::iterator it; - for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { - SrsSharedPtrMessage* msg = *it; - if ((ret = consumer->enqueue(msg->copy(), tba, tbv)) != ERROR_SUCCESS) { - srs_error("dispatch cached gop failed. ret=%d", ret); - return ret; - } - } - srs_trace("dispatch cached gop success. count=%d, duration=%d", (int)gop_cache.size(), consumer->get_time()); - - return ret; + int ret = ERROR_SUCCESS; + + std::vector::iterator it; + for (it = gop_cache.begin(); it != gop_cache.end(); ++it) { + SrsSharedPtrMessage* msg = *it; + if ((ret = consumer->enqueue(msg->copy(), tba, tbv)) != ERROR_SUCCESS) { + srs_error("dispatch cached gop failed. ret=%d", ret); + return ret; + } + } + srs_trace("dispatch cached gop success. count=%d, duration=%d", (int)gop_cache.size(), consumer->get_time()); + + return ret; } std::map SrsSource::pool; SrsSource* SrsSource::find(SrsRequest* req) { - string stream_url = req->get_stream_url(); - string vhost = req->vhost; - - if (pool.find(stream_url) == pool.end()) { - pool[stream_url] = new SrsSource(req); - srs_verbose("create new source for url=%s, vhost=%s", stream_url.c_str(), vhost.c_str()); - } - - return pool[stream_url]; + string stream_url = req->get_stream_url(); + string vhost = req->vhost; + + if (pool.find(stream_url) == pool.end()) { + pool[stream_url] = new SrsSource(req); + srs_verbose("create new source for url=%s, vhost=%s", stream_url.c_str(), vhost.c_str()); + } + + return pool[stream_url]; } SrsSource::SrsSource(SrsRequest* _req) { - req = _req->copy(); - + req = _req->copy(); + #ifdef SRS_HLS - hls = new SrsHls(this); + hls = new SrsHls(this); #endif #ifdef SRS_FFMPEG - encoder = new SrsEncoder(); + encoder = new SrsEncoder(); #endif - - cache_metadata = cache_sh_video = cache_sh_audio = NULL; - - frame_rate = sample_rate = 0; - _can_publish = true; - - gop_cache = new SrsGopCache(); - - _srs_config->subscribe(this); + + cache_metadata = cache_sh_video = cache_sh_audio = NULL; + + frame_rate = sample_rate = 0; + _can_publish = true; + + gop_cache = new SrsGopCache(); + + _srs_config->subscribe(this); } SrsSource::~SrsSource() { - _srs_config->unsubscribe(this); - - if (true) { - std::vector::iterator it; - for (it = consumers.begin(); it != consumers.end(); ++it) { - SrsConsumer* consumer = *it; - srs_freep(consumer); - } - consumers.clear(); - } + _srs_config->unsubscribe(this); + + if (true) { + std::vector::iterator it; + for (it = consumers.begin(); it != consumers.end(); ++it) { + SrsConsumer* consumer = *it; + srs_freep(consumer); + } + consumers.clear(); + } - if (true) { - std::vector::iterator it; - for (it = forwarders.begin(); it != forwarders.end(); ++it) { - SrsForwarder* forwarder = *it; - srs_freep(forwarder); - } - forwarders.clear(); - } - - srs_freep(cache_metadata); - srs_freep(cache_sh_video); - srs_freep(cache_sh_audio); - - srs_freep(gop_cache); - + if (true) { + std::vector::iterator it; + for (it = forwarders.begin(); it != forwarders.end(); ++it) { + SrsForwarder* forwarder = *it; + srs_freep(forwarder); + } + forwarders.clear(); + } + + srs_freep(cache_metadata); + srs_freep(cache_sh_video); + srs_freep(cache_sh_audio); + + srs_freep(gop_cache); + #ifdef SRS_HLS - srs_freep(hls); + srs_freep(hls); #endif #ifdef SRS_FFMPEG - srs_freep(encoder); + srs_freep(encoder); #endif - srs_freep(req); + srs_freep(req); } int SrsSource::on_reload_gop_cache(string vhost) { - int ret = ERROR_SUCCESS; - - if (req->vhost != vhost) { - return ret; - } - - // gop cache changed. - bool enabled_cache = _srs_config->get_gop_cache(vhost); - - srs_trace("vhost %s gop_cache changed to %d, source url=%s", - vhost.c_str(), enabled_cache, req->get_stream_url().c_str()); - - set_cache(enabled_cache); - - return ret; + int ret = ERROR_SUCCESS; + + if (req->vhost != vhost) { + return ret; + } + + // gop cache changed. + bool enabled_cache = _srs_config->get_gop_cache(vhost); + + srs_trace("vhost %s gop_cache changed to %d, source url=%s", + vhost.c_str(), enabled_cache, req->get_stream_url().c_str()); + + set_cache(enabled_cache); + + return ret; } int SrsSource::on_reload_queue_length(string vhost) { - int ret = ERROR_SUCCESS; - - if (req->vhost != vhost) { - return ret; - } + int ret = ERROR_SUCCESS; + + if (req->vhost != vhost) { + return ret; + } - double queue_size = _srs_config->get_queue_length(req->vhost); - - if (true) { - std::vector::iterator it; - - for (it = consumers.begin(); it != consumers.end(); ++it) { - SrsConsumer* consumer = *it; - consumer->set_queue_size(queue_size); - } + double queue_size = _srs_config->get_queue_length(req->vhost); + + if (true) { + std::vector::iterator it; + + for (it = consumers.begin(); it != consumers.end(); ++it) { + SrsConsumer* consumer = *it; + consumer->set_queue_size(queue_size); + } - srs_trace("consumers reload queue size success."); - } - - if (true) { - std::vector::iterator it; - - for (it = forwarders.begin(); it != forwarders.end(); ++it) { - SrsForwarder* forwarder = *it; - forwarder->set_queue_size(queue_size); - } + srs_trace("consumers reload queue size success."); + } + + if (true) { + std::vector::iterator it; + + for (it = forwarders.begin(); it != forwarders.end(); ++it) { + SrsForwarder* forwarder = *it; + forwarder->set_queue_size(queue_size); + } - srs_trace("forwarders reload queue size success."); - } - - return ret; + srs_trace("forwarders reload queue size success."); + } + + return ret; } int SrsSource::on_reload_forward(string vhost) { - int ret = ERROR_SUCCESS; - - if (req->vhost != vhost) { - return ret; - } + int ret = ERROR_SUCCESS; + + if (req->vhost != vhost) { + return ret; + } - // forwarders - destroy_forwarders(); - if ((ret = create_forwarders()) != ERROR_SUCCESS) { - srs_error("create forwarders failed. ret=%d", ret); - return ret; - } + // forwarders + destroy_forwarders(); + if ((ret = create_forwarders()) != ERROR_SUCCESS) { + srs_error("create forwarders failed. ret=%d", ret); + return ret; + } - srs_trace("vhost %s forwarders reload success", vhost.c_str()); - - return ret; + srs_trace("vhost %s forwarders reload success", vhost.c_str()); + + return ret; } int SrsSource::on_reload_hls(string vhost) { - int ret = ERROR_SUCCESS; - - if (req->vhost != vhost) { - return ret; - } - + int ret = ERROR_SUCCESS; + + if (req->vhost != vhost) { + return ret; + } + #ifdef SRS_HLS - hls->on_unpublish(); - if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { - srs_error("hls publish failed. ret=%d", ret); - return ret; - } - srs_trace("vhost %s hls reload success", vhost.c_str()); + hls->on_unpublish(); + if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { + srs_error("hls publish failed. ret=%d", ret); + return ret; + } + srs_trace("vhost %s hls reload success", vhost.c_str()); #endif - - return ret; + + return ret; } int SrsSource::on_reload_transcode(string vhost) { - int ret = ERROR_SUCCESS; - - if (req->vhost != vhost) { - return ret; - } - + int ret = ERROR_SUCCESS; + + if (req->vhost != vhost) { + return ret; + } + #ifdef SRS_FFMPEG - encoder->on_unpublish(); - if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { - srs_error("start encoder failed. ret=%d", ret); - return ret; - } - srs_trace("vhost %s transcode reload success", vhost.c_str()); + encoder->on_unpublish(); + if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { + srs_error("start encoder failed. ret=%d", ret); + return ret; + } + srs_trace("vhost %s transcode reload success", vhost.c_str()); #endif - - return ret; + + return ret; } int SrsSource::on_forwarder_start(SrsForwarder* forwarder) { - int ret = ERROR_SUCCESS; - - // feed the forwarder the metadata/sequence header, - // when reload to enable the forwarder. - if (cache_metadata && (ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { - srs_error("forwarder process onMetaData message failed. ret=%d", ret); - return ret; - } - if (cache_sh_video && (ret = forwarder->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { - srs_error("forwarder process video sequence header message failed. ret=%d", ret); - return ret; - } - if (cache_sh_audio && (ret = forwarder->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { - srs_error("forwarder process audio sequence header message failed. ret=%d", ret); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + // feed the forwarder the metadata/sequence header, + // when reload to enable the forwarder. + if (cache_metadata && (ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { + srs_error("forwarder process onMetaData message failed. ret=%d", ret); + return ret; + } + if (cache_sh_video && (ret = forwarder->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { + srs_error("forwarder process video sequence header message failed. ret=%d", ret); + return ret; + } + if (cache_sh_audio && (ret = forwarder->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { + srs_error("forwarder process audio sequence header message failed. ret=%d", ret); + return ret; + } + + return ret; } int SrsSource::on_hls_start() { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + #ifdef SRS_HLS - - // feed the hls the metadata/sequence header, - // when reload to enable the hls. - // TODO: maybe need to decode the metadata? - if (cache_sh_video && (ret = hls->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { - srs_error("hls process video sequence header message failed. ret=%d", ret); - return ret; - } - if (cache_sh_audio && (ret = hls->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { - srs_error("hls process audio sequence header message failed. ret=%d", ret); - return ret; - } - + + // feed the hls the metadata/sequence header, + // when reload to enable the hls. + // TODO: maybe need to decode the metadata? + if (cache_sh_video && (ret = hls->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { + srs_error("hls process video sequence header message failed. ret=%d", ret); + return ret; + } + if (cache_sh_audio && (ret = hls->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { + srs_error("hls process audio sequence header message failed. ret=%d", ret); + return ret; + } + #endif - - return ret; + + return ret; } bool SrsSource::can_publish() { - return _can_publish; + return _can_publish; } int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata) { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + #ifdef SRS_HLS - if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { - srs_error("hls process onMetaData message failed. ret=%d", ret); - return ret; - } + if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { + srs_error("hls process onMetaData message failed. ret=%d", ret); + return ret; + } #endif - - metadata->metadata->set("server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); - metadata->metadata->set("contributor", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY_AUTHROS)); - - SrsAmf0Any* prop = NULL; - if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { - if (prop->is_number()) { - sample_rate = (int)prop->to_number(); - } - } - if ((prop = metadata->metadata->get_property("framerate")) != NULL) { - if (prop->is_number()) { - frame_rate = (int)prop->to_number(); - } - } - - // encode the metadata to payload - int size = metadata->get_payload_length(); - if (size <= 0) { - srs_warn("ignore the invalid metadata. size=%d", size); - return ret; - } - srs_verbose("get metadata size success."); - - char* payload = NULL; - if ((ret = metadata->encode(size, payload)) != ERROR_SUCCESS) { - srs_error("encode metadata error. ret=%d", ret); - srs_freepa(payload); - return ret; - } - srs_verbose("encode metadata success."); - - // create a shared ptr message. - srs_freep(cache_metadata); - cache_metadata = new SrsSharedPtrMessage(); - - // dump message to shared ptr message. - if ((ret = cache_metadata->initialize(&msg->header, payload, size)) != ERROR_SUCCESS) { - srs_error("initialize the cache metadata failed. ret=%d", ret); - return ret; - } - srs_verbose("initialize shared ptr metadata success."); - - // copy to all consumer - if (true) { - std::vector::iterator it; - for (it = consumers.begin(); it != consumers.end(); ++it) { - SrsConsumer* consumer = *it; - if ((ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { - srs_error("dispatch the metadata failed. ret=%d", ret); - return ret; - } - } - srs_trace("dispatch metadata success."); - } - - // copy to all forwarders - if (true) { - std::vector::iterator it; - for (it = forwarders.begin(); it != forwarders.end(); ++it) { - SrsForwarder* forwarder = *it; - if ((ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { - srs_error("forwarder process onMetaData message failed. ret=%d", ret); - return ret; - } - } - } - - return ret; + + metadata->metadata->set("server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); + metadata->metadata->set("contributor", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY_AUTHROS)); + + SrsAmf0Any* prop = NULL; + if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { + if (prop->is_number()) { + sample_rate = (int)prop->to_number(); + } + } + if ((prop = metadata->metadata->get_property("framerate")) != NULL) { + if (prop->is_number()) { + frame_rate = (int)prop->to_number(); + } + } + + // encode the metadata to payload + int size = metadata->get_payload_length(); + if (size <= 0) { + srs_warn("ignore the invalid metadata. size=%d", size); + return ret; + } + srs_verbose("get metadata size success."); + + char* payload = NULL; + if ((ret = metadata->encode(size, payload)) != ERROR_SUCCESS) { + srs_error("encode metadata error. ret=%d", ret); + srs_freepa(payload); + return ret; + } + srs_verbose("encode metadata success."); + + // create a shared ptr message. + srs_freep(cache_metadata); + cache_metadata = new SrsSharedPtrMessage(); + + // dump message to shared ptr message. + if ((ret = cache_metadata->initialize(&msg->header, payload, size)) != ERROR_SUCCESS) { + srs_error("initialize the cache metadata failed. ret=%d", ret); + return ret; + } + srs_verbose("initialize shared ptr metadata success."); + + // copy to all consumer + if (true) { + std::vector::iterator it; + for (it = consumers.begin(); it != consumers.end(); ++it) { + SrsConsumer* consumer = *it; + if ((ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { + srs_error("dispatch the metadata failed. ret=%d", ret); + return ret; + } + } + srs_trace("dispatch metadata success."); + } + + // copy to all forwarders + if (true) { + std::vector::iterator it; + for (it = forwarders.begin(); it != forwarders.end(); ++it) { + SrsForwarder* forwarder = *it; + if ((ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { + srs_error("forwarder process onMetaData message failed. ret=%d", ret); + return ret; + } + } + } + + return ret; } int SrsSource::on_audio(SrsCommonMessage* audio) { - int ret = ERROR_SUCCESS; - - SrsSharedPtrMessage* msg = new SrsSharedPtrMessage(); - SrsAutoFree(SrsSharedPtrMessage, msg, false); - if ((ret = msg->initialize(audio)) != ERROR_SUCCESS) { - srs_error("initialize the audio failed. ret=%d", ret); - return ret; - } - srs_verbose("initialize shared ptr audio success."); - + int ret = ERROR_SUCCESS; + + SrsSharedPtrMessage* msg = new SrsSharedPtrMessage(); + SrsAutoFree(SrsSharedPtrMessage, msg, false); + if ((ret = msg->initialize(audio)) != ERROR_SUCCESS) { + srs_error("initialize the audio failed. ret=%d", ret); + return ret; + } + srs_verbose("initialize shared ptr audio success."); + #ifdef SRS_HLS - if ((ret = hls->on_audio(msg->copy())) != ERROR_SUCCESS) { - srs_warn("hls process audio message failed, ignore and disable hls. ret=%d", ret); - - // unpublish, ignore ret. - hls->on_unpublish(); - - // ignore. - ret = ERROR_SUCCESS; - } + if ((ret = hls->on_audio(msg->copy())) != ERROR_SUCCESS) { + srs_warn("hls process audio message failed, ignore and disable hls. ret=%d", ret); + + // unpublish, ignore ret. + hls->on_unpublish(); + + // ignore. + ret = ERROR_SUCCESS; + } #endif - - // copy to all consumer - if (true) { - std::vector::iterator it; - for (it = consumers.begin(); it != consumers.end(); ++it) { - SrsConsumer* consumer = *it; - if ((ret = consumer->enqueue(msg->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { - srs_error("dispatch the audio failed. ret=%d", ret); - return ret; - } - } - srs_info("dispatch audio success."); - } + + // copy to all consumer + if (true) { + std::vector::iterator it; + for (it = consumers.begin(); it != consumers.end(); ++it) { + SrsConsumer* consumer = *it; + if ((ret = consumer->enqueue(msg->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { + srs_error("dispatch the audio failed. ret=%d", ret); + return ret; + } + } + srs_info("dispatch audio success."); + } - // copy to all forwarders. - if (true) { - std::vector::iterator it; - for (it = forwarders.begin(); it != forwarders.end(); ++it) { - SrsForwarder* forwarder = *it; - if ((ret = forwarder->on_audio(msg->copy())) != ERROR_SUCCESS) { - srs_error("forwarder process audio message failed. ret=%d", ret); - return ret; - } - } - } + // copy to all forwarders. + if (true) { + std::vector::iterator it; + for (it = forwarders.begin(); it != forwarders.end(); ++it) { + SrsForwarder* forwarder = *it; + if ((ret = forwarder->on_audio(msg->copy())) != ERROR_SUCCESS) { + srs_error("forwarder process audio message failed. ret=%d", ret); + return ret; + } + } + } - // cache the sequence header if h264 - if (SrsCodec::audio_is_sequence_header(msg->payload, msg->size)) { - srs_freep(cache_sh_audio); - cache_sh_audio = msg->copy(); - srs_trace("update audio sequence header success. size=%d", msg->header.payload_length); - return ret; - } - - // cache the last gop packets - if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { - srs_error("shrink gop cache failed. ret=%d", ret); - return ret; - } - srs_verbose("cache gop success."); - - return ret; + // cache the sequence header if h264 + if (SrsCodec::audio_is_sequence_header(msg->payload, msg->size)) { + srs_freep(cache_sh_audio); + cache_sh_audio = msg->copy(); + srs_trace("update audio sequence header success. size=%d", msg->header.payload_length); + return ret; + } + + // cache the last gop packets + if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { + srs_error("shrink gop cache failed. ret=%d", ret); + return ret; + } + srs_verbose("cache gop success."); + + return ret; } int SrsSource::on_video(SrsCommonMessage* video) { - int ret = ERROR_SUCCESS; - - SrsSharedPtrMessage* msg = new SrsSharedPtrMessage(); - SrsAutoFree(SrsSharedPtrMessage, msg, false); - if ((ret = msg->initialize(video)) != ERROR_SUCCESS) { - srs_error("initialize the video failed. ret=%d", ret); - return ret; - } - srs_verbose("initialize shared ptr video success."); - + int ret = ERROR_SUCCESS; + + SrsSharedPtrMessage* msg = new SrsSharedPtrMessage(); + SrsAutoFree(SrsSharedPtrMessage, msg, false); + if ((ret = msg->initialize(video)) != ERROR_SUCCESS) { + srs_error("initialize the video failed. ret=%d", ret); + return ret; + } + srs_verbose("initialize shared ptr video success."); + #ifdef SRS_HLS - if ((ret = hls->on_video(msg->copy())) != ERROR_SUCCESS) { - srs_warn("hls process video message failed, ignore and disable hls. ret=%d", ret); - - // unpublish, ignore ret. - hls->on_unpublish(); - - // ignore. - ret = ERROR_SUCCESS; - } + if ((ret = hls->on_video(msg->copy())) != ERROR_SUCCESS) { + srs_warn("hls process video message failed, ignore and disable hls. ret=%d", ret); + + // unpublish, ignore ret. + hls->on_unpublish(); + + // ignore. + ret = ERROR_SUCCESS; + } #endif - - // copy to all consumer - if (true) { - std::vector::iterator it; - for (it = consumers.begin(); it != consumers.end(); ++it) { - SrsConsumer* consumer = *it; - if ((ret = consumer->enqueue(msg->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { - srs_error("dispatch the video failed. ret=%d", ret); - return ret; - } - } - srs_info("dispatch video success."); - } + + // copy to all consumer + if (true) { + std::vector::iterator it; + for (it = consumers.begin(); it != consumers.end(); ++it) { + SrsConsumer* consumer = *it; + if ((ret = consumer->enqueue(msg->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { + srs_error("dispatch the video failed. ret=%d", ret); + return ret; + } + } + srs_info("dispatch video success."); + } - // copy to all forwarders. - if (true) { - std::vector::iterator it; - for (it = forwarders.begin(); it != forwarders.end(); ++it) { - SrsForwarder* forwarder = *it; - if ((ret = forwarder->on_video(msg->copy())) != ERROR_SUCCESS) { - srs_error("forwarder process video message failed. ret=%d", ret); - return ret; - } - } - } + // copy to all forwarders. + if (true) { + std::vector::iterator it; + for (it = forwarders.begin(); it != forwarders.end(); ++it) { + SrsForwarder* forwarder = *it; + if ((ret = forwarder->on_video(msg->copy())) != ERROR_SUCCESS) { + srs_error("forwarder process video message failed. ret=%d", ret); + return ret; + } + } + } - // cache the sequence header if h264 - if (SrsCodec::video_is_sequence_header(msg->payload, msg->size)) { - srs_freep(cache_sh_video); - cache_sh_video = msg->copy(); - srs_trace("update video sequence header success. size=%d", msg->header.payload_length); - return ret; - } + // cache the sequence header if h264 + if (SrsCodec::video_is_sequence_header(msg->payload, msg->size)) { + srs_freep(cache_sh_video); + cache_sh_video = msg->copy(); + srs_trace("update video sequence header success. size=%d", msg->header.payload_length); + return ret; + } - // cache the last gop packets - if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { - srs_error("gop cache msg failed. ret=%d", ret); - return ret; - } - srs_verbose("cache gop success."); - - return ret; + // cache the last gop packets + if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) { + srs_error("gop cache msg failed. ret=%d", ret); + return ret; + } + srs_verbose("cache gop success."); + + return ret; } int SrsSource::on_publish(SrsRequest* _req) { - int ret = ERROR_SUCCESS; - - // update the request object. - srs_freep(req); - req = _req->copy(); - srs_assert(req); - - _can_publish = false; - - // create forwarders - if ((ret = create_forwarders()) != ERROR_SUCCESS) { - srs_error("create forwarders failed. ret=%d", ret); - return ret; - } - + int ret = ERROR_SUCCESS; + + // update the request object. + srs_freep(req); + req = _req->copy(); + srs_assert(req); + + _can_publish = false; + + // create forwarders + if ((ret = create_forwarders()) != ERROR_SUCCESS) { + srs_error("create forwarders failed. ret=%d", ret); + return ret; + } + #ifdef SRS_FFMPEG - if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { - srs_error("start encoder failed. ret=%d", ret); - return ret; - } + if ((ret = encoder->on_publish(req)) != ERROR_SUCCESS) { + srs_error("start encoder failed. ret=%d", ret); + return ret; + } #endif - + #ifdef SRS_HLS - if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { - srs_error("start hls failed. ret=%d", ret); - return ret; - } + if ((ret = hls->on_publish(req)) != ERROR_SUCCESS) { + srs_error("start hls failed. ret=%d", ret); + return ret; + } #endif - return ret; + return ret; } void SrsSource::on_unpublish() { - // destroy all forwarders - destroy_forwarders(); + // destroy all forwarders + destroy_forwarders(); #ifdef SRS_FFMPEG - encoder->on_unpublish(); + encoder->on_unpublish(); #endif - // TODO: HLS should continue previous sequence and stream. + // TODO: HLS should continue previous sequence and stream. #ifdef SRS_HLS - hls->on_unpublish(); + hls->on_unpublish(); #endif - gop_cache->clear(); + gop_cache->clear(); - srs_freep(cache_metadata); - frame_rate = sample_rate = 0; - - srs_freep(cache_sh_video); - srs_freep(cache_sh_audio); - - srs_trace("clear cache/metadata/sequence-headers when unpublish."); - - _can_publish = true; + srs_freep(cache_metadata); + frame_rate = sample_rate = 0; + + srs_freep(cache_sh_video); + srs_freep(cache_sh_audio); + + srs_trace("clear cache/metadata/sequence-headers when unpublish."); + + _can_publish = true; } int SrsSource::create_consumer(SrsConsumer*& consumer) { - int ret = ERROR_SUCCESS; - - consumer = new SrsConsumer(this); - consumers.push_back(consumer); - - double queue_size = _srs_config->get_queue_length(req->vhost); - consumer->set_queue_size(queue_size); + int ret = ERROR_SUCCESS; + + consumer = new SrsConsumer(this); + consumers.push_back(consumer); + + double queue_size = _srs_config->get_queue_length(req->vhost); + consumer->set_queue_size(queue_size); - if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { - srs_error("dispatch metadata failed. ret=%d", ret); - return ret; - } - srs_info("dispatch metadata success"); - - if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { - srs_error("dispatch video sequence header failed. ret=%d", ret); - return ret; - } - srs_info("dispatch video sequence header success"); - - if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { - srs_error("dispatch audio sequence header failed. ret=%d", ret); - return ret; - } - srs_info("dispatch audio sequence header success"); - - if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) { - return ret; - } - - srs_trace("create consumer, queue_size=%.2f, tba=%d, tbv=%d", queue_size, sample_rate, frame_rate); - - return ret; + if (cache_metadata && (ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { + srs_error("dispatch metadata failed. ret=%d", ret); + return ret; + } + srs_info("dispatch metadata success"); + + if (cache_sh_video && (ret = consumer->enqueue(cache_sh_video->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { + srs_error("dispatch video sequence header failed. ret=%d", ret); + return ret; + } + srs_info("dispatch video sequence header success"); + + if (cache_sh_audio && (ret = consumer->enqueue(cache_sh_audio->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { + srs_error("dispatch audio sequence header failed. ret=%d", ret); + return ret; + } + srs_info("dispatch audio sequence header success"); + + if ((ret = gop_cache->dump(consumer, sample_rate, frame_rate)) != ERROR_SUCCESS) { + return ret; + } + + srs_trace("create consumer, queue_size=%.2f, tba=%d, tbv=%d", queue_size, sample_rate, frame_rate); + + return ret; } void SrsSource::on_consumer_destroy(SrsConsumer* consumer) { - std::vector::iterator it; - it = std::find(consumers.begin(), consumers.end(), consumer); - if (it != consumers.end()) { - consumers.erase(it); - } - srs_info("handle consumer destroy success."); + std::vector::iterator it; + it = std::find(consumers.begin(), consumers.end(), consumer); + if (it != consumers.end()) { + consumers.erase(it); + } + srs_info("handle consumer destroy success."); } void SrsSource::set_cache(bool enabled) { - gop_cache->set(enabled); + gop_cache->set(enabled); } int SrsSource::create_forwarders() { - int ret = ERROR_SUCCESS; - - SrsConfDirective* conf = _srs_config->get_forward(req->vhost); - for (int i = 0; conf && i < (int)conf->args.size(); i++) { - std::string forward_server = conf->args.at(i); - - SrsForwarder* forwarder = new SrsForwarder(this); - forwarders.push_back(forwarder); - - double queue_size = _srs_config->get_queue_length(req->vhost); - forwarder->set_queue_size(queue_size); - - if ((ret = forwarder->on_publish(req, forward_server)) != ERROR_SUCCESS) { - srs_error("start forwarder failed. " - "vhost=%s, app=%s, stream=%s, forward-to=%s", - req->vhost.c_str(), req->app.c_str(), req->stream.c_str(), - forward_server.c_str()); - return ret; - } - } + int ret = ERROR_SUCCESS; + + SrsConfDirective* conf = _srs_config->get_forward(req->vhost); + for (int i = 0; conf && i < (int)conf->args.size(); i++) { + std::string forward_server = conf->args.at(i); + + SrsForwarder* forwarder = new SrsForwarder(this); + forwarders.push_back(forwarder); + + double queue_size = _srs_config->get_queue_length(req->vhost); + forwarder->set_queue_size(queue_size); + + if ((ret = forwarder->on_publish(req, forward_server)) != ERROR_SUCCESS) { + srs_error("start forwarder failed. " + "vhost=%s, app=%s, stream=%s, forward-to=%s", + req->vhost.c_str(), req->app.c_str(), req->stream.c_str(), + forward_server.c_str()); + return ret; + } + } - return ret; + return ret; } void SrsSource::destroy_forwarders() { - std::vector::iterator it; - for (it = forwarders.begin(); it != forwarders.end(); ++it) { - SrsForwarder* forwarder = *it; - forwarder->on_unpublish(); - srs_freep(forwarder); - } - forwarders.clear(); + std::vector::iterator it; + for (it = forwarders.begin(); it != forwarders.end(); ++it) { + SrsForwarder* forwarder = *it; + forwarder->on_unpublish(); + srs_freep(forwarder); + } + forwarders.clear(); } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index 39692c1c4..9f0c554e5 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -57,20 +57,20 @@ class SrsEncoder; class SrsRtmpJitter { private: - int64_t last_pkt_time; - int64_t last_pkt_correct_time; + int64_t last_pkt_time; + int64_t last_pkt_correct_time; public: - SrsRtmpJitter(); - virtual ~SrsRtmpJitter(); + SrsRtmpJitter(); + virtual ~SrsRtmpJitter(); public: - /** - * detect the time jitter and correct it. - */ - virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); - /** - * get current client time, the last packet time. - */ - virtual int get_time(); + /** + * detect the time jitter and correct it. + */ + virtual int correct(SrsSharedPtrMessage* msg, int tba, int tbv); + /** + * get current client time, the last packet time. + */ + virtual int get_time(); }; /** @@ -80,39 +80,39 @@ public: class SrsMessageQueue { private: - int64_t av_start_time; - int64_t av_end_time; - int queue_size_ms; - std::vector msgs; + int64_t av_start_time; + int64_t av_end_time; + int queue_size_ms; + std::vector msgs; public: - SrsMessageQueue(); - virtual ~SrsMessageQueue(); + SrsMessageQueue(); + virtual ~SrsMessageQueue(); public: - /** - * set the queue size - * @param queue_size the queue size in seconds. - */ - virtual void set_queue_size(double queue_size); + /** + * set the queue size + * @param queue_size the queue size in seconds. + */ + virtual void set_queue_size(double queue_size); public: - /** - * enqueue the message, the timestamp always monotonically. - * @param msg, the msg to enqueue, user never free it whatever the return code. - */ - virtual int enqueue(SrsSharedPtrMessage* msg); - /** - * get packets in consumer queue. - * @pmsgs SrsMessages*[], output the prt array. - * @count the count in array. - * @max_count the max count to dequeue, 0 to dequeue all. - */ - virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); + /** + * enqueue the message, the timestamp always monotonically. + * @param msg, the msg to enqueue, user never free it whatever the return code. + */ + virtual int enqueue(SrsSharedPtrMessage* msg); + /** + * get packets in consumer queue. + * @pmsgs SrsMessages*[], output the prt array. + * @count the count in array. + * @max_count the max count to dequeue, 0 to dequeue all. + */ + virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); private: - /** - * remove a gop from the front. - * if no iframe found, clear it. - */ - virtual void shrink(); - virtual void clear(); + /** + * remove a gop from the front. + * if no iframe found, clear it. + */ + virtual void shrink(); + virtual void clear(); }; /** @@ -121,39 +121,39 @@ private: class SrsConsumer { private: - SrsRtmpJitter* jitter; - SrsSource* source; - SrsMessageQueue* queue; - bool paused; + SrsRtmpJitter* jitter; + SrsSource* source; + SrsMessageQueue* queue; + bool paused; public: - SrsConsumer(SrsSource* _source); - virtual ~SrsConsumer(); + SrsConsumer(SrsSource* _source); + virtual ~SrsConsumer(); public: - virtual void set_queue_size(double queue_size); + virtual void set_queue_size(double queue_size); public: - /** - * get current client time, the last packet time. - */ - virtual int get_time(); - /** - * enqueue an shared ptr message. - * @param tba timebase of audio. - * used to calc the audio time delta if time-jitter detected. - * @param tbv timebase of video. - * used to calc the video time delta if time-jitter detected. - */ - virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv); - /** - * get packets in consumer queue. - * @pmsgs SrsMessages*[], output the prt array. - * @count the count in array. - * @max_count the max count to dequeue, 0 to dequeue all. - */ - virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); - /** - * when client send the pause message. - */ - virtual int on_play_client_pause(bool is_pause); + /** + * get current client time, the last packet time. + */ + virtual int get_time(); + /** + * enqueue an shared ptr message. + * @param tba timebase of audio. + * used to calc the audio time delta if time-jitter detected. + * @param tbv timebase of video. + * used to calc the video time delta if time-jitter detected. + */ + virtual int enqueue(SrsSharedPtrMessage* msg, int tba, int tbv); + /** + * get packets in consumer queue. + * @pmsgs SrsMessages*[], output the prt array. + * @count the count in array. + * @max_count the max count to dequeue, 0 to dequeue all. + */ + virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); + /** + * when client send the pause message. + */ + virtual int on_play_client_pause(bool is_pause); }; /** @@ -164,33 +164,33 @@ public: class SrsGopCache { private: - /** - * if disabled the gop cache, - * the client will wait for the next keyframe for h264, - * and will be black-screen. - */ - bool enable_gop_cache; - /** - * the video frame count, avoid cache for pure audio stream. - */ - int cached_video_count; - /** - * cached gop. - */ - std::vector gop_cache; + /** + * if disabled the gop cache, + * the client will wait for the next keyframe for h264, + * and will be black-screen. + */ + bool enable_gop_cache; + /** + * the video frame count, avoid cache for pure audio stream. + */ + int cached_video_count; + /** + * cached gop. + */ + std::vector gop_cache; public: - SrsGopCache(); - virtual ~SrsGopCache(); + SrsGopCache(); + virtual ~SrsGopCache(); public: - virtual void set(bool enabled); - /** - * only for h264 codec - * 1. cache the gop when got h264 video packet. - * 2. clear gop when got keyframe. - */ - virtual int cache(SrsSharedPtrMessage* msg); - virtual void clear(); - virtual int dump(SrsConsumer* consumer, int tba, int tbv); + virtual void set(bool enabled); + /** + * only for h264 codec + * 1. cache the gop when got h264 video packet. + * 2. clear gop when got keyframe. + */ + virtual int cache(SrsSharedPtrMessage* msg); + virtual void clear(); + virtual int dump(SrsConsumer* consumer, int tba, int tbv); }; /** @@ -199,89 +199,89 @@ public: class SrsSource : public ISrsReloadHandler { private: - static std::map pool; + static std::map pool; public: - /** - * find stream by vhost/app/stream. - * @param req the client request. - * @return the matched source, never be NULL. - * @remark stream_url should without port and schema. - */ - static SrsSource* find(SrsRequest* req); + /** + * find stream by vhost/app/stream. + * @param req the client request. + * @return the matched source, never be NULL. + * @remark stream_url should without port and schema. + */ + static SrsSource* find(SrsRequest* req); private: - // deep copy of client request. - SrsRequest* req; - // to delivery stream to clients. - std::vector consumers; - // hls handler. + // deep copy of client request. + SrsRequest* req; + // to delivery stream to clients. + std::vector consumers; + // hls handler. #ifdef SRS_HLS - SrsHls* hls; + SrsHls* hls; #endif - // transcoding handler. + // transcoding handler. #ifdef SRS_FFMPEG - SrsEncoder* encoder; + SrsEncoder* encoder; #endif - // gop cache for client fast startup. - SrsGopCache* gop_cache; - // to forward stream to other servers - std::vector forwarders; + // gop cache for client fast startup. + SrsGopCache* gop_cache; + // to forward stream to other servers + std::vector forwarders; private: - /** - * the sample rate of audio in metadata. - */ - int sample_rate; - /** - * the video frame rate in metadata. - */ - int frame_rate; - /** - * can publish, true when is not streaming - */ - bool _can_publish; + /** + * the sample rate of audio in metadata. + */ + int sample_rate; + /** + * the video frame rate in metadata. + */ + int frame_rate; + /** + * can publish, true when is not streaming + */ + bool _can_publish; private: - SrsSharedPtrMessage* cache_metadata; - // the cached video sequence header. - SrsSharedPtrMessage* cache_sh_video; - // the cached audio sequence header. - SrsSharedPtrMessage* cache_sh_audio; + SrsSharedPtrMessage* cache_metadata; + // the cached video sequence header. + SrsSharedPtrMessage* cache_sh_video; + // the cached audio sequence header. + SrsSharedPtrMessage* cache_sh_audio; public: - /** - * @param _req the client request object, - * this object will deep copy it for reload. - */ - SrsSource(SrsRequest* _req); - virtual ~SrsSource(); + /** + * @param _req the client request object, + * this object will deep copy it for reload. + */ + SrsSource(SrsRequest* _req); + virtual ~SrsSource(); // interface ISrsReloadHandler public: - virtual int on_reload_gop_cache(std::string vhost); - virtual int on_reload_queue_length(std::string vhost); - virtual int on_reload_forward(std::string vhost); - virtual int on_reload_hls(std::string vhost); - virtual int on_reload_transcode(std::string vhost); + virtual int on_reload_gop_cache(std::string vhost); + virtual int on_reload_queue_length(std::string vhost); + virtual int on_reload_forward(std::string vhost); + virtual int on_reload_hls(std::string vhost); + virtual int on_reload_transcode(std::string vhost); public: - // for the SrsForwarder to callback to request the sequence headers. - virtual int on_forwarder_start(SrsForwarder* forwarder); - // for the SrsHls to callback to request the sequence headers. - virtual int on_hls_start(); + // for the SrsForwarder to callback to request the sequence headers. + virtual int on_forwarder_start(SrsForwarder* forwarder); + // for the SrsHls to callback to request the sequence headers. + virtual int on_hls_start(); public: - virtual bool can_publish(); - virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); - virtual int on_audio(SrsCommonMessage* audio); - virtual int on_video(SrsCommonMessage* video); - /** - * publish stream event notify. - * @param _req the request from client, the source will deep copy it, - * for when reload the request of client maybe invalid. - */ - virtual int on_publish(SrsRequest* _req); - virtual void on_unpublish(); + virtual bool can_publish(); + virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); + virtual int on_audio(SrsCommonMessage* audio); + virtual int on_video(SrsCommonMessage* video); + /** + * publish stream event notify. + * @param _req the request from client, the source will deep copy it, + * for when reload the request of client maybe invalid. + */ + virtual int on_publish(SrsRequest* _req); + virtual void on_unpublish(); public: - virtual int create_consumer(SrsConsumer*& consumer); - virtual void on_consumer_destroy(SrsConsumer* consumer); - virtual void set_cache(bool enabled); + virtual int create_consumer(SrsConsumer*& consumer); + virtual void on_consumer_destroy(SrsConsumer* consumer); + virtual void set_cache(bool enabled); private: - virtual int create_forwarders(); - virtual void destroy_forwarders(); + virtual int create_forwarders(); + virtual void destroy_forwarders(); }; #endif \ No newline at end of file diff --git a/trunk/src/app/srs_app_st.cpp b/trunk/src/app/srs_app_st.cpp index 5b465d3a5..8e54117bf 100644 --- a/trunk/src/app/srs_app_st.cpp +++ b/trunk/src/app/srs_app_st.cpp @@ -25,13 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. void srs_close_stfd(st_netfd_t& stfd) { - if (stfd) { - int fd = st_netfd_fileno(stfd); - st_netfd_close(stfd); - stfd = NULL; - - // st does not close it sometimes, - // close it manually. - close(fd); - } + if (stfd) { + int fd = st_netfd_fileno(stfd); + st_netfd_close(stfd); + stfd = NULL; + + // st does not close it sometimes, + // close it manually. + close(fd); + } } diff --git a/trunk/src/app/srs_app_thread.cpp b/trunk/src/app/srs_app_thread.cpp index 621c6946a..66a3a6827 100644 --- a/trunk/src/app/srs_app_thread.cpp +++ b/trunk/src/app/srs_app_thread.cpp @@ -40,14 +40,14 @@ void ISrsThreadHandler::on_enter_loop() int ISrsThreadHandler::on_before_cycle() { - int ret = ERROR_SUCCESS; - return ret; + int ret = ERROR_SUCCESS; + return ret; } int ISrsThreadHandler::on_end_cycle() { - int ret = ERROR_SUCCESS; - return ret; + int ret = ERROR_SUCCESS; + return ret; } void ISrsThreadHandler::on_leave_loop() @@ -56,29 +56,29 @@ void ISrsThreadHandler::on_leave_loop() SrsThread::SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us) { - handler = thread_handler; - cycle_interval_us = interval_us; - - tid = NULL; - loop = false; + handler = thread_handler; + cycle_interval_us = interval_us; + + tid = NULL; + loop = false; } SrsThread::~SrsThread() { - stop(); + stop(); } int SrsThread::start() { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + if(tid) { srs_info("thread already running."); return ret; } if((tid = st_thread_create(thread_fun, this, 1, 0)) == NULL){ - ret = ERROR_ST_CREATE_CYCLE_THREAD; + ret = ERROR_ST_CREATE_CYCLE_THREAD; srs_error("st_thread_create failed. ret=%d", ret); return ret; } @@ -88,74 +88,74 @@ int SrsThread::start() void SrsThread::stop() { - if (tid) { - loop = false; - - // the interrupt will cause the socket to read/write error, - // which will terminate the cycle thread. - st_thread_interrupt(tid); - - // wait the thread to exit. - st_thread_join(tid, NULL); - - tid = NULL; - } + if (tid) { + loop = false; + + // the interrupt will cause the socket to read/write error, + // which will terminate the cycle thread. + st_thread_interrupt(tid); + + // wait the thread to exit. + st_thread_join(tid, NULL); + + tid = NULL; + } } bool SrsThread::can_loop() { - return loop; + return loop; } void SrsThread::thread_cycle() { - int ret = ERROR_SUCCESS; - - srs_assert(handler); - - _srs_context->generate_id(); - srs_trace("thread cycle start"); + int ret = ERROR_SUCCESS; + + srs_assert(handler); + + _srs_context->generate_id(); + srs_trace("thread cycle start"); - handler->on_end_cycle(); - - loop = true; - while (loop) { - if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) { - srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret); - goto failed; - } - srs_info("thread on before cycle success"); - - if ((ret = handler->cycle()) != ERROR_SUCCESS) { - srs_warn("thread cycle failed, ignored and retry, ret=%d", ret); - goto failed; - } - srs_info("thread cycle success"); - - if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) { - srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret); - goto failed; - } - srs_info("thread on end cycle success"); + handler->on_end_cycle(); + + loop = true; + while (loop) { + if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) { + srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret); + goto failed; + } + srs_info("thread on before cycle success"); + + if ((ret = handler->cycle()) != ERROR_SUCCESS) { + srs_warn("thread cycle failed, ignored and retry, ret=%d", ret); + goto failed; + } + srs_info("thread cycle success"); + + if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) { + srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret); + goto failed; + } + srs_info("thread on end cycle success"); failed: - if (!loop) { - break; - } - - st_usleep(cycle_interval_us); - } - - handler->on_leave_loop(); - srs_trace("thread cycle finished"); + if (!loop) { + break; + } + + st_usleep(cycle_interval_us); + } + + handler->on_leave_loop(); + srs_trace("thread cycle finished"); } void* SrsThread::thread_fun(void* arg) { - SrsThread* obj = (SrsThread*)arg; - srs_assert(obj); - - obj->thread_cycle(); - - return NULL; + SrsThread* obj = (SrsThread*)arg; + srs_assert(obj); + + obj->thread_cycle(); + + return NULL; } \ No newline at end of file diff --git a/trunk/src/app/srs_app_thread.hpp b/trunk/src/app/srs_app_thread.hpp index f29f045ae..140c71576 100644 --- a/trunk/src/app/srs_app_thread.hpp +++ b/trunk/src/app/srs_app_thread.hpp @@ -34,14 +34,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** * the handler for the thread, callback interface. * the thread model defines as: -* handler->on_enter_loop() -* while loop: -* handler->on_before_cycle() -* handler->cycle() -* handler->on_end_cycle() -* if !loop then break for user stop thread. -* sleep(CycleIntervalMilliseconds) -* handler->on_leave_loop() +* handler->on_enter_loop() +* while loop: +* handler->on_before_cycle() +* handler->cycle() +* handler->on_end_cycle() +* if !loop then break for user stop thread. +* sleep(CycleIntervalMilliseconds) +* handler->on_leave_loop() * when stop, the thread will interrupt the st_thread, * which will cause the socket to return error and * terminate the cycle thread. @@ -49,31 +49,31 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * when thread interrupt, the socket maybe not got EINT, * espectially on st_usleep(), so the cycle must check the loop, * when handler->cycle() has loop itself, for example: -* handler->cycle() is: -* while (true): -* st_usleep(0); -* if (read_from_socket(skt) < 0) break; +* handler->cycle() is: +* while (true): +* st_usleep(0); +* if (read_from_socket(skt) < 0) break; * if thread stop when read_from_socket, it's ok, the loop will break, * but when thread stop interrupt the s_usleep(0), then the loop is * death loop. * in a word, the handler->cycle() must: -* handler->cycle() is: -* while (pthread->can_loop()): -* st_usleep(0); -* if (read_from_socket(skt) < 0) break; +* handler->cycle() is: +* while (pthread->can_loop()): +* st_usleep(0); +* if (read_from_socket(skt) < 0) break; * check the loop, then it works. */ class ISrsThreadHandler { public: - ISrsThreadHandler(); - virtual ~ISrsThreadHandler(); + ISrsThreadHandler(); + virtual ~ISrsThreadHandler(); public: - virtual void on_enter_loop(); - virtual int on_before_cycle(); - virtual int cycle() = 0; - virtual int on_end_cycle(); - virtual void on_leave_loop(); + virtual void on_enter_loop(); + virtual int on_before_cycle(); + virtual int cycle() = 0; + virtual int on_end_cycle(); + virtual void on_leave_loop(); }; /** @@ -83,41 +83,41 @@ public: class SrsThread { private: - st_thread_t tid; - bool loop; + st_thread_t tid; + bool loop; private: - ISrsThreadHandler* handler; - int64_t cycle_interval_us; + ISrsThreadHandler* handler; + int64_t cycle_interval_us; public: - /** - * initialize the thread. - * @param thread_handler, the cycle handler for the thread. - * @param interval_us, the sleep interval when cycle finished. - */ - SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us); - virtual ~SrsThread(); + /** + * initialize the thread. + * @param thread_handler, the cycle handler for the thread. + * @param interval_us, the sleep interval when cycle finished. + */ + SrsThread(ISrsThreadHandler* thread_handler, int64_t interval_us); + virtual ~SrsThread(); public: - /** - * start the thread, invoke the cycle of handler util - * user stop the thread. - * @remark ignore any error of cycle of handler. - * @remark user can start multiple times, ignore if already started. - */ - virtual int start(); - /** - * stop the thread, wait for the thread to terminate. - * @remark user can stop multiple times, ignore if already stopped. - */ - virtual void stop(); - /** - * whether the thread should loop, - * used for handler->cycle() which has a loop method, - * to check this method, break if false. - */ - virtual bool can_loop(); + /** + * start the thread, invoke the cycle of handler util + * user stop the thread. + * @remark ignore any error of cycle of handler. + * @remark user can start multiple times, ignore if already started. + */ + virtual int start(); + /** + * stop the thread, wait for the thread to terminate. + * @remark user can stop multiple times, ignore if already stopped. + */ + virtual void stop(); + /** + * whether the thread should loop, + * used for handler->cycle() which has a loop method, + * to check this method, break if false. + */ + virtual bool can_loop(); private: - virtual void thread_cycle(); - static void* thread_fun(void* arg); + virtual void thread_cycle(); + static void* thread_fun(void* arg); }; #endif diff --git a/trunk/src/core/srs_core.cpp b/trunk/src/core/srs_core.cpp index 4574837bb..5cd92389a 100644 --- a/trunk/src/core/srs_core.cpp +++ b/trunk/src/core/srs_core.cpp @@ -32,7 +32,7 @@ static int64_t _srs_system_time_us_cache = 0; 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() @@ -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 ret = str; - - if (old_str == new_str) { - return ret; - } - - size_t pos = 0; - while ((pos = ret.find(old_str, pos)) != std::string::npos) { - ret = ret.replace(pos, old_str.length(), new_str); - pos += new_str.length(); - } - - return ret; + std::string ret = str; + + if (old_str == new_str) { + return ret; + } + + size_t pos = 0; + while ((pos = ret.find(old_str, pos)) != std::string::npos) { + ret = ret.replace(pos, old_str.length(), new_str); + pos += new_str.length(); + } + + return ret; } std::string srs_dns_resolve(std::string host) diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index b05d5f1ed..0dfce3578 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -69,18 +69,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // free the p and set to NULL. // p must be a T*. #define srs_freep(p) \ - if (p) { \ - delete p; \ - p = NULL; \ - } \ - (void)0 + if (p) { \ + delete p; \ + p = NULL; \ + } \ + (void)0 // free the p which represents a array #define srs_freepa(p) \ - if (p) { \ - delete[] p; \ - p = NULL; \ - } \ - (void)0 + if (p) { \ + delete[] p; \ + p = NULL; \ + } \ + (void)0 // compare #define srs_min(a, b) (((a) < (b))? (a) : (b)) diff --git a/trunk/src/core/srs_core_autofree.hpp b/trunk/src/core/srs_core_autofree.hpp index 513a4dcf5..2938bdc82 100644 --- a/trunk/src/core/srs_core_autofree.hpp +++ b/trunk/src/core/srs_core_autofree.hpp @@ -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. */ #define SrsAutoFree(className, instance, is_array) \ - __SrsAutoFree _auto_free_##instance(&instance, is_array) + __SrsAutoFree _auto_free_##instance(&instance, is_array) template class __SrsAutoFree diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index d5dc12f10..2d70b365e 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -46,46 +46,46 @@ SrsBuffer::~SrsBuffer() int SrsBuffer::size() { - return (int)data.size(); + return (int)data.size(); } char* SrsBuffer::bytes() { - return &data.at(0); + return &data.at(0); } 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) { - 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 ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if (required_size < 0) { - ret = ERROR_SYSTEM_SIZE_NEGATIVE; - srs_error("size is negative. size=%d, ret=%d", required_size, ret); - return ret; - } + if (required_size < 0) { + ret = ERROR_SYSTEM_SIZE_NEGATIVE; + srs_error("size is negative. size=%d, ret=%d", required_size, ret); + return ret; + } - while (size() < required_size) { - char buffer[SOCKET_READ_SIZE]; - - ssize_t nread; - if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) { - return ret; - } - - srs_assert((int)nread > 0); - append(buffer, (int)nread); - } - - return ret; + while (size() < required_size) { + char buffer[SOCKET_READ_SIZE]; + + ssize_t nread; + if ((ret = skt->read(buffer, SOCKET_READ_SIZE, &nread)) != ERROR_SUCCESS) { + return ret; + } + + srs_assert((int)nread > 0); + append(buffer, (int)nread); + } + + return ret; } diff --git a/trunk/src/kernel/srs_kernel_buffer.hpp b/trunk/src/kernel/srs_kernel_buffer.hpp index 309f96680..d09e20c70 100644 --- a/trunk/src/kernel/srs_kernel_buffer.hpp +++ b/trunk/src/kernel/srs_kernel_buffer.hpp @@ -38,8 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class ISrsBufferReader { public: - ISrsBufferReader(); - virtual ~ISrsBufferReader(); + ISrsBufferReader(); + virtual ~ISrsBufferReader(); // for protocol/amf0/msg-codec public: virtual int read(const void* buf, size_t size, ssize_t* nread) = 0; @@ -53,18 +53,18 @@ public: class SrsBuffer { private: - std::vector data; + std::vector data; public: - SrsBuffer(); - virtual ~SrsBuffer(); + SrsBuffer(); + virtual ~SrsBuffer(); public: - virtual int size(); - virtual char* bytes(); - virtual void erase(int size); + virtual int size(); + virtual char* bytes(); + virtual void erase(int size); private: - virtual void append(char* bytes, int size); + virtual void append(char* bytes, int size); public: - virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size); + virtual int ensure_buffer_bytes(ISrsBufferReader* skt, int required_size); }; #endif \ No newline at end of file diff --git a/trunk/src/kernel/srs_kernel_error.cpp b/trunk/src/kernel/srs_kernel_error.cpp index 73fc0f06e..66ab81cac 100644 --- a/trunk/src/kernel/srs_kernel_error.cpp +++ b/trunk/src/kernel/srs_kernel_error.cpp @@ -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) { - return error_code == ERROR_CONTROL_RTMP_CLOSE - || error_code == ERROR_CONTROL_REPUBLISH; + return error_code == ERROR_CONTROL_RTMP_CLOSE + || error_code == ERROR_CONTROL_REPUBLISH; } bool srs_is_client_gracefully_close(int error_code) { - return error_code == ERROR_SOCKET_READ - || error_code == ERROR_SOCKET_READ_FULLY - || error_code == ERROR_SOCKET_WRITE; + return error_code == ERROR_SOCKET_READ + || error_code == ERROR_SOCKET_READ_FULLY + || error_code == ERROR_SOCKET_WRITE; } diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 99a6fea3d..d190ed764 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -30,133 +30,133 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include -#define ERROR_SUCCESS 0 +#define ERROR_SUCCESS 0 -#define ERROR_ST_SET_EPOLL 100 -#define ERROR_ST_INITIALIZE 101 -#define ERROR_ST_OPEN_SOCKET 102 -#define ERROR_ST_CREATE_LISTEN_THREAD 103 -#define ERROR_ST_CREATE_CYCLE_THREAD 104 -#define ERROR_ST_CONNECT 105 +#define ERROR_ST_SET_EPOLL 100 +#define ERROR_ST_INITIALIZE 101 +#define ERROR_ST_OPEN_SOCKET 102 +#define ERROR_ST_CREATE_LISTEN_THREAD 103 +#define ERROR_ST_CREATE_CYCLE_THREAD 104 +#define ERROR_ST_CONNECT 105 -#define ERROR_SOCKET_CREATE 200 -#define ERROR_SOCKET_SETREUSE 201 -#define ERROR_SOCKET_BIND 202 -#define ERROR_SOCKET_LISTEN 203 -#define ERROR_SOCKET_CLOSED 204 -#define ERROR_SOCKET_GET_PEER_NAME 205 -#define ERROR_SOCKET_GET_PEER_IP 206 -#define ERROR_SOCKET_READ 207 -#define ERROR_SOCKET_READ_FULLY 208 -#define ERROR_SOCKET_WRITE 209 -#define ERROR_SOCKET_WAIT 210 -#define ERROR_SOCKET_TIMEOUT 211 +#define ERROR_SOCKET_CREATE 200 +#define ERROR_SOCKET_SETREUSE 201 +#define ERROR_SOCKET_BIND 202 +#define ERROR_SOCKET_LISTEN 203 +#define ERROR_SOCKET_CLOSED 204 +#define ERROR_SOCKET_GET_PEER_NAME 205 +#define ERROR_SOCKET_GET_PEER_IP 206 +#define ERROR_SOCKET_READ 207 +#define ERROR_SOCKET_READ_FULLY 208 +#define ERROR_SOCKET_WRITE 209 +#define ERROR_SOCKET_WAIT 210 +#define ERROR_SOCKET_TIMEOUT 211 #define ERROR_SOCKET_GET_LOCAL_IP 212 -#define ERROR_RTMP_PLAIN_REQUIRED 300 -#define ERROR_RTMP_CHUNK_START 301 -#define ERROR_RTMP_MSG_INVLIAD_SIZE 302 -#define ERROR_RTMP_AMF0_DECODE 303 -#define ERROR_RTMP_AMF0_INVALID 304 -#define ERROR_RTMP_REQ_CONNECT 305 -#define ERROR_RTMP_REQ_TCURL 306 -#define ERROR_RTMP_MESSAGE_DECODE 307 -#define ERROR_RTMP_MESSAGE_ENCODE 308 -#define ERROR_RTMP_AMF0_ENCODE 309 -#define ERROR_RTMP_CHUNK_SIZE 310 -#define ERROR_RTMP_TRY_SIMPLE_HS 311 -#define ERROR_RTMP_CH_SCHEMA 312 -#define ERROR_RTMP_PACKET_SIZE 313 -#define ERROR_RTMP_VHOST_NOT_FOUND 314 -#define ERROR_RTMP_ACCESS_DENIED 315 -#define ERROR_RTMP_HANDSHAKE 316 -#define ERROR_RTMP_NO_REQUEST 317 +#define ERROR_RTMP_PLAIN_REQUIRED 300 +#define ERROR_RTMP_CHUNK_START 301 +#define ERROR_RTMP_MSG_INVLIAD_SIZE 302 +#define ERROR_RTMP_AMF0_DECODE 303 +#define ERROR_RTMP_AMF0_INVALID 304 +#define ERROR_RTMP_REQ_CONNECT 305 +#define ERROR_RTMP_REQ_TCURL 306 +#define ERROR_RTMP_MESSAGE_DECODE 307 +#define ERROR_RTMP_MESSAGE_ENCODE 308 +#define ERROR_RTMP_AMF0_ENCODE 309 +#define ERROR_RTMP_CHUNK_SIZE 310 +#define ERROR_RTMP_TRY_SIMPLE_HS 311 +#define ERROR_RTMP_CH_SCHEMA 312 +#define ERROR_RTMP_PACKET_SIZE 313 +#define ERROR_RTMP_VHOST_NOT_FOUND 314 +#define ERROR_RTMP_ACCESS_DENIED 315 +#define ERROR_RTMP_HANDSHAKE 316 +#define ERROR_RTMP_NO_REQUEST 317 // if user use complex handshake, but without ssl, // 1. srs is ok, ignore and turn to simple handshake. // 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_PACKET_INVALID 401 -#define ERROR_SYSTEM_CLIENT_INVALID 402 -#define ERROR_SYSTEM_ASSERT_FAILED 403 -#define ERROR_SYSTEM_SIZE_NEGATIVE 404 -#define ERROR_SYSTEM_CONFIG_INVALID 405 -#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406 -#define ERROR_SYSTEM_CONFIG_BLOCK_START 407 -#define ERROR_SYSTEM_CONFIG_BLOCK_END 408 -#define ERROR_SYSTEM_CONFIG_EOF 409 -#define ERROR_SYSTEM_STREAM_BUSY 410 -#define ERROR_SYSTEM_IP_INVALID 411 -#define ERROR_SYSTEM_FORWARD_LOOP 412 -#define ERROR_SYSTEM_WAITPID 413 -#define ERROR_SYSTEM_BANDWIDTH_KEY 414 -#define ERROR_SYSTEM_BANDWIDTH_DENIED 415 +#define ERROR_SYSTEM_STREAM_INIT 400 +#define ERROR_SYSTEM_PACKET_INVALID 401 +#define ERROR_SYSTEM_CLIENT_INVALID 402 +#define ERROR_SYSTEM_ASSERT_FAILED 403 +#define ERROR_SYSTEM_SIZE_NEGATIVE 404 +#define ERROR_SYSTEM_CONFIG_INVALID 405 +#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406 +#define ERROR_SYSTEM_CONFIG_BLOCK_START 407 +#define ERROR_SYSTEM_CONFIG_BLOCK_END 408 +#define ERROR_SYSTEM_CONFIG_EOF 409 +#define ERROR_SYSTEM_STREAM_BUSY 410 +#define ERROR_SYSTEM_IP_INVALID 411 +#define ERROR_SYSTEM_FORWARD_LOOP 412 +#define ERROR_SYSTEM_WAITPID 413 +#define ERROR_SYSTEM_BANDWIDTH_KEY 414 +#define ERROR_SYSTEM_BANDWIDTH_DENIED 415 // see librtmp. // failed when open ssl create the dh -#define ERROR_OpenSslCreateDH 500 +#define ERROR_OpenSslCreateDH 500 // failed when open ssl create the Private key. -#define ERROR_OpenSslCreateP 501 +#define ERROR_OpenSslCreateP 501 // when open ssl create G. -#define ERROR_OpenSslCreateG 502 +#define ERROR_OpenSslCreateG 502 // when open ssl parse P1024 -#define ERROR_OpenSslParseP1024 503 +#define ERROR_OpenSslParseP1024 503 // when open ssl set G -#define ERROR_OpenSslSetG 504 +#define ERROR_OpenSslSetG 504 // when open ssl generate DHKeys -#define ERROR_OpenSslGenerateDHKeys 505 +#define ERROR_OpenSslGenerateDHKeys 505 // when open ssl share key already computed. -#define ERROR_OpenSslShareKeyComputed 506 +#define ERROR_OpenSslShareKeyComputed 506 // when open ssl get shared key size. -#define ERROR_OpenSslGetSharedKeySize 507 +#define ERROR_OpenSslGetSharedKeySize 507 // when open ssl get peer public key. -#define ERROR_OpenSslGetPeerPublicKey 508 +#define ERROR_OpenSslGetPeerPublicKey 508 // when open ssl compute shared key. -#define ERROR_OpenSslComputeSharedKey 509 +#define ERROR_OpenSslComputeSharedKey 509 // when open ssl is invalid DH state. -#define ERROR_OpenSslInvalidDHState 510 +#define ERROR_OpenSslInvalidDHState 510 // when open ssl copy key -#define ERROR_OpenSslCopyKey 511 +#define ERROR_OpenSslCopyKey 511 // when open ssl sha256 digest key invalid size. -#define ERROR_OpenSslSha256DigestSize 512 +#define ERROR_OpenSslSha256DigestSize 512 -#define ERROR_HLS_METADATA 600 -#define ERROR_HLS_DECODE_ERROR 601 -#define ERROR_HLS_CREATE_DIR 602 -#define ERROR_HLS_OPEN_FAILED 603 -#define ERROR_HLS_WRITE_FAILED 604 -#define ERROR_HLS_AAC_FRAME_LENGTH 605 -#define ERROR_HLS_AVC_SAMPLE_SIZE 606 +#define ERROR_HLS_METADATA 600 +#define ERROR_HLS_DECODE_ERROR 601 +#define ERROR_HLS_CREATE_DIR 602 +#define ERROR_HLS_OPEN_FAILED 603 +#define ERROR_HLS_WRITE_FAILED 604 +#define ERROR_HLS_AAC_FRAME_LENGTH 605 +#define ERROR_HLS_AVC_SAMPLE_SIZE 606 -#define ERROR_ENCODER_VCODEC 700 -#define ERROR_ENCODER_OUTPUT 701 -#define ERROR_ENCODER_ACHANNELS 702 -#define ERROR_ENCODER_ASAMPLE_RATE 703 -#define ERROR_ENCODER_ABITRATE 704 -#define ERROR_ENCODER_ACODEC 705 -#define ERROR_ENCODER_VPRESET 706 -#define ERROR_ENCODER_VPROFILE 707 -#define ERROR_ENCODER_VTHREADS 708 -#define ERROR_ENCODER_VHEIGHT 709 -#define ERROR_ENCODER_VWIDTH 710 -#define ERROR_ENCODER_VFPS 711 -#define ERROR_ENCODER_VBITRATE 712 -#define ERROR_ENCODER_FORK 713 -#define ERROR_ENCODER_LOOP 714 -#define ERROR_ENCODER_OPEN 715 -#define ERROR_ENCODER_DUP2 716 +#define ERROR_ENCODER_VCODEC 700 +#define ERROR_ENCODER_OUTPUT 701 +#define ERROR_ENCODER_ACHANNELS 702 +#define ERROR_ENCODER_ASAMPLE_RATE 703 +#define ERROR_ENCODER_ABITRATE 704 +#define ERROR_ENCODER_ACODEC 705 +#define ERROR_ENCODER_VPRESET 706 +#define ERROR_ENCODER_VPROFILE 707 +#define ERROR_ENCODER_VTHREADS 708 +#define ERROR_ENCODER_VHEIGHT 709 +#define ERROR_ENCODER_VWIDTH 710 +#define ERROR_ENCODER_VFPS 711 +#define ERROR_ENCODER_VBITRATE 712 +#define ERROR_ENCODER_FORK 713 +#define ERROR_ENCODER_LOOP 714 +#define ERROR_ENCODER_OPEN 715 +#define ERROR_ENCODER_DUP2 716 -#define ERROR_HTTP_PARSE_URI 800 -#define ERROR_HTTP_DATA_INVLIAD 801 -#define ERROR_HTTP_PARSE_HEADER 802 +#define ERROR_HTTP_PARSE_URI 800 +#define ERROR_HTTP_DATA_INVLIAD 801 +#define ERROR_HTTP_PARSE_HEADER 802 // system control message, // not an error, but special control logic. // sys ctl: rtmp close stream, support replay. -#define ERROR_CONTROL_RTMP_CLOSE 900 +#define ERROR_CONTROL_RTMP_CLOSE 900 // FMLE stop publish and republish. -#define ERROR_CONTROL_REPUBLISH 901 +#define ERROR_CONTROL_REPUBLISH 901 /** * whether the error code is an system control error. diff --git a/trunk/src/kernel/srs_kernel_log.cpp b/trunk/src/kernel/srs_kernel_log.cpp index 8518e7fc3..20d25495f 100644 --- a/trunk/src/kernel/srs_kernel_log.cpp +++ b/trunk/src/kernel/srs_kernel_log.cpp @@ -65,6 +65,6 @@ void ISrsThreadContext::generate_id() int ISrsThreadContext::get_id() { - return 0; + return 0; } diff --git a/trunk/src/kernel/srs_kernel_log.hpp b/trunk/src/kernel/srs_kernel_log.hpp index ac4371663..8d507d6dd 100644 --- a/trunk/src/kernel/srs_kernel_log.hpp +++ b/trunk/src/kernel/srs_kernel_log.hpp @@ -110,16 +110,16 @@ extern ISrsThreadContext* _srs_context; #endif #if 1 - #undef srs_verbose - #define srs_verbose(msg, ...) (void)0 + #undef srs_verbose + #define srs_verbose(msg, ...) (void)0 #endif #if 1 - #undef srs_info - #define srs_info(msg, ...) (void)0 + #undef srs_info + #define srs_info(msg, ...) (void)0 #endif #if 0 - #undef srs_trace - #define srs_trace(msg, ...) (void)0 + #undef srs_trace + #define srs_trace(msg, ...) (void)0 #endif #endif diff --git a/trunk/src/kernel/srs_kernel_stream.cpp b/trunk/src/kernel/srs_kernel_stream.cpp index ed55f1c12..2137e30df 100644 --- a/trunk/src/kernel/srs_kernel_stream.cpp +++ b/trunk/src/kernel/srs_kernel_stream.cpp @@ -28,8 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SrsStream::SrsStream() { - p = bytes = NULL; - size = 0; + p = bytes = NULL; + size = 0; } SrsStream::~SrsStream() @@ -38,113 +38,113 @@ SrsStream::~SrsStream() int SrsStream::initialize(char* _bytes, int _size) { - int ret = ERROR_SUCCESS; - - if (!_bytes) { - ret = ERROR_SYSTEM_STREAM_INIT; - srs_error("stream param bytes must not be NULL. ret=%d", ret); - return ret; - } - - if (_size <= 0) { - ret = ERROR_SYSTEM_STREAM_INIT; - srs_error("stream param size must be positive. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + if (!_bytes) { + ret = ERROR_SYSTEM_STREAM_INIT; + srs_error("stream param bytes must not be NULL. ret=%d", ret); + return ret; + } + + if (_size <= 0) { + ret = ERROR_SYSTEM_STREAM_INIT; + srs_error("stream param size must be positive. ret=%d", ret); + return ret; + } - size = _size; - p = bytes = _bytes; + size = _size; + p = bytes = _bytes; - return ret; + return ret; } void SrsStream::reset() { - p = bytes; + p = bytes; } bool SrsStream::empty() { - return !p || !bytes || (p >= bytes + size); + return !p || !bytes || (p >= bytes + 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) { - p += size; + p += size; } int SrsStream::pos() { - return p - bytes; + return p - bytes; } int SrsStream::left() { - return size - pos(); + return size - pos(); } char* SrsStream::current() { - return p; + return p; } int8_t SrsStream::read_1bytes() { - srs_assert(require(1)); - - return (int8_t)*p++; + srs_assert(require(1)); + + return (int8_t)*p++; } int16_t SrsStream::read_2bytes() { - srs_assert(require(2)); - - int16_t value; - pp = (char*)&value; - pp[1] = *p++; - pp[0] = *p++; - - return value; + srs_assert(require(2)); + + int16_t value; + pp = (char*)&value; + pp[1] = *p++; + pp[0] = *p++; + + return value; } int32_t SrsStream::read_3bytes() { - srs_assert(require(3)); - - int32_t value = 0x00; - pp = (char*)&value; - pp[2] = *p++; - pp[1] = *p++; - pp[0] = *p++; - - return value; + srs_assert(require(3)); + + int32_t value = 0x00; + pp = (char*)&value; + pp[2] = *p++; + pp[1] = *p++; + pp[0] = *p++; + + return value; } int32_t SrsStream::read_4bytes() { - srs_assert(require(4)); - - int32_t value; - pp = (char*)&value; - pp[3] = *p++; - pp[2] = *p++; - pp[1] = *p++; - pp[0] = *p++; - - return value; + srs_assert(require(4)); + + int32_t value; + pp = (char*)&value; + pp[3] = *p++; + pp[2] = *p++; + pp[1] = *p++; + pp[0] = *p++; + + return value; } int64_t SrsStream::read_8bytes() { - srs_assert(require(8)); - - int64_t value; - pp = (char*)&value; + srs_assert(require(8)); + + int64_t value; + pp = (char*)&value; pp[7] = *p++; pp[6] = *p++; pp[5] = *p++; @@ -153,69 +153,69 @@ int64_t SrsStream::read_8bytes() pp[2] = *p++; pp[1] = *p++; pp[0] = *p++; - - return value; + + return value; } std::string SrsStream::read_string(int len) { - srs_assert(require(len)); - - std::string value; - value.append(p, len); - - p += len; - - return value; + srs_assert(require(len)); + + std::string value; + value.append(p, len); + + p += len; + + return value; } void SrsStream::write_1bytes(int8_t value) { - srs_assert(require(1)); - - *p++ = value; + srs_assert(require(1)); + + *p++ = value; } void SrsStream::write_2bytes(int16_t value) { - srs_assert(require(2)); - - pp = (char*)&value; - *p++ = pp[1]; - *p++ = pp[0]; + srs_assert(require(2)); + + pp = (char*)&value; + *p++ = pp[1]; + *p++ = pp[0]; } void SrsStream::write_4bytes(int32_t value) { - srs_assert(require(4)); - - pp = (char*)&value; - *p++ = pp[3]; - *p++ = pp[2]; - *p++ = pp[1]; - *p++ = pp[0]; + srs_assert(require(4)); + + pp = (char*)&value; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; } void SrsStream::write_8bytes(int64_t value) { - srs_assert(require(8)); - - pp = (char*)&value; - *p++ = pp[7]; - *p++ = pp[6]; - *p++ = pp[5]; - *p++ = pp[4]; - *p++ = pp[3]; - *p++ = pp[2]; - *p++ = pp[1]; - *p++ = pp[0]; + srs_assert(require(8)); + + pp = (char*)&value; + *p++ = pp[7]; + *p++ = pp[6]; + *p++ = pp[5]; + *p++ = pp[4]; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; } void SrsStream::write_string(std::string value) { - srs_assert(require(value.length())); - - memcpy(p, value.data(), value.length()); - p += value.length(); + srs_assert(require(value.length())); + + memcpy(p, value.data(), value.length()); + p += value.length(); } diff --git a/trunk/src/kernel/srs_kernel_stream.hpp b/trunk/src/kernel/srs_kernel_stream.hpp index 1466a1773..060278875 100644 --- a/trunk/src/kernel/srs_kernel_stream.hpp +++ b/trunk/src/kernel/srs_kernel_stream.hpp @@ -36,95 +36,95 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsStream { private: - char* p; - char* pp; - char* bytes; - int size; + char* p; + char* pp; + char* bytes; + int size; public: - SrsStream(); - virtual ~SrsStream(); + SrsStream(); + virtual ~SrsStream(); public: - /** - * initialize the stream from bytes. - * @_bytes, must not be NULL, or return error. - * @_size, must be positive, or return error. - * @remark, stream never free the _bytes, user must free it. - */ - virtual int initialize(char* _bytes, int _size); - /** - * reset the position to beginning. - */ - virtual void reset(); - /** - * whether stream is empty. - * if empty, never read or write. - */ - virtual bool empty(); - /** - * whether required size is ok. - * @return true if stream can read/write specified required_size bytes. - */ - virtual bool require(int required_size); - /** - * to skip some size. - * @size can be any value. positive to forward; nagetive to backward. - */ - virtual void skip(int size); - /** - * tell the current pos. - */ - virtual int pos(); - /** - * left size of bytes. - */ - virtual int left(); - virtual char* current(); + /** + * initialize the stream from bytes. + * @_bytes, must not be NULL, or return error. + * @_size, must be positive, or return error. + * @remark, stream never free the _bytes, user must free it. + */ + virtual int initialize(char* _bytes, int _size); + /** + * reset the position to beginning. + */ + virtual void reset(); + /** + * whether stream is empty. + * if empty, never read or write. + */ + virtual bool empty(); + /** + * whether required size is ok. + * @return true if stream can read/write specified required_size bytes. + */ + virtual bool require(int required_size); + /** + * to skip some size. + * @size can be any value. positive to forward; nagetive to backward. + */ + virtual void skip(int size); + /** + * tell the current pos. + */ + virtual int pos(); + /** + * left size of bytes. + */ + virtual int left(); + virtual char* current(); public: - /** - * get 1bytes char from stream. - */ - virtual int8_t read_1bytes(); - /** - * get 2bytes int from stream. - */ - virtual int16_t read_2bytes(); - /** - * get 3bytes int from stream. - */ - virtual int32_t read_3bytes(); - /** - * get 4bytes int from stream. - */ - virtual int32_t read_4bytes(); - /** - * get 8bytes int from stream. - */ - virtual int64_t read_8bytes(); - /** - * get string from stream, length specifies by param len. - */ - virtual std::string read_string(int len); + /** + * get 1bytes char from stream. + */ + virtual int8_t read_1bytes(); + /** + * get 2bytes int from stream. + */ + virtual int16_t read_2bytes(); + /** + * get 3bytes int from stream. + */ + virtual int32_t read_3bytes(); + /** + * get 4bytes int from stream. + */ + virtual int32_t read_4bytes(); + /** + * get 8bytes int from stream. + */ + virtual int64_t read_8bytes(); + /** + * get string from stream, length specifies by param len. + */ + virtual std::string read_string(int len); public: - /** - * write 1bytes char to stream. - */ - virtual void write_1bytes(int8_t value); - /** - * write 2bytes int to stream. - */ - virtual void write_2bytes(int16_t value); - /** - * write 4bytes int to stream. - */ - virtual void write_4bytes(int32_t value); - /** - * write 8bytes int to stream. - */ - virtual void write_8bytes(int64_t value); - /** - * write string to stream - */ - virtual void write_string(std::string value); + /** + * write 1bytes char to stream. + */ + virtual void write_1bytes(int8_t value); + /** + * write 2bytes int to stream. + */ + virtual void write_2bytes(int16_t value); + /** + * write 4bytes int to stream. + */ + virtual void write_4bytes(int32_t value); + /** + * write 8bytes int to stream. + */ + virtual void write_8bytes(int64_t value); + /** + * write string to stream + */ + virtual void write_string(std::string value); }; #endif \ No newline at end of file diff --git a/trunk/src/libs/srs_lib_simple_socket.cpp b/trunk/src/libs/srs_lib_simple_socket.cpp index 50715e14f..bb24dc993 100644 --- a/trunk/src/libs/srs_lib_simple_socket.cpp +++ b/trunk/src/libs/srs_lib_simple_socket.cpp @@ -34,25 +34,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #ifndef ST_UTIME_NO_TIMEOUT - #define ST_UTIME_NO_TIMEOUT -1 + #define ST_UTIME_NO_TIMEOUT -1 #endif SimpleSocketStream::SimpleSocketStream() { - fd = -1; - send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; - recv_bytes = send_bytes = 0; - - srs_update_system_time_ms(); - start_time_ms = srs_get_system_time_ms(); + fd = -1; + send_timeout = recv_timeout = ST_UTIME_NO_TIMEOUT; + recv_bytes = send_bytes = 0; + + srs_update_system_time_ms(); + start_time_ms = srs_get_system_time_ms(); } SimpleSocketStream::~SimpleSocketStream() { - if (fd != -1) { - ::close(fd); - fd = -1; - } + if (fd != -1) { + ::close(fd); + fd = -1; + } } int SimpleSocketStream::create_socket() @@ -61,7 +61,7 @@ int SimpleSocketStream::create_socket() return -1; } - return ERROR_SUCCESS; + return ERROR_SUCCESS; } 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 ERROR_SUCCESS; + return ERROR_SUCCESS; } // ISrsBufferReader int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread) { - int ret = ERROR_SUCCESS; - - *nread = ::recv(fd, (void*)buf, size, 0); + int ret = ERROR_SUCCESS; + + *nread = ::recv(fd, (void*)buf, size, 0); // On success a non-negative integer indicating the number of bytes actually read is returned // (a value of 0 means the network connection is closed or end of file is reached). if (*nread <= 0) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + if (*nread == 0) { errno = ECONNRESET; } @@ -100,131 +100,131 @@ int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread) } recv_bytes += *nread; - - return ret; + + return ret; } // ISrsProtocolReader void SimpleSocketStream::set_recv_timeout(int64_t timeout_us) { - recv_timeout = timeout_us; + recv_timeout = timeout_us; } int64_t SimpleSocketStream::get_recv_timeout() { - return recv_timeout; + return recv_timeout; } int64_t SimpleSocketStream::get_recv_bytes() { - return recv_bytes; + return recv_bytes; } int SimpleSocketStream::get_recv_kbps() { - srs_update_system_time_ms(); - int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; - - if (diff_ms <= 0) { - return 0; - } - - return recv_bytes * 8 / diff_ms; + srs_update_system_time_ms(); + int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; + + if (diff_ms <= 0) { + return 0; + } + + return recv_bytes * 8 / diff_ms; } // ISrsProtocolWriter void SimpleSocketStream::set_send_timeout(int64_t timeout_us) { - send_timeout = timeout_us; + send_timeout = timeout_us; } int64_t SimpleSocketStream::get_send_timeout() { - return send_timeout; + return send_timeout; } int64_t SimpleSocketStream::get_send_bytes() { - return send_bytes; + return send_bytes; } int SimpleSocketStream::get_send_kbps() { - srs_update_system_time_ms(); - int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; - - if (diff_ms <= 0) { - return 0; - } - - return send_bytes * 8 / diff_ms; + srs_update_system_time_ms(); + int64_t diff_ms = srs_get_system_time_ms() - start_time_ms; + + if (diff_ms <= 0) { + return 0; + } + + return send_bytes * 8 / diff_ms; } int 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); if (*nwrite <= 0) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + return ERROR_SOCKET_WRITE; } send_bytes += *nwrite; - return ret; + return ret; } // ISrsProtocolReaderWriter 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 ret = ERROR_SUCCESS; - - size_t left = size; - *nread = 0; - - while (left > 0) { - char* this_buf = (char*)buf + *nread; - ssize_t this_nread; - - if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) { - return ret; - } - - *nread += this_nread; - left -= this_nread; - } + int ret = ERROR_SUCCESS; + + size_t left = size; + *nread = 0; + + while (left > 0) { + char* this_buf = (char*)buf + *nread; + ssize_t this_nread; + + if ((ret = this->read(this_buf, left, &this_nread)) != ERROR_SUCCESS) { + return ret; + } + + *nread += this_nread; + left -= this_nread; + } recv_bytes += *nread; - - return ret; + + return ret; } 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); if (*nwrite <= 0) { - if (errno == ETIME) { - return ERROR_SOCKET_TIMEOUT; - } - + if (errno == ETIME) { + return ERROR_SOCKET_TIMEOUT; + } + return ERROR_SOCKET_WRITE; } send_bytes += *nwrite; - return ret; + return ret; } diff --git a/trunk/src/libs/srs_lib_simple_socket.hpp b/trunk/src/libs/srs_lib_simple_socket.hpp index a2740afc0..58d4a4fab 100644 --- a/trunk/src/libs/srs_lib_simple_socket.hpp +++ b/trunk/src/libs/srs_lib_simple_socket.hpp @@ -39,37 +39,37 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SimpleSocketStream : public ISrsProtocolReaderWriter { private: - int64_t start_time_ms; - int64_t recv_timeout; - int64_t send_timeout; - int64_t recv_bytes; - int64_t send_bytes; - int fd; + int64_t start_time_ms; + int64_t recv_timeout; + int64_t send_timeout; + int64_t recv_bytes; + int64_t send_bytes; + int fd; public: SimpleSocketStream(); virtual ~SimpleSocketStream(); public: - virtual int create_socket(); - virtual int connect(const char* server, int port); + virtual int create_socket(); + virtual int connect(const char* server, int port); // ISrsBufferReader public: virtual int read(const void* buf, size_t size, ssize_t* nread); // ISrsProtocolReader public: - virtual void set_recv_timeout(int64_t timeout_us); - virtual int64_t get_recv_timeout(); - virtual int64_t get_recv_bytes(); - virtual int get_recv_kbps(); + virtual void set_recv_timeout(int64_t timeout_us); + virtual int64_t get_recv_timeout(); + virtual int64_t get_recv_bytes(); + virtual int get_recv_kbps(); // ISrsProtocolWriter public: - virtual void set_send_timeout(int64_t timeout_us); - virtual int64_t get_send_timeout(); - virtual int64_t get_send_bytes(); - virtual int get_send_kbps(); + virtual void set_send_timeout(int64_t timeout_us); + virtual int64_t get_send_timeout(); + virtual int64_t get_send_bytes(); + virtual int get_send_kbps(); virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite); // ISrsProtocolReaderWriter 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 write(const void* buf, size_t size, ssize_t* nwrite); }; diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index c7dd0a502..5de542537 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -38,9 +38,9 @@ using namespace std; // if user want to define log, define the folowing macro. #ifndef SRS_RTMP_USER_DEFINED_LOG - // kernel module. - ISrsLog* _srs_log = new ISrsLog(); - ISrsThreadContext* _srs_context = new ISrsThreadContext(); + // kernel module. + ISrsLog* _srs_log = new ISrsLog(); + ISrsThreadContext* _srs_context = new ISrsThreadContext(); #endif /** @@ -48,14 +48,14 @@ using namespace std; */ struct Context { - std::string url; - std::string tcUrl; - std::string host; - std::string port; - std::string vhost; - std::string app; - std::string stream; - + std::string url; + std::string tcUrl; + std::string host; + std::string port; + std::string vhost; + std::string app; + std::string stream; + SrsRtmpClient* rtmp; SimpleSocketStream* skt; int stream_id; @@ -73,68 +73,68 @@ struct Context int srs_librtmp_context_connect(Context* context) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; // parse uri - size_t pos = string::npos; - string uri = context->url; - // tcUrl, stream - if ((pos = uri.rfind("/")) != string::npos) { - context->stream = uri.substr(pos + 1); - context->tcUrl = uri = uri.substr(0, pos); - } - // schema - if ((pos = uri.find("rtmp://")) != string::npos) { - uri = uri.substr(pos + 7); - } - // host/vhost/port - if ((pos = uri.find(":")) != string::npos) { - context->vhost = context->host = uri.substr(0, pos); - uri = uri.substr(pos + 1); - - if ((pos = uri.find("/")) != string::npos) { - context->port = uri.substr(0, pos); - uri = uri.substr(pos + 1); - } - } else { - if ((pos = uri.find("/")) != string::npos) { - context->vhost = context->host = uri.substr(0, pos); - uri = uri.substr(pos + 1); - } - context->port = RTMP_DEFAULT_PORT; - } - // app - context->app = uri; - // query of app - if ((pos = uri.find("?")) != string::npos) { - context->app = uri.substr(0, pos); - string query = uri.substr(pos + 1); - if ((pos = query.find("vhost=")) != string::npos) { - context->vhost = query.substr(pos + 6); - if ((pos = context->vhost.find("&")) != string::npos) { - context->vhost = context->vhost.substr(pos); - } - } - } + size_t pos = string::npos; + string uri = context->url; + // tcUrl, stream + if ((pos = uri.rfind("/")) != string::npos) { + context->stream = uri.substr(pos + 1); + context->tcUrl = uri = uri.substr(0, pos); + } + // schema + if ((pos = uri.find("rtmp://")) != string::npos) { + uri = uri.substr(pos + 7); + } + // host/vhost/port + if ((pos = uri.find(":")) != string::npos) { + context->vhost = context->host = uri.substr(0, pos); + uri = uri.substr(pos + 1); + + if ((pos = uri.find("/")) != string::npos) { + context->port = uri.substr(0, pos); + uri = uri.substr(pos + 1); + } + } else { + if ((pos = uri.find("/")) != string::npos) { + context->vhost = context->host = uri.substr(0, pos); + uri = uri.substr(pos + 1); + } + context->port = RTMP_DEFAULT_PORT; + } + // app + context->app = uri; + // query of app + if ((pos = uri.find("?")) != string::npos) { + context->app = uri.substr(0, pos); + string query = uri.substr(pos + 1); + if ((pos = query.find("vhost=")) != string::npos) { + context->vhost = query.substr(pos + 6); + if ((pos = context->vhost.find("&")) != string::npos) { + context->vhost = context->vhost.substr(pos); + } + } + } // create socket - srs_freep(context->skt); - context->skt = new SimpleSocketStream(); - - if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) { - return ret; - } - - // connect to server:port - string server = srs_dns_resolve(context->host); - if (server.empty()) { - return -1; - } - if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) { - return ret; - } - - return ret; + srs_freep(context->skt); + context->skt = new SimpleSocketStream(); + + if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) { + return ret; + } + + // connect to server:port + string server = srs_dns_resolve(context->host); + if (server.empty()) { + return -1; + } + if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) { + return ret; + } + + return ret; } #ifdef __cplusplus @@ -144,7 +144,7 @@ extern "C"{ srs_rtmp_t srs_rtmp_create(const char* url) { Context* context = new Context(); - context->url = url; + context->url = url; return context; } @@ -158,8 +158,8 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp) int srs_simple_handshake(srs_rtmp_t rtmp) { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); 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) { return ret; } - - // simple handshake - srs_freep(context->rtmp); - context->rtmp = new SrsRtmpClient(context->skt); - - if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) { - return ret; - } - - return ret; + + // simple handshake + srs_freep(context->rtmp); + context->rtmp = new SrsRtmpClient(context->skt); + + if ((ret = context->rtmp->simple_handshake()) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int srs_complex_handshake(srs_rtmp_t rtmp) { #ifndef SRS_SSL - return ERROR_RTMP_HS_SSL_REQUIRE; + return ERROR_RTMP_HS_SSL_REQUIRE; #endif - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); 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) { return ret; } - - // complex handshake - srs_freep(context->rtmp); - context->rtmp = new SrsRtmpClient(context->skt); - - if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) { - return ret; - } - - return ret; + + // complex handshake + srs_freep(context->rtmp); + context->rtmp = new SrsRtmpClient(context->skt); + + if ((ret = context->rtmp->complex_handshake()) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int srs_connect_app(srs_rtmp_t rtmp) { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; - - string tcUrl = "rtmp://"; - tcUrl += context->vhost; - tcUrl += ":"; - tcUrl += context->port; - tcUrl += "/"; - tcUrl += context->app; - - if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) { - return ret; - } - - return ret; + + string tcUrl = "rtmp://"; + tcUrl += context->vhost; + tcUrl += ":"; + tcUrl += context->port; + tcUrl += "/"; + tcUrl += context->app; + + if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } int srs_play_stream(srs_rtmp_t rtmp) { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; @@ -241,13 +241,13 @@ int srs_play_stream(srs_rtmp_t rtmp) return ret; } - return ret; + return ret; } int srs_publish_stream(srs_rtmp_t rtmp) { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; @@ -255,30 +255,30 @@ int srs_publish_stream(srs_rtmp_t rtmp) return ret; } - return ret; + return ret; } const char* srs_type2string(int type) { - switch (type) { - case SRS_RTMP_TYPE_AUDIO: return "Audio"; - case SRS_RTMP_TYPE_VIDEO: return "Video"; - case SRS_RTMP_TYPE_SCRIPT: return "Data"; - default: return "Unknown"; - } - - return "Unknown"; + switch (type) { + case SRS_RTMP_TYPE_AUDIO: return "Audio"; + case SRS_RTMP_TYPE_VIDEO: return "Video"; + case SRS_RTMP_TYPE_SCRIPT: return "Data"; + default: return "Unknown"; + } + + return "Unknown"; } int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size) { - *type = 0; - *timestamp = 0; - *data = NULL; - *size = 0; - - int ret = ERROR_SUCCESS; - + *type = 0; + *timestamp = 0; + *data = NULL; + *size = 0; + + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); 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; } - return ret; + return ret; } 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); Context* context = (Context*)rtmp; - - SrsSharedPtrMessage* msg = NULL; - - if (type == SRS_RTMP_TYPE_AUDIO) { - SrsMessageHeader header; - header.initialize_audio(size, timestamp, context->stream_id); - - msg = new SrsSharedPtrMessage(); - if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { - srs_freepa(data); - return ret; - } - } else if (type == SRS_RTMP_TYPE_VIDEO) { - SrsMessageHeader header; - header.initialize_video(size, timestamp, context->stream_id); - - msg = new SrsSharedPtrMessage(); - if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { - srs_freepa(data); - return ret; - } - } else if (type == SRS_RTMP_TYPE_SCRIPT) { - SrsMessageHeader header; - header.initialize_amf0_script(size, context->stream_id); - - msg = new SrsSharedPtrMessage(); - if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { - srs_freepa(data); - return ret; - } - } - - if (msg) { - // send out encoded msg. - if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } else { - // directly free data if not sent out. - srs_freepa(data); - } - - return ret; + + SrsSharedPtrMessage* msg = NULL; + + if (type == SRS_RTMP_TYPE_AUDIO) { + SrsMessageHeader header; + header.initialize_audio(size, timestamp, context->stream_id); + + msg = new SrsSharedPtrMessage(); + if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { + srs_freepa(data); + return ret; + } + } else if (type == SRS_RTMP_TYPE_VIDEO) { + SrsMessageHeader header; + header.initialize_video(size, timestamp, context->stream_id); + + msg = new SrsSharedPtrMessage(); + if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { + srs_freepa(data); + return ret; + } + } else if (type == SRS_RTMP_TYPE_SCRIPT) { + SrsMessageHeader header; + header.initialize_amf0_script(size, context->stream_id); + + msg = new SrsSharedPtrMessage(); + if ((ret = msg->initialize(&header, data, size)) != ERROR_SUCCESS) { + srs_freepa(data); + return ret; + } + } + + if (msg) { + // send out encoded msg. + if ((ret = context->rtmp->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } else { + // directly free data if not sent out. + srs_freepa(data); + } + + return ret; } int srs_ssl_enabled() { #ifndef SRS_SSL - return false; + return false; #endif - return true; + return true; } int srs_version_major() { - return ::atoi(VERSION_MAJOR); + return ::atoi(VERSION_MAJOR); } int srs_version_minor() { - return ::atoi(VERSION_MINOR); + return ::atoi(VERSION_MINOR); } int srs_version_revision() { - return ::atoi(VERSION_REVISION); + return ::atoi(VERSION_REVISION); } #ifdef __cplusplus diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index 1734e39e6..4fdfc9b73 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -48,7 +48,7 @@ typedef void* srs_rtmp_t; /** * create/destroy a rtmp protocol stack. * @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. */ 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 /** * convert the flv tag type to string. -* SRS_RTMP_TYPE_AUDIO to "Audio" -* SRS_RTMP_TYPE_VIDEO to "Video" -* SRS_RTMP_TYPE_SCRIPT to "Data" -* otherwise, "Unknown" +* SRS_RTMP_TYPE_AUDIO to "Audio" +* SRS_RTMP_TYPE_VIDEO to "Video" +* SRS_RTMP_TYPE_SCRIPT to "Data" +* otherwise, "Unknown" */ const char* srs_type2string(int type); /** * read a audio/video/script-data packet from rtmp stream. * @param type, output the packet type, macros: -* SRS_RTMP_TYPE_AUDIO, FlvTagAudio -* SRS_RTMP_TYPE_VIDEO, FlvTagVideo -* SRS_RTMP_TYPE_SCRIPT, FlvTagScript +* SRS_RTMP_TYPE_AUDIO, FlvTagAudio +* SRS_RTMP_TYPE_VIDEO, FlvTagVideo +* SRS_RTMP_TYPE_SCRIPT, FlvTagScript * @param timestamp, in ms, overflow in 50days * @param data, the packet data, according to type: -* FlvTagAudio, @see "E.4.2.1 AUDIODATA" -* FlvTagVideo, @see "E.4.3.1 VIDEODATA" -* FlvTagScript, @see "E.4.4.1 SCRIPTDATA" +* FlvTagAudio, @see "E.4.2.1 AUDIODATA" +* FlvTagVideo, @see "E.4.3.1 VIDEODATA" +* FlvTagScript, @see "E.4.4.1 SCRIPTDATA" * @param size, size of packet. * @return the error code. 0 for success; otherwise, error. * diff --git a/trunk/src/main/srs_main_bandcheck.cpp b/trunk/src/main/srs_main_bandcheck.cpp index 38c953da3..8092161a1 100644 --- a/trunk/src/main/srs_main_bandcheck.cpp +++ b/trunk/src/main/srs_main_bandcheck.cpp @@ -158,8 +158,8 @@ public: private: int connect_server(); private: - st_netfd_t stfd; - ISrsProtocolReaderWriter* skt; + st_netfd_t stfd; + ISrsProtocolReaderWriter* skt; SrsBandCheckClient* bandCheck_Client; std::string server_address; int server_port; @@ -493,8 +493,8 @@ int SrsBandCheckClient::expect_stop_pub() this->set_recv_timeout(1000 * 1000); this->set_send_timeout(1000 * 1000); - SrsCommonMessage* msg; - SrsBandwidthPacket* pkt; + SrsCommonMessage* msg; + SrsBandwidthPacket* pkt; if ((ret = srs_rtmp_expect_message(this->protocol, &msg, &pkt)) != ERROR_SUCCESS) { return ret; } @@ -641,16 +641,16 @@ int SrsBandCheckClient::send_final() SrsBandCheck::SrsBandCheck() { - skt = NULL; - bandCheck_Client = NULL; - stfd = NULL; + skt = NULL; + bandCheck_Client = NULL; + stfd = NULL; } SrsBandCheck::~SrsBandCheck() { - srs_freep(bandCheck_Client); - srs_freep(skt); - srs_close_stfd(stfd); + srs_freep(bandCheck_Client); + srs_freep(skt); + srs_close_stfd(stfd); } int SrsBandCheck::check(const std::string &app, const std::string &tcUrl) @@ -709,7 +709,7 @@ int SrsBandCheck::connect_server() return ret; } - skt = new SrsSocket(stfd); + skt = new SrsSocket(stfd); bandCheck_Client = new SrsBandCheckClient(skt); // connect to server. @@ -757,7 +757,7 @@ int init_st() void print_help(char** argv) { printf( - "Usage: %s [OPTION]...\n" + "Usage: %s [OPTION]...\n" "test band width from client to rtmp server.\n" "Mandatory arguments to long options are mandatory for short options too.\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" " -h, --help display this help and exit \n" "\n" - "For example:\n" - " %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e" + "For example:\n" + " %s -i 127.0.0.1 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e" "\n\n" "Exit status:\n" "0 if OK,\n" diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 53d6c7c05..b8534dd96 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -38,21 +38,21 @@ SrsServer* _srs_server = new SrsServer(); #include #ifdef SRS_GPERF_MP - #include + #include #endif #ifdef SRS_GPERF_CP - #include + #include #endif void handler(int signo) { - srs_trace("get a signal, signo=%d", signo); - _srs_server->on_signal(signo); + srs_trace("get a signal, signo=%d", signo); + _srs_server->on_signal(signo); } int main(int argc, char** argv) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; #ifdef SRS_GPERF_MP HeapProfilerStart("gperf.srs.gmp"); @@ -60,37 +60,37 @@ int main(int argc, char** argv) #ifdef SRS_GPERF_CP ProfilerStart("gperf.srs.gcp"); #endif - - signal(SIGNAL_RELOAD, handler); - signal(SIGINT, handler); - - if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) { - return ret; - } + + signal(SIGNAL_RELOAD, handler); + signal(SIGINT, handler); + + if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) { + return ret; + } #ifdef SRS_GPERF_MC - #ifdef SRS_GPERF_MP - srs_error("option --with-gmc confict with --with-gmp, " - "@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, " - "it is not possible to run both the heap-checker and heap profiler at the same time"); - return -1; - #endif + #ifdef SRS_GPERF_MP + srs_error("option --with-gmc confict with --with-gmp, " + "@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, " + "it is not possible to run both the heap-checker and heap profiler at the same time"); + return -1; + #endif #endif - - if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) { - return ret; - } - - // TODO: create log dir in _srs_config->get_log_dir() - - if ((ret = _srs_server->listen()) != ERROR_SUCCESS) { - return ret; - } - - if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) { - return ret; - } - + + if ((ret = _srs_server->initialize()) != ERROR_SUCCESS) { + return ret; + } + + // TODO: create log dir in _srs_config->get_log_dir() + + if ((ret = _srs_server->listen()) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = _srs_server->cycle()) != ERROR_SUCCESS) { + return ret; + } + return 0; } diff --git a/trunk/src/rtmp/srs_protocol_amf0.cpp b/trunk/src/rtmp/srs_protocol_amf0.cpp index cc93282ad..5054d0402 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.cpp +++ b/trunk/src/rtmp/srs_protocol_amf0.cpp @@ -32,30 +32,30 @@ using namespace std; #include // AMF0 marker -#define RTMP_AMF0_Number 0x00 -#define RTMP_AMF0_Boolean 0x01 -#define RTMP_AMF0_String 0x02 -#define RTMP_AMF0_Object 0x03 -#define RTMP_AMF0_MovieClip 0x04 // reserved, not supported -#define RTMP_AMF0_Null 0x05 -#define RTMP_AMF0_Undefined 0x06 -#define RTMP_AMF0_Reference 0x07 -#define RTMP_AMF0_EcmaArray 0x08 -#define RTMP_AMF0_ObjectEnd 0x09 -#define RTMP_AMF0_StrictArray 0x0A -#define RTMP_AMF0_Date 0x0B -#define RTMP_AMF0_LongString 0x0C -#define RTMP_AMF0_UnSupported 0x0D -#define RTMP_AMF0_RecordSet 0x0E // reserved, not supported -#define RTMP_AMF0_XmlDocument 0x0F -#define RTMP_AMF0_TypedObject 0x10 +#define RTMP_AMF0_Number 0x00 +#define RTMP_AMF0_Boolean 0x01 +#define RTMP_AMF0_String 0x02 +#define RTMP_AMF0_Object 0x03 +#define RTMP_AMF0_MovieClip 0x04 // reserved, not supported +#define RTMP_AMF0_Null 0x05 +#define RTMP_AMF0_Undefined 0x06 +#define RTMP_AMF0_Reference 0x07 +#define RTMP_AMF0_EcmaArray 0x08 +#define RTMP_AMF0_ObjectEnd 0x09 +#define RTMP_AMF0_StrictArray 0x0A +#define RTMP_AMF0_Date 0x0B +#define RTMP_AMF0_LongString 0x0C +#define RTMP_AMF0_UnSupported 0x0D +#define RTMP_AMF0_RecordSet 0x0E // reserved, not supported +#define RTMP_AMF0_XmlDocument 0x0F +#define RTMP_AMF0_TypedObject 0x10 // AVM+ object is the AMF3 object. -#define RTMP_AMF0_AVMplusObject 0x11 +#define RTMP_AMF0_AVMplusObject 0x11 // origin array whos data takes the same form as LengthValueBytes -#define RTMP_AMF0_OriginStrictArray 0x20 +#define RTMP_AMF0_OriginStrictArray 0x20 // User defined -#define RTMP_AMF0_Invalid 0x3F +#define RTMP_AMF0_Invalid 0x3F /** * read amf0 string from stream. @@ -67,34 +67,34 @@ using namespace std; class __SrsAmf0String : public SrsAmf0Any { public: - std::string value; + std::string value; - __SrsAmf0String(const char* _value); - virtual ~__SrsAmf0String(); - - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); + __SrsAmf0String(const char* _value); + virtual ~__SrsAmf0String(); + + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); }; /** * read amf0 boolean from stream. * 2.4 String Type * boolean-type = boolean-marker U8 -* 0 is false, <> 0 is true +* 0 is false, <> 0 is true * @return default value is false. */ class __SrsAmf0Boolean : public SrsAmf0Any { public: - bool value; + bool value; - __SrsAmf0Boolean(bool _value); - virtual ~__SrsAmf0Boolean(); - - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); + __SrsAmf0Boolean(bool _value); + virtual ~__SrsAmf0Boolean(); + + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); }; /** @@ -106,14 +106,14 @@ public: class __SrsAmf0Number : public SrsAmf0Any { public: - double value; + double value; - __SrsAmf0Number(double _value); - virtual ~__SrsAmf0Number(); - - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); + __SrsAmf0Number(double _value); + virtual ~__SrsAmf0Number(); + + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); }; /** @@ -124,12 +124,12 @@ public: class __SrsAmf0Null : public SrsAmf0Any { public: - __SrsAmf0Null(); - virtual ~__SrsAmf0Null(); - - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); + __SrsAmf0Null(); + virtual ~__SrsAmf0Null(); + + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); }; /** @@ -140,12 +140,12 @@ public: class __SrsAmf0Undefined : public SrsAmf0Any { public: - __SrsAmf0Undefined(); - virtual ~__SrsAmf0Undefined(); - - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); + __SrsAmf0Undefined(); + virtual ~__SrsAmf0Undefined(); + + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); }; /** @@ -157,21 +157,21 @@ public: class __SrsUnSortedHashtable { private: - typedef std::pair SrsObjectPropertyType; - std::vector properties; + typedef std::pair SrsObjectPropertyType; + std::vector properties; public: - __SrsUnSortedHashtable(); - virtual ~__SrsUnSortedHashtable(); - - virtual int count(); - virtual void clear(); - virtual std::string key_at(int index); - virtual SrsAmf0Any* value_at(int index); - virtual void set(std::string key, SrsAmf0Any* value); - - virtual SrsAmf0Any* get_property(std::string name); - virtual SrsAmf0Any* ensure_property_string(std::string name); - virtual SrsAmf0Any* ensure_property_number(std::string name); + __SrsUnSortedHashtable(); + virtual ~__SrsUnSortedHashtable(); + + virtual int count(); + virtual void clear(); + virtual std::string key_at(int index); + virtual SrsAmf0Any* value_at(int index); + virtual void set(std::string key, SrsAmf0Any* value); + + virtual SrsAmf0Any* get_property(std::string name); + virtual SrsAmf0Any* ensure_property_string(std::string name); + virtual SrsAmf0Any* ensure_property_number(std::string name); }; /** @@ -182,14 +182,14 @@ public: class __SrsAmf0ObjectEOF : public SrsAmf0Any { public: - int16_t utf8_empty; + int16_t utf8_empty; - __SrsAmf0ObjectEOF(); - virtual ~__SrsAmf0ObjectEOF(); - - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); + __SrsAmf0ObjectEOF(); + virtual ~__SrsAmf0ObjectEOF(); + + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); }; /** @@ -208,7 +208,7 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value); SrsAmf0Any::SrsAmf0Any() { - marker = RTMP_AMF0_Invalid; + marker = RTMP_AMF0_Invalid; } SrsAmf0Any::~SrsAmf0Any() @@ -217,180 +217,180 @@ SrsAmf0Any::~SrsAmf0Any() bool SrsAmf0Any::is_string() { - return marker == RTMP_AMF0_String; + return marker == RTMP_AMF0_String; } bool SrsAmf0Any::is_boolean() { - return marker == RTMP_AMF0_Boolean; + return marker == RTMP_AMF0_Boolean; } bool SrsAmf0Any::is_number() { - return marker == RTMP_AMF0_Number; + return marker == RTMP_AMF0_Number; } bool SrsAmf0Any::is_null() { - return marker == RTMP_AMF0_Null; + return marker == RTMP_AMF0_Null; } bool SrsAmf0Any::is_undefined() { - return marker == RTMP_AMF0_Undefined; + return marker == RTMP_AMF0_Undefined; } bool SrsAmf0Any::is_object() { - return marker == RTMP_AMF0_Object; + return marker == RTMP_AMF0_Object; } bool SrsAmf0Any::is_ecma_array() { - return marker == RTMP_AMF0_EcmaArray; + return marker == RTMP_AMF0_EcmaArray; } string SrsAmf0Any::to_str() { - __SrsAmf0String* p = dynamic_cast<__SrsAmf0String*>(this); - srs_assert(p != NULL); - return p->value; + __SrsAmf0String* p = dynamic_cast<__SrsAmf0String*>(this); + srs_assert(p != NULL); + return p->value; } bool SrsAmf0Any::to_boolean() { - __SrsAmf0Boolean* p = dynamic_cast<__SrsAmf0Boolean*>(this); - srs_assert(p != NULL); - return p->value; + __SrsAmf0Boolean* p = dynamic_cast<__SrsAmf0Boolean*>(this); + srs_assert(p != NULL); + return p->value; } double SrsAmf0Any::to_number() { - __SrsAmf0Number* p = dynamic_cast<__SrsAmf0Number*>(this); - srs_assert(p != NULL); - return p->value; + __SrsAmf0Number* p = dynamic_cast<__SrsAmf0Number*>(this); + srs_assert(p != NULL); + return p->value; } SrsAmf0Object* SrsAmf0Any::to_object() { - SrsAmf0Object* p = dynamic_cast(this); - srs_assert(p != NULL); - return p; + SrsAmf0Object* p = dynamic_cast(this); + srs_assert(p != NULL); + return p; } SrsAmf0EcmaArray* SrsAmf0Any::to_ecma_array() { - SrsAmf0EcmaArray* p = dynamic_cast(this); - srs_assert(p != NULL); - return p; + SrsAmf0EcmaArray* p = dynamic_cast(this); + srs_assert(p != NULL); + return p; } bool SrsAmf0Any::is_object_eof() { - return marker == RTMP_AMF0_ObjectEnd; + return marker == RTMP_AMF0_ObjectEnd; } SrsAmf0Any* SrsAmf0Any::str(const char* value) { - return new __SrsAmf0String(value); + return new __SrsAmf0String(value); } SrsAmf0Any* SrsAmf0Any::boolean(bool value) { - return new __SrsAmf0Boolean(value); + return new __SrsAmf0Boolean(value); } SrsAmf0Any* SrsAmf0Any::number(double value) { - return new __SrsAmf0Number(value); + return new __SrsAmf0Number(value); } SrsAmf0Any* SrsAmf0Any::null() { - return new __SrsAmf0Null(); + return new __SrsAmf0Null(); } SrsAmf0Any* SrsAmf0Any::undefined() { - return new __SrsAmf0Undefined(); + return new __SrsAmf0Undefined(); } SrsAmf0Object* SrsAmf0Any::object() { - return new SrsAmf0Object(); + return new SrsAmf0Object(); } SrsAmf0Any* SrsAmf0Any::object_eof() { - return new __SrsAmf0ObjectEOF(); + return new __SrsAmf0ObjectEOF(); } SrsAmf0EcmaArray* SrsAmf0Any::ecma_array() { - return new SrsAmf0EcmaArray(); + return new SrsAmf0EcmaArray(); } int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue) { - int ret = ERROR_SUCCESS; - - // detect the object-eof specially - if (srs_amf0_is_object_eof(stream)) { - *ppvalue = new __SrsAmf0ObjectEOF(); - return ret; - } - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read any marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - srs_verbose("amf0 any marker success"); - - // backward the 1byte marker. - stream->skip(-1); - - switch (marker) { - case RTMP_AMF0_String: { - *ppvalue = SrsAmf0Any::str(); - return ret; - } - case RTMP_AMF0_Boolean: { - *ppvalue = SrsAmf0Any::boolean(); - return ret; - } - case RTMP_AMF0_Number: { - *ppvalue = SrsAmf0Any::number(); - return ret; - } - case RTMP_AMF0_Null: { - *ppvalue = SrsAmf0Any::null(); - return ret; - } - case RTMP_AMF0_Undefined: { - *ppvalue = SrsAmf0Any::undefined(); - return ret; - } - case RTMP_AMF0_Object: { - *ppvalue = SrsAmf0Any::object(); - return ret; - } - case RTMP_AMF0_EcmaArray: { - *ppvalue = SrsAmf0Any::ecma_array(); - return ret; - } - case RTMP_AMF0_Invalid: - default: { - ret = ERROR_RTMP_AMF0_INVALID; - srs_error("invalid amf0 message type. marker=%#x, ret=%d", marker, ret); - return ret; - } - } - - return ret; + int ret = ERROR_SUCCESS; + + // detect the object-eof specially + if (srs_amf0_is_object_eof(stream)) { + *ppvalue = new __SrsAmf0ObjectEOF(); + return ret; + } + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read any marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + srs_verbose("amf0 any marker success"); + + // backward the 1byte marker. + stream->skip(-1); + + switch (marker) { + case RTMP_AMF0_String: { + *ppvalue = SrsAmf0Any::str(); + return ret; + } + case RTMP_AMF0_Boolean: { + *ppvalue = SrsAmf0Any::boolean(); + return ret; + } + case RTMP_AMF0_Number: { + *ppvalue = SrsAmf0Any::number(); + return ret; + } + case RTMP_AMF0_Null: { + *ppvalue = SrsAmf0Any::null(); + return ret; + } + case RTMP_AMF0_Undefined: { + *ppvalue = SrsAmf0Any::undefined(); + return ret; + } + case RTMP_AMF0_Object: { + *ppvalue = SrsAmf0Any::object(); + return ret; + } + case RTMP_AMF0_EcmaArray: { + *ppvalue = SrsAmf0Any::ecma_array(); + return ret; + } + case RTMP_AMF0_Invalid: + default: { + ret = ERROR_RTMP_AMF0_INVALID; + srs_error("invalid amf0 message type. marker=%#x, ret=%d", marker, ret); + return ret; + } + } + + return ret; } __SrsUnSortedHashtable::__SrsUnSortedHashtable() @@ -399,113 +399,113 @@ __SrsUnSortedHashtable::__SrsUnSortedHashtable() __SrsUnSortedHashtable::~__SrsUnSortedHashtable() { - std::vector::iterator it; - for (it = properties.begin(); it != properties.end(); ++it) { - SrsObjectPropertyType& elem = *it; - SrsAmf0Any* any = elem.second; - srs_freep(any); - } - properties.clear(); + std::vector::iterator it; + for (it = properties.begin(); it != properties.end(); ++it) { + SrsObjectPropertyType& elem = *it; + SrsAmf0Any* any = elem.second; + srs_freep(any); + } + properties.clear(); } int __SrsUnSortedHashtable::count() { - return (int)properties.size(); + return (int)properties.size(); } void __SrsUnSortedHashtable::clear() { - properties.clear(); + properties.clear(); } string __SrsUnSortedHashtable::key_at(int index) { - srs_assert(index < count()); - SrsObjectPropertyType& elem = properties[index]; - return elem.first; + srs_assert(index < count()); + SrsObjectPropertyType& elem = properties[index]; + return elem.first; } SrsAmf0Any* __SrsUnSortedHashtable::value_at(int index) { - srs_assert(index < count()); - SrsObjectPropertyType& elem = properties[index]; - return elem.second; + srs_assert(index < count()); + SrsObjectPropertyType& elem = properties[index]; + return elem.second; } void __SrsUnSortedHashtable::set(string key, SrsAmf0Any* value) { - if (!value) { - srs_warn("add a NULL propertity %s", key.c_str()); - return; - } - - std::vector::iterator it; - - for (it = properties.begin(); it != properties.end(); ++it) { - SrsObjectPropertyType& elem = *it; - std::string name = elem.first; - SrsAmf0Any* any = elem.second; - - if (key == name) { - srs_freep(any); - properties.erase(it); - break; - } - } - - properties.push_back(std::make_pair(key, value)); + if (!value) { + srs_warn("add a NULL propertity %s", key.c_str()); + return; + } + + std::vector::iterator it; + + for (it = properties.begin(); it != properties.end(); ++it) { + SrsObjectPropertyType& elem = *it; + std::string name = elem.first; + SrsAmf0Any* any = elem.second; + + if (key == name) { + srs_freep(any); + properties.erase(it); + break; + } + } + + properties.push_back(std::make_pair(key, value)); } SrsAmf0Any* __SrsUnSortedHashtable::get_property(string name) { - std::vector::iterator it; - - for (it = properties.begin(); it != properties.end(); ++it) { - SrsObjectPropertyType& elem = *it; - std::string key = elem.first; - SrsAmf0Any* any = elem.second; - if (key == name) { - return any; - } - } - - return NULL; + std::vector::iterator it; + + for (it = properties.begin(); it != properties.end(); ++it) { + SrsObjectPropertyType& elem = *it; + std::string key = elem.first; + SrsAmf0Any* any = elem.second; + if (key == name) { + return any; + } + } + + return NULL; } SrsAmf0Any* __SrsUnSortedHashtable::ensure_property_string(string name) { - SrsAmf0Any* prop = get_property(name); - - if (!prop) { - return NULL; - } - - if (!prop->is_string()) { - return NULL; - } - - return prop; + SrsAmf0Any* prop = get_property(name); + + if (!prop) { + return NULL; + } + + if (!prop->is_string()) { + return NULL; + } + + return prop; } SrsAmf0Any* __SrsUnSortedHashtable::ensure_property_number(string name) { - SrsAmf0Any* prop = get_property(name); - - if (!prop) { - return NULL; - } - - if (!prop->is_number()) { - return NULL; - } - - return prop; + SrsAmf0Any* prop = get_property(name); + + if (!prop) { + return NULL; + } + + if (!prop->is_number()) { + return NULL; + } + + return prop; } __SrsAmf0ObjectEOF::__SrsAmf0ObjectEOF() { - marker = RTMP_AMF0_ObjectEnd; - utf8_empty = 0x00; + marker = RTMP_AMF0_ObjectEnd; + utf8_empty = 0x00; } __SrsAmf0ObjectEOF::~__SrsAmf0ObjectEOF() @@ -514,491 +514,491 @@ __SrsAmf0ObjectEOF::~__SrsAmf0ObjectEOF() int __SrsAmf0ObjectEOF::total_size() { - return SrsAmf0Size::object_eof(); + return SrsAmf0Size::object_eof(); } int __SrsAmf0ObjectEOF::read(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // value - if (!stream->require(2)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read object eof value failed. ret=%d", ret); - return ret; - } - int16_t temp = stream->read_2bytes(); - if (temp != 0x00) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read object eof value check failed. " - "must be 0x00, actual is %#x, ret=%d", temp, ret); - return ret; - } - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read object eof marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_ObjectEnd) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check object eof marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret); - return ret; - } - srs_verbose("amf0 read object eof marker success"); - - srs_verbose("amf0 read object eof success"); - - return ret; + int ret = ERROR_SUCCESS; + + // value + if (!stream->require(2)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read object eof value failed. ret=%d", ret); + return ret; + } + int16_t temp = stream->read_2bytes(); + if (temp != 0x00) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read object eof value check failed. " + "must be 0x00, actual is %#x, ret=%d", temp, ret); + return ret; + } + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read object eof marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_ObjectEnd) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check object eof marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret); + return ret; + } + srs_verbose("amf0 read object eof marker success"); + + srs_verbose("amf0 read object eof success"); + + return ret; } int __SrsAmf0ObjectEOF::write(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // value - if (!stream->require(2)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write object eof value failed. ret=%d", ret); - return ret; - } - stream->write_2bytes(0x00); - srs_verbose("amf0 write object eof value success"); - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write object eof marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_ObjectEnd); - - srs_verbose("amf0 read object eof success"); - - return ret; + int ret = ERROR_SUCCESS; + + // value + if (!stream->require(2)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write object eof value failed. ret=%d", ret); + return ret; + } + stream->write_2bytes(0x00); + srs_verbose("amf0 write object eof value success"); + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write object eof marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_ObjectEnd); + + srs_verbose("amf0 read object eof success"); + + return ret; } SrsAmf0Object::SrsAmf0Object() { - properties = new __SrsUnSortedHashtable(); - eof = new __SrsAmf0ObjectEOF(); - marker = RTMP_AMF0_Object; + properties = new __SrsUnSortedHashtable(); + eof = new __SrsAmf0ObjectEOF(); + marker = RTMP_AMF0_Object; } SrsAmf0Object::~SrsAmf0Object() { - srs_freep(properties); - srs_freep(eof); + srs_freep(properties); + srs_freep(eof); } int SrsAmf0Object::total_size() { - int size = 1; - - for (int i = 0; i < properties->count(); i++){ - std::string name = key_at(i); - SrsAmf0Any* value = value_at(i); - - size += SrsAmf0Size::utf8(name); - size += SrsAmf0Size::any(value); - } - - size += SrsAmf0Size::object_eof(); - - return size; + int size = 1; + + for (int i = 0; i < properties->count(); i++){ + std::string name = key_at(i); + SrsAmf0Any* value = value_at(i); + + size += SrsAmf0Size::utf8(name); + size += SrsAmf0Size::any(value); + } + + size += SrsAmf0Size::object_eof(); + + return size; } int SrsAmf0Object::read(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read object marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_Object) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check object marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret); - return ret; - } - srs_verbose("amf0 read object marker success"); - - // value - while (!stream->empty()) { - // detect whether is eof. - if (srs_amf0_is_object_eof(stream)) { - __SrsAmf0ObjectEOF pbj_eof; - if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) { - srs_error("amf0 object read eof failed. ret=%d", ret); - return ret; - } - srs_info("amf0 read object EOF."); - break; - } - - // property-name: utf8 string - std::string property_name; - if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) { - srs_error("amf0 object read property name failed. ret=%d", ret); - return ret; - } - // property-value: any - SrsAmf0Any* property_value = NULL; - if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) { - srs_error("amf0 object read property_value failed. " - "name=%s, ret=%d", property_name.c_str(), ret); - srs_freep(property_value); - return ret; - } - - // add property - this->set(property_name, property_value); - } - - return ret; + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read object marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_Object) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check object marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret); + return ret; + } + srs_verbose("amf0 read object marker success"); + + // value + while (!stream->empty()) { + // detect whether is eof. + if (srs_amf0_is_object_eof(stream)) { + __SrsAmf0ObjectEOF pbj_eof; + if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 object read eof failed. ret=%d", ret); + return ret; + } + srs_info("amf0 read object EOF."); + break; + } + + // property-name: utf8 string + std::string property_name; + if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) { + srs_error("amf0 object read property name failed. ret=%d", ret); + return ret; + } + // property-value: any + SrsAmf0Any* property_value = NULL; + if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) { + srs_error("amf0 object read property_value failed. " + "name=%s, ret=%d", property_name.c_str(), ret); + srs_freep(property_value); + return ret; + } + + // add property + this->set(property_name, property_value); + } + + return ret; } int SrsAmf0Object::write(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write object marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_Object); - srs_verbose("amf0 write object marker success"); - - // value - for (int i = 0; i < properties->count(); i++) { - std::string name = this->key_at(i); - SrsAmf0Any* any = this->value_at(i); - - if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { - srs_error("write object property name failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) { - srs_error("write object property value failed. ret=%d", ret); - return ret; - } - - srs_verbose("write amf0 property success. name=%s", name.c_str()); - } - - if ((ret = eof->write(stream)) != ERROR_SUCCESS) { - srs_error("write object eof failed. ret=%d", ret); - return ret; - } - - srs_verbose("write amf0 object success."); - - return ret; + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write object marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_Object); + srs_verbose("amf0 write object marker success"); + + // value + for (int i = 0; i < properties->count(); i++) { + std::string name = this->key_at(i); + SrsAmf0Any* any = this->value_at(i); + + if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { + srs_error("write object property name failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) { + srs_error("write object property value failed. ret=%d", ret); + return ret; + } + + srs_verbose("write amf0 property success. name=%s", name.c_str()); + } + + if ((ret = eof->write(stream)) != ERROR_SUCCESS) { + srs_error("write object eof failed. ret=%d", ret); + return ret; + } + + srs_verbose("write amf0 object success."); + + return ret; } int SrsAmf0Object::count() { - return properties->count(); + return properties->count(); } string SrsAmf0Object::key_at(int index) { - return properties->key_at(index); + return properties->key_at(index); } SrsAmf0Any* SrsAmf0Object::value_at(int index) { - return properties->value_at(index); + return properties->value_at(index); } void SrsAmf0Object::set(string key, SrsAmf0Any* value) { - properties->set(key, value); + properties->set(key, value); } SrsAmf0Any* SrsAmf0Object::get_property(string name) { - return properties->get_property(name); + return properties->get_property(name); } SrsAmf0Any* SrsAmf0Object::ensure_property_string(string name) { - return properties->ensure_property_string(name); + return properties->ensure_property_string(name); } SrsAmf0Any* SrsAmf0Object::ensure_property_number(string name) { - return properties->ensure_property_number(name); + return properties->ensure_property_number(name); } SrsAmf0EcmaArray::SrsAmf0EcmaArray() { - properties = new __SrsUnSortedHashtable(); - eof = new __SrsAmf0ObjectEOF(); - marker = RTMP_AMF0_EcmaArray; + properties = new __SrsUnSortedHashtable(); + eof = new __SrsAmf0ObjectEOF(); + marker = RTMP_AMF0_EcmaArray; } SrsAmf0EcmaArray::~SrsAmf0EcmaArray() { - srs_freep(properties); - srs_freep(eof); + srs_freep(properties); + srs_freep(eof); } int SrsAmf0EcmaArray::total_size() { - int size = 1 + 4; - - for (int i = 0; i < properties->count(); i++){ - std::string name = key_at(i); - SrsAmf0Any* value = value_at(i); - - size += SrsAmf0Size::utf8(name); - size += SrsAmf0Size::any(value); - } - - size += SrsAmf0Size::object_eof(); - - return size; + int size = 1 + 4; + + for (int i = 0; i < properties->count(); i++){ + std::string name = key_at(i); + SrsAmf0Any* value = value_at(i); + + size += SrsAmf0Size::utf8(name); + size += SrsAmf0Size::any(value); + } + + size += SrsAmf0Size::object_eof(); + + return size; } int SrsAmf0EcmaArray::read(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read ecma_array marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_EcmaArray) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check ecma_array marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret); - return ret; - } - srs_verbose("amf0 read ecma_array marker success"); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read ecma_array marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_EcmaArray) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check ecma_array marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret); + return ret; + } + srs_verbose("amf0 read ecma_array marker success"); - // count - if (!stream->require(4)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read ecma_array count failed. ret=%d", ret); - return ret; - } - - int32_t count = stream->read_4bytes(); - srs_verbose("amf0 read ecma_array count success. count=%d", count); - - // value - this->_count = count; + // count + if (!stream->require(4)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read ecma_array count failed. ret=%d", ret); + return ret; + } + + int32_t count = stream->read_4bytes(); + srs_verbose("amf0 read ecma_array count success. count=%d", count); + + // value + this->_count = count; - while (!stream->empty()) { - // detect whether is eof. - if (srs_amf0_is_object_eof(stream)) { - __SrsAmf0ObjectEOF pbj_eof; - if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) { - srs_error("amf0 ecma_array read eof failed. ret=%d", ret); - return ret; - } - srs_info("amf0 read ecma_array EOF."); - break; - } - - // property-name: utf8 string - std::string property_name; - if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) { - srs_error("amf0 ecma_array read property name failed. ret=%d", ret); - return ret; - } - // property-value: any - SrsAmf0Any* property_value = NULL; - if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) { - srs_error("amf0 ecma_array read property_value failed. " - "name=%s, ret=%d", property_name.c_str(), ret); - return ret; - } - - // add property - this->set(property_name, property_value); - } - - return ret; + while (!stream->empty()) { + // detect whether is eof. + if (srs_amf0_is_object_eof(stream)) { + __SrsAmf0ObjectEOF pbj_eof; + if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 ecma_array read eof failed. ret=%d", ret); + return ret; + } + srs_info("amf0 read ecma_array EOF."); + break; + } + + // property-name: utf8 string + std::string property_name; + if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) { + srs_error("amf0 ecma_array read property name failed. ret=%d", ret); + return ret; + } + // property-value: any + SrsAmf0Any* property_value = NULL; + if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) { + srs_error("amf0 ecma_array read property_value failed. " + "name=%s, ret=%d", property_name.c_str(), ret); + return ret; + } + + // add property + this->set(property_name, property_value); + } + + return ret; } int SrsAmf0EcmaArray::write(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write ecma_array marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_EcmaArray); - srs_verbose("amf0 write ecma_array marker success"); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write ecma_array marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_EcmaArray); + srs_verbose("amf0 write ecma_array marker success"); - // count - if (!stream->require(4)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write ecma_array count failed. ret=%d", ret); - return ret; - } - - stream->write_4bytes(this->_count); - srs_verbose("amf0 write ecma_array count success. count=%d", _count); - - // value - for (int i = 0; i < properties->count(); i++) { - std::string name = this->key_at(i); - SrsAmf0Any* any = this->value_at(i); - - if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { - srs_error("write ecma_array property name failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) { - srs_error("write ecma_array property value failed. ret=%d", ret); - return ret; - } - - srs_verbose("write amf0 property success. name=%s", name.c_str()); - } - - if ((ret = eof->write(stream)) != ERROR_SUCCESS) { - srs_error("write ecma_array eof failed. ret=%d", ret); - return ret; - } - - srs_verbose("write ecma_array object success."); - - return ret; + // count + if (!stream->require(4)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write ecma_array count failed. ret=%d", ret); + return ret; + } + + stream->write_4bytes(this->_count); + srs_verbose("amf0 write ecma_array count success. count=%d", _count); + + // value + for (int i = 0; i < properties->count(); i++) { + std::string name = this->key_at(i); + SrsAmf0Any* any = this->value_at(i); + + if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { + srs_error("write ecma_array property name failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) { + srs_error("write ecma_array property value failed. ret=%d", ret); + return ret; + } + + srs_verbose("write amf0 property success. name=%s", name.c_str()); + } + + if ((ret = eof->write(stream)) != ERROR_SUCCESS) { + srs_error("write ecma_array eof failed. ret=%d", ret); + return ret; + } + + srs_verbose("write ecma_array object success."); + + return ret; } void SrsAmf0EcmaArray::clear() { - properties->clear(); + properties->clear(); } int SrsAmf0EcmaArray::count() { - return properties->count(); + return properties->count(); } string SrsAmf0EcmaArray::key_at(int index) { - return properties->key_at(index); + return properties->key_at(index); } SrsAmf0Any* SrsAmf0EcmaArray::value_at(int index) { - return properties->value_at(index); + return properties->value_at(index); } void SrsAmf0EcmaArray::set(string key, SrsAmf0Any* value) { - properties->set(key, value); + properties->set(key, value); } SrsAmf0Any* SrsAmf0EcmaArray::get_property(string name) { - return properties->get_property(name); + return properties->get_property(name); } SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_string(string name) { - return properties->ensure_property_string(name); + return properties->ensure_property_string(name); } SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_number(string name) { - return properties->ensure_property_number(name); + return properties->ensure_property_number(name); } int SrsAmf0Size::utf8(string value) { - return 2 + value.length(); + return 2 + value.length(); } int SrsAmf0Size::str(string value) { - return 1 + SrsAmf0Size::utf8(value); + return 1 + SrsAmf0Size::utf8(value); } int SrsAmf0Size::number() { - return 1 + 8; + return 1 + 8; } int SrsAmf0Size::null() { - return 1; + return 1; } int SrsAmf0Size::undefined() { - return 1; + return 1; } int SrsAmf0Size::boolean() { - return 1 + 1; + return 1 + 1; } int SrsAmf0Size::object(SrsAmf0Object* obj) { - if (!obj) { - return 0; - } - - return obj->total_size(); + if (!obj) { + return 0; + } + + return obj->total_size(); } int SrsAmf0Size::object_eof() { - return 2 + 1; + return 2 + 1; } int SrsAmf0Size::ecma_array(SrsAmf0EcmaArray* arr) { - if (!arr) { - return 0; - } - - return arr->total_size(); + if (!arr) { + return 0; + } + + return arr->total_size(); } int SrsAmf0Size::any(SrsAmf0Any* o) { - if (!o) { - return 0; - } - - return o->total_size(); + if (!o) { + return 0; + } + + return o->total_size(); } __SrsAmf0String::__SrsAmf0String(const char* _value) { - marker = RTMP_AMF0_String; - if (_value) { - value = _value; - } + marker = RTMP_AMF0_String; + if (_value) { + value = _value; + } } __SrsAmf0String::~__SrsAmf0String() @@ -1007,23 +1007,23 @@ __SrsAmf0String::~__SrsAmf0String() int __SrsAmf0String::total_size() { - return SrsAmf0Size::str(value); + return SrsAmf0Size::str(value); } int __SrsAmf0String::read(SrsStream* stream) { - return srs_amf0_read_string(stream, value); + return srs_amf0_read_string(stream, value); } int __SrsAmf0String::write(SrsStream* stream) { - return srs_amf0_write_string(stream, value); + return srs_amf0_write_string(stream, value); } __SrsAmf0Boolean::__SrsAmf0Boolean(bool _value) { - marker = RTMP_AMF0_Boolean; - value = _value; + marker = RTMP_AMF0_Boolean; + value = _value; } __SrsAmf0Boolean::~__SrsAmf0Boolean() @@ -1032,23 +1032,23 @@ __SrsAmf0Boolean::~__SrsAmf0Boolean() int __SrsAmf0Boolean::total_size() { - return SrsAmf0Size::boolean(); + return SrsAmf0Size::boolean(); } int __SrsAmf0Boolean::read(SrsStream* stream) { - return srs_amf0_read_boolean(stream, value); + return srs_amf0_read_boolean(stream, value); } int __SrsAmf0Boolean::write(SrsStream* stream) { - return srs_amf0_write_boolean(stream, value); + return srs_amf0_write_boolean(stream, value); } __SrsAmf0Number::__SrsAmf0Number(double _value) { - marker = RTMP_AMF0_Number; - value = _value; + marker = RTMP_AMF0_Number; + value = _value; } __SrsAmf0Number::~__SrsAmf0Number() @@ -1057,22 +1057,22 @@ __SrsAmf0Number::~__SrsAmf0Number() int __SrsAmf0Number::total_size() { - return SrsAmf0Size::number(); + return SrsAmf0Size::number(); } int __SrsAmf0Number::read(SrsStream* stream) { - return srs_amf0_read_number(stream, value); + return srs_amf0_read_number(stream, value); } int __SrsAmf0Number::write(SrsStream* stream) { - return srs_amf0_write_number(stream, value); + return srs_amf0_write_number(stream, value); } __SrsAmf0Null::__SrsAmf0Null() { - marker = RTMP_AMF0_Null; + marker = RTMP_AMF0_Null; } __SrsAmf0Null::~__SrsAmf0Null() @@ -1081,22 +1081,22 @@ __SrsAmf0Null::~__SrsAmf0Null() int __SrsAmf0Null::total_size() { - return SrsAmf0Size::null(); + return SrsAmf0Size::null(); } int __SrsAmf0Null::read(SrsStream* stream) { - return srs_amf0_read_null(stream); + return srs_amf0_read_null(stream); } int __SrsAmf0Null::write(SrsStream* stream) { - return srs_amf0_write_null(stream); + return srs_amf0_write_null(stream); } __SrsAmf0Undefined::__SrsAmf0Undefined() { - marker = RTMP_AMF0_Undefined; + marker = RTMP_AMF0_Undefined; } __SrsAmf0Undefined::~__SrsAmf0Undefined() @@ -1105,409 +1105,409 @@ __SrsAmf0Undefined::~__SrsAmf0Undefined() int __SrsAmf0Undefined::total_size() { - return SrsAmf0Size::undefined(); + return SrsAmf0Size::undefined(); } int __SrsAmf0Undefined::read(SrsStream* stream) { - return srs_amf0_read_undefined(stream); + return srs_amf0_read_undefined(stream); } int __SrsAmf0Undefined::write(SrsStream* stream) { - return srs_amf0_write_undefined(stream); + return srs_amf0_write_undefined(stream); } int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue) { - int ret = ERROR_SUCCESS; - - if ((ret = SrsAmf0Any::discovery(stream, ppvalue)) != ERROR_SUCCESS) { - srs_error("amf0 discovery any elem failed. ret=%d", ret); - return ret; - } - - srs_assert(*ppvalue); - - if ((ret = (*ppvalue)->read(stream)) != ERROR_SUCCESS) { - srs_error("amf0 parse elem failed. ret=%d", ret); - srs_freep(*ppvalue); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = SrsAmf0Any::discovery(stream, ppvalue)) != ERROR_SUCCESS) { + srs_error("amf0 discovery any elem failed. ret=%d", ret); + return ret; + } + + srs_assert(*ppvalue); + + if ((ret = (*ppvalue)->read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 parse elem failed. ret=%d", ret); + srs_freep(*ppvalue); + return ret; + } + + return ret; } int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) { - srs_assert(value != NULL); - return value->write(stream); + srs_assert(value != NULL); + return value->write(stream); } int srs_amf0_read_utf8(SrsStream* stream, string& value) { - int ret = ERROR_SUCCESS; - - // len - if (!stream->require(2)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read string length failed. ret=%d", ret); - return ret; - } - int16_t len = stream->read_2bytes(); - srs_verbose("amf0 read string length success. len=%d", len); - - // empty string - if (len <= 0) { - srs_verbose("amf0 read empty string. ret=%d", ret); - return ret; - } - - // data - if (!stream->require(len)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read string data failed. ret=%d", ret); - return ret; - } - std::string str = stream->read_string(len); - - // support utf8-1 only - // 1.3.1 Strings and UTF-8 - // UTF8-1 = %x00-7F - // TODO: support other utf-8 strings - /*for (int i = 0; i < len; i++) { - char ch = *(str.data() + i); - if ((ch & 0x80) != 0) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("ignored. only support utf8-1, 0x00-0x7F, actual is %#x. ret=%d", (int)ch, ret); - ret = ERROR_SUCCESS; - } - }*/ - - value = str; - srs_verbose("amf0 read string data success. str=%s", str.c_str()); - - return ret; + int ret = ERROR_SUCCESS; + + // len + if (!stream->require(2)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read string length failed. ret=%d", ret); + return ret; + } + int16_t len = stream->read_2bytes(); + srs_verbose("amf0 read string length success. len=%d", len); + + // empty string + if (len <= 0) { + srs_verbose("amf0 read empty string. ret=%d", ret); + return ret; + } + + // data + if (!stream->require(len)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read string data failed. ret=%d", ret); + return ret; + } + std::string str = stream->read_string(len); + + // support utf8-1 only + // 1.3.1 Strings and UTF-8 + // UTF8-1 = %x00-7F + // TODO: support other utf-8 strings + /*for (int i = 0; i < len; i++) { + char ch = *(str.data() + i); + if ((ch & 0x80) != 0) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("ignored. only support utf8-1, 0x00-0x7F, actual is %#x. ret=%d", (int)ch, ret); + ret = ERROR_SUCCESS; + } + }*/ + + value = str; + srs_verbose("amf0 read string data success. str=%s", str.c_str()); + + return ret; } int srs_amf0_write_utf8(SrsStream* stream, string value) { - int ret = ERROR_SUCCESS; - - // len - if (!stream->require(2)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write string length failed. ret=%d", ret); - return ret; - } - stream->write_2bytes(value.length()); - srs_verbose("amf0 write string length success. len=%d", (int)value.length()); - - // empty string - if (value.length() <= 0) { - srs_verbose("amf0 write empty string. ret=%d", ret); - return ret; - } - - // data - if (!stream->require(value.length())) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write string data failed. ret=%d", ret); - return ret; - } - stream->write_string(value); - srs_verbose("amf0 write string data success. str=%s", value.c_str()); - - return ret; + int ret = ERROR_SUCCESS; + + // len + if (!stream->require(2)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write string length failed. ret=%d", ret); + return ret; + } + stream->write_2bytes(value.length()); + srs_verbose("amf0 write string length success. len=%d", (int)value.length()); + + // empty string + if (value.length() <= 0) { + srs_verbose("amf0 write empty string. ret=%d", ret); + return ret; + } + + // data + if (!stream->require(value.length())) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write string data failed. ret=%d", ret); + return ret; + } + stream->write_string(value); + srs_verbose("amf0 write string data success. str=%s", value.c_str()); + + return ret; } int srs_amf0_read_string(SrsStream* stream, string& value) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read string marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_String) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check string marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_String, ret); - return ret; - } - srs_verbose("amf0 read string marker success"); - - return srs_amf0_read_utf8(stream, value); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read string marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_String) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check string marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_String, ret); + return ret; + } + srs_verbose("amf0 read string marker success"); + + return srs_amf0_read_utf8(stream, value); } int srs_amf0_write_string(SrsStream* stream, string value) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write string marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_String); - srs_verbose("amf0 write string marker success"); - - return srs_amf0_write_utf8(stream, value); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write string marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_String); + srs_verbose("amf0 write string marker success"); + + return srs_amf0_write_utf8(stream, value); } int srs_amf0_read_boolean(SrsStream* stream, bool& value) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read bool marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_Boolean) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check bool marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Boolean, ret); - return ret; - } - srs_verbose("amf0 read bool marker success"); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read bool marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_Boolean) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check bool marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Boolean, ret); + return ret; + } + srs_verbose("amf0 read bool marker success"); - // value - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read bool value failed. ret=%d", ret); - return ret; - } + // value + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read bool value failed. ret=%d", ret); + return ret; + } - if (stream->read_1bytes() == 0) { - value = false; - } else { - value = true; - } - - srs_verbose("amf0 read bool value success. value=%d", value); - - return ret; + if (stream->read_1bytes() == 0) { + value = false; + } else { + value = true; + } + + srs_verbose("amf0 read bool value success. value=%d", value); + + return ret; } int srs_amf0_write_boolean(SrsStream* stream, bool value) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write bool marker failed. ret=%d", ret); - return ret; - } - stream->write_1bytes(RTMP_AMF0_Boolean); - srs_verbose("amf0 write bool marker success"); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write bool marker failed. ret=%d", ret); + return ret; + } + stream->write_1bytes(RTMP_AMF0_Boolean); + srs_verbose("amf0 write bool marker success"); - // value - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write bool value failed. ret=%d", ret); - return ret; - } + // value + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write bool value failed. ret=%d", ret); + return ret; + } - if (value) { - stream->write_1bytes(0x01); - } else { - stream->write_1bytes(0x00); - } - - srs_verbose("amf0 write bool value success. value=%d", value); - - return ret; + if (value) { + stream->write_1bytes(0x01); + } else { + stream->write_1bytes(0x00); + } + + srs_verbose("amf0 write bool value success. value=%d", value); + + return ret; } int srs_amf0_read_number(SrsStream* stream, double& value) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read number marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_Number) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check number marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Number, ret); - return ret; - } - srs_verbose("amf0 read number marker success"); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read number marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_Number) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check number marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Number, ret); + return ret; + } + srs_verbose("amf0 read number marker success"); - // value - if (!stream->require(8)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read number value failed. ret=%d", ret); - return ret; - } + // value + if (!stream->require(8)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read number value failed. ret=%d", ret); + return ret; + } - int64_t temp = stream->read_8bytes(); - memcpy(&value, &temp, 8); - - srs_verbose("amf0 read number value success. value=%.2f", value); - - return ret; + int64_t temp = stream->read_8bytes(); + memcpy(&value, &temp, 8); + + srs_verbose("amf0 read number value success. value=%.2f", value); + + return ret; } int srs_amf0_write_number(SrsStream* stream, double value) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write number marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_Number); - srs_verbose("amf0 write number marker success"); + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write number marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_Number); + srs_verbose("amf0 write number marker success"); - // value - if (!stream->require(8)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write number value failed. ret=%d", ret); - return ret; - } + // value + if (!stream->require(8)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write number value failed. ret=%d", ret); + return ret; + } - int64_t temp = 0x00; - memcpy(&temp, &value, 8); - stream->write_8bytes(temp); - - srs_verbose("amf0 write number value success. value=%.2f", value); - - return ret; + int64_t temp = 0x00; + memcpy(&temp, &value, 8); + stream->write_8bytes(temp); + + srs_verbose("amf0 write number value success. value=%.2f", value); + + return ret; } int srs_amf0_read_null(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read null marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_Null) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check null marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret); - return ret; - } - srs_verbose("amf0 read null success"); - - return ret; + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read null marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_Null) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check null marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret); + return ret; + } + srs_verbose("amf0 read null success"); + + return ret; } int srs_amf0_write_null(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write null marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_Null); - srs_verbose("amf0 write null marker success"); - - return ret; + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write null marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_Null); + srs_verbose("amf0 write null marker success"); + + return ret; } int srs_amf0_read_undefined(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 read undefined marker failed. ret=%d", ret); - return ret; - } - - char marker = stream->read_1bytes(); - if (marker != RTMP_AMF0_Undefined) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 check undefined marker failed. " - "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Undefined, ret); - return ret; - } - srs_verbose("amf0 read undefined success"); - - return ret; + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 read undefined marker failed. ret=%d", ret); + return ret; + } + + char marker = stream->read_1bytes(); + if (marker != RTMP_AMF0_Undefined) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 check undefined marker failed. " + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Undefined, ret); + return ret; + } + srs_verbose("amf0 read undefined success"); + + return ret; } int srs_amf0_write_undefined(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write undefined marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_Undefined); - srs_verbose("amf0 write undefined marker success"); - - return ret; + int ret = ERROR_SUCCESS; + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write undefined marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_Undefined); + srs_verbose("amf0 write undefined marker success"); + + return ret; } bool srs_amf0_is_object_eof(SrsStream* stream) { - // detect the object-eof specially - if (stream->require(3)) { - int32_t flag = stream->read_3bytes(); - stream->skip(-3); - - return 0x09 == flag; - } - - return false; + // detect the object-eof specially + if (stream->require(3)) { + int32_t flag = stream->read_3bytes(); + stream->skip(-3); + + return 0x09 == flag; + } + + return false; } int srs_amf0_write_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF* value) { - int ret = ERROR_SUCCESS; - - srs_assert(value != NULL); - - // value - if (!stream->require(2)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write object eof value failed. ret=%d", ret); - return ret; - } - stream->write_2bytes(0x00); - srs_verbose("amf0 write object eof value success"); - - // marker - if (!stream->require(1)) { - ret = ERROR_RTMP_AMF0_ENCODE; - srs_error("amf0 write object eof marker failed. ret=%d", ret); - return ret; - } - - stream->write_1bytes(RTMP_AMF0_ObjectEnd); - - srs_verbose("amf0 read object eof success"); - - return ret; + int ret = ERROR_SUCCESS; + + srs_assert(value != NULL); + + // value + if (!stream->require(2)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write object eof value failed. ret=%d", ret); + return ret; + } + stream->write_2bytes(0x00); + srs_verbose("amf0 write object eof value success"); + + // marker + if (!stream->require(1)) { + ret = ERROR_RTMP_AMF0_ENCODE; + srs_error("amf0 write object eof marker failed. ret=%d", ret); + return ret; + } + + stream->write_1bytes(RTMP_AMF0_ObjectEnd); + + srs_verbose("amf0 read object eof success"); + + return ret; } diff --git a/trunk/src/rtmp/srs_protocol_amf0.hpp b/trunk/src/rtmp/srs_protocol_amf0.hpp index 802388d59..f9bccaefc 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.hpp +++ b/trunk/src/rtmp/srs_protocol_amf0.hpp @@ -43,29 +43,29 @@ class __SrsAmf0ObjectEOF; //////////////////////////////////////////////////////////////////////// // amf0 codec // 1. SrsAmf0Any: read any from stream -// SrsAmf0Any* pany = NULL; -// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) { -// return ret; -// } -// srs_assert(pany); // if success, always valid object. +// SrsAmf0Any* pany = NULL; +// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) { +// return ret; +// } +// srs_assert(pany); // if success, always valid object. // 2. SrsAmf0Any: convert to specifid type, for instance, string -// SrsAmf0Any* pany = ... -// if (pany->is_string()) { -// string v = pany->to_str(); -// } +// SrsAmf0Any* pany = ... +// if (pany->is_string()) { +// string v = pany->to_str(); +// } // 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 -// int size = SrsAmf0Size::str("winlin"); +// int size = SrsAmf0Size::str("winlin"); // 5. SrsAmf0Object: create the amf0 object. -// SrsAmf0Object* obj = SrsAmf0Any::object(); +// SrsAmf0Object* obj = SrsAmf0Any::object(); // 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: // 1. total_size(): the total memory size the object wrote to buffer. // 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. //////////////////////////////////////////////////////////////////////// @@ -76,73 +76,73 @@ class __SrsAmf0ObjectEOF; * any amf0 value. * 2.1 Types Overview * value-type = number-type | boolean-type | string-type | object-type -* | null-marker | undefined-marker | reference-type | ecma-array-type -* | strict-array-type | date-type | long-string-type | xml-document-type -* | typed-object-type +* | null-marker | undefined-marker | reference-type | ecma-array-type +* | strict-array-type | date-type | long-string-type | xml-document-type +* | typed-object-type */ class SrsAmf0Any { public: - char marker; + char marker; public: - SrsAmf0Any(); - virtual ~SrsAmf0Any(); + SrsAmf0Any(); + virtual ~SrsAmf0Any(); public: - virtual bool is_string(); - virtual bool is_boolean(); - virtual bool is_number(); - virtual bool is_null(); - virtual bool is_undefined(); - virtual bool is_object(); - virtual bool is_object_eof(); - virtual bool is_ecma_array(); + virtual bool is_string(); + virtual bool is_boolean(); + virtual bool is_number(); + virtual bool is_null(); + virtual bool is_undefined(); + virtual bool is_object(); + virtual bool is_object_eof(); + virtual bool is_ecma_array(); public: - /** - * get the string of any when is_string() indicates true. - * user must ensure the type is a string, or assert failed. - */ - virtual std::string to_str(); - /** - * get the boolean of any when is_boolean() indicates true. - * user must ensure the type is a boolean, or assert failed. - */ - virtual bool to_boolean(); - /** - * get the number of any when is_number() indicates true. - * user must ensure the type is a number, or assert failed. - */ - virtual double to_number(); - /** - * get the object of any when is_object() indicates true. - * user must ensure the type is a object, or assert failed. - */ - virtual SrsAmf0Object* to_object(); - /** - * get the ecma array of any when is_ecma_array() indicates true. - * user must ensure the type is a ecma array, or assert failed. - */ - virtual SrsAmf0EcmaArray* to_ecma_array(); + /** + * get the string of any when is_string() indicates true. + * user must ensure the type is a string, or assert failed. + */ + virtual std::string to_str(); + /** + * get the boolean of any when is_boolean() indicates true. + * user must ensure the type is a boolean, or assert failed. + */ + virtual bool to_boolean(); + /** + * get the number of any when is_number() indicates true. + * user must ensure the type is a number, or assert failed. + */ + virtual double to_number(); + /** + * get the object of any when is_object() indicates true. + * user must ensure the type is a object, or assert failed. + */ + virtual SrsAmf0Object* to_object(); + /** + * get the ecma array of any when is_ecma_array() indicates true. + * user must ensure the type is a ecma array, or assert failed. + */ + virtual SrsAmf0EcmaArray* to_ecma_array(); public: - /** - * get the size of amf0 any, including the marker size. - */ - virtual int total_size() = 0; - /** - * read elem from stream - */ - virtual int read(SrsStream* stream) = 0; - virtual int write(SrsStream* stream) = 0; + /** + * get the size of amf0 any, including the marker size. + */ + virtual int total_size() = 0; + /** + * read elem from stream + */ + virtual int read(SrsStream* stream) = 0; + virtual int write(SrsStream* stream) = 0; public: - static SrsAmf0Any* str(const char* value = NULL); - static SrsAmf0Any* boolean(bool value = false); - static SrsAmf0Any* number(double value = 0.0); - static SrsAmf0Any* null(); - static SrsAmf0Any* undefined(); - static SrsAmf0Object* object(); - static SrsAmf0Any* object_eof(); - static SrsAmf0EcmaArray* ecma_array(); + static SrsAmf0Any* str(const char* value = NULL); + static SrsAmf0Any* boolean(bool value = false); + static SrsAmf0Any* number(double value = 0.0); + static SrsAmf0Any* null(); + static SrsAmf0Any* undefined(); + static SrsAmf0Object* object(); + static SrsAmf0Any* object_eof(); + static SrsAmf0EcmaArray* ecma_array(); public: - static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue); + static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue); }; /** @@ -153,33 +153,33 @@ public: class SrsAmf0Object : public SrsAmf0Any { private: - __SrsUnSortedHashtable* properties; - __SrsAmf0ObjectEOF* eof; + __SrsUnSortedHashtable* properties; + __SrsAmf0ObjectEOF* eof; private: - // use SrsAmf0Any::object() to create it. - friend class SrsAmf0Any; - SrsAmf0Object(); + // use SrsAmf0Any::object() to create it. + friend class SrsAmf0Any; + SrsAmf0Object(); public: - virtual ~SrsAmf0Object(); + virtual ~SrsAmf0Object(); public: - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); - + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); + public: - virtual int count(); - // @remark: max index is count(). - virtual std::string key_at(int index); - // @remark: max index is count(). - virtual SrsAmf0Any* value_at(int index); - + virtual int count(); + // @remark: max index is count(). + virtual std::string key_at(int index); + // @remark: max index is count(). + virtual SrsAmf0Any* value_at(int index); + public: - virtual void set(std::string key, SrsAmf0Any* value); - virtual SrsAmf0Any* get_property(std::string name); - virtual SrsAmf0Any* ensure_property_string(std::string name); - virtual SrsAmf0Any* ensure_property_number(std::string name); + virtual void set(std::string key, SrsAmf0Any* value); + virtual SrsAmf0Any* get_property(std::string name); + virtual SrsAmf0Any* ensure_property_string(std::string name); + virtual SrsAmf0Any* ensure_property_number(std::string name); }; /** @@ -191,35 +191,35 @@ public: class SrsAmf0EcmaArray : public SrsAmf0Any { private: - __SrsUnSortedHashtable* properties; - __SrsAmf0ObjectEOF* eof; - int32_t _count; + __SrsUnSortedHashtable* properties; + __SrsAmf0ObjectEOF* eof; + int32_t _count; private: - // use SrsAmf0Any::ecma_array() to create it. - friend class SrsAmf0Any; - SrsAmf0EcmaArray(); + // use SrsAmf0Any::ecma_array() to create it. + friend class SrsAmf0Any; + SrsAmf0EcmaArray(); public: - virtual ~SrsAmf0EcmaArray(); + virtual ~SrsAmf0EcmaArray(); public: - virtual int total_size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); - + virtual int total_size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); + public: - virtual void clear(); - virtual int count(); - // @remark: max index is count(). - virtual std::string key_at(int index); - // @remark: max index is count(). - virtual SrsAmf0Any* value_at(int index); + virtual void clear(); + virtual int count(); + // @remark: max index is count(). + virtual std::string key_at(int index); + // @remark: max index is count(). + virtual SrsAmf0Any* value_at(int index); public: - virtual void set(std::string key, SrsAmf0Any* value); - virtual SrsAmf0Any* get_property(std::string name); - virtual SrsAmf0Any* ensure_property_string(std::string name); - virtual SrsAmf0Any* ensure_property_number(std::string name); + virtual void set(std::string key, SrsAmf0Any* value); + virtual SrsAmf0Any* get_property(std::string name); + virtual SrsAmf0Any* ensure_property_string(std::string name); + virtual SrsAmf0Any* ensure_property_number(std::string name); }; /** @@ -228,22 +228,22 @@ public: class SrsAmf0Size { public: - static int utf8(std::string value); - static int str(std::string value); - static int number(); - static int null(); - static int undefined(); - static int boolean(); - static int object(SrsAmf0Object* obj); - static int object_eof(); - static int ecma_array(SrsAmf0EcmaArray* arr); - static int any(SrsAmf0Any* o); + static int utf8(std::string value); + static int str(std::string value); + static int number(); + static int null(); + static int undefined(); + static int boolean(); + static int object(SrsAmf0Object* obj); + static int object_eof(); + static int ecma_array(SrsAmf0EcmaArray* arr); + static int any(SrsAmf0Any* o); }; /** * read anything from stream. * @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); @@ -259,7 +259,7 @@ extern int srs_amf0_write_string(SrsStream* stream, std::string value); * read amf0 boolean from stream. * 2.4 String Type * 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_write_boolean(SrsStream* stream, bool value); diff --git a/trunk/src/rtmp/srs_protocol_handshake.cpp b/trunk/src/rtmp/srs_protocol_handshake.cpp index af7f8f109..bcc0fe943 100644 --- a/trunk/src/rtmp/srs_protocol_handshake.cpp +++ b/trunk/src/rtmp/srs_protocol_handshake.cpp @@ -33,15 +33,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. void srs_random_generate(char* bytes, int size) { - static char cdata[] = { - 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72, 0x74, 0x6d, 0x70, 0x2d, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x2d, 0x77, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, 0x31, 0x32, 0x36, - 0x2e, 0x63, 0x6f, 0x6d - }; - for (int i = 0; i < size; i++) { - bytes[i] = cdata[rand() % (sizeof(cdata) - 1)]; - } + static char cdata[] = { + 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72, 0x74, 0x6d, 0x70, 0x2d, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x2d, 0x77, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, 0x31, 0x32, 0x36, + 0x2e, 0x63, 0x6f, 0x6d + }; + for (int i = 0; i < size; i++) { + bytes[i] = cdata[rand() % (sizeof(cdata) - 1)]; + } } #ifdef SRS_SSL @@ -101,10 +101,10 @@ int openssl_HMACsha256(const void* data, int data_size, const void* key, int key "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ "FFFFFFFFFFFFFFFF" int __openssl_generate_key( - u_int8_t*& _private_key, u_int8_t*& _public_key, int32_t& size, - DH*& pdh, int32_t& bits_count, u_int8_t*& shared_key, int32_t& shared_key_length, BIGNUM*& peer_public_key + u_int8_t*& _private_key, u_int8_t*& _public_key, int32_t& size, + DH*& pdh, int32_t& bits_count, u_int8_t*& shared_key, int32_t& shared_key_length, BIGNUM*& peer_public_key ){ - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; //1. Create the DH if ((pdh = DH_new()) == NULL) { @@ -174,7 +174,7 @@ int __openssl_generate_key( // CopyPublicKey if (pdh == NULL) { ret = ERROR_OpenSslComputeSharedKey; - return ret; + return ret; } int32_t keySize = BN_num_bytes(pdh->pub_key); @@ -204,8 +204,8 @@ int openssl_generate_key(char* _private_key, char* _public_key, int32_t size) BIGNUM* peer_public_key = NULL; ret = __openssl_generate_key( - (u_int8_t*&)_private_key, (u_int8_t*&)_public_key, size, - pdh, bits_count, shared_key, shared_key_length, peer_public_key + (u_int8_t*&)_private_key, (u_int8_t*&)_public_key, size, + pdh, bits_count, shared_key, shared_key_length, peer_public_key ); if (pdh != NULL) { @@ -239,363 +239,363 @@ int openssl_generate_key(char* _private_key, char* _public_key, int32_t size) /** * 764bytes key结构 -* random-data: (offset)bytes -* key-data: 128bytes -* random-data: (764-offset-128-4)bytes -* offset: 4bytes +* random-data: (offset)bytes +* key-data: 128bytes +* random-data: (764-offset-128-4)bytes +* offset: 4bytes */ struct key_block { - // (offset)bytes - char* random0; - int random0_size; - - // 128bytes - char key[128]; - - // (764-offset-128-4)bytes - char* random1; - int random1_size; - - // 4bytes - int32_t offset; + // (offset)bytes + char* random0; + int random0_size; + + // 128bytes + char key[128]; + + // (764-offset-128-4)bytes + char* random1; + int random1_size; + + // 4bytes + int32_t offset; }; // calc the offset of key, // the key->offset cannot be used as the offset of key. int srs_key_block_get_offset(key_block* key) { - int max_offset_size = 764 - 128 - 4; - - int offset = 0; - u_int8_t* pp = (u_int8_t*)&key->offset; - offset += *pp++; - offset += *pp++; - offset += *pp++; - offset += *pp++; + int max_offset_size = 764 - 128 - 4; + + int offset = 0; + u_int8_t* pp = (u_int8_t*)&key->offset; + offset += *pp++; + offset += *pp++; + offset += *pp++; + offset += *pp++; - return offset % max_offset_size; + return offset % max_offset_size; } // create new key block data. // if created, user must free it by srs_key_block_free void srs_key_block_init(key_block* key) { - key->offset = (int32_t)rand(); - key->random0 = NULL; - key->random1 = NULL; - - int offset = srs_key_block_get_offset(key); - srs_assert(offset >= 0); - - key->random0_size = offset; - if (key->random0_size > 0) { - key->random0 = new char[key->random0_size]; - srs_random_generate(key->random0, key->random0_size); - } - - srs_random_generate(key->key, sizeof(key->key)); - - key->random1_size = 764 - offset - 128 - 4; - if (key->random1_size > 0) { - key->random1 = new char[key->random1_size]; - srs_random_generate(key->random1, key->random1_size); - } + key->offset = (int32_t)rand(); + key->random0 = NULL; + key->random1 = NULL; + + int offset = srs_key_block_get_offset(key); + srs_assert(offset >= 0); + + key->random0_size = offset; + if (key->random0_size > 0) { + key->random0 = new char[key->random0_size]; + srs_random_generate(key->random0, key->random0_size); + } + + srs_random_generate(key->key, sizeof(key->key)); + + key->random1_size = 764 - offset - 128 - 4; + if (key->random1_size > 0) { + key->random1 = new char[key->random1_size]; + srs_random_generate(key->random1, key->random1_size); + } } // parse key block from c1s1. // if created, user must free it by srs_key_block_free // @c1s1_key_bytes the key start bytes, maybe c1s1 or c1s1+764 int srs_key_block_parse(key_block* key, char* c1s1_key_bytes) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - char* pp = c1s1_key_bytes + 764; - - pp -= sizeof(int32_t); - key->offset = *(int32_t*)pp; - - key->random0 = NULL; - key->random1 = NULL; - - int offset = srs_key_block_get_offset(key); - srs_assert(offset >= 0); - - pp = c1s1_key_bytes; - key->random0_size = offset; - if (key->random0_size > 0) { - key->random0 = new char[key->random0_size]; - memcpy(key->random0, pp, key->random0_size); - } - pp += key->random0_size; - - memcpy(key->key, pp, sizeof(key->key)); - pp += sizeof(key->key); - - key->random1_size = 764 - offset - 128 - 4; - if (key->random1_size > 0) { - key->random1 = new char[key->random1_size]; - memcpy(key->random1, pp, key->random1_size); - } - - return ret; + char* pp = c1s1_key_bytes + 764; + + pp -= sizeof(int32_t); + key->offset = *(int32_t*)pp; + + key->random0 = NULL; + key->random1 = NULL; + + int offset = srs_key_block_get_offset(key); + srs_assert(offset >= 0); + + pp = c1s1_key_bytes; + key->random0_size = offset; + if (key->random0_size > 0) { + key->random0 = new char[key->random0_size]; + memcpy(key->random0, pp, key->random0_size); + } + pp += key->random0_size; + + memcpy(key->key, pp, sizeof(key->key)); + pp += sizeof(key->key); + + key->random1_size = 764 - offset - 128 - 4; + if (key->random1_size > 0) { + key->random1 = new char[key->random1_size]; + memcpy(key->random1, pp, key->random1_size); + } + + return ret; } // free the block data create by // srs_key_block_init or srs_key_block_parse void srs_key_block_free(key_block* key) { - if (key->random0) { - srs_freepa(key->random0); - } - if (key->random1) { - srs_freepa(key->random1); - } + if (key->random0) { + srs_freepa(key->random0); + } + if (key->random1) { + srs_freepa(key->random1); + } } /** * 764bytes digest结构 -* offset: 4bytes -* random-data: (offset)bytes -* digest-data: 32bytes -* random-data: (764-4-offset-32)bytes +* offset: 4bytes +* random-data: (offset)bytes +* digest-data: 32bytes +* random-data: (764-4-offset-32)bytes */ struct digest_block { - // 4bytes - int32_t offset; - - // (offset)bytes - char* random0; - int random0_size; - - // 32bytes - char digest[32]; - - // (764-4-offset-32)bytes - char* random1; - int random1_size; + // 4bytes + int32_t offset; + + // (offset)bytes + char* random0; + int random0_size; + + // 32bytes + char digest[32]; + + // (764-4-offset-32)bytes + char* random1; + int random1_size; }; // calc the offset of digest, // the key->offset cannot be used as the offset of digest. int srs_digest_block_get_offset(digest_block* digest) { - int max_offset_size = 764 - 32 - 4; - - int offset = 0; - u_int8_t* pp = (u_int8_t*)&digest->offset; - offset += *pp++; - offset += *pp++; - offset += *pp++; - offset += *pp++; + int max_offset_size = 764 - 32 - 4; + + int offset = 0; + u_int8_t* pp = (u_int8_t*)&digest->offset; + offset += *pp++; + offset += *pp++; + offset += *pp++; + offset += *pp++; - return offset % max_offset_size; + return offset % max_offset_size; } // create new digest block data. // if created, user must free it by srs_digest_block_free void srs_digest_block_init(digest_block* digest) { - digest->offset = (int32_t)rand(); - digest->random0 = NULL; - digest->random1 = NULL; - - int offset = srs_digest_block_get_offset(digest); - srs_assert(offset >= 0); - - digest->random0_size = offset; - if (digest->random0_size > 0) { - digest->random0 = new char[digest->random0_size]; - srs_random_generate(digest->random0, digest->random0_size); - } - - srs_random_generate(digest->digest, sizeof(digest->digest)); - - digest->random1_size = 764 - 4 - offset - 32; - if (digest->random1_size > 0) { - digest->random1 = new char[digest->random1_size]; - srs_random_generate(digest->random1, digest->random1_size); - } + digest->offset = (int32_t)rand(); + digest->random0 = NULL; + digest->random1 = NULL; + + int offset = srs_digest_block_get_offset(digest); + srs_assert(offset >= 0); + + digest->random0_size = offset; + if (digest->random0_size > 0) { + digest->random0 = new char[digest->random0_size]; + srs_random_generate(digest->random0, digest->random0_size); + } + + srs_random_generate(digest->digest, sizeof(digest->digest)); + + digest->random1_size = 764 - 4 - offset - 32; + if (digest->random1_size > 0) { + digest->random1 = new char[digest->random1_size]; + srs_random_generate(digest->random1, digest->random1_size); + } } // parse digest block from c1s1. // if created, user must free it by srs_digest_block_free // @c1s1_digest_bytes the digest start bytes, maybe c1s1 or c1s1+764 int srs_digest_block_parse(digest_block* digest, char* c1s1_digest_bytes) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - char* pp = c1s1_digest_bytes; - - digest->offset = *(int32_t*)pp; - pp += sizeof(int32_t); - - digest->random0 = NULL; - digest->random1 = NULL; - - int offset = srs_digest_block_get_offset(digest); - srs_assert(offset >= 0); - - digest->random0_size = offset; - if (digest->random0_size > 0) { - digest->random0 = new char[digest->random0_size]; - memcpy(digest->random0, pp, digest->random0_size); - } - pp += digest->random0_size; - - memcpy(digest->digest, pp, sizeof(digest->digest)); - pp += sizeof(digest->digest); - - digest->random1_size = 764 - 4 - offset - 32; - if (digest->random1_size > 0) { - digest->random1 = new char[digest->random1_size]; - memcpy(digest->random1, pp, digest->random1_size); - } - - return ret; + char* pp = c1s1_digest_bytes; + + digest->offset = *(int32_t*)pp; + pp += sizeof(int32_t); + + digest->random0 = NULL; + digest->random1 = NULL; + + int offset = srs_digest_block_get_offset(digest); + srs_assert(offset >= 0); + + digest->random0_size = offset; + if (digest->random0_size > 0) { + digest->random0 = new char[digest->random0_size]; + memcpy(digest->random0, pp, digest->random0_size); + } + pp += digest->random0_size; + + memcpy(digest->digest, pp, sizeof(digest->digest)); + pp += sizeof(digest->digest); + + digest->random1_size = 764 - 4 - offset - 32; + if (digest->random1_size > 0) { + digest->random1 = new char[digest->random1_size]; + memcpy(digest->random1, pp, digest->random1_size); + } + + return ret; } // free the block data create by // srs_digest_block_init or srs_digest_block_parse void srs_digest_block_free(digest_block* digest) { - if (digest->random0) { - srs_freepa(digest->random0); - } - if (digest->random1) { - srs_freepa(digest->random1); - } + if (digest->random0) { + srs_freepa(digest->random0); + } + if (digest->random1) { + srs_freepa(digest->random1); + } } /** * the schema type. */ enum srs_schema_type { - srs_schema0 = 0, // key-digest sequence - srs_schema1 = 1, // digest-key sequence - srs_schema_invalid = 2, + srs_schema0 = 0, // key-digest sequence + srs_schema1 = 1, // digest-key sequence + srs_schema_invalid = 2, }; void __srs_time_copy_to(char*& pp, int32_t time) { - // 4bytes time - *(int32_t*)pp = time; - pp += 4; + // 4bytes time + *(int32_t*)pp = time; + pp += 4; } void __srs_version_copy_to(char*& pp, int32_t version) { - // 4bytes version - *(int32_t*)pp = version; - pp += 4; + // 4bytes version + *(int32_t*)pp = version; + pp += 4; } void __srs_key_copy_to(char*& pp, key_block* key) { - // 764bytes key block - if (key->random0_size > 0) { - memcpy(pp, key->random0, key->random0_size); - } - pp += key->random0_size; - - memcpy(pp, key->key, sizeof(key->key)); - pp += sizeof(key->key); - - if (key->random1_size > 0) { - memcpy(pp, key->random1, key->random1_size); - } - pp += key->random1_size; - - *(int32_t*)pp = key->offset; - pp += 4; + // 764bytes key block + if (key->random0_size > 0) { + memcpy(pp, key->random0, key->random0_size); + } + pp += key->random0_size; + + memcpy(pp, key->key, sizeof(key->key)); + pp += sizeof(key->key); + + if (key->random1_size > 0) { + memcpy(pp, key->random1, key->random1_size); + } + pp += key->random1_size; + + *(int32_t*)pp = key->offset; + pp += 4; } void __srs_digest_copy_to(char*& pp, digest_block* digest, bool with_digest) { - // 732bytes digest block without the 32bytes digest-data - // nbytes digest block part1 - *(int32_t*)pp = digest->offset; - pp += 4; - - if (digest->random0_size > 0) { - memcpy(pp, digest->random0, digest->random0_size); - } - pp += digest->random0_size; - - // digest - if (with_digest) { - memcpy(pp, digest->digest, 32); - pp += 32; - } - - // nbytes digest block part2 - if (digest->random1_size > 0) { - memcpy(pp, digest->random1, digest->random1_size); - } - pp += digest->random1_size; + // 732bytes digest block without the 32bytes digest-data + // nbytes digest block part1 + *(int32_t*)pp = digest->offset; + pp += 4; + + if (digest->random0_size > 0) { + memcpy(pp, digest->random0, digest->random0_size); + } + pp += digest->random0_size; + + // digest + if (with_digest) { + memcpy(pp, digest->digest, 32); + pp += 32; + } + + // nbytes digest block part2 + if (digest->random1_size > 0) { + memcpy(pp, digest->random1, digest->random1_size); + } + pp += digest->random1_size; } /** * copy whole c1s1 to bytes. */ void srs_schema0_copy_to(char* bytes, bool with_digest, - int32_t time, int32_t version, key_block* key, digest_block* digest) + int32_t time, int32_t version, key_block* key, digest_block* digest) { - char* pp = bytes; + char* pp = bytes; - __srs_time_copy_to(pp, time); - __srs_version_copy_to(pp, version); - __srs_key_copy_to(pp, key); - __srs_digest_copy_to(pp, digest, with_digest); - - if (with_digest) { - srs_assert(pp - bytes == 1536); - } else { - srs_assert(pp - bytes == 1536 - 32); - } + __srs_time_copy_to(pp, time); + __srs_version_copy_to(pp, version); + __srs_key_copy_to(pp, key); + __srs_digest_copy_to(pp, digest, with_digest); + + if (with_digest) { + srs_assert(pp - bytes == 1536); + } else { + srs_assert(pp - bytes == 1536 - 32); + } } void srs_schema1_copy_to(char* bytes, bool with_digest, - int32_t time, int32_t version, digest_block* digest, key_block* key) + int32_t time, int32_t version, digest_block* digest, key_block* key) { - char* pp = bytes; + char* pp = bytes; - __srs_time_copy_to(pp, time); - __srs_version_copy_to(pp, version); - __srs_digest_copy_to(pp, digest, with_digest); - __srs_key_copy_to(pp, key); - - if (with_digest) { - srs_assert(pp - bytes == 1536); - } else { - srs_assert(pp - bytes == 1536 - 32); - } + __srs_time_copy_to(pp, time); + __srs_version_copy_to(pp, version); + __srs_digest_copy_to(pp, digest, with_digest); + __srs_key_copy_to(pp, key); + + if (with_digest) { + srs_assert(pp - bytes == 1536); + } else { + srs_assert(pp - bytes == 1536 - 32); + } } /** * c1s1 is splited by digest: -* c1s1-part1: n bytes (time, version, key and digest-part1). -* digest-data: 32bytes -* c1s1-part2: (1536-n-32)bytes (digest-part2) +* c1s1-part1: n bytes (time, version, key and digest-part1). +* digest-data: 32bytes +* c1s1-part2: (1536-n-32)bytes (digest-part2) */ char* srs_bytes_join_schema0(int32_t time, int32_t version, key_block* key, digest_block* digest) { - char* bytes = new char[1536 -32]; - - srs_schema0_copy_to(bytes, false, time, version, key, digest); - - return bytes; + char* bytes = new char[1536 -32]; + + srs_schema0_copy_to(bytes, false, time, version, key, digest); + + return bytes; } /** * c1s1 is splited by digest: -* c1s1-part1: n bytes (time, version and digest-part1). -* digest-data: 32bytes -* c1s1-part2: (1536-n-32)bytes (digest-part2 and key) +* c1s1-part1: n bytes (time, version and digest-part1). +* digest-data: 32bytes +* c1s1-part2: (1536-n-32)bytes (digest-part2 and key) */ char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key) { - char* bytes = new char[1536 -32]; - - srs_schema1_copy_to(bytes, false, time, version, digest, key); - - return bytes; + char* bytes = new char[1536 -32]; + + srs_schema1_copy_to(bytes, false, time, version, digest, key); + + return bytes; } /** * compare the memory in bytes. */ bool srs_bytes_equals(void* pa, void* pb, int size){ - u_int8_t* a = (u_int8_t*)pa; - u_int8_t* b = (u_int8_t*)pb; - + u_int8_t* a = (u_int8_t*)pa; + u_int8_t* b = (u_int8_t*)pb; + for(int i = 0; i < size; i++){ if(a[i] != b[i]){ return false; @@ -607,83 +607,83 @@ bool srs_bytes_equals(void* pa, void* pb, int size){ /** * c1s1 schema0 -* time: 4bytes -* version: 4bytes -* key: 764bytes -* digest: 764bytes +* time: 4bytes +* version: 4bytes +* key: 764bytes +* digest: 764bytes * c1s1 schema1 -* time: 4bytes -* version: 4bytes -* digest: 764bytes -* key: 764bytes +* time: 4bytes +* version: 4bytes +* digest: 764bytes +* key: 764bytes */ struct c1s1 { - union block { - key_block key; - digest_block digest; - }; - - // 4bytes - int32_t time; - // 4bytes - int32_t version; - // 764bytes - // if schema0, use key - // if schema1, use digest - block block0; - // 764bytes - // if schema0, use digest - // if schema1, use key - block block1; - - // the logic schema - srs_schema_type schema; - - c1s1(); - virtual ~c1s1(); - /** - * get the digest key. - */ - virtual char* get_digest(); - /** - * copy to bytes. - */ - virtual void dump(char* _c1s1); - - /** - * client: create and sign c1 by schema. - * sign the c1, generate the digest. - * calc_c1_digest(c1, schema) { - * get c1s1-joined from c1 by specified schema - * digest-data = HMACsha256(c1s1-joined, FPKey, 30) - * return digest-data; - * } - * random fill 1536bytes c1 // also fill the c1-128bytes-key - * time = time() // c1[0-3] - * version = [0x80, 0x00, 0x07, 0x02] // c1[4-7] - * schema = choose schema0 or schema1 - * digest-data = calc_c1_digest(c1, schema) - * copy digest-data to c1 - */ - virtual int c1_create(srs_schema_type _schema); - /** - * server: parse the c1s1, discovery the key and digest by schema. - * use the c1_validate_digest() to valid the digest of c1. - */ - virtual int c1_parse(char* _c1s1, srs_schema_type _schema); - /** - * server: validate the parsed schema and c1s1 - */ - virtual int c1_validate_digest(bool& is_valid); - /** - * server: create and sign the s1 from c1. - */ - virtual int s1_create(c1s1* c1); + union block { + key_block key; + digest_block digest; + }; + + // 4bytes + int32_t time; + // 4bytes + int32_t version; + // 764bytes + // if schema0, use key + // if schema1, use digest + block block0; + // 764bytes + // if schema0, use digest + // if schema1, use key + block block1; + + // the logic schema + srs_schema_type schema; + + c1s1(); + virtual ~c1s1(); + /** + * get the digest key. + */ + virtual char* get_digest(); + /** + * copy to bytes. + */ + virtual void dump(char* _c1s1); + + /** + * client: create and sign c1 by schema. + * sign the c1, generate the digest. + * calc_c1_digest(c1, schema) { + * get c1s1-joined from c1 by specified schema + * digest-data = HMACsha256(c1s1-joined, FPKey, 30) + * return digest-data; + * } + * random fill 1536bytes c1 // also fill the c1-128bytes-key + * time = time() // c1[0-3] + * version = [0x80, 0x00, 0x07, 0x02] // c1[4-7] + * schema = choose schema0 or schema1 + * digest-data = calc_c1_digest(c1, schema) + * copy digest-data to c1 + */ + virtual int c1_create(srs_schema_type _schema); + /** + * server: parse the c1s1, discovery the key and digest by schema. + * use the c1_validate_digest() to valid the digest of c1. + */ + virtual int c1_parse(char* _c1s1, srs_schema_type _schema); + /** + * server: validate the parsed schema and c1s1 + */ + virtual int c1_validate_digest(bool& is_valid); + /** + * server: create and sign the s1 from c1. + */ + virtual int s1_create(c1s1* c1); private: - virtual int calc_s1_digest(char*& digest); - virtual int calc_c1_digest(char*& digest); - virtual void destroy_blocks(); + virtual int calc_s1_digest(char*& digest); + virtual int calc_c1_digest(char*& digest); + virtual void destroy_blocks(); }; /** @@ -693,42 +693,42 @@ private: */ struct c2s2 { - char random[1504]; - char digest[32]; - - c2s2(); - virtual ~c2s2(); - - /** - * copy to bytes. - */ - virtual void dump(char* _c2s2); + char random[1504]; + char digest[32]; + + c2s2(); + virtual ~c2s2(); + + /** + * copy to bytes. + */ + virtual void dump(char* _c2s2); - /** - * create c2. - * random fill c2s2 1536 bytes - * - * // client generate C2, or server valid C2 - * temp-key = HMACsha256(s1-digest, FPKey, 62) - * c2-digest-data = HMACsha256(c2-random-data, temp-key, 32) - */ - virtual int c2_create(c1s1* s1); - - /** - * create s2. - * random fill c2s2 1536 bytes - * - * // server generate S2, or client valid S2 - * temp-key = HMACsha256(c1-digest, FMSKey, 68) - * s2-digest-data = HMACsha256(s2-random-data, temp-key, 32) - */ - virtual int s2_create(c1s1* c1); + /** + * create c2. + * random fill c2s2 1536 bytes + * + * // client generate C2, or server valid C2 + * temp-key = HMACsha256(s1-digest, FPKey, 62) + * c2-digest-data = HMACsha256(c2-random-data, temp-key, 32) + */ + virtual int c2_create(c1s1* s1); + + /** + * create s2. + * random fill c2s2 1536 bytes + * + * // server generate S2, or client valid S2 + * temp-key = HMACsha256(c1-digest, FMSKey, 68) + * s2-digest-data = HMACsha256(s2-random-data, temp-key, 32) + */ + virtual int s2_create(c1s1* c1); }; c2s2::c2s2() { - srs_random_generate(random, 1504); - srs_random_generate(digest, 32); + srs_random_generate(random, 1504); + srs_random_generate(digest, 32); } c2s2::~c2s2() @@ -737,324 +737,324 @@ c2s2::~c2s2() void c2s2::dump(char* _c2s2) { - memcpy(_c2s2, random, 1504); - memcpy(_c2s2 + 1504, digest, 32); + memcpy(_c2s2, random, 1504); + memcpy(_c2s2 + 1504, digest, 32); } int c2s2::c2_create(c1s1* s1) { - int ret = ERROR_SUCCESS; - - char temp_key[OpensslHashSize]; - if ((ret = openssl_HMACsha256(s1->get_digest(), 32, SrsGenuineFPKey, 62, temp_key)) != ERROR_SUCCESS) { - srs_error("create c2 temp key failed. ret=%d", ret); - return ret; - } - srs_verbose("generate c2 temp key success."); - - char _digest[OpensslHashSize]; - if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { - srs_error("create c2 digest failed. ret=%d", ret); - return ret; - } - srs_verbose("generate c2 digest success."); - - memcpy(digest, _digest, 32); - - return ret; + int ret = ERROR_SUCCESS; + + char temp_key[OpensslHashSize]; + if ((ret = openssl_HMACsha256(s1->get_digest(), 32, SrsGenuineFPKey, 62, temp_key)) != ERROR_SUCCESS) { + srs_error("create c2 temp key failed. ret=%d", ret); + return ret; + } + srs_verbose("generate c2 temp key success."); + + char _digest[OpensslHashSize]; + if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { + srs_error("create c2 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("generate c2 digest success."); + + memcpy(digest, _digest, 32); + + return ret; } int c2s2::s2_create(c1s1* c1) { - int ret = ERROR_SUCCESS; - - char temp_key[OpensslHashSize]; - if ((ret = openssl_HMACsha256(c1->get_digest(), 32, SrsGenuineFMSKey, 68, temp_key)) != ERROR_SUCCESS) { - srs_error("create s2 temp key failed. ret=%d", ret); - return ret; - } - srs_verbose("generate s2 temp key success."); - - char _digest[OpensslHashSize]; - if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { - srs_error("create s2 digest failed. ret=%d", ret); - return ret; - } - srs_verbose("generate s2 digest success."); - - memcpy(digest, _digest, 32); - - return ret; + int ret = ERROR_SUCCESS; + + char temp_key[OpensslHashSize]; + if ((ret = openssl_HMACsha256(c1->get_digest(), 32, SrsGenuineFMSKey, 68, temp_key)) != ERROR_SUCCESS) { + srs_error("create s2 temp key failed. ret=%d", ret); + return ret; + } + srs_verbose("generate s2 temp key success."); + + char _digest[OpensslHashSize]; + if ((ret = openssl_HMACsha256(random, 1504, temp_key, 32, _digest)) != ERROR_SUCCESS) { + srs_error("create s2 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("generate s2 digest success."); + + memcpy(digest, _digest, 32); + + return ret; } c1s1::c1s1() { - schema = srs_schema_invalid; + schema = srs_schema_invalid; } c1s1::~c1s1() { - destroy_blocks(); + destroy_blocks(); } char* c1s1::get_digest() { - srs_assert(schema != srs_schema_invalid); - - if (schema == srs_schema0) { - return block1.digest.digest; - } else { - return block0.digest.digest; - } + srs_assert(schema != srs_schema_invalid); + + if (schema == srs_schema0) { + return block1.digest.digest; + } else { + return block0.digest.digest; + } } void c1s1::dump(char* _c1s1) { - srs_assert(schema != srs_schema_invalid); - - if (schema == srs_schema0) { - srs_schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest); - } else { - srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key); - } + srs_assert(schema != srs_schema_invalid); + + if (schema == srs_schema0) { + srs_schema0_copy_to(_c1s1, true, time, version, &block0.key, &block1.digest); + } else { + srs_schema1_copy_to(_c1s1, true, time, version, &block0.digest, &block1.key); + } } int c1s1::c1_create(srs_schema_type _schema) { - int ret = ERROR_SUCCESS; - - if (_schema == srs_schema_invalid) { - ret = ERROR_RTMP_CH_SCHEMA; - srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret); - return ret; - } - - destroy_blocks(); - - time = ::time(NULL); - version = 0x02070080; // client c1 version - - if (_schema == srs_schema0) { - srs_key_block_init(&block0.key); - srs_digest_block_init(&block1.digest); - } else { - srs_digest_block_init(&block0.digest); - srs_key_block_init(&block1.key); - } - - schema = _schema; - - char* digest = NULL; - - if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) { - srs_error("sign c1 error, failed to calc digest. ret=%d", ret); - return ret; - } - - srs_assert(digest != NULL); - SrsAutoFree(char, digest, true); - - if (schema == srs_schema0) { - memcpy(block1.digest.digest, digest, 32); - } else { - memcpy(block0.digest.digest, digest, 32); - } - - return ret; + int ret = ERROR_SUCCESS; + + if (_schema == srs_schema_invalid) { + ret = ERROR_RTMP_CH_SCHEMA; + srs_error("create c1 failed. invalid schema=%d, ret=%d", _schema, ret); + return ret; + } + + destroy_blocks(); + + time = ::time(NULL); + version = 0x02070080; // client c1 version + + if (_schema == srs_schema0) { + srs_key_block_init(&block0.key); + srs_digest_block_init(&block1.digest); + } else { + srs_digest_block_init(&block0.digest); + srs_key_block_init(&block1.key); + } + + schema = _schema; + + char* digest = NULL; + + if ((ret = calc_c1_digest(digest)) != ERROR_SUCCESS) { + srs_error("sign c1 error, failed to calc digest. ret=%d", ret); + return ret; + } + + srs_assert(digest != NULL); + SrsAutoFree(char, digest, true); + + if (schema == srs_schema0) { + memcpy(block1.digest.digest, digest, 32); + } else { + memcpy(block0.digest.digest, digest, 32); + } + + return ret; } int c1s1::c1_parse(char* _c1s1, srs_schema_type _schema) { - int ret = ERROR_SUCCESS; - - if (_schema == srs_schema_invalid) { - ret = ERROR_RTMP_CH_SCHEMA; - srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); - return ret; - } - - destroy_blocks(); - - time = *(int32_t*)_c1s1; - version = *(int32_t*)(_c1s1 + 4); // client c1 version - - if (_schema == srs_schema0) { - if ((ret = srs_key_block_parse(&block0.key, _c1s1 + 8)) != ERROR_SUCCESS) { - srs_error("parse the c1 key failed. ret=%d", ret); - return ret; - } - if ((ret = srs_digest_block_parse(&block1.digest, _c1s1 + 8 + 764)) != ERROR_SUCCESS) { - srs_error("parse the c1 digest failed. ret=%d", ret); - return ret; - } - srs_verbose("parse c1 key-digest success"); - } else if (_schema == srs_schema1) { - if ((ret = srs_digest_block_parse(&block0.digest, _c1s1 + 8)) != ERROR_SUCCESS) { - srs_error("parse the c1 key failed. ret=%d", ret); - return ret; - } - if ((ret = srs_key_block_parse(&block1.key, _c1s1 + 8 + 764)) != ERROR_SUCCESS) { - srs_error("parse the c1 digest failed. ret=%d", ret); - return ret; - } - srs_verbose("parse c1 digest-key success"); - } else { - ret = ERROR_RTMP_CH_SCHEMA; - srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); - return ret; - } - - schema = _schema; - - return ret; + int ret = ERROR_SUCCESS; + + if (_schema == srs_schema_invalid) { + ret = ERROR_RTMP_CH_SCHEMA; + srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); + return ret; + } + + destroy_blocks(); + + time = *(int32_t*)_c1s1; + version = *(int32_t*)(_c1s1 + 4); // client c1 version + + if (_schema == srs_schema0) { + if ((ret = srs_key_block_parse(&block0.key, _c1s1 + 8)) != ERROR_SUCCESS) { + srs_error("parse the c1 key failed. ret=%d", ret); + return ret; + } + if ((ret = srs_digest_block_parse(&block1.digest, _c1s1 + 8 + 764)) != ERROR_SUCCESS) { + srs_error("parse the c1 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("parse c1 key-digest success"); + } else if (_schema == srs_schema1) { + if ((ret = srs_digest_block_parse(&block0.digest, _c1s1 + 8)) != ERROR_SUCCESS) { + srs_error("parse the c1 key failed. ret=%d", ret); + return ret; + } + if ((ret = srs_key_block_parse(&block1.key, _c1s1 + 8 + 764)) != ERROR_SUCCESS) { + srs_error("parse the c1 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("parse c1 digest-key success"); + } else { + ret = ERROR_RTMP_CH_SCHEMA; + srs_error("parse c1 failed. invalid schema=%d, ret=%d", _schema, ret); + return ret; + } + + schema = _schema; + + return ret; } int c1s1::c1_validate_digest(bool& is_valid) { - int ret = ERROR_SUCCESS; - - char* c1_digest = NULL; - - if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) { - srs_error("validate c1 error, failed to calc digest. ret=%d", ret); - return ret; - } - - srs_assert(c1_digest != NULL); - SrsAutoFree(char, c1_digest, true); - - if (schema == srs_schema0) { - is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32); - } else { - is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32); - } - - return ret; + int ret = ERROR_SUCCESS; + + char* c1_digest = NULL; + + if ((ret = calc_c1_digest(c1_digest)) != ERROR_SUCCESS) { + srs_error("validate c1 error, failed to calc digest. ret=%d", ret); + return ret; + } + + srs_assert(c1_digest != NULL); + SrsAutoFree(char, c1_digest, true); + + if (schema == srs_schema0) { + is_valid = srs_bytes_equals(block1.digest.digest, c1_digest, 32); + } else { + is_valid = srs_bytes_equals(block0.digest.digest, c1_digest, 32); + } + + return ret; } int c1s1::s1_create(c1s1* c1) { - int ret = ERROR_SUCCESS; - - if (c1->schema == srs_schema_invalid) { - ret = ERROR_RTMP_CH_SCHEMA; - srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret); - return ret; - } - - destroy_blocks(); - schema = c1->schema; - - time = ::time(NULL); - version = 0x01000504; // server s1 version - - if (schema == srs_schema0) { - srs_key_block_init(&block0.key); - srs_digest_block_init(&block1.digest); - } else { - srs_digest_block_init(&block0.digest); - srs_key_block_init(&block1.key); - } - - if (schema == srs_schema0) { - if ((ret = openssl_generate_key(c1->block0.key.key, block0.key.key, 128)) != ERROR_SUCCESS) { - srs_error("calc s1 key failed. ret=%d", ret); - return ret; - } - } else { - if ((ret = openssl_generate_key(c1->block1.key.key, block1.key.key, 128)) != ERROR_SUCCESS) { - srs_error("calc s1 key failed. ret=%d", ret); - return ret; - } - } - srs_verbose("calc s1 key success."); - - char* s1_digest = NULL; - if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) { - srs_error("calc s1 digest failed. ret=%d", ret); - return ret; - } - srs_verbose("calc s1 digest success."); - - srs_assert(s1_digest != NULL); - SrsAutoFree(char, s1_digest, true); - - if (schema == srs_schema0) { - memcpy(block1.digest.digest, s1_digest, 32); - } else { - memcpy(block0.digest.digest, s1_digest, 32); - } - srs_verbose("copy s1 key success."); - - return ret; + int ret = ERROR_SUCCESS; + + if (c1->schema == srs_schema_invalid) { + ret = ERROR_RTMP_CH_SCHEMA; + srs_error("create s1 failed. invalid schema=%d, ret=%d", c1->schema, ret); + return ret; + } + + destroy_blocks(); + schema = c1->schema; + + time = ::time(NULL); + version = 0x01000504; // server s1 version + + if (schema == srs_schema0) { + srs_key_block_init(&block0.key); + srs_digest_block_init(&block1.digest); + } else { + srs_digest_block_init(&block0.digest); + srs_key_block_init(&block1.key); + } + + if (schema == srs_schema0) { + if ((ret = openssl_generate_key(c1->block0.key.key, block0.key.key, 128)) != ERROR_SUCCESS) { + srs_error("calc s1 key failed. ret=%d", ret); + return ret; + } + } else { + if ((ret = openssl_generate_key(c1->block1.key.key, block1.key.key, 128)) != ERROR_SUCCESS) { + srs_error("calc s1 key failed. ret=%d", ret); + return ret; + } + } + srs_verbose("calc s1 key success."); + + char* s1_digest = NULL; + if ((ret = calc_s1_digest(s1_digest)) != ERROR_SUCCESS) { + srs_error("calc s1 digest failed. ret=%d", ret); + return ret; + } + srs_verbose("calc s1 digest success."); + + srs_assert(s1_digest != NULL); + SrsAutoFree(char, s1_digest, true); + + if (schema == srs_schema0) { + memcpy(block1.digest.digest, s1_digest, 32); + } else { + memcpy(block0.digest.digest, s1_digest, 32); + } + srs_verbose("copy s1 key success."); + + return ret; } int c1s1::calc_s1_digest(char*& digest) { - int ret = ERROR_SUCCESS; - - srs_assert(schema == srs_schema0 || schema == srs_schema1); - - char* c1s1_joined_bytes = NULL; + int ret = ERROR_SUCCESS; + + srs_assert(schema == srs_schema0 || schema == srs_schema1); + + char* c1s1_joined_bytes = NULL; - if (schema == srs_schema0) { - c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); - } else { - c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key); - } - - srs_assert(c1s1_joined_bytes != NULL); - SrsAutoFree(char, c1s1_joined_bytes, true); - - digest = new char[OpensslHashSize]; - if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFMSKey, 36, digest)) != ERROR_SUCCESS) { - srs_error("calc digest for s1 failed. ret=%d", ret); - return ret; - } - srs_verbose("digest calculated for s1"); - - return ret; + if (schema == srs_schema0) { + c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); + } else { + c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key); + } + + srs_assert(c1s1_joined_bytes != NULL); + SrsAutoFree(char, c1s1_joined_bytes, true); + + digest = new char[OpensslHashSize]; + if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFMSKey, 36, digest)) != ERROR_SUCCESS) { + srs_error("calc digest for s1 failed. ret=%d", ret); + return ret; + } + srs_verbose("digest calculated for s1"); + + return ret; } int c1s1::calc_c1_digest(char*& digest) { - int ret = ERROR_SUCCESS; - - srs_assert(schema == srs_schema0 || schema == srs_schema1); - - char* c1s1_joined_bytes = NULL; + int ret = ERROR_SUCCESS; + + srs_assert(schema == srs_schema0 || schema == srs_schema1); + + char* c1s1_joined_bytes = NULL; - if (schema == srs_schema0) { - c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); - } else { - c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key); - } - - srs_assert(c1s1_joined_bytes != NULL); - SrsAutoFree(char, c1s1_joined_bytes, true); - - digest = new char[OpensslHashSize]; - if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFPKey, 30, digest)) != ERROR_SUCCESS) { - srs_error("calc digest for c1 failed. ret=%d", ret); - return ret; - } - srs_verbose("digest calculated for c1"); - - return ret; + if (schema == srs_schema0) { + c1s1_joined_bytes = srs_bytes_join_schema0(time, version, &block0.key, &block1.digest); + } else { + c1s1_joined_bytes = srs_bytes_join_schema1(time, version, &block0.digest, &block1.key); + } + + srs_assert(c1s1_joined_bytes != NULL); + SrsAutoFree(char, c1s1_joined_bytes, true); + + digest = new char[OpensslHashSize]; + if ((ret = openssl_HMACsha256(c1s1_joined_bytes, 1536 - 32, SrsGenuineFPKey, 30, digest)) != ERROR_SUCCESS) { + srs_error("calc digest for c1 failed. ret=%d", ret); + return ret; + } + srs_verbose("digest calculated for c1"); + + return ret; } void c1s1::destroy_blocks() { - if (schema == srs_schema_invalid) { - return; - } - - if (schema == srs_schema0) { - srs_key_block_free(&block0.key); - srs_digest_block_free(&block1.digest); - } else { - srs_digest_block_free(&block0.digest); - srs_key_block_free(&block1.key); - } + if (schema == srs_schema_invalid) { + return; + } + + if (schema == srs_schema0) { + srs_key_block_free(&block0.key); + srs_digest_block_free(&block1.digest); + } else { + srs_digest_block_free(&block0.digest); + srs_key_block_free(&block1.key); + } } #endif @@ -1069,8 +1069,8 @@ SrsSimpleHandshake::~SrsSimpleHandshake() int SrsSimpleHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, SrsComplexHandshake* complex_hs) { - int ret = ERROR_SUCCESS; - + int ret = ERROR_SUCCESS; + ssize_t nsize; char* c0c1 = new char[1537]; @@ -1081,32 +1081,32 @@ int SrsSimpleHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, Srs } srs_verbose("read c0c1 success."); - // plain text required. - if (c0c1[0] != 0x03) { - ret = ERROR_RTMP_PLAIN_REQUIRED; - srs_warn("only support rtmp plain text. ret=%d", ret); - return ret; - } + // plain text required. + if (c0c1[0] != 0x03) { + ret = ERROR_RTMP_PLAIN_REQUIRED; + srs_warn("only support rtmp plain text. ret=%d", ret); + return ret; + } srs_verbose("check c0 success, required plain text."); // try complex handshake if (complex_hs) { - ret = complex_hs->handshake_with_client(skt, c0c1 + 1); - if (ret == ERROR_SUCCESS) { - srs_trace("complex handshake success."); - return ret; - } - if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { - srs_error("complex handshake failed. ret=%d", ret); - return ret; - } - srs_info("rollback complex to simple handshake. ret=%d", ret); + ret = complex_hs->handshake_with_client(skt, c0c1 + 1); + if (ret == ERROR_SUCCESS) { + srs_trace("complex handshake success."); + return ret; + } + if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { + srs_error("complex handshake failed. ret=%d", ret); + return ret; + } + srs_info("rollback complex to simple handshake. ret=%d", ret); } - - char* s0s1s2 = new char[3073]; - srs_random_generate(s0s1s2, 3073); + + char* s0s1s2 = new char[3073]; + srs_random_generate(s0s1s2, 3073); SrsAutoFree(char, s0s1s2, true); - // plain text required. + // plain text required. s0s1s2[0] = 0x03; if ((ret = skt->write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { srs_warn("simple handshake send s0s1s2 failed. ret=%d", ret); @@ -1124,44 +1124,44 @@ int SrsSimpleHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, Srs srs_trace("simple handshake success."); - return ret; + return ret; } int SrsSimpleHandshake::handshake_with_server(ISrsProtocolReaderWriter* skt, SrsComplexHandshake* complex_hs) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; // try complex handshake if (complex_hs) { - ret = complex_hs->handshake_with_server(skt); - if (ret == ERROR_SUCCESS) { - srs_trace("complex handshake success."); - return ret; - } - if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { - srs_error("complex handshake failed. ret=%d", ret); - return ret; - } - srs_info("rollback complex to simple handshake. ret=%d", ret); + ret = complex_hs->handshake_with_server(skt); + if (ret == ERROR_SUCCESS) { + srs_trace("complex handshake success."); + return ret; + } + if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { + srs_error("complex handshake failed. ret=%d", ret); + return ret; + } + srs_info("rollback complex to simple handshake. ret=%d", ret); } - - // simple handshake + + // simple handshake ssize_t nsize; char* c0c1 = new char[1537]; SrsAutoFree(char, c0c1, true); - srs_random_generate(c0c1, 1537); - // plain text required. - c0c1[0] = 0x03; - + srs_random_generate(c0c1, 1537); + // plain text required. + c0c1[0] = 0x03; + if ((ret = skt->write(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { srs_warn("write c0c1 failed. ret=%d", ret); return ret; } srs_verbose("write c0c1 success."); - - char* s0s1s2 = new char[3073]; + + char* s0s1s2 = new char[3073]; SrsAutoFree(char, s0s1s2, true); if ((ret = skt->read_fully(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { srs_warn("simple handshake recv s0s1s2 failed. ret=%d", ret); @@ -1169,7 +1169,7 @@ int SrsSimpleHandshake::handshake_with_server(ISrsProtocolReaderWriter* skt, Srs } srs_verbose("simple handshake recv s0s1s2 success."); - // plain text required. + // plain text required. if (s0s1s2[0] != 0x03) { ret = ERROR_RTMP_HANDSHAKE; srs_warn("handshake failed, plain text required. ret=%d", ret); @@ -1178,7 +1178,7 @@ int SrsSimpleHandshake::handshake_with_server(ISrsProtocolReaderWriter* skt, Srs char* c2 = new char[1536]; SrsAutoFree(char, c2, true); - srs_random_generate(c2, 1536); + srs_random_generate(c2, 1536); if ((ret = skt->write(c2, 1536, &nsize)) != ERROR_SUCCESS) { srs_warn("simple handshake write c2 failed. ret=%d", ret); return ret; @@ -1187,7 +1187,7 @@ int SrsSimpleHandshake::handshake_with_server(ISrsProtocolReaderWriter* skt, Srs srs_trace("simple handshake success."); - return ret; + return ret; } SrsComplexHandshake::SrsComplexHandshake() @@ -1201,67 +1201,67 @@ SrsComplexHandshake::~SrsComplexHandshake() #ifndef SRS_SSL int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* /*skt*/, char* /*_c1*/) { - return ERROR_RTMP_TRY_SIMPLE_HS; + return ERROR_RTMP_TRY_SIMPLE_HS; } #else int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, char* _c1) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; ssize_t nsize; - - static bool _random_initialized = false; - if (!_random_initialized) { - srand(0); - _random_initialized = true; - srs_trace("srand initialized the random."); - } - - // decode c1 - c1s1 c1; - // try schema0. - if ((ret = c1.c1_parse(_c1, srs_schema0)) != ERROR_SUCCESS) { - srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); - return ret; - } - // try schema1 - bool is_valid = false; - if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { - if ((ret = c1.c1_parse(_c1, srs_schema1)) != ERROR_SUCCESS) { - srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); - return ret; - } - - if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { - ret = ERROR_RTMP_TRY_SIMPLE_HS; - srs_info("all schema valid failed, try simple handshake. ret=%d", ret); - return ret; - } - } - srs_verbose("decode c1 success."); - - // encode s1 - c1s1 s1; - if ((ret = s1.s1_create(&c1)) != ERROR_SUCCESS) { - srs_error("create s1 from c1 failed. ret=%d", ret); - return ret; - } - srs_verbose("create s1 from c1 success."); - - c2s2 s2; - if ((ret = s2.s2_create(&c1)) != ERROR_SUCCESS) { - srs_error("create s2 from c1 failed. ret=%d", ret); - return ret; - } - srs_verbose("create s2 from c1 success."); - - // sendout s0s1s2 - char* s0s1s2 = new char[3073]; + + static bool _random_initialized = false; + if (!_random_initialized) { + srand(0); + _random_initialized = true; + srs_trace("srand initialized the random."); + } + + // decode c1 + c1s1 c1; + // try schema0. + if ((ret = c1.c1_parse(_c1, srs_schema0)) != ERROR_SUCCESS) { + srs_error("parse c1 schema%d error. ret=%d", srs_schema0, ret); + return ret; + } + // try schema1 + bool is_valid = false; + if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { + if ((ret = c1.c1_parse(_c1, srs_schema1)) != ERROR_SUCCESS) { + srs_error("parse c1 schema%d error. ret=%d", srs_schema1, ret); + return ret; + } + + if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) { + ret = ERROR_RTMP_TRY_SIMPLE_HS; + srs_info("all schema valid failed, try simple handshake. ret=%d", ret); + return ret; + } + } + srs_verbose("decode c1 success."); + + // encode s1 + c1s1 s1; + if ((ret = s1.s1_create(&c1)) != ERROR_SUCCESS) { + srs_error("create s1 from c1 failed. ret=%d", ret); + return ret; + } + srs_verbose("create s1 from c1 success."); + + c2s2 s2; + if ((ret = s2.s2_create(&c1)) != ERROR_SUCCESS) { + srs_error("create s2 from c1 failed. ret=%d", ret); + return ret; + } + srs_verbose("create s2 from c1 success."); + + // sendout s0s1s2 + char* s0s1s2 = new char[3073]; SrsAutoFree(char, s0s1s2, true); - // plain text required. - s0s1s2[0] = 0x03; - s1.dump(s0s1s2 + 1); - s2.dump(s0s1s2 + 1537); + // plain text required. + s0s1s2[0] = 0x03; + s1.dump(s0s1s2 + 1); + s2.dump(s0s1s2 + 1537); if ((ret = skt->write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { srs_warn("complex handshake send s0s1s2 failed. ret=%d", ret); return ret; @@ -1276,25 +1276,25 @@ int SrsComplexHandshake::handshake_with_client(ISrsProtocolReaderWriter* skt, ch return ret; } srs_verbose("complex handshake read c2 success."); - - return ret; + + return ret; } #endif #ifndef SRS_SSL int SrsComplexHandshake::handshake_with_server(ISrsProtocolReaderWriter* /*skt*/) { - return ERROR_RTMP_TRY_SIMPLE_HS; + return ERROR_RTMP_TRY_SIMPLE_HS; } #else int SrsComplexHandshake::handshake_with_server(ISrsProtocolReaderWriter* /*skt*/) { - int ret = ERROR_SUCCESS; - - // TODO: implements complex handshake. - ret = ERROR_RTMP_TRY_SIMPLE_HS; - - return ret; + int ret = ERROR_SUCCESS; + + // TODO: implements complex handshake. + ret = ERROR_RTMP_TRY_SIMPLE_HS; + + return ret; } #endif diff --git a/trunk/src/rtmp/srs_protocol_handshake.hpp b/trunk/src/rtmp/srs_protocol_handshake.hpp index a6d22a20c..a9bd2c9b5 100644 --- a/trunk/src/rtmp/srs_protocol_handshake.hpp +++ b/trunk/src/rtmp/srs_protocol_handshake.hpp @@ -39,17 +39,17 @@ class SrsComplexHandshake; class SrsSimpleHandshake { public: - SrsSimpleHandshake(); - virtual ~SrsSimpleHandshake(); + SrsSimpleHandshake(); + virtual ~SrsSimpleHandshake(); public: - /** - * simple handshake. - * @param complex_hs, try complex handshake first, - * if NULL, use simple handshake. - * if failed, rollback to simple handshake. - */ - virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); - virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); + /** + * simple handshake. + * @param complex_hs, try complex handshake first, + * if NULL, use simple handshake. + * if failed, rollback to simple handshake. + */ + virtual int handshake_with_client(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); + virtual int handshake_with_server(ISrsProtocolReaderWriter* io, SrsComplexHandshake* complex_hs); }; /** @@ -60,20 +60,20 @@ public: class SrsComplexHandshake { public: - SrsComplexHandshake(); - virtual ~SrsComplexHandshake(); + SrsComplexHandshake(); + virtual ~SrsComplexHandshake(); public: - /** - * complex hanshake. - * @_c1, size of c1 must be 1536. - * @remark, user must free the c1. - * @return user must: - * continue connect app if success, - * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, - * otherwise, disconnect - */ - virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1); - virtual int handshake_with_server(ISrsProtocolReaderWriter* io); + /** + * complex hanshake. + * @_c1, size of c1 must be 1536. + * @remark, user must free the c1. + * @return user must: + * continue connect app if success, + * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, + * otherwise, disconnect + */ + virtual int handshake_with_client(ISrsProtocolReaderWriter* io, char* _c1); + virtual int handshake_with_server(ISrsProtocolReaderWriter* io); }; #endif \ No newline at end of file diff --git a/trunk/src/rtmp/srs_protocol_io.hpp b/trunk/src/rtmp/srs_protocol_io.hpp index 2787e7cba..2e9fe1464 100644 --- a/trunk/src/rtmp/srs_protocol_io.hpp +++ b/trunk/src/rtmp/srs_protocol_io.hpp @@ -40,14 +40,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class ISrsProtocolReader : public ISrsBufferReader { public: - ISrsProtocolReader(); - virtual ~ISrsProtocolReader(); + ISrsProtocolReader(); + virtual ~ISrsProtocolReader(); // for protocol public: - virtual void set_recv_timeout(int64_t timeout_us) = 0; - virtual int64_t get_recv_timeout() = 0; - virtual int64_t get_recv_bytes() = 0; - virtual int get_recv_kbps() = 0; + virtual void set_recv_timeout(int64_t timeout_us) = 0; + virtual int64_t get_recv_timeout() = 0; + virtual int64_t get_recv_bytes() = 0; + virtual int get_recv_kbps() = 0; }; /** @@ -56,28 +56,28 @@ public: class ISrsProtocolWriter { public: - ISrsProtocolWriter(); - virtual ~ISrsProtocolWriter(); + ISrsProtocolWriter(); + virtual ~ISrsProtocolWriter(); // for protocol public: - virtual void set_send_timeout(int64_t timeout_us) = 0; - virtual int64_t get_send_timeout() = 0; - virtual int64_t get_send_bytes() = 0; - virtual int get_send_kbps() = 0; + virtual void set_send_timeout(int64_t timeout_us) = 0; + virtual int64_t get_send_timeout() = 0; + virtual int64_t get_send_bytes() = 0; + virtual int get_send_kbps() = 0; virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite) = 0; }; class ISrsProtocolReaderWriter : public ISrsProtocolReader, public ISrsProtocolWriter { public: - ISrsProtocolReaderWriter(); - virtual ~ISrsProtocolReaderWriter(); + ISrsProtocolReaderWriter(); + virtual ~ISrsProtocolReaderWriter(); // for protocol public: - /** - * whether the specified timeout_us is never timeout. - */ - virtual bool is_never_timeout(int64_t timeout_us) = 0; + /** + * whether the specified timeout_us is never timeout. + */ + virtual bool is_never_timeout(int64_t timeout_us) = 0; // for handshake. public: virtual int read_fully(const void* buf, size_t size, ssize_t* nread) = 0; diff --git a/trunk/src/rtmp/srs_protocol_rtmp.cpp b/trunk/src/rtmp/srs_protocol_rtmp.cpp index 7a4d7e0dc..3d199708a 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.cpp @@ -37,43 +37,43 @@ using namespace std; /** * the signature for packets to client. */ -#define RTMP_SIG_FMS_VER "3,5,3,888" -#define RTMP_SIG_AMF0_VER 0 -#define RTMP_SIG_CLIENT_ID "ASAICiss" +#define RTMP_SIG_FMS_VER "3,5,3,888" +#define RTMP_SIG_AMF0_VER 0 +#define RTMP_SIG_CLIENT_ID "ASAICiss" /** * onStatus consts. */ -#define StatusLevel "level" -#define StatusCode "code" -#define StatusDescription "description" -#define StatusDetails "details" -#define StatusClientId "clientid" +#define StatusLevel "level" +#define StatusCode "code" +#define StatusDescription "description" +#define StatusDetails "details" +#define StatusClientId "clientid" // status value -#define StatusLevelStatus "status" +#define StatusLevelStatus "status" // status error #define StatusLevelError "error" // code value -#define StatusCodeConnectSuccess "NetConnection.Connect.Success" -#define StatusCodeConnectRejected "NetConnection.Connect.Rejected" -#define StatusCodeStreamReset "NetStream.Play.Reset" -#define StatusCodeStreamStart "NetStream.Play.Start" -#define StatusCodeStreamPause "NetStream.Pause.Notify" -#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" -#define StatusCodePublishStart "NetStream.Publish.Start" -#define StatusCodeDataStart "NetStream.Data.Start" -#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" +#define StatusCodeConnectSuccess "NetConnection.Connect.Success" +#define StatusCodeConnectRejected "NetConnection.Connect.Rejected" +#define StatusCodeStreamReset "NetStream.Play.Reset" +#define StatusCodeStreamStart "NetStream.Play.Start" +#define StatusCodeStreamPause "NetStream.Pause.Notify" +#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" +#define StatusCodePublishStart "NetStream.Publish.Start" +#define StatusCodeDataStart "NetStream.Data.Start" +#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" // FMLE -#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" -#define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" +#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" +#define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" // default stream id for response the createStream request. -#define SRS_DEFAULT_SID 1 +#define SRS_DEFAULT_SID 1 SrsRequest::SrsRequest() { - objectEncoding = RTMP_SIG_AMF0_VER; + objectEncoding = RTMP_SIG_AMF0_VER; } SrsRequest::~SrsRequest() @@ -82,94 +82,94 @@ SrsRequest::~SrsRequest() SrsRequest* SrsRequest::copy() { - SrsRequest* cp = new SrsRequest(); - - cp->app = app; - cp->objectEncoding = objectEncoding; - cp->pageUrl = pageUrl; - cp->port = port; - cp->schema = schema; - cp->stream = stream; - cp->swfUrl = swfUrl; - cp->tcUrl = tcUrl; - cp->vhost = vhost; - - return cp; + SrsRequest* cp = new SrsRequest(); + + cp->app = app; + cp->objectEncoding = objectEncoding; + cp->pageUrl = pageUrl; + cp->port = port; + cp->schema = schema; + cp->stream = stream; + cp->swfUrl = swfUrl; + cp->tcUrl = tcUrl; + cp->vhost = vhost; + + return cp; } int SrsRequest::discovery_app() { - int ret = ERROR_SUCCESS; - - size_t pos = std::string::npos; - std::string url = tcUrl; - - if ((pos = url.find("://")) != std::string::npos) { - schema = url.substr(0, pos); - url = url.substr(schema.length() + 3); - srs_verbose("discovery schema=%s", schema.c_str()); - } - - if ((pos = url.find("/")) != std::string::npos) { - vhost = url.substr(0, pos); - url = url.substr(vhost.length() + 1); - srs_verbose("discovery vhost=%s", vhost.c_str()); - } + int ret = ERROR_SUCCESS; + + size_t pos = std::string::npos; + std::string url = tcUrl; + + if ((pos = url.find("://")) != std::string::npos) { + schema = url.substr(0, pos); + url = url.substr(schema.length() + 3); + srs_verbose("discovery schema=%s", schema.c_str()); + } + + if ((pos = url.find("/")) != std::string::npos) { + vhost = url.substr(0, pos); + url = url.substr(vhost.length() + 1); + srs_verbose("discovery vhost=%s", vhost.c_str()); + } - port = RTMP_DEFAULT_PORT; - if ((pos = vhost.find(":")) != std::string::npos) { - port = vhost.substr(pos + 1); - vhost = vhost.substr(0, pos); - srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); - } - - app = url; - srs_vhost_resolve(vhost, app); - strip(); - - return ret; + port = RTMP_DEFAULT_PORT; + if ((pos = vhost.find(":")) != std::string::npos) { + port = vhost.substr(pos + 1); + vhost = vhost.substr(0, pos); + srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); + } + + app = url; + srs_vhost_resolve(vhost, app); + strip(); + + return ret; } string SrsRequest::get_stream_url() { - std::string url = ""; - - url += vhost; - url += "/"; - url += app; - url += "/"; - url += stream; + std::string url = ""; + + url += vhost; + url += "/"; + url += app; + url += "/"; + url += stream; - return url; + return url; } void SrsRequest::strip() { - trim(vhost, "/ \n\r\t"); - trim(app, "/ \n\r\t"); - trim(stream, "/ \n\r\t"); + trim(vhost, "/ \n\r\t"); + trim(app, "/ \n\r\t"); + trim(stream, "/ \n\r\t"); } string& SrsRequest::trim(string& str, string chs) { - for (int i = 0; i < (int)chs.length(); i++) { - char ch = chs.at(i); - - for (std::string::iterator it = str.begin(); it != str.end();) { - if (ch == *it) { - it = str.erase(it); - } else { - ++it; - } - } - } - - return str; + for (int i = 0; i < (int)chs.length(); i++) { + char ch = chs.at(i); + + for (std::string::iterator it = str.begin(); it != str.end();) { + if (ch == *it) { + it = str.erase(it); + } else { + ++it; + } + } + } + + return str; } SrsResponse::SrsResponse() { - stream_id = SRS_DEFAULT_SID; + stream_id = SRS_DEFAULT_SID; } SrsResponse::~SrsResponse() @@ -178,69 +178,69 @@ SrsResponse::~SrsResponse() string srs_client_type_string(SrsClientType type) { - switch (type) { - case SrsClientPlay: return "Play"; - case SrsClientFlashPublish: return "FlashPublish"; - case SrsClientFMLEPublish: return "FMLEPublish"; - default: return "Unknown"; - } - return "Unknown"; + switch (type) { + case SrsClientPlay: return "Play"; + case SrsClientFlashPublish: return "FlashPublish"; + case SrsClientFMLEPublish: return "FMLEPublish"; + default: return "Unknown"; + } + return "Unknown"; } SrsRtmpClient::SrsRtmpClient(ISrsProtocolReaderWriter* skt) { - io = skt; - protocol = new SrsProtocol(skt); + io = skt; + protocol = new SrsProtocol(skt); } SrsRtmpClient::~SrsRtmpClient() { - srs_freep(protocol); + srs_freep(protocol); } void SrsRtmpClient::set_recv_timeout(int64_t timeout_us) { - protocol->set_recv_timeout(timeout_us); + protocol->set_recv_timeout(timeout_us); } void SrsRtmpClient::set_send_timeout(int64_t timeout_us) { - protocol->set_send_timeout(timeout_us); + protocol->set_send_timeout(timeout_us); } int64_t SrsRtmpClient::get_recv_bytes() { - return protocol->get_recv_bytes(); + return protocol->get_recv_bytes(); } int64_t SrsRtmpClient::get_send_bytes() { - return protocol->get_send_bytes(); + return protocol->get_send_bytes(); } int SrsRtmpClient::get_recv_kbps() { - return protocol->get_recv_kbps(); + return protocol->get_recv_kbps(); } int SrsRtmpClient::get_send_kbps() { - return protocol->get_send_kbps(); + return protocol->get_send_kbps(); } int SrsRtmpClient::recv_message(SrsCommonMessage** pmsg) { - return protocol->recv_message(pmsg); + return protocol->recv_message(pmsg); } int SrsRtmpClient::send_message(ISrsMessage* msg) { - return protocol->send_message(msg); + return protocol->send_message(msg); } int SrsRtmpClient::handshake() { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; SrsComplexHandshake complex_hs; SrsSimpleHandshake simple_hs; @@ -253,7 +253,7 @@ int SrsRtmpClient::handshake() int SrsRtmpClient::simple_handshake() { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; SrsSimpleHandshake simple_hs; if ((ret = simple_hs.handshake_with_server(io, NULL)) != ERROR_SUCCESS) { @@ -265,343 +265,343 @@ int SrsRtmpClient::simple_handshake() int SrsRtmpClient::complex_handshake() { - // TODO: FIXME: only use complex handshake. + // TODO: FIXME: only use complex handshake. return handshake(); } int SrsRtmpClient::connect_app(string app, string tc_url) { - int ret = ERROR_SUCCESS; - - // Connect(vhost, app) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); - msg->set_packet(pkt, 0); - - pkt->command_object = SrsAmf0Any::object(); - pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); - pkt->command_object->set("swfUrl", SrsAmf0Any::str()); - pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); - pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); - pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); - pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); - pkt->command_object->set("videoCodecs", SrsAmf0Any::number(252)); - pkt->command_object->set("videoFunction", SrsAmf0Any::number(1)); - pkt->command_object->set("pageUrl", SrsAmf0Any::str()); - pkt->command_object->set("objectEncoding", SrsAmf0Any::number(0)); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } - - // Set Window Acknowledgement size(2500000) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); - - pkt->ackowledgement_window_size = 2500000; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } - - // expect connect _result - SrsCommonMessage* msg = NULL; - SrsConnectAppResPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect connect app response message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get connect app response message"); - + int ret = ERROR_SUCCESS; + + // Connect(vhost, app) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); + msg->set_packet(pkt, 0); + + pkt->command_object = SrsAmf0Any::object(); + pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); + pkt->command_object->set("swfUrl", SrsAmf0Any::str()); + pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); + pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); + pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); + pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); + pkt->command_object->set("videoCodecs", SrsAmf0Any::number(252)); + pkt->command_object->set("videoFunction", SrsAmf0Any::number(1)); + pkt->command_object->set("pageUrl", SrsAmf0Any::str()); + pkt->command_object->set("objectEncoding", SrsAmf0Any::number(0)); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } + + // Set Window Acknowledgement size(2500000) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); + + pkt->ackowledgement_window_size = 2500000; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } + + // expect connect _result + SrsCommonMessage* msg = NULL; + SrsConnectAppResPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect connect app response message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get connect app response message"); + return ret; } int SrsRtmpClient::create_stream(int& stream_id) { - int ret = ERROR_SUCCESS; - - // CreateStream - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } + int ret = ERROR_SUCCESS; + + // CreateStream + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } - // CreateStream _result. - if (true) { - SrsCommonMessage* msg = NULL; - SrsCreateStreamResPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect create stream response message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get create stream response message"); + // CreateStream _result. + if (true) { + SrsCommonMessage* msg = NULL; + SrsCreateStreamResPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect create stream response message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get create stream response message"); - stream_id = (int)pkt->stream_id; - } - - return ret; + stream_id = (int)pkt->stream_id; + } + + return ret; } int SrsRtmpClient::play(string stream, int stream_id) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - // Play(stream) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsPlayPacket* pkt = new SrsPlayPacket(); - - pkt->stream_name = stream; - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send play stream failed. " - "stream=%s, stream_id=%d, ret=%d", - stream.c_str(), stream_id, ret); - return ret; - } - } - - // SetBufferLength(1000ms) - int buffer_length_ms = 1000; - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCSetBufferLength; - pkt->event_data = stream_id; - pkt->extra_data = buffer_length_ms; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set buffer length failed. " - "stream=%s, stream_id=%d, bufferLength=%d, ret=%d", - stream.c_str(), stream_id, buffer_length_ms, ret); - return ret; - } - } - - // SetChunkSize - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); - - pkt->chunk_size = SRS_CONF_DEFAULT_CHUNK_SIZE; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set chunk size failed. " - "stream=%s, chunk_size=%d, ret=%d", - stream.c_str(), SRS_CONF_DEFAULT_CHUNK_SIZE, ret); - return ret; - } - } - - return ret; + // Play(stream) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsPlayPacket* pkt = new SrsPlayPacket(); + + pkt->stream_name = stream; + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send play stream failed. " + "stream=%s, stream_id=%d, ret=%d", + stream.c_str(), stream_id, ret); + return ret; + } + } + + // SetBufferLength(1000ms) + int buffer_length_ms = 1000; + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCSetBufferLength; + pkt->event_data = stream_id; + pkt->extra_data = buffer_length_ms; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set buffer length failed. " + "stream=%s, stream_id=%d, bufferLength=%d, ret=%d", + stream.c_str(), stream_id, buffer_length_ms, ret); + return ret; + } + } + + // SetChunkSize + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); + + pkt->chunk_size = SRS_CONF_DEFAULT_CHUNK_SIZE; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set chunk size failed. " + "stream=%s, chunk_size=%d, ret=%d", + stream.c_str(), SRS_CONF_DEFAULT_CHUNK_SIZE, ret); + return ret; + } + } + + return ret; } int SrsRtmpClient::publish(string stream, int stream_id) { - int ret = ERROR_SUCCESS; - - // SetChunkSize - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); - - pkt->chunk_size = SRS_CONF_DEFAULT_CHUNK_SIZE; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set chunk size failed. " - "stream=%s, chunk_size=%d, ret=%d", - stream.c_str(), SRS_CONF_DEFAULT_CHUNK_SIZE, ret); - return ret; - } - } + int ret = ERROR_SUCCESS; + + // SetChunkSize + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); + + pkt->chunk_size = SRS_CONF_DEFAULT_CHUNK_SIZE; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set chunk size failed. " + "stream=%s, chunk_size=%d, ret=%d", + stream.c_str(), SRS_CONF_DEFAULT_CHUNK_SIZE, ret); + return ret; + } + } - // publish(stream) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsPublishPacket* pkt = new SrsPublishPacket(); - - pkt->stream_name = stream; - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send publish message failed. " - "stream=%s, stream_id=%d, ret=%d", - stream.c_str(), stream_id, ret); - return ret; - } - } - - return ret; + // publish(stream) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsPublishPacket* pkt = new SrsPublishPacket(); + + pkt->stream_name = stream; + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send publish message failed. " + "stream=%s, stream_id=%d, ret=%d", + stream.c_str(), stream_id, ret); + return ret; + } + } + + return ret; } int SrsRtmpClient::fmle_publish(string stream, int& stream_id) { - stream_id = 0; - - int ret = ERROR_SUCCESS; - - // SrsFMLEStartPacket - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartPacket* pkt = SrsFMLEStartPacket::create_release_stream(stream); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FMLE publish " - "release stream failed. stream=%s, ret=%d", stream.c_str(), ret); - return ret; - } - } - - // FCPublish - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartPacket* pkt = SrsFMLEStartPacket::create_FC_publish(stream); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FMLE publish " - "FCPublish failed. stream=%s, ret=%d", stream.c_str(), ret); - return ret; - } - } - - // CreateStream - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); - - pkt->transaction_id = 4; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FMLE publish " - "createStream failed. stream=%s, ret=%d", stream.c_str(), ret); - return ret; - } - } - - // expect result of CreateStream - if (true) { - SrsCommonMessage* msg = NULL; - SrsCreateStreamResPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect create stream response message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get create stream response message"); + stream_id = 0; + + int ret = ERROR_SUCCESS; + + // SrsFMLEStartPacket + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartPacket* pkt = SrsFMLEStartPacket::create_release_stream(stream); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FMLE publish " + "release stream failed. stream=%s, ret=%d", stream.c_str(), ret); + return ret; + } + } + + // FCPublish + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartPacket* pkt = SrsFMLEStartPacket::create_FC_publish(stream); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FMLE publish " + "FCPublish failed. stream=%s, ret=%d", stream.c_str(), ret); + return ret; + } + } + + // CreateStream + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); + + pkt->transaction_id = 4; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FMLE publish " + "createStream failed. stream=%s, ret=%d", stream.c_str(), ret); + return ret; + } + } + + // expect result of CreateStream + if (true) { + SrsCommonMessage* msg = NULL; + SrsCreateStreamResPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect create stream response message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get create stream response message"); - stream_id = (int)pkt->stream_id; - } + stream_id = (int)pkt->stream_id; + } - // publish(stream) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsPublishPacket* pkt = new SrsPublishPacket(); - - pkt->stream_name = stream; - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FMLE publish publish failed. " - "stream=%s, stream_id=%d, ret=%d", stream.c_str(), stream_id, ret); - return ret; - } - } - - return ret; + // publish(stream) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsPublishPacket* pkt = new SrsPublishPacket(); + + pkt->stream_name = stream; + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FMLE publish publish failed. " + "stream=%s, stream_id=%d, ret=%d", stream.c_str(), stream_id, ret); + return ret; + } + } + + return ret; } SrsRtmpServer::SrsRtmpServer(ISrsProtocolReaderWriter* skt) { - io = skt; - protocol = new SrsProtocol(skt); + io = skt; + protocol = new SrsProtocol(skt); } SrsRtmpServer::~SrsRtmpServer() { - srs_freep(protocol); + srs_freep(protocol); } SrsProtocol* SrsRtmpServer::get_protocol() { - return protocol; + return protocol; } void SrsRtmpServer::set_recv_timeout(int64_t timeout_us) { - protocol->set_recv_timeout(timeout_us); + protocol->set_recv_timeout(timeout_us); } int64_t SrsRtmpServer::get_recv_timeout() { - return protocol->get_recv_timeout(); + return protocol->get_recv_timeout(); } void SrsRtmpServer::set_send_timeout(int64_t timeout_us) { - protocol->set_send_timeout(timeout_us); + protocol->set_send_timeout(timeout_us); } int64_t SrsRtmpServer::get_send_timeout() { - return protocol->get_send_timeout(); + return protocol->get_send_timeout(); } int64_t SrsRtmpServer::get_recv_bytes() { - return protocol->get_recv_bytes(); + return protocol->get_recv_bytes(); } int64_t SrsRtmpServer::get_send_bytes() { - return protocol->get_send_bytes(); + return protocol->get_send_bytes(); } int SrsRtmpServer::get_recv_kbps() { - return protocol->get_recv_kbps(); + return protocol->get_recv_kbps(); } int SrsRtmpServer::get_send_kbps() { - return protocol->get_send_kbps(); + return protocol->get_send_kbps(); } int SrsRtmpServer::recv_message(SrsCommonMessage** pmsg) { - return protocol->recv_message(pmsg); + return protocol->recv_message(pmsg); } int SrsRtmpServer::send_message(ISrsMessage* msg) { - return protocol->send_message(msg); + return protocol->send_message(msg); } int SrsRtmpServer::handshake() { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; SrsComplexHandshake complex_hs; SrsSimpleHandshake simple_hs; @@ -614,125 +614,125 @@ int SrsRtmpServer::handshake() int SrsRtmpServer::connect_app(SrsRequest* req) { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = NULL; - SrsConnectAppPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect connect app message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get connect app message"); - - SrsAmf0Any* prop = NULL; - - if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { - ret = ERROR_RTMP_REQ_CONNECT; - srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); - return ret; - } - req->tcUrl = prop->to_str(); - - if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { - req->pageUrl = prop->to_str(); - } - - if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { - req->swfUrl = prop->to_str(); - } - - if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { - req->objectEncoding = prop->to_number(); - } - - srs_info("get connect app message params success."); - - return req->discovery_app(); + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = NULL; + SrsConnectAppPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect connect app message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get connect app message"); + + SrsAmf0Any* prop = NULL; + + if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { + ret = ERROR_RTMP_REQ_CONNECT; + srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); + return ret; + } + req->tcUrl = prop->to_str(); + + if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { + req->pageUrl = prop->to_str(); + } + + if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { + req->swfUrl = prop->to_str(); + } + + if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { + req->objectEncoding = prop->to_number(); + } + + srs_info("get connect app message params success."); + + return req->discovery_app(); } int SrsRtmpServer::set_window_ack_size(int ack_size) { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); - - pkt->ackowledgement_window_size = ack_size; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send ack size message failed. ret=%d", ret); - return ret; - } - srs_info("send ack size message success. ack_size=%d", ack_size); - - return ret; + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); + + pkt->ackowledgement_window_size = ack_size; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send ack size message failed. ret=%d", ret); + return ret; + } + srs_info("send ack size message success. ack_size=%d", ack_size); + + return ret; } int SrsRtmpServer::set_peer_bandwidth(int bandwidth, int type) { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); - - pkt->bandwidth = bandwidth; - pkt->type = type; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set bandwidth message failed. ret=%d", ret); - return ret; - } - srs_info("send set bandwidth message " - "success. bandwidth=%d, type=%d", bandwidth, type); - - return ret; + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); + + pkt->bandwidth = bandwidth; + pkt->type = type; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set bandwidth message failed. ret=%d", ret); + return ret; + } + srs_info("send set bandwidth message " + "success. bandwidth=%d, type=%d", bandwidth, type); + + return ret; } int SrsRtmpServer::response_connect_app(SrsRequest *req, const char* server_ip) { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); - - pkt->props->set("fmsVer", SrsAmf0Any::str("FMS/"RTMP_SIG_FMS_VER)); - pkt->props->set("capabilities", SrsAmf0Any::number(127)); - pkt->props->set("mode", SrsAmf0Any::number(1)); - - pkt->info->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->info->set(StatusCode, SrsAmf0Any::str(StatusCodeConnectSuccess)); - pkt->info->set(StatusDescription, SrsAmf0Any::str("Connection succeeded")); - pkt->info->set("objectEncoding", SrsAmf0Any::number(req->objectEncoding)); - SrsAmf0EcmaArray* data = SrsAmf0Any::ecma_array(); - pkt->info->set("data", data); - - data->set("version", SrsAmf0Any::str(RTMP_SIG_FMS_VER)); - data->set("srs_sig", SrsAmf0Any::str(RTMP_SIG_SRS_KEY)); - data->set("srs_server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); - data->set("srs_license", SrsAmf0Any::str(RTMP_SIG_SRS_LICENSE)); - data->set("srs_role", SrsAmf0Any::str(RTMP_SIG_SRS_ROLE)); - data->set("srs_url", SrsAmf0Any::str(RTMP_SIG_SRS_URL)); - data->set("srs_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION)); - data->set("srs_site", SrsAmf0Any::str(RTMP_SIG_SRS_WEB)); - data->set("srs_email", SrsAmf0Any::str(RTMP_SIG_SRS_EMAIL)); - data->set("srs_copyright", SrsAmf0Any::str(RTMP_SIG_SRS_COPYRIGHT)); - data->set("srs_primary_authors", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY_AUTHROS)); - + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); + + pkt->props->set("fmsVer", SrsAmf0Any::str("FMS/"RTMP_SIG_FMS_VER)); + pkt->props->set("capabilities", SrsAmf0Any::number(127)); + pkt->props->set("mode", SrsAmf0Any::number(1)); + + pkt->info->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->info->set(StatusCode, SrsAmf0Any::str(StatusCodeConnectSuccess)); + pkt->info->set(StatusDescription, SrsAmf0Any::str("Connection succeeded")); + pkt->info->set("objectEncoding", SrsAmf0Any::number(req->objectEncoding)); + SrsAmf0EcmaArray* data = SrsAmf0Any::ecma_array(); + pkt->info->set("data", data); + + data->set("version", SrsAmf0Any::str(RTMP_SIG_FMS_VER)); + data->set("srs_sig", SrsAmf0Any::str(RTMP_SIG_SRS_KEY)); + data->set("srs_server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); + data->set("srs_license", SrsAmf0Any::str(RTMP_SIG_SRS_LICENSE)); + data->set("srs_role", SrsAmf0Any::str(RTMP_SIG_SRS_ROLE)); + data->set("srs_url", SrsAmf0Any::str(RTMP_SIG_SRS_URL)); + data->set("srs_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION)); + data->set("srs_site", SrsAmf0Any::str(RTMP_SIG_SRS_WEB)); + data->set("srs_email", SrsAmf0Any::str(RTMP_SIG_SRS_EMAIL)); + data->set("srs_copyright", SrsAmf0Any::str(RTMP_SIG_SRS_COPYRIGHT)); + data->set("srs_primary_authors", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY_AUTHROS)); + if (server_ip) { data->set("srs_server_ip", SrsAmf0Any::str(server_ip)); } - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send connect app response message failed. ret=%d", ret); - return ret; - } - srs_info("send connect app response message success."); - + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send connect app response message failed. ret=%d", ret); + return ret; + } + srs_info("send connect app response message success."); + return ret; } @@ -759,551 +759,551 @@ void SrsRtmpServer::response_connect_reject(SrsRequest *req, const char* desc) int SrsRtmpServer::on_bw_done() { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onBWDone message failed. ret=%d", ret); - return ret; - } - srs_info("send onBWDone message success."); - - return ret; + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onBWDone message failed. ret=%d", ret); + return ret; + } + srs_info("send onBWDone message success."); + + return ret; } int SrsRtmpServer::identify_client(int stream_id, SrsClientType& type, string& stream_name) { - type = SrsClientUnknown; - int ret = ERROR_SUCCESS; - - while (true) { - SrsCommonMessage* msg = NULL; - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("recv identify client message failed. ret=%d", ret); - return ret; - } + type = SrsClientUnknown; + int ret = ERROR_SUCCESS; + + while (true) { + SrsCommonMessage* msg = NULL; + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("recv identify client message failed. ret=%d", ret); + return ret; + } - SrsAutoFree(SrsCommonMessage, msg, false); + SrsAutoFree(SrsCommonMessage, msg, false); - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { - srs_trace("identify ignore messages except " - "AMF0/AMF3 command message. type=%#x", msg->header.message_type); - continue; - } - - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { - srs_error("identify decode message failed. ret=%d", ret); - return ret; - } - - SrsPacket* pkt = msg->get_packet(); - if (dynamic_cast(pkt)) { - srs_info("identify client by create stream, play or flash publish."); - return identify_create_stream_client(dynamic_cast(pkt), stream_id, type, stream_name); - } - if (dynamic_cast(pkt)) { - srs_info("identify client by releaseStream, fmle publish."); - return identify_fmle_publish_client(dynamic_cast(pkt), type, stream_name); - } - if (dynamic_cast(pkt)) { - srs_info("level0 identify client by play."); - return identify_play_client(dynamic_cast(pkt), type, stream_name); - } - - srs_trace("ignore AMF0/AMF3 command message."); - } - - return ret; + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { + srs_trace("identify ignore messages except " + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); + continue; + } + + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { + srs_error("identify decode message failed. ret=%d", ret); + return ret; + } + + SrsPacket* pkt = msg->get_packet(); + if (dynamic_cast(pkt)) { + srs_info("identify client by create stream, play or flash publish."); + return identify_create_stream_client(dynamic_cast(pkt), stream_id, type, stream_name); + } + if (dynamic_cast(pkt)) { + srs_info("identify client by releaseStream, fmle publish."); + return identify_fmle_publish_client(dynamic_cast(pkt), type, stream_name); + } + if (dynamic_cast(pkt)) { + srs_info("level0 identify client by play."); + return identify_play_client(dynamic_cast(pkt), type, stream_name); + } + + srs_trace("ignore AMF0/AMF3 command message."); + } + + return ret; } int SrsRtmpServer::set_chunk_size(int chunk_size) { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); - - pkt->chunk_size = chunk_size; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set chunk size message failed. ret=%d", ret); - return ret; - } - srs_info("send set chunk size message success. chunk_size=%d", chunk_size); - - return ret; + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); + + pkt->chunk_size = chunk_size; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set chunk size message failed. ret=%d", ret); + return ret; + } + srs_info("send set chunk size message success. chunk_size=%d", chunk_size); + + return ret; } int SrsRtmpServer::start_play(int stream_id) { - int ret = ERROR_SUCCESS; - - // StreamBegin - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCStreamBegin; - pkt->event_data = stream_id; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); - return ret; - } - srs_info("send PCUC(StreamBegin) message success."); - } - - // onStatus(NetStream.Play.Reset) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamReset)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Playing and resetting stream.")); - pkt->data->set(StatusDetails, SrsAmf0Any::str("stream")); - pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Play.Reset) message success."); - } - - // onStatus(NetStream.Play.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamStart)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Started playing stream.")); - pkt->data->set(StatusDetails, SrsAmf0Any::str("stream")); - pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Play.Reset) message success."); - } - - // |RtmpSampleAccess(false, false) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); - return ret; - } - srs_info("send |RtmpSampleAccess(false, false) message success."); - } - - // onStatus(NetStream.Data.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); - - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeDataStart)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Data.Start) message success."); - } - - srs_info("start play success."); - - return ret; + int ret = ERROR_SUCCESS; + + // StreamBegin + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCStreamBegin; + pkt->event_data = stream_id; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); + return ret; + } + srs_info("send PCUC(StreamBegin) message success."); + } + + // onStatus(NetStream.Play.Reset) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamReset)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Playing and resetting stream.")); + pkt->data->set(StatusDetails, SrsAmf0Any::str("stream")); + pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Play.Reset) message success."); + } + + // onStatus(NetStream.Play.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamStart)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Started playing stream.")); + pkt->data->set(StatusDetails, SrsAmf0Any::str("stream")); + pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Play.Reset) message success."); + } + + // |RtmpSampleAccess(false, false) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); + return ret; + } + srs_info("send |RtmpSampleAccess(false, false) message success."); + } + + // onStatus(NetStream.Data.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); + + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeDataStart)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Data.Start) message success."); + } + + srs_info("start play success."); + + return ret; } int SrsRtmpServer::on_play_client_pause(int stream_id, bool is_pause) { - int ret = ERROR_SUCCESS; - - if (is_pause) { - // onStatus(NetStream.Pause.Notify) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamPause)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Paused stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Pause.Notify) message success."); - } - // StreamEOF - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCStreamEOF; - pkt->event_data = stream_id; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret); - return ret; - } - srs_info("send PCUC(StreamEOF) message success."); - } - } else { - // onStatus(NetStream.Unpause.Notify) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamUnpause)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Unpaused stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Unpause.Notify) message success."); - } - // StreanBegin - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCStreamBegin; - pkt->event_data = stream_id; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret); - return ret; - } - srs_info("send PCUC(StreanBegin) message success."); - } - } - - return ret; + int ret = ERROR_SUCCESS; + + if (is_pause) { + // onStatus(NetStream.Pause.Notify) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamPause)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Paused stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Pause.Notify) message success."); + } + // StreamEOF + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCStreamEOF; + pkt->event_data = stream_id; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret); + return ret; + } + srs_info("send PCUC(StreamEOF) message success."); + } + } else { + // onStatus(NetStream.Unpause.Notify) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeStreamUnpause)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Unpaused stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Unpause.Notify) message success."); + } + // StreanBegin + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCStreamBegin; + pkt->event_data = stream_id; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret); + return ret; + } + srs_info("send PCUC(StreanBegin) message success."); + } + } + + return ret; } int SrsRtmpServer::start_fmle_publish(int stream_id) { - int ret = ERROR_SUCCESS; - - // FCPublish - double fc_publish_tid = 0; - if (true) { - SrsCommonMessage* msg = NULL; - SrsFMLEStartPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("recv FCPublish message failed. ret=%d", ret); - return ret; - } - srs_info("recv FCPublish request message success."); - - SrsAutoFree(SrsCommonMessage, msg, false); - fc_publish_tid = pkt->transaction_id; - } - // FCPublish response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FCPublish response message failed. ret=%d", ret); - return ret; - } - srs_info("send FCPublish response message success."); - } - - // createStream - double create_stream_tid = 0; - if (true) { - SrsCommonMessage* msg = NULL; - SrsCreateStreamPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("recv createStream message failed. ret=%d", ret); - return ret; - } - srs_info("recv createStream request message success."); - - SrsAutoFree(SrsCommonMessage, msg, false); - create_stream_tid = pkt->transaction_id; - } - // createStream response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send createStream response message failed. ret=%d", ret); - return ret; - } - srs_info("send createStream response message success."); - } - - // publish - if (true) { - SrsCommonMessage* msg = NULL; - SrsPublishPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("recv publish message failed. ret=%d", ret); - return ret; - } - srs_info("recv publish request message success."); - - SrsAutoFree(SrsCommonMessage, msg, false); - } - // publish response onFCPublish(NetStream.Publish.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onFCPublish(NetStream.Publish.Start) message success."); - } - // publish response onStatus(NetStream.Publish.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); - pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Publish.Start) message success."); - } - - srs_info("FMLE publish success."); - - return ret; + int ret = ERROR_SUCCESS; + + // FCPublish + double fc_publish_tid = 0; + if (true) { + SrsCommonMessage* msg = NULL; + SrsFMLEStartPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv FCPublish message failed. ret=%d", ret); + return ret; + } + srs_info("recv FCPublish request message success."); + + SrsAutoFree(SrsCommonMessage, msg, false); + fc_publish_tid = pkt->transaction_id; + } + // FCPublish response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FCPublish response message failed. ret=%d", ret); + return ret; + } + srs_info("send FCPublish response message success."); + } + + // createStream + double create_stream_tid = 0; + if (true) { + SrsCommonMessage* msg = NULL; + SrsCreateStreamPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv createStream message failed. ret=%d", ret); + return ret; + } + srs_info("recv createStream request message success."); + + SrsAutoFree(SrsCommonMessage, msg, false); + create_stream_tid = pkt->transaction_id; + } + // createStream response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send createStream response message failed. ret=%d", ret); + return ret; + } + srs_info("send createStream response message success."); + } + + // publish + if (true) { + SrsCommonMessage* msg = NULL; + SrsPublishPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv publish message failed. ret=%d", ret); + return ret; + } + srs_info("recv publish request message success."); + + SrsAutoFree(SrsCommonMessage, msg, false); + } + // publish response onFCPublish(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onFCPublish(NetStream.Publish.Start) message success."); + } + // publish response onStatus(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); + pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Publish.Start) message success."); + } + + srs_info("FMLE publish success."); + + return ret; } int SrsRtmpServer::fmle_unpublish(int stream_id, double unpublish_tid) { - int ret = ERROR_SUCCESS; - - // publish response onFCUnpublish(NetStream.unpublish.Success) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH; - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeUnpublishSuccess)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Stop publishing stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onFCUnpublish(NetStream.unpublish.Success) message failed. ret=%d", ret); - return ret; - } - srs_info("send onFCUnpublish(NetStream.unpublish.Success) message success."); - } - // FCUnpublish response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(unpublish_tid); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FCUnpublish response message failed. ret=%d", ret); - return ret; - } - srs_info("send FCUnpublish response message success."); - } - // publish response onStatus(NetStream.Unpublish.Success) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeUnpublishSuccess)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Stream is now unpublished")); - pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Unpublish.Success) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Unpublish.Success) message success."); - } - - srs_info("FMLE unpublish success."); - - return ret; + int ret = ERROR_SUCCESS; + + // publish response onFCUnpublish(NetStream.unpublish.Success) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH; + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeUnpublishSuccess)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Stop publishing stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onFCUnpublish(NetStream.unpublish.Success) message failed. ret=%d", ret); + return ret; + } + srs_info("send onFCUnpublish(NetStream.unpublish.Success) message success."); + } + // FCUnpublish response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(unpublish_tid); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FCUnpublish response message failed. ret=%d", ret); + return ret; + } + srs_info("send FCUnpublish response message success."); + } + // publish response onStatus(NetStream.Unpublish.Success) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodeUnpublishSuccess)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Stream is now unpublished")); + pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Unpublish.Success) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Unpublish.Success) message success."); + } + + srs_info("FMLE unpublish success."); + + return ret; } int SrsRtmpServer::start_flash_publish(int stream_id) { - int ret = ERROR_SUCCESS; - - // publish response onStatus(NetStream.Publish.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); - pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); - pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); - pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Publish.Start) message success."); - } - - srs_info("flash publish success."); - - return ret; + int ret = ERROR_SUCCESS; + + // publish response onStatus(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, SrsAmf0Any::str(StatusLevelStatus)); + pkt->data->set(StatusCode, SrsAmf0Any::str(StatusCodePublishStart)); + pkt->data->set(StatusDescription, SrsAmf0Any::str("Started publishing stream.")); + pkt->data->set(StatusClientId, SrsAmf0Any::str(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Publish.Start) message success."); + } + + srs_info("flash publish success."); + + return ret; } int SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, string& stream_name) { - int ret = ERROR_SUCCESS; - - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send createStream response message failed. ret=%d", ret); - return ret; - } - srs_info("send createStream response message success."); - } - - while (true) { - SrsCommonMessage* msg = NULL; - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("recv identify client message failed. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send createStream response message failed. ret=%d", ret); + return ret; + } + srs_info("send createStream response message success."); + } + + while (true) { + SrsCommonMessage* msg = NULL; + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("recv identify client message failed. ret=%d", ret); + return ret; + } - SrsAutoFree(SrsCommonMessage, msg, false); + SrsAutoFree(SrsCommonMessage, msg, false); - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { - srs_trace("identify ignore messages except " - "AMF0/AMF3 command message. type=%#x", msg->header.message_type); - continue; - } - - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { - srs_error("identify decode message failed. ret=%d", ret); - return ret; - } - - SrsPacket* pkt = msg->get_packet(); - if (dynamic_cast(pkt)) { - srs_info("level1 identify client by play."); - return identify_play_client(dynamic_cast(pkt), type, stream_name); - } - if (dynamic_cast(pkt)) { - srs_info("identify client by publish, falsh publish."); - return identify_flash_publish_client(dynamic_cast(pkt), type, stream_name); - } - - srs_trace("ignore AMF0/AMF3 command message."); - } - - return ret; + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { + srs_trace("identify ignore messages except " + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); + continue; + } + + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { + srs_error("identify decode message failed. ret=%d", ret); + return ret; + } + + SrsPacket* pkt = msg->get_packet(); + if (dynamic_cast(pkt)) { + srs_info("level1 identify client by play."); + return identify_play_client(dynamic_cast(pkt), type, stream_name); + } + if (dynamic_cast(pkt)) { + srs_info("identify client by publish, falsh publish."); + return identify_flash_publish_client(dynamic_cast(pkt), type, stream_name); + } + + srs_trace("ignore AMF0/AMF3 command message."); + } + + return ret; } int SrsRtmpServer::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, string& stream_name) { - int ret = ERROR_SUCCESS; - - type = SrsClientFMLEPublish; - stream_name = req->stream_name; - - // releaseStream response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send releaseStream response message failed. ret=%d", ret); - return ret; - } - srs_info("send releaseStream response message success."); - } - - return ret; + int ret = ERROR_SUCCESS; + + type = SrsClientFMLEPublish; + stream_name = req->stream_name; + + // releaseStream response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send releaseStream response message failed. ret=%d", ret); + return ret; + } + srs_info("send releaseStream response message success."); + } + + return ret; } int SrsRtmpServer::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, string& stream_name) { - int ret = ERROR_SUCCESS; - - type = SrsClientFlashPublish; - stream_name = req->stream_name; - - return ret; + int ret = ERROR_SUCCESS; + + type = SrsClientFlashPublish; + stream_name = req->stream_name; + + return ret; } int SrsRtmpServer::identify_play_client(SrsPlayPacket* req, SrsClientType& type, string& stream_name) { - int ret = ERROR_SUCCESS; - - type = SrsClientPlay; - stream_name = req->stream_name; - - srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); + int ret = ERROR_SUCCESS; + + type = SrsClientPlay; + stream_name = req->stream_name; + + srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); - return ret; + return ret; } diff --git a/trunk/src/rtmp/srs_protocol_rtmp.hpp b/trunk/src/rtmp/srs_protocol_rtmp.hpp index 4f4cc40cd..b863d3599 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.hpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.hpp @@ -48,41 +48,41 @@ class SrsPlayPacket; */ struct SrsRequest { - /** - * tcUrl: rtmp://request_vhost:port/app/stream - * support pass vhost in query string, such as: - * rtmp://ip:port/app?vhost=request_vhost/stream - * rtmp://ip:port/app...vhost...request_vhost/stream - */ - std::string tcUrl; - std::string pageUrl; - std::string swfUrl; - double objectEncoding; - - std::string schema; - std::string vhost; - std::string port; - std::string app; - std::string stream; - - SrsRequest(); - virtual ~SrsRequest(); + /** + * tcUrl: rtmp://request_vhost:port/app/stream + * support pass vhost in query string, such as: + * rtmp://ip:port/app?vhost=request_vhost/stream + * rtmp://ip:port/app...vhost...request_vhost/stream + */ + std::string tcUrl; + std::string pageUrl; + std::string swfUrl; + double objectEncoding; + + std::string schema; + std::string vhost; + std::string port; + std::string app; + std::string stream; + + SrsRequest(); + virtual ~SrsRequest(); - /** - * deep copy the request, for source to use it to support reload, - * for when initialize the source, the request is valid, - * when reload it, the request maybe invalid, so need to copy it. - */ - virtual SrsRequest* copy(); - - /** - * disconvery vhost/app from tcUrl. - */ - virtual int discovery_app(); - virtual std::string get_stream_url(); - virtual void strip(); + /** + * deep copy the request, for source to use it to support reload, + * for when initialize the source, the request is valid, + * when reload it, the request maybe invalid, so need to copy it. + */ + virtual SrsRequest* copy(); + + /** + * disconvery vhost/app from tcUrl. + */ + virtual int discovery_app(); + virtual std::string get_stream_url(); + virtual void strip(); 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 { - int stream_id; - - SrsResponse(); - virtual ~SrsResponse(); + int stream_id; + + SrsResponse(); + virtual ~SrsResponse(); }; /** @@ -101,10 +101,10 @@ struct SrsResponse */ enum SrsClientType { - SrsClientUnknown, - SrsClientPlay, - SrsClientFMLEPublish, - SrsClientFlashPublish, + SrsClientUnknown, + SrsClientPlay, + SrsClientFMLEPublish, + SrsClientFlashPublish, }; std::string srs_client_type_string(SrsClientType type); @@ -114,36 +114,36 @@ std::string srs_client_type_string(SrsClientType type); class SrsRtmpClient { protected: - SrsProtocol* protocol; - ISrsProtocolReaderWriter* io; + SrsProtocol* protocol; + ISrsProtocolReaderWriter* io; public: - SrsRtmpClient(ISrsProtocolReaderWriter* skt); - virtual ~SrsRtmpClient(); + SrsRtmpClient(ISrsProtocolReaderWriter* skt); + virtual ~SrsRtmpClient(); public: - virtual void set_recv_timeout(int64_t timeout_us); - virtual void set_send_timeout(int64_t timeout_us); - virtual int64_t get_recv_bytes(); - virtual int64_t get_send_bytes(); - virtual int get_recv_kbps(); - virtual int get_send_kbps(); - virtual int recv_message(SrsCommonMessage** pmsg); - virtual int send_message(ISrsMessage* msg); + virtual void set_recv_timeout(int64_t timeout_us); + virtual void set_send_timeout(int64_t timeout_us); + virtual int64_t get_recv_bytes(); + virtual int64_t get_send_bytes(); + virtual int get_recv_kbps(); + virtual int get_send_kbps(); + virtual int recv_message(SrsCommonMessage** pmsg); + virtual int send_message(ISrsMessage* msg); public: - // try complex, then simple handshake. - virtual int handshake(); - // only use simple handshake - virtual int simple_handshake(); - // only use complex handshake - virtual int complex_handshake(); - virtual int connect_app(std::string app, std::string tc_url); - virtual int create_stream(int& stream_id); - virtual int play(std::string stream, int stream_id); - // flash publish schema: - // connect-app => create-stream => flash-publish - virtual int publish(std::string stream, int stream_id); - // FMLE publish schema: - // connect-app => FMLE publish - virtual int fmle_publish(std::string stream, int& stream_id); + // try complex, then simple handshake. + virtual int handshake(); + // only use simple handshake + virtual int simple_handshake(); + // only use complex handshake + virtual int complex_handshake(); + virtual int connect_app(std::string app, std::string tc_url); + virtual int create_stream(int& stream_id); + virtual int play(std::string stream, int stream_id); + // flash publish schema: + // connect-app => create-stream => flash-publish + virtual int publish(std::string stream, int stream_id); + // FMLE publish schema: + // connect-app => FMLE publish + virtual int fmle_publish(std::string stream, int& stream_id); }; /** @@ -155,93 +155,93 @@ public: class SrsRtmpServer { private: - SrsProtocol* protocol; - ISrsProtocolReaderWriter* io; + SrsProtocol* protocol; + ISrsProtocolReaderWriter* io; public: - SrsRtmpServer(ISrsProtocolReaderWriter* skt); - virtual ~SrsRtmpServer(); + SrsRtmpServer(ISrsProtocolReaderWriter* skt); + virtual ~SrsRtmpServer(); public: - virtual SrsProtocol* get_protocol(); - virtual void set_recv_timeout(int64_t timeout_us); - virtual int64_t get_recv_timeout(); - virtual void set_send_timeout(int64_t timeout_us); - virtual int64_t get_send_timeout(); - virtual int64_t get_recv_bytes(); - virtual int64_t get_send_bytes(); - virtual int get_recv_kbps(); - virtual int get_send_kbps(); - virtual int recv_message(SrsCommonMessage** pmsg); - virtual int send_message(ISrsMessage* msg); + virtual SrsProtocol* get_protocol(); + virtual void set_recv_timeout(int64_t timeout_us); + virtual int64_t get_recv_timeout(); + virtual void set_send_timeout(int64_t timeout_us); + virtual int64_t get_send_timeout(); + virtual int64_t get_recv_bytes(); + virtual int64_t get_send_bytes(); + virtual int get_recv_kbps(); + virtual int get_send_kbps(); + virtual int recv_message(SrsCommonMessage** pmsg); + virtual int send_message(ISrsMessage* msg); public: - virtual int handshake(); - virtual int connect_app(SrsRequest* req); - virtual int set_window_ack_size(int ack_size); - /** - * @type: The sender can mark this message hard (0), soft (1), or dynamic (2) - * using the Limit type field. - */ - virtual int set_peer_bandwidth(int bandwidth, int type); - /** - * @param server_ip the ip of server. - */ + virtual int handshake(); + virtual int connect_app(SrsRequest* req); + virtual int set_window_ack_size(int ack_size); + /** + * @type: The sender can mark this message hard (0), soft (1), or dynamic (2) + * using the Limit type field. + */ + virtual int set_peer_bandwidth(int bandwidth, int type); + /** + * @param server_ip the ip of server. + */ virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL); virtual void response_connect_reject(SrsRequest* req, const char* desc); - virtual int on_bw_done(); - /** - * recv some message to identify the client. - * @stream_id, client will createStream to play or publish by flash, - * the stream_id used to response the createStream request. - * @type, output the client type. - */ - virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name); - /** - * set the chunk size when client type identified. - */ - virtual int set_chunk_size(int chunk_size); - /** - * when client type is play, response with packets: - * StreamBegin, - * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start)., - * |RtmpSampleAccess(false, false), - * onStatus(NetStream.Data.Start). - */ - virtual int start_play(int stream_id); - /** - * when client(type is play) send pause message, - * if is_pause, response the following packets: - * onStatus(NetStream.Pause.Notify) - * StreamEOF - * if not is_pause, response the following packets: - * onStatus(NetStream.Unpause.Notify) - * StreamBegin - */ - virtual int on_play_client_pause(int stream_id, bool is_pause); - /** - * when client type is publish, response with packets: - * releaseStream response - * FCPublish - * FCPublish response - * createStream response - * onFCPublish(NetStream.Publish.Start) - * onStatus(NetStream.Publish.Start) - */ - virtual int start_fmle_publish(int stream_id); - /** - * process the FMLE unpublish event. - * @unpublish_tid the unpublish request transaction id. - */ - virtual int fmle_unpublish(int stream_id, double unpublish_tid); - /** - * when client type is publish, response with packets: - * onStatus(NetStream.Publish.Start) - */ - virtual int start_flash_publish(int stream_id); + virtual int on_bw_done(); + /** + * recv some message to identify the client. + * @stream_id, client will createStream to play or publish by flash, + * the stream_id used to response the createStream request. + * @type, output the client type. + */ + virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name); + /** + * set the chunk size when client type identified. + */ + virtual int set_chunk_size(int chunk_size); + /** + * when client type is play, response with packets: + * StreamBegin, + * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start)., + * |RtmpSampleAccess(false, false), + * onStatus(NetStream.Data.Start). + */ + virtual int start_play(int stream_id); + /** + * when client(type is play) send pause message, + * if is_pause, response the following packets: + * onStatus(NetStream.Pause.Notify) + * StreamEOF + * if not is_pause, response the following packets: + * onStatus(NetStream.Unpause.Notify) + * StreamBegin + */ + virtual int on_play_client_pause(int stream_id, bool is_pause); + /** + * when client type is publish, response with packets: + * releaseStream response + * FCPublish + * FCPublish response + * createStream response + * onFCPublish(NetStream.Publish.Start) + * onStatus(NetStream.Publish.Start) + */ + virtual int start_fmle_publish(int stream_id); + /** + * process the FMLE unpublish event. + * @unpublish_tid the unpublish request transaction id. + */ + virtual int fmle_unpublish(int stream_id, double unpublish_tid); + /** + * when client type is publish, response with packets: + * onStatus(NetStream.Publish.Start) + */ + virtual int start_flash_publish(int stream_id); private: - 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_flash_publish_client(SrsPublishPacket* req, 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_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name); 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 diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp index 64a419d28..318ca6a94 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp @@ -45,12 +45,12 @@ reserved for usage with RTM Chunk Stream protocol. Protocol messages with IDs 3-6 are reserved for usage of RTMP. Protocol message with ID 7 is used between edge server and origin server. */ -#define RTMP_MSG_SetChunkSize 0x01 -#define RTMP_MSG_AbortMessage 0x02 -#define RTMP_MSG_Acknowledgement 0x03 -#define RTMP_MSG_UserControlMessage 0x04 -#define RTMP_MSG_WindowAcknowledgementSize 0x05 -#define RTMP_MSG_SetPeerBandwidth 0x06 +#define RTMP_MSG_SetChunkSize 0x01 +#define RTMP_MSG_AbortMessage 0x02 +#define RTMP_MSG_Acknowledgement 0x03 +#define RTMP_MSG_UserControlMessage 0x04 +#define RTMP_MSG_WindowAcknowledgementSize 0x05 +#define RTMP_MSG_SetPeerBandwidth 0x06 #define RTMP_MSG_EdgeAndOriginServerCommand 0x07 /** 3. Types of messages @@ -71,8 +71,8 @@ contains related parameters. A client or a server can request Remote Procedure Calls (RPC) over streams that are communicated using the command messages to the peer. */ -#define RTMP_MSG_AMF3CommandMessage 17 // 0x11 -#define RTMP_MSG_AMF0CommandMessage 20 // 0x14 +#define RTMP_MSG_AMF3CommandMessage 17 // 0x11 +#define RTMP_MSG_AMF0CommandMessage 20 // 0x14 /** 3.2. Data message The client or the server sends this message to send Metadata or any @@ -81,8 +81,8 @@ data(audio, video etc.) like creation time, duration, theme and so on. These messages have been assigned message type value of 18 for AMF0 and message type value of 15 for AMF3. */ -#define RTMP_MSG_AMF0DataMessage 18 // 0x12 -#define RTMP_MSG_AMF3DataMessage 15 // 0x0F +#define RTMP_MSG_AMF0DataMessage 18 // 0x12 +#define RTMP_MSG_AMF3DataMessage 15 // 0x0F /** 3.3. Shared object message A shared object is a Flash object (a collection of name value pairs) @@ -91,14 +91,14 @@ so on. The message types kMsgContainer=19 for AMF0 and kMsgContainerEx=16 for AMF3 are reserved for shared object events. Each message can contain multiple events. */ -#define RTMP_MSG_AMF3SharedObject 16 // 0x10 -#define RTMP_MSG_AMF0SharedObject 19 // 0x13 +#define RTMP_MSG_AMF3SharedObject 16 // 0x10 +#define RTMP_MSG_AMF0SharedObject 19 // 0x13 /** 3.4. Audio message The client or the server sends this message to send audio data to the peer. The message type value of 8 is reserved for audio messages. */ -#define RTMP_MSG_AudioMessage 8 // 0x08 +#define RTMP_MSG_AudioMessage 8 // 0x08 /* * 3.5. Video message The client or the server sends this message to send video data to the @@ -107,14 +107,14 @@ These messages are large and can delay the sending of other type of messages. To avoid such a situation, the video message is assigned the lowest priority. */ -#define RTMP_MSG_VideoMessage 9 // 0x09 +#define RTMP_MSG_VideoMessage 9 // 0x09 /** 3.6. Aggregate message An aggregate message is a single message that contains a list of submessages. The message type value of 22 is reserved for aggregate messages. */ -#define RTMP_MSG_AggregateMessage 22 // 0x16 +#define RTMP_MSG_AggregateMessage 22 // 0x16 /**************************************************************************** ***************************************************************************** @@ -128,21 +128,21 @@ messages. // Chunks of Type 0 are 11 bytes long. This type MUST be used at the // start of a chunk stream, and whenever the stream timestamp goes // backward (e.g., because of a backward seek). -#define RTMP_FMT_TYPE0 0 +#define RTMP_FMT_TYPE0 0 // 6.1.2.2. Type 1 // Chunks of Type 1 are 7 bytes long. The message stream ID is not // included; this chunk takes the same stream ID as the preceding chunk. // Streams with variable-sized messages (for example, many video // formats) SHOULD use this format for the first chunk of each new // message after the first. -#define RTMP_FMT_TYPE1 1 +#define RTMP_FMT_TYPE1 1 // 6.1.2.3. Type 2 // Chunks of Type 2 are 3 bytes long. Neither the stream ID nor the // message length is included; this chunk has the same stream ID and // message length as the preceding chunk. Streams with constant-sized // messages (for example, some audio and data formats) SHOULD use this // format for the first chunk of each message after the first. -#define RTMP_FMT_TYPE2 2 +#define RTMP_FMT_TYPE2 2 // 6.1.2.4. Type 3 // Chunks of Type 3 have no header. Stream ID, message length and // timestamp delta are not present; chunks of this type take values from @@ -157,7 +157,7 @@ messages. // need for a chunk of type 2 to register the delta. If Type 3 chunk // follows a Type 0 chunk, then timestamp delta for this Type 3 chunk is // the same as the timestamp of Type 0 chunk. -#define RTMP_FMT_TYPE3 3 +#define RTMP_FMT_TYPE3 3 /**************************************************************************** ***************************************************************************** @@ -172,9 +172,9 @@ messages. * good for high-bit rate streaming. Chunk size is maintained * independently for each direction. */ -#define RTMP_DEFAULT_CHUNK_SIZE 128 -#define RTMP_MIN_CHUNK_SIZE 128 -#define RTMP_MAX_CHUNK_SIZE 65536 +#define RTMP_DEFAULT_CHUNK_SIZE 128 +#define RTMP_MIN_CHUNK_SIZE 128 +#define RTMP_MAX_CHUNK_SIZE 65536 /** * 6.1. Chunk Format @@ -187,7 +187,7 @@ messages. * the normal timestamp field MUST NOT be used and MUST be set to * 0xffffff and the extended timestamp MUST be sent. */ -#define RTMP_EXTENDED_TIMESTAMP 0xFFFFFF +#define RTMP_EXTENDED_TIMESTAMP 0xFFFFFF /**************************************************************************** ***************************************************************************** @@ -195,22 +195,22 @@ messages. /** * amf0 command message, command name macros */ -#define RTMP_AMF0_COMMAND_CONNECT "connect" -#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" +#define RTMP_AMF0_COMMAND_CONNECT "connect" +#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" #define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream" -#define RTMP_AMF0_COMMAND_PLAY "play" -#define RTMP_AMF0_COMMAND_PAUSE "pause" -#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" -#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" -#define RTMP_AMF0_COMMAND_RESULT "_result" -#define RTMP_AMF0_COMMAND_ERROR "_error" -#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" -#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" -#define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish" -#define RTMP_AMF0_COMMAND_PUBLISH "publish" -#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess" -#define RTMP_AMF0_DATA_SET_DATAFRAME "@setDataFrame" -#define RTMP_AMF0_DATA_ON_METADATA "onMetaData" +#define RTMP_AMF0_COMMAND_PLAY "play" +#define RTMP_AMF0_COMMAND_PAUSE "pause" +#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" +#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" +#define RTMP_AMF0_COMMAND_RESULT "_result" +#define RTMP_AMF0_COMMAND_ERROR "_error" +#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" +#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" +#define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish" +#define RTMP_AMF0_COMMAND_PUBLISH "publish" +#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess" +#define RTMP_AMF0_DATA_SET_DATAFRAME "@setDataFrame" +#define RTMP_AMF0_DATA_ON_METADATA "onMetaData" /** * band width check method name, which will be invoked by client. @@ -287,637 +287,637 @@ messages. SrsProtocol::AckWindowSize::AckWindowSize() { - ack_window_size = acked_size = 0; + ack_window_size = acked_size = 0; } SrsProtocol::SrsProtocol(ISrsProtocolReaderWriter* io) { - buffer = new SrsBuffer(); - skt = io; - - in_chunk_size = out_chunk_size = RTMP_DEFAULT_CHUNK_SIZE; + buffer = new SrsBuffer(); + skt = io; + + in_chunk_size = out_chunk_size = RTMP_DEFAULT_CHUNK_SIZE; } SrsProtocol::~SrsProtocol() { - std::map::iterator it; - - for (it = chunk_streams.begin(); it != chunk_streams.end(); ++it) { - SrsChunkStream* stream = it->second; - srs_freep(stream); - } + std::map::iterator it; + + for (it = chunk_streams.begin(); it != chunk_streams.end(); ++it) { + SrsChunkStream* stream = it->second; + srs_freep(stream); + } - chunk_streams.clear(); - - srs_freep(buffer); + chunk_streams.clear(); + + srs_freep(buffer); } string SrsProtocol::get_request_name(double transcationId) { - if (requests.find(transcationId) == requests.end()) { - return ""; - } - - return requests[transcationId]; + if (requests.find(transcationId) == requests.end()) { + return ""; + } + + return requests[transcationId]; } void SrsProtocol::set_recv_timeout(int64_t timeout_us) { - return skt->set_recv_timeout(timeout_us); + return skt->set_recv_timeout(timeout_us); } int64_t SrsProtocol::get_recv_timeout() { - return skt->get_recv_timeout(); + return skt->get_recv_timeout(); } void SrsProtocol::set_send_timeout(int64_t timeout_us) { - return skt->set_send_timeout(timeout_us); + return skt->set_send_timeout(timeout_us); } int64_t SrsProtocol::get_send_timeout() { - return skt->get_send_timeout(); + return skt->get_send_timeout(); } int64_t SrsProtocol::get_recv_bytes() { - return skt->get_recv_bytes(); + return skt->get_recv_bytes(); } int64_t SrsProtocol::get_send_bytes() { - return skt->get_send_bytes(); + return skt->get_send_bytes(); } int SrsProtocol::get_recv_kbps() { - return skt->get_recv_kbps(); + return skt->get_recv_kbps(); } int SrsProtocol::get_send_kbps() { - return skt->get_send_kbps(); + return skt->get_send_kbps(); } int SrsProtocol::recv_message(SrsCommonMessage** pmsg) { - *pmsg = NULL; - - int ret = ERROR_SUCCESS; - - while (true) { - SrsCommonMessage* msg = NULL; - - if ((ret = recv_interlaced_message(&msg)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("recv interlaced message failed. ret=%d", ret); - } - return ret; - } - srs_verbose("entire msg received"); - - if (!msg) { - continue; - } - - if (msg->size <= 0 || msg->header.payload_length <= 0) { - srs_trace("ignore empty message(type=%d, size=%d, time=%"PRId64", sid=%d).", - msg->header.message_type, msg->header.payload_length, - msg->header.timestamp, msg->header.stream_id); - srs_freep(msg); - continue; - } - - if ((ret = on_recv_message(msg)) != ERROR_SUCCESS) { - srs_error("hook the received msg failed. ret=%d", ret); - srs_freep(msg); - return ret; - } - - srs_verbose("get a msg with raw/undecoded payload"); - *pmsg = msg; - break; - } - - return ret; + *pmsg = NULL; + + int ret = ERROR_SUCCESS; + + while (true) { + SrsCommonMessage* msg = NULL; + + if ((ret = recv_interlaced_message(&msg)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("recv interlaced message failed. ret=%d", ret); + } + return ret; + } + srs_verbose("entire msg received"); + + if (!msg) { + continue; + } + + if (msg->size <= 0 || msg->header.payload_length <= 0) { + srs_trace("ignore empty message(type=%d, size=%d, time=%"PRId64", sid=%d).", + msg->header.message_type, msg->header.payload_length, + msg->header.timestamp, msg->header.stream_id); + srs_freep(msg); + continue; + } + + if ((ret = on_recv_message(msg)) != ERROR_SUCCESS) { + srs_error("hook the received msg failed. ret=%d", ret); + srs_freep(msg); + return ret; + } + + srs_verbose("get a msg with raw/undecoded payload"); + *pmsg = msg; + break; + } + + return ret; } int SrsProtocol::send_message(ISrsMessage* msg) { - int ret = ERROR_SUCCESS; - - // free msg whatever return value. - SrsAutoFree(ISrsMessage, msg, false); - - if ((ret = msg->encode_packet()) != ERROR_SUCCESS) { - srs_error("encode packet to message payload failed. ret=%d", ret); - return ret; - } - srs_info("encode packet to message payload success"); + int ret = ERROR_SUCCESS; + + // free msg whatever return value. + SrsAutoFree(ISrsMessage, msg, false); + + if ((ret = msg->encode_packet()) != ERROR_SUCCESS) { + srs_error("encode packet to message payload failed. ret=%d", ret); + return ret; + } + srs_info("encode packet to message payload success"); - // p set to current write position, - // it's ok when payload is NULL and size is 0. - char* p = (char*)msg->payload; - - // always write the header event payload is empty. - do { - // generate the header. - char* pheader = NULL; - int header_size = 0; - - if (p == (char*)msg->payload) { - // write new chunk stream header, fmt is 0 - pheader = out_header_fmt0; - *pheader++ = 0x00 | (msg->get_perfer_cid() & 0x3F); - - // chunk message header, 11 bytes - // timestamp, 3bytes, big-endian - u_int32_t timestamp = (u_int32_t)msg->header.timestamp; - if (timestamp >= RTMP_EXTENDED_TIMESTAMP) { - *pheader++ = 0xFF; - *pheader++ = 0xFF; - *pheader++ = 0xFF; - } else { - pp = (char*)×tamp; - *pheader++ = pp[2]; - *pheader++ = pp[1]; - *pheader++ = pp[0]; - } - - // message_length, 3bytes, big-endian - pp = (char*)&msg->header.payload_length; - *pheader++ = pp[2]; - *pheader++ = pp[1]; - *pheader++ = pp[0]; - - // message_type, 1bytes - *pheader++ = msg->header.message_type; - - // message_length, 3bytes, little-endian - pp = (char*)&msg->header.stream_id; - *pheader++ = pp[0]; - *pheader++ = pp[1]; - *pheader++ = pp[2]; - *pheader++ = pp[3]; - - // chunk extended timestamp header, 0 or 4 bytes, big-endian - if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ - pp = (char*)×tamp; - *pheader++ = pp[3]; - *pheader++ = pp[2]; - *pheader++ = pp[1]; - *pheader++ = pp[0]; - } - - header_size = pheader - out_header_fmt0; - pheader = out_header_fmt0; - } else { - // write no message header chunk stream, fmt is 3 - pheader = out_header_fmt3; - *pheader++ = 0xC0 | (msg->get_perfer_cid() & 0x3F); - - // chunk extended timestamp header, 0 or 4 bytes, big-endian - // 6.1.3. Extended Timestamp - // This field is transmitted only when the normal time stamp in the - // chunk message header is set to 0x00ffffff. If normal time stamp is - // set to any value less than 0x00ffffff, this field MUST NOT be - // present. This field MUST NOT be present if the timestamp field is not - // present. Type 3 chunks MUST NOT have this field. - // adobe changed for Type3 chunk: - // FMLE always sendout the extended-timestamp, - // must send the extended-timestamp to FMS, - // must send the extended-timestamp to flash-player. - // @see: ngx_rtmp_prepare_message - // @see: http://blog.csdn.net/win_lin/article/details/13363699 - u_int32_t timestamp = (u_int32_t)msg->header.timestamp; - if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ - pp = (char*)×tamp; - *pheader++ = pp[3]; - *pheader++ = pp[2]; - *pheader++ = pp[1]; - *pheader++ = pp[0]; - } - - header_size = pheader - out_header_fmt3; - pheader = out_header_fmt3; - } - - // sendout header and payload by writev. - // decrease the sys invoke count to get higher performance. - int payload_size = msg->size - (p - (char*)msg->payload); - payload_size = srs_min(payload_size, out_chunk_size); - - // send by writev - iovec iov[2]; - iov[0].iov_base = pheader; - iov[0].iov_len = header_size; - iov[1].iov_base = p; - iov[1].iov_len = payload_size; - - ssize_t nwrite; - if ((ret = skt->writev(iov, 2, &nwrite)) != ERROR_SUCCESS) { - srs_error("send with writev failed. ret=%d", ret); - return ret; - } - - // consume sendout bytes when not empty packet. - if (msg->payload && msg->size > 0) { - p += payload_size; - } - } while (p < (char*)msg->payload + msg->size); - - if ((ret = on_send_message(msg)) != ERROR_SUCCESS) { - srs_error("hook the send message failed. ret=%d", ret); - return ret; - } - - return ret; + // p set to current write position, + // it's ok when payload is NULL and size is 0. + char* p = (char*)msg->payload; + + // always write the header event payload is empty. + do { + // generate the header. + char* pheader = NULL; + int header_size = 0; + + if (p == (char*)msg->payload) { + // write new chunk stream header, fmt is 0 + pheader = out_header_fmt0; + *pheader++ = 0x00 | (msg->get_perfer_cid() & 0x3F); + + // chunk message header, 11 bytes + // timestamp, 3bytes, big-endian + u_int32_t timestamp = (u_int32_t)msg->header.timestamp; + if (timestamp >= RTMP_EXTENDED_TIMESTAMP) { + *pheader++ = 0xFF; + *pheader++ = 0xFF; + *pheader++ = 0xFF; + } else { + pp = (char*)×tamp; + *pheader++ = pp[2]; + *pheader++ = pp[1]; + *pheader++ = pp[0]; + } + + // message_length, 3bytes, big-endian + pp = (char*)&msg->header.payload_length; + *pheader++ = pp[2]; + *pheader++ = pp[1]; + *pheader++ = pp[0]; + + // message_type, 1bytes + *pheader++ = msg->header.message_type; + + // message_length, 3bytes, little-endian + pp = (char*)&msg->header.stream_id; + *pheader++ = pp[0]; + *pheader++ = pp[1]; + *pheader++ = pp[2]; + *pheader++ = pp[3]; + + // chunk extended timestamp header, 0 or 4 bytes, big-endian + if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ + pp = (char*)×tamp; + *pheader++ = pp[3]; + *pheader++ = pp[2]; + *pheader++ = pp[1]; + *pheader++ = pp[0]; + } + + header_size = pheader - out_header_fmt0; + pheader = out_header_fmt0; + } else { + // write no message header chunk stream, fmt is 3 + pheader = out_header_fmt3; + *pheader++ = 0xC0 | (msg->get_perfer_cid() & 0x3F); + + // chunk extended timestamp header, 0 or 4 bytes, big-endian + // 6.1.3. Extended Timestamp + // This field is transmitted only when the normal time stamp in the + // chunk message header is set to 0x00ffffff. If normal time stamp is + // set to any value less than 0x00ffffff, this field MUST NOT be + // present. This field MUST NOT be present if the timestamp field is not + // present. Type 3 chunks MUST NOT have this field. + // adobe changed for Type3 chunk: + // FMLE always sendout the extended-timestamp, + // must send the extended-timestamp to FMS, + // must send the extended-timestamp to flash-player. + // @see: ngx_rtmp_prepare_message + // @see: http://blog.csdn.net/win_lin/article/details/13363699 + u_int32_t timestamp = (u_int32_t)msg->header.timestamp; + if(timestamp >= RTMP_EXTENDED_TIMESTAMP){ + pp = (char*)×tamp; + *pheader++ = pp[3]; + *pheader++ = pp[2]; + *pheader++ = pp[1]; + *pheader++ = pp[0]; + } + + header_size = pheader - out_header_fmt3; + pheader = out_header_fmt3; + } + + // sendout header and payload by writev. + // decrease the sys invoke count to get higher performance. + int payload_size = msg->size - (p - (char*)msg->payload); + payload_size = srs_min(payload_size, out_chunk_size); + + // send by writev + iovec iov[2]; + iov[0].iov_base = pheader; + iov[0].iov_len = header_size; + iov[1].iov_base = p; + iov[1].iov_len = payload_size; + + ssize_t nwrite; + if ((ret = skt->writev(iov, 2, &nwrite)) != ERROR_SUCCESS) { + srs_error("send with writev failed. ret=%d", ret); + return ret; + } + + // consume sendout bytes when not empty packet. + if (msg->payload && msg->size > 0) { + p += payload_size; + } + } while (p < (char*)msg->payload + msg->size); + + if ((ret = on_send_message(msg)) != ERROR_SUCCESS) { + srs_error("hook the send message failed. ret=%d", ret); + return ret; + } + + return ret; } int SrsProtocol::response_acknowledgement_message() { - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsAcknowledgementPacket* pkt = new SrsAcknowledgementPacket(); - - in_ack_size.acked_size = pkt->sequence_number = skt->get_recv_bytes(); - msg->set_packet(pkt, 0); - - if ((ret = send_message(msg)) != ERROR_SUCCESS) { - srs_error("send acknowledgement failed. ret=%d", ret); - return ret; - } - srs_verbose("send acknowledgement success."); - - return ret; + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsAcknowledgementPacket* pkt = new SrsAcknowledgementPacket(); + + in_ack_size.acked_size = pkt->sequence_number = skt->get_recv_bytes(); + msg->set_packet(pkt, 0); + + if ((ret = send_message(msg)) != ERROR_SUCCESS) { + srs_error("send acknowledgement failed. ret=%d", ret); + return ret; + } + srs_verbose("send acknowledgement success."); + + return ret; } int SrsProtocol::response_ping_message(int32_t timestamp) { - int ret = ERROR_SUCCESS; - - srs_trace("get a ping request, response it. timestamp=%d", timestamp); - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCPingResponse; - pkt->event_data = timestamp; - msg->set_packet(pkt, 0); - - if ((ret = send_message(msg)) != ERROR_SUCCESS) { - srs_error("send ping response failed. ret=%d", ret); - return ret; - } - srs_verbose("send ping response success."); - - return ret; + int ret = ERROR_SUCCESS; + + srs_trace("get a ping request, response it. timestamp=%d", timestamp); + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCPingResponse; + pkt->event_data = timestamp; + msg->set_packet(pkt, 0); + + if ((ret = send_message(msg)) != ERROR_SUCCESS) { + srs_error("send ping response failed. ret=%d", ret); + return ret; + } + srs_verbose("send ping response success."); + + return ret; } int SrsProtocol::on_recv_message(SrsCommonMessage* msg) { - int ret = ERROR_SUCCESS; - - srs_assert(msg != NULL); - - // acknowledgement - if (in_ack_size.ack_window_size > 0 && skt->get_recv_bytes() - in_ack_size.acked_size > in_ack_size.ack_window_size) { - if ((ret = response_acknowledgement_message()) != ERROR_SUCCESS) { - return ret; - } - } - - switch (msg->header.message_type) { - case RTMP_MSG_SetChunkSize: - case RTMP_MSG_UserControlMessage: - case RTMP_MSG_WindowAcknowledgementSize: - if ((ret = msg->decode_packet(this)) != ERROR_SUCCESS) { - srs_error("decode packet from message payload failed. ret=%d", ret); - return ret; - } - srs_verbose("decode packet from message payload success."); - break; - } - - switch (msg->header.message_type) { - case RTMP_MSG_WindowAcknowledgementSize: { - SrsSetWindowAckSizePacket* pkt = dynamic_cast(msg->get_packet()); - srs_assert(pkt != NULL); - - if (pkt->ackowledgement_window_size > 0) { - in_ack_size.ack_window_size = pkt->ackowledgement_window_size; - srs_trace("set ack window size to %d", pkt->ackowledgement_window_size); - } else { - srs_warn("ignored. set ack window size is %d", pkt->ackowledgement_window_size); - } - break; - } - case RTMP_MSG_SetChunkSize: { - SrsSetChunkSizePacket* pkt = dynamic_cast(msg->get_packet()); - srs_assert(pkt != NULL); - - in_chunk_size = pkt->chunk_size; - - srs_trace("set input chunk size to %d", pkt->chunk_size); - break; - } - case RTMP_MSG_UserControlMessage: { - SrsUserControlPacket* pkt = dynamic_cast(msg->get_packet()); - srs_assert(pkt != NULL); - - if (pkt->event_type == SrcPCUCSetBufferLength) { - srs_trace("ignored. set buffer length to %d", pkt->extra_data); - } - if (pkt->event_type == SrcPCUCPingRequest) { - if ((ret = response_ping_message(pkt->event_data)) != ERROR_SUCCESS) { - return ret; - } - } - break; - } - } - - return ret; + int ret = ERROR_SUCCESS; + + srs_assert(msg != NULL); + + // acknowledgement + if (in_ack_size.ack_window_size > 0 && skt->get_recv_bytes() - in_ack_size.acked_size > in_ack_size.ack_window_size) { + if ((ret = response_acknowledgement_message()) != ERROR_SUCCESS) { + return ret; + } + } + + switch (msg->header.message_type) { + case RTMP_MSG_SetChunkSize: + case RTMP_MSG_UserControlMessage: + case RTMP_MSG_WindowAcknowledgementSize: + if ((ret = msg->decode_packet(this)) != ERROR_SUCCESS) { + srs_error("decode packet from message payload failed. ret=%d", ret); + return ret; + } + srs_verbose("decode packet from message payload success."); + break; + } + + switch (msg->header.message_type) { + case RTMP_MSG_WindowAcknowledgementSize: { + SrsSetWindowAckSizePacket* pkt = dynamic_cast(msg->get_packet()); + srs_assert(pkt != NULL); + + if (pkt->ackowledgement_window_size > 0) { + in_ack_size.ack_window_size = pkt->ackowledgement_window_size; + srs_trace("set ack window size to %d", pkt->ackowledgement_window_size); + } else { + srs_warn("ignored. set ack window size is %d", pkt->ackowledgement_window_size); + } + break; + } + case RTMP_MSG_SetChunkSize: { + SrsSetChunkSizePacket* pkt = dynamic_cast(msg->get_packet()); + srs_assert(pkt != NULL); + + in_chunk_size = pkt->chunk_size; + + srs_trace("set input chunk size to %d", pkt->chunk_size); + break; + } + case RTMP_MSG_UserControlMessage: { + SrsUserControlPacket* pkt = dynamic_cast(msg->get_packet()); + srs_assert(pkt != NULL); + + if (pkt->event_type == SrcPCUCSetBufferLength) { + srs_trace("ignored. set buffer length to %d", pkt->extra_data); + } + if (pkt->event_type == SrcPCUCPingRequest) { + if ((ret = response_ping_message(pkt->event_data)) != ERROR_SUCCESS) { + return ret; + } + } + break; + } + } + + return ret; } int SrsProtocol::on_send_message(ISrsMessage* msg) { - int ret = ERROR_SUCCESS; - - if (!msg->can_decode()) { - srs_verbose("ignore the un-decodable message."); - return ret; - } - - SrsCommonMessage* common_msg = dynamic_cast(msg); - if (!msg) { - srs_verbose("ignore the shared ptr message."); - return ret; - } - - srs_assert(common_msg != NULL); - - switch (common_msg->header.message_type) { - case RTMP_MSG_SetChunkSize: { - SrsSetChunkSizePacket* pkt = dynamic_cast(common_msg->get_packet()); - srs_assert(pkt != NULL); - - out_chunk_size = pkt->chunk_size; - - srs_trace("set output chunk size to %d", pkt->chunk_size); - break; - } - case RTMP_MSG_AMF0CommandMessage: - case RTMP_MSG_AMF3CommandMessage: { - if (true) { - SrsConnectAppPacket* pkt = NULL; - pkt = dynamic_cast(common_msg->get_packet()); - if (pkt) { - requests[pkt->transaction_id] = pkt->command_name; - break; - } - } - if (true) { - SrsCreateStreamPacket* pkt = NULL; - pkt = dynamic_cast(common_msg->get_packet()); - if (pkt) { - requests[pkt->transaction_id] = pkt->command_name; - break; - } - } - if (true) { - SrsFMLEStartPacket* pkt = NULL; - pkt = dynamic_cast(common_msg->get_packet()); - if (pkt) { - requests[pkt->transaction_id] = pkt->command_name; - break; - } - } - break; - } - } - - return ret; + int ret = ERROR_SUCCESS; + + if (!msg->can_decode()) { + srs_verbose("ignore the un-decodable message."); + return ret; + } + + SrsCommonMessage* common_msg = dynamic_cast(msg); + if (!msg) { + srs_verbose("ignore the shared ptr message."); + return ret; + } + + srs_assert(common_msg != NULL); + + switch (common_msg->header.message_type) { + case RTMP_MSG_SetChunkSize: { + SrsSetChunkSizePacket* pkt = dynamic_cast(common_msg->get_packet()); + srs_assert(pkt != NULL); + + out_chunk_size = pkt->chunk_size; + + srs_trace("set output chunk size to %d", pkt->chunk_size); + break; + } + case RTMP_MSG_AMF0CommandMessage: + case RTMP_MSG_AMF3CommandMessage: { + if (true) { + SrsConnectAppPacket* pkt = NULL; + pkt = dynamic_cast(common_msg->get_packet()); + if (pkt) { + requests[pkt->transaction_id] = pkt->command_name; + break; + } + } + if (true) { + SrsCreateStreamPacket* pkt = NULL; + pkt = dynamic_cast(common_msg->get_packet()); + if (pkt) { + requests[pkt->transaction_id] = pkt->command_name; + break; + } + } + if (true) { + SrsFMLEStartPacket* pkt = NULL; + pkt = dynamic_cast(common_msg->get_packet()); + if (pkt) { + requests[pkt->transaction_id] = pkt->command_name; + break; + } + } + break; + } + } + + return ret; } int SrsProtocol::recv_interlaced_message(SrsCommonMessage** pmsg) { - int ret = ERROR_SUCCESS; - - // chunk stream basic header. - char fmt = 0; - int cid = 0; - int bh_size = 0; - if ((ret = read_basic_header(fmt, cid, bh_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read basic header failed. ret=%d", ret); - } - return ret; - } - srs_verbose("read basic header success. fmt=%d, cid=%d, bh_size=%d", fmt, cid, bh_size); - - // once we got the chunk message header, - // that is there is a real message in cache, - // increase the timeout to got it. - // For example, in the play loop, we set timeout to 100ms, - // when we got a chunk header, we should increase the timeout, - // or we maybe timeout and disconnect the client. - int64_t timeout_us = skt->get_recv_timeout(); - if (!skt->is_never_timeout(timeout_us)) { - int64_t pkt_timeout_us = srs_max(timeout_us, SRS_MIN_RECV_TIMEOUT_US); - skt->set_recv_timeout(pkt_timeout_us); - srs_verbose("change recv timeout_us " - "from %"PRId64" to %"PRId64"", timeout_us, pkt_timeout_us); - } - - // get the cached chunk stream. - SrsChunkStream* chunk = NULL; - - if (chunk_streams.find(cid) == chunk_streams.end()) { - chunk = chunk_streams[cid] = new SrsChunkStream(cid); - srs_verbose("cache new chunk stream: fmt=%d, cid=%d", fmt, cid); - } else { - chunk = chunk_streams[cid]; - srs_verbose("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", - chunk->fmt, chunk->cid, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, chunk->header.payload_length, - chunk->header.timestamp, chunk->header.stream_id); - } + int ret = ERROR_SUCCESS; + + // chunk stream basic header. + char fmt = 0; + int cid = 0; + int bh_size = 0; + if ((ret = read_basic_header(fmt, cid, bh_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read basic header failed. ret=%d", ret); + } + return ret; + } + srs_verbose("read basic header success. fmt=%d, cid=%d, bh_size=%d", fmt, cid, bh_size); + + // once we got the chunk message header, + // that is there is a real message in cache, + // increase the timeout to got it. + // For example, in the play loop, we set timeout to 100ms, + // when we got a chunk header, we should increase the timeout, + // or we maybe timeout and disconnect the client. + int64_t timeout_us = skt->get_recv_timeout(); + if (!skt->is_never_timeout(timeout_us)) { + int64_t pkt_timeout_us = srs_max(timeout_us, SRS_MIN_RECV_TIMEOUT_US); + skt->set_recv_timeout(pkt_timeout_us); + srs_verbose("change recv timeout_us " + "from %"PRId64" to %"PRId64"", timeout_us, pkt_timeout_us); + } + + // get the cached chunk stream. + SrsChunkStream* chunk = NULL; + + if (chunk_streams.find(cid) == chunk_streams.end()) { + chunk = chunk_streams[cid] = new SrsChunkStream(cid); + srs_verbose("cache new chunk stream: fmt=%d, cid=%d", fmt, cid); + } else { + chunk = chunk_streams[cid]; + srs_verbose("cached chunk stream: fmt=%d, cid=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", + chunk->fmt, chunk->cid, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, chunk->header.payload_length, + chunk->header.timestamp, chunk->header.stream_id); + } - // chunk stream message header - int mh_size = 0; - if ((ret = read_message_header(chunk, fmt, bh_size, mh_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read message header failed. ret=%d", ret); - } - return ret; - } - srs_verbose("read message header success. " - "fmt=%d, mh_size=%d, ext_time=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", - fmt, mh_size, chunk->extended_timestamp, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, - chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); - - // read msg payload from chunk stream. - SrsCommonMessage* msg = NULL; - int payload_size = 0; - if ((ret = read_message_payload(chunk, bh_size, mh_size, payload_size, &msg)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read message payload failed. ret=%d", ret); - } - return ret; - } - - // reset the recv timeout - if (!skt->is_never_timeout(timeout_us)) { - skt->set_recv_timeout(timeout_us); - srs_verbose("reset recv timeout_us to %"PRId64"", timeout_us); - } - - // not got an entire RTMP message, try next chunk. - if (!msg) { - srs_verbose("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", - payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, - chunk->header.timestamp, chunk->header.stream_id); - return ret; - } - - *pmsg = msg; - srs_info("get entire message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", - payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, - chunk->header.timestamp, chunk->header.stream_id); - - return ret; + // chunk stream message header + int mh_size = 0; + if ((ret = read_message_header(chunk, fmt, bh_size, mh_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read message header failed. ret=%d", ret); + } + return ret; + } + srs_verbose("read message header success. " + "fmt=%d, mh_size=%d, ext_time=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", + fmt, mh_size, chunk->extended_timestamp, (chunk->msg? chunk->msg->size : 0), chunk->header.message_type, + chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); + + // read msg payload from chunk stream. + SrsCommonMessage* msg = NULL; + int payload_size = 0; + if ((ret = read_message_payload(chunk, bh_size, mh_size, payload_size, &msg)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read message payload failed. ret=%d", ret); + } + return ret; + } + + // reset the recv timeout + if (!skt->is_never_timeout(timeout_us)) { + skt->set_recv_timeout(timeout_us); + srs_verbose("reset recv timeout_us to %"PRId64"", timeout_us); + } + + // not got an entire RTMP message, try next chunk. + if (!msg) { + srs_verbose("get partial message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", + payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, + chunk->header.timestamp, chunk->header.stream_id); + return ret; + } + + *pmsg = msg; + srs_info("get entire message success. chunk_payload_size=%d, size=%d, message(type=%d, size=%d, time=%"PRId64", sid=%d)", + payload_size, (msg? msg->size : (chunk->msg? chunk->msg->size : 0)), chunk->header.message_type, chunk->header.payload_length, + chunk->header.timestamp, chunk->header.stream_id); + + return ret; } int SrsProtocol::read_basic_header(char& fmt, int& cid, int& bh_size) { - int ret = ERROR_SUCCESS; - - int required_size = 1; - if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read 1bytes basic header failed. required_size=%d, ret=%d", required_size, ret); - } - return ret; - } - - char* p = buffer->bytes(); - + int ret = ERROR_SUCCESS; + + int required_size = 1; + if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read 1bytes basic header failed. required_size=%d, ret=%d", required_size, ret); + } + return ret; + } + + char* p = buffer->bytes(); + fmt = (*p >> 6) & 0x03; cid = *p & 0x3f; bh_size = 1; if (cid > 1) { - srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid); + srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid); return ret; } - if (cid == 0) { - required_size = 2; - if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read 2bytes basic header failed. required_size=%d, ret=%d", required_size, ret); - } - return ret; - } - - cid = 64; - cid += *(++p); - bh_size = 2; - srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid); - } else if (cid == 1) { - required_size = 3; - if ((ret = buffer->ensure_buffer_bytes(skt, 3)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read 3bytes basic header failed. required_size=%d, ret=%d", required_size, ret); - } - return ret; - } - - cid = 64; - cid += *(++p); - cid += *(++p) * 256; - bh_size = 3; - srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid); - } else { - srs_error("invalid path, impossible basic header."); - srs_assert(false); - } - - return ret; + if (cid == 0) { + required_size = 2; + if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read 2bytes basic header failed. required_size=%d, ret=%d", required_size, ret); + } + return ret; + } + + cid = 64; + cid += *(++p); + bh_size = 2; + srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid); + } else if (cid == 1) { + required_size = 3; + if ((ret = buffer->ensure_buffer_bytes(skt, 3)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read 3bytes basic header failed. required_size=%d, ret=%d", required_size, ret); + } + return ret; + } + + cid = 64; + cid += *(++p); + cid += *(++p) * 256; + bh_size = 3; + srs_verbose("%dbytes basic header parsed. fmt=%d, cid=%d", bh_size, fmt, cid); + } else { + srs_error("invalid path, impossible basic header."); + srs_assert(false); + } + + return ret; } int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_size, int& mh_size) { - int ret = ERROR_SUCCESS; - - /** - * we should not assert anything about fmt, for the first packet. - * (when first packet, the chunk->msg is NULL). - * the fmt maybe 0/1/2/3, the FMLE will send a 0xC4 for some audio packet. - * the previous packet is: - * 04 // fmt=0, cid=4 - * 00 00 1a // timestamp=26 - * 00 00 9d // payload_length=157 - * 08 // message_type=8(audio) - * 01 00 00 00 // stream_id=1 - * the current packet maybe: - * c4 // fmt=3, cid=4 - * it's ok, for the packet is audio, and timestamp delta is 26. - * the current packet must be parsed as: - * fmt=0, cid=4 - * timestamp=26+26=52 - * payload_length=157 - * message_type=8(audio) - * stream_id=1 - * so we must update the timestamp even fmt=3 for first packet. - */ - // fresh packet used to update the timestamp even fmt=3 for first packet. - bool is_fresh_packet = !chunk->msg; - - // but, we can ensure that when a chunk stream is fresh, - // the fmt must be 0, a new stream. - if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) { - ret = ERROR_RTMP_CHUNK_START; - srs_error("chunk stream is fresh, " - "fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret); - return ret; - } + int ret = ERROR_SUCCESS; + + /** + * we should not assert anything about fmt, for the first packet. + * (when first packet, the chunk->msg is NULL). + * the fmt maybe 0/1/2/3, the FMLE will send a 0xC4 for some audio packet. + * the previous packet is: + * 04 // fmt=0, cid=4 + * 00 00 1a // timestamp=26 + * 00 00 9d // payload_length=157 + * 08 // message_type=8(audio) + * 01 00 00 00 // stream_id=1 + * the current packet maybe: + * c4 // fmt=3, cid=4 + * it's ok, for the packet is audio, and timestamp delta is 26. + * the current packet must be parsed as: + * fmt=0, cid=4 + * timestamp=26+26=52 + * payload_length=157 + * message_type=8(audio) + * stream_id=1 + * so we must update the timestamp even fmt=3 for first packet. + */ + // fresh packet used to update the timestamp even fmt=3 for first packet. + bool is_fresh_packet = !chunk->msg; + + // but, we can ensure that when a chunk stream is fresh, + // the fmt must be 0, a new stream. + if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) { + ret = ERROR_RTMP_CHUNK_START; + srs_error("chunk stream is fresh, " + "fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret); + return ret; + } - // when exists cache msg, means got an partial message, - // the fmt must not be type0 which means new message. - if (chunk->msg && fmt == RTMP_FMT_TYPE0) { - ret = ERROR_RTMP_CHUNK_START; - srs_error("chunk stream exists, " - "fmt must not be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret); - return ret; - } - - // create msg when new chunk stream start - if (!chunk->msg) { - chunk->msg = new SrsCommonMessage(); - srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid); - } + // when exists cache msg, means got an partial message, + // the fmt must not be type0 which means new message. + if (chunk->msg && fmt == RTMP_FMT_TYPE0) { + ret = ERROR_RTMP_CHUNK_START; + srs_error("chunk stream exists, " + "fmt must not be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret); + return ret; + } + + // create msg when new chunk stream start + if (!chunk->msg) { + chunk->msg = new SrsCommonMessage(); + srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid); + } - // read message header from socket to buffer. - static char mh_sizes[] = {11, 7, 3, 0}; - mh_size = mh_sizes[(int)fmt]; - srs_verbose("calc chunk message header size. fmt=%d, mh_size=%d", fmt, mh_size); - - int required_size = bh_size + mh_size; - if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read %dbytes message header failed. required_size=%d, ret=%d", mh_size, required_size, ret); - } - return ret; - } - char* p = buffer->bytes() + bh_size; - - // parse the message header. - // see also: ngx_rtmp_recv - if (fmt <= RTMP_FMT_TYPE2) { + // read message header from socket to buffer. + static char mh_sizes[] = {11, 7, 3, 0}; + mh_size = mh_sizes[(int)fmt]; + srs_verbose("calc chunk message header size. fmt=%d, mh_size=%d", fmt, mh_size); + + int required_size = bh_size + mh_size; + if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read %dbytes message header failed. required_size=%d, ret=%d", mh_size, required_size, ret); + } + return ret; + } + char* p = buffer->bytes() + bh_size; + + // parse the message header. + // see also: ngx_rtmp_recv + if (fmt <= RTMP_FMT_TYPE2) { char* pp = (char*)&chunk->header.timestamp_delta; pp[2] = *p++; pp[1] = *p++; @@ -947,24 +947,24 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz // MUST NOT be present. For values greater than or equal to 0xffffff // the normal timestamp field MUST NOT be used and MUST be set to // 0xffffff and the extended timestamp MUST be sent. - // + // // if extended timestamp, the timestamp must >= RTMP_EXTENDED_TIMESTAMP // we set the timestamp to RTMP_EXTENDED_TIMESTAMP to identify we // got an extended timestamp. - chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP; + chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP; } else { - if (fmt == RTMP_FMT_TYPE0) { - // 6.1.2.1. Type 0 - // For a type-0 chunk, the absolute timestamp of the message is sent - // here. - chunk->header.timestamp = chunk->header.timestamp_delta; - } else { - // 6.1.2.2. Type 1 - // 6.1.2.3. Type 2 - // For a type-1 or type-2 chunk, the difference between the previous - // chunk's timestamp and the current chunk's timestamp is sent here. - chunk->header.timestamp += chunk->header.timestamp_delta; - } + if (fmt == RTMP_FMT_TYPE0) { + // 6.1.2.1. Type 0 + // For a type-0 chunk, the absolute timestamp of the message is sent + // here. + chunk->header.timestamp = chunk->header.timestamp_delta; + } else { + // 6.1.2.2. Type 1 + // 6.1.2.3. Type 2 + // For a type-1 or type-2 chunk, the difference between the previous + // chunk's timestamp and the current chunk's timestamp is sent here. + chunk->header.timestamp += chunk->header.timestamp_delta; + } } if (fmt <= RTMP_FMT_TYPE1) { @@ -978,8 +978,8 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz if (chunk->msg->size > 0 && chunk->msg->size != chunk->header.payload_length) { ret = ERROR_RTMP_PACKET_SIZE; srs_error("msg exists in chunk cache, " - "size=%d cannot change to %d, ret=%d", - chunk->msg->size, chunk->header.payload_length, ret); + "size=%d cannot change to %d, ret=%d", + chunk->msg->size, chunk->header.payload_length, ret); return ret; } @@ -991,47 +991,47 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz pp[1] = *p++; pp[2] = *p++; pp[3] = *p++; - srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64", payload=%d, type=%d, sid=%d", - fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, - chunk->header.message_type, chunk->header.stream_id); - } else { - srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64", payload=%d, type=%d", - fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, - chunk->header.message_type); - } - } else { - srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64"", - fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp); - } - } else { - // update the timestamp even fmt=3 for first stream - if (is_fresh_packet && !chunk->extended_timestamp) { - chunk->header.timestamp += chunk->header.timestamp_delta; - } - srs_verbose("header read completed. fmt=%d, size=%d, ext_time=%d", - fmt, mh_size, chunk->extended_timestamp); - } - - if (chunk->extended_timestamp) { - mh_size += 4; - required_size = bh_size + mh_size; - srs_verbose("read header ext time. fmt=%d, ext_time=%d, mh_size=%d", fmt, chunk->extended_timestamp, mh_size); - if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read %dbytes message header failed. required_size=%d, ret=%d", mh_size, required_size, ret); - } - return ret; - } + srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64", payload=%d, type=%d, sid=%d", + fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, + chunk->header.message_type, chunk->header.stream_id); + } else { + srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64", payload=%d, type=%d", + fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp, chunk->header.payload_length, + chunk->header.message_type); + } + } else { + srs_verbose("header read completed. fmt=%d, mh_size=%d, ext_time=%d, time=%"PRId64"", + fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp); + } + } else { + // update the timestamp even fmt=3 for first stream + if (is_fresh_packet && !chunk->extended_timestamp) { + chunk->header.timestamp += chunk->header.timestamp_delta; + } + srs_verbose("header read completed. fmt=%d, size=%d, ext_time=%d", + fmt, mh_size, chunk->extended_timestamp); + } + + if (chunk->extended_timestamp) { + mh_size += 4; + required_size = bh_size + mh_size; + srs_verbose("read header ext time. fmt=%d, ext_time=%d, mh_size=%d", fmt, chunk->extended_timestamp, mh_size); + if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read %dbytes message header failed. required_size=%d, ret=%d", mh_size, required_size, ret); + } + return ret; + } - u_int32_t timestamp = 0x00; + u_int32_t timestamp = 0x00; char* pp = (char*)×tamp; pp[3] = *p++; pp[2] = *p++; pp[1] = *p++; pp[0] = *p++; - // ffmpeg/librtmp may donot send this filed, need to detect the value. - // @see also: http://blog.csdn.net/win_lin/article/details/13363699 + // ffmpeg/librtmp may donot send this filed, need to detect the value. + // @see also: http://blog.csdn.net/win_lin/article/details/13363699 // compare to the chunk timestamp, which is set by chunk message header // type 0,1 or 2. u_int32_t chunk_timestamp = chunk->header.timestamp; @@ -1041,121 +1041,121 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz } else { chunk->header.timestamp = timestamp; } - srs_verbose("header read ext_time completed. time=%"PRId64"", chunk->header.timestamp); - } - - // the extended-timestamp must be unsigned-int, - // 24bits timestamp: 0xffffff = 16777215ms = 16777.215s = 4.66h - // 32bits timestamp: 0xffffffff = 4294967295ms = 4294967.295s = 1193.046h = 49.71d - // because the rtmp protocol says the 32bits timestamp is about "50 days": - // 3. Byte Order, Alignment, and Time Format - // Because timestamps are generally only 32 bits long, they will roll - // over after fewer than 50 days. - // - // but, its sample says the timestamp is 31bits: - // An application could assume, for example, that all - // adjacent timestamps are within 2^31 milliseconds of each other, so - // 10000 comes after 4000000000, while 3000000000 comes before - // 4000000000. - // and flv specification says timestamp is 31bits: - // Extension of the Timestamp field to form a SI32 value. This - // field represents the upper 8 bits, while the previous - // Timestamp field represents the lower 24 bits of the time in - // milliseconds. - // in a word, 31bits timestamp is ok. + srs_verbose("header read ext_time completed. time=%"PRId64"", chunk->header.timestamp); + } + + // the extended-timestamp must be unsigned-int, + // 24bits timestamp: 0xffffff = 16777215ms = 16777.215s = 4.66h + // 32bits timestamp: 0xffffffff = 4294967295ms = 4294967.295s = 1193.046h = 49.71d + // because the rtmp protocol says the 32bits timestamp is about "50 days": + // 3. Byte Order, Alignment, and Time Format + // Because timestamps are generally only 32 bits long, they will roll + // over after fewer than 50 days. + // + // but, its sample says the timestamp is 31bits: + // An application could assume, for example, that all + // adjacent timestamps are within 2^31 milliseconds of each other, so + // 10000 comes after 4000000000, while 3000000000 comes before + // 4000000000. + // and flv specification says timestamp is 31bits: + // Extension of the Timestamp field to form a SI32 value. This + // field represents the upper 8 bits, while the previous + // Timestamp field represents the lower 24 bits of the time in + // milliseconds. + // in a word, 31bits timestamp is ok. // convert extended timestamp to 31bits. chunk->header.timestamp &= 0x7fffffff; - - // valid message - if (chunk->header.payload_length < 0) { - ret = ERROR_RTMP_MSG_INVLIAD_SIZE; - srs_error("RTMP message size must not be negative. size=%d, ret=%d", - chunk->header.payload_length, ret); - return ret; - } - - // copy header to msg - chunk->msg->header = chunk->header; - - // increase the msg count, the chunk stream can accept fmt=1/2/3 message now. - chunk->msg_count++; - - return ret; + + // valid message + if (chunk->header.payload_length < 0) { + ret = ERROR_RTMP_MSG_INVLIAD_SIZE; + srs_error("RTMP message size must not be negative. size=%d, ret=%d", + chunk->header.payload_length, ret); + return ret; + } + + // copy header to msg + chunk->msg->header = chunk->header; + + // increase the msg count, the chunk stream can accept fmt=1/2/3 message now. + chunk->msg_count++; + + return ret; } int SrsProtocol::read_message_payload(SrsChunkStream* chunk, int bh_size, int mh_size, int& payload_size, SrsCommonMessage** pmsg) { - int ret = ERROR_SUCCESS; - - // empty message - if (chunk->header.payload_length <= 0) { - // need erase the header in buffer. - buffer->erase(bh_size + mh_size); - - srs_trace("get an empty RTMP " - "message(type=%d, size=%d, time=%"PRId64", sid=%d)", chunk->header.message_type, - chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); - - *pmsg = chunk->msg; - chunk->msg = NULL; - - return ret; - } - srs_assert(chunk->header.payload_length > 0); - - // the chunk payload size. - payload_size = chunk->header.payload_length - chunk->msg->size; - payload_size = srs_min(payload_size, in_chunk_size); - srs_verbose("chunk payload size is %d, message_size=%d, received_size=%d, in_chunk_size=%d", - payload_size, chunk->header.payload_length, chunk->msg->size, in_chunk_size); + int ret = ERROR_SUCCESS; + + // empty message + if (chunk->header.payload_length <= 0) { + // need erase the header in buffer. + buffer->erase(bh_size + mh_size); + + srs_trace("get an empty RTMP " + "message(type=%d, size=%d, time=%"PRId64", sid=%d)", chunk->header.message_type, + chunk->header.payload_length, chunk->header.timestamp, chunk->header.stream_id); + + *pmsg = chunk->msg; + chunk->msg = NULL; + + return ret; + } + srs_assert(chunk->header.payload_length > 0); + + // the chunk payload size. + payload_size = chunk->header.payload_length - chunk->msg->size; + payload_size = srs_min(payload_size, in_chunk_size); + srs_verbose("chunk payload size is %d, message_size=%d, received_size=%d, in_chunk_size=%d", + payload_size, chunk->header.payload_length, chunk->msg->size, in_chunk_size); - // create msg payload if not initialized - if (!chunk->msg->payload) { - chunk->msg->payload = new int8_t[chunk->header.payload_length]; - memset(chunk->msg->payload, 0, chunk->header.payload_length); - srs_verbose("create empty payload for RTMP message. size=%d", chunk->header.payload_length); - } - - // read payload to buffer - int required_size = bh_size + mh_size + payload_size; - if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { - if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { - srs_error("read payload failed. required_size=%d, ret=%d", required_size, ret); - } - return ret; - } - memcpy(chunk->msg->payload + chunk->msg->size, buffer->bytes() + bh_size + mh_size, payload_size); - buffer->erase(bh_size + mh_size + payload_size); - chunk->msg->size += payload_size; - - srs_verbose("chunk payload read completed. bh_size=%d, mh_size=%d, payload_size=%d", bh_size, mh_size, payload_size); - - // got entire RTMP message? - if (chunk->header.payload_length == chunk->msg->size) { - *pmsg = chunk->msg; - chunk->msg = NULL; - srs_verbose("get entire RTMP message(type=%d, size=%d, time=%"PRId64", sid=%d)", - chunk->header.message_type, chunk->header.payload_length, - chunk->header.timestamp, chunk->header.stream_id); - return ret; - } - - srs_verbose("get partial RTMP message(type=%d, size=%d, time=%"PRId64", sid=%d), partial size=%d", - chunk->header.message_type, chunk->header.payload_length, - chunk->header.timestamp, chunk->header.stream_id, - chunk->msg->size); - - return ret; + // create msg payload if not initialized + if (!chunk->msg->payload) { + chunk->msg->payload = new int8_t[chunk->header.payload_length]; + memset(chunk->msg->payload, 0, chunk->header.payload_length); + srs_verbose("create empty payload for RTMP message. size=%d", chunk->header.payload_length); + } + + // read payload to buffer + int required_size = bh_size + mh_size + payload_size; + if ((ret = buffer->ensure_buffer_bytes(skt, required_size)) != ERROR_SUCCESS) { + if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) { + srs_error("read payload failed. required_size=%d, ret=%d", required_size, ret); + } + return ret; + } + memcpy(chunk->msg->payload + chunk->msg->size, buffer->bytes() + bh_size + mh_size, payload_size); + buffer->erase(bh_size + mh_size + payload_size); + chunk->msg->size += payload_size; + + srs_verbose("chunk payload read completed. bh_size=%d, mh_size=%d, payload_size=%d", bh_size, mh_size, payload_size); + + // got entire RTMP message? + if (chunk->header.payload_length == chunk->msg->size) { + *pmsg = chunk->msg; + chunk->msg = NULL; + srs_verbose("get entire RTMP message(type=%d, size=%d, time=%"PRId64", sid=%d)", + chunk->header.message_type, chunk->header.payload_length, + chunk->header.timestamp, chunk->header.stream_id); + return ret; + } + + srs_verbose("get partial RTMP message(type=%d, size=%d, time=%"PRId64", sid=%d), partial size=%d", + chunk->header.message_type, chunk->header.payload_length, + chunk->header.timestamp, chunk->header.stream_id, + chunk->msg->size); + + return ret; } SrsMessageHeader::SrsMessageHeader() { - message_type = 0; - payload_length = 0; - timestamp_delta = 0; - stream_id = 0; - - timestamp = 0; + message_type = 0; + payload_length = 0; + timestamp_delta = 0; + stream_id = 0; + + timestamp = 0; } SrsMessageHeader::~SrsMessageHeader() @@ -1164,267 +1164,267 @@ SrsMessageHeader::~SrsMessageHeader() bool SrsMessageHeader::is_audio() { - return message_type == RTMP_MSG_AudioMessage; + return message_type == RTMP_MSG_AudioMessage; } bool SrsMessageHeader::is_video() { - return message_type == RTMP_MSG_VideoMessage; + return message_type == RTMP_MSG_VideoMessage; } bool SrsMessageHeader::is_amf0_command() { - return message_type == RTMP_MSG_AMF0CommandMessage; + return message_type == RTMP_MSG_AMF0CommandMessage; } bool SrsMessageHeader::is_amf0_data() { - return message_type == RTMP_MSG_AMF0DataMessage; + return message_type == RTMP_MSG_AMF0DataMessage; } bool SrsMessageHeader::is_amf3_command() { - return message_type == RTMP_MSG_AMF3CommandMessage; + return message_type == RTMP_MSG_AMF3CommandMessage; } bool SrsMessageHeader::is_amf3_data() { - return message_type == RTMP_MSG_AMF3DataMessage; + return message_type == RTMP_MSG_AMF3DataMessage; } bool SrsMessageHeader::is_window_ackledgement_size() { - return message_type == RTMP_MSG_WindowAcknowledgementSize; + return message_type == RTMP_MSG_WindowAcknowledgementSize; } bool SrsMessageHeader::is_set_chunk_size() { - return message_type == RTMP_MSG_SetChunkSize; + return message_type == RTMP_MSG_SetChunkSize; } bool SrsMessageHeader::is_user_control_message() { - return message_type == RTMP_MSG_UserControlMessage; + return message_type == RTMP_MSG_UserControlMessage; } void SrsMessageHeader::initialize_amf0_script(int size, int stream) { - message_type = RTMP_MSG_AMF0DataMessage; - payload_length = (int32_t)size; - timestamp_delta = (int32_t)0; - timestamp = (int64_t)0; - stream_id = (int32_t)stream; + message_type = RTMP_MSG_AMF0DataMessage; + payload_length = (int32_t)size; + timestamp_delta = (int32_t)0; + timestamp = (int64_t)0; + stream_id = (int32_t)stream; } void SrsMessageHeader::initialize_audio(int size, u_int32_t time, int stream) { - message_type = RTMP_MSG_AudioMessage; - payload_length = (int32_t)size; - timestamp_delta = (int32_t)time; - timestamp = (int64_t)time; - stream_id = (int32_t)stream; + message_type = RTMP_MSG_AudioMessage; + payload_length = (int32_t)size; + timestamp_delta = (int32_t)time; + timestamp = (int64_t)time; + stream_id = (int32_t)stream; } void SrsMessageHeader::initialize_video(int size, u_int32_t time, int stream) { - message_type = RTMP_MSG_VideoMessage; - payload_length = (int32_t)size; - timestamp_delta = (int32_t)time; - timestamp = (int64_t)time; - stream_id = (int32_t)stream; + message_type = RTMP_MSG_VideoMessage; + payload_length = (int32_t)size; + timestamp_delta = (int32_t)time; + timestamp = (int64_t)time; + stream_id = (int32_t)stream; } SrsChunkStream::SrsChunkStream(int _cid) { - fmt = 0; - cid = _cid; - extended_timestamp = false; - msg = NULL; - msg_count = 0; + fmt = 0; + cid = _cid; + extended_timestamp = false; + msg = NULL; + msg_count = 0; } SrsChunkStream::~SrsChunkStream() { - srs_freep(msg); + srs_freep(msg); } ISrsMessage::ISrsMessage() { - payload = NULL; - size = 0; + payload = NULL; + size = 0; } ISrsMessage::~ISrsMessage() -{ +{ } SrsCommonMessage::SrsCommonMessage() { - stream = NULL; - packet = NULL; + stream = NULL; + packet = NULL; } SrsCommonMessage::~SrsCommonMessage() -{ - // we must directly free the ptrs, - // nevery use the virtual functions to delete, - // for in the destructor, the virtual functions is disabled. - - srs_freepa(payload); - srs_freep(packet); - srs_freep(stream); +{ + // we must directly free the ptrs, + // nevery use the virtual functions to delete, + // for in the destructor, the virtual functions is disabled. + + srs_freepa(payload); + srs_freep(packet); + srs_freep(stream); } bool SrsCommonMessage::can_decode() { - return true; + return true; } int SrsCommonMessage::decode_packet(SrsProtocol* protocol) { - int ret = ERROR_SUCCESS; - - srs_assert(payload != NULL); - srs_assert(size > 0); - - if (packet) { - srs_verbose("msg already decoded"); - return ret; - } - - if (!stream) { - srs_verbose("create decode stream for message."); - stream = new SrsStream(); - } - - // initialize the decode stream for all message, - // it's ok for the initialize if fast and without memory copy. - if ((ret = stream->initialize((char*)payload, size)) != ERROR_SUCCESS) { - srs_error("initialize stream failed. ret=%d", ret); - return ret; - } - srs_verbose("decode stream initialized success"); - - // decode specified packet type - if (header.is_amf0_command() || header.is_amf3_command() || header.is_amf0_data() || header.is_amf3_data()) { - srs_verbose("start to decode AMF0/AMF3 command message."); - - // skip 1bytes to decode the amf3 command. - if (header.is_amf3_command() && stream->require(1)) { - srs_verbose("skip 1bytes to decode AMF3 command"); - stream->skip(1); - } - - // amf0 command message. - // need to read the command name. - std::string command; - if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) { - srs_error("decode AMF0/AMF3 command name failed. ret=%d", ret); - return ret; - } - srs_verbose("AMF0/AMF3 command message, command_name=%s", command.c_str()); - - // result/error packet - if (command == RTMP_AMF0_COMMAND_RESULT || command == RTMP_AMF0_COMMAND_ERROR) { - double transactionId = 0.0; - if ((ret = srs_amf0_read_number(stream, transactionId)) != ERROR_SUCCESS) { - srs_error("decode AMF0/AMF3 transcationId failed. ret=%d", ret); - return ret; - } - srs_verbose("AMF0/AMF3 command id, transcationId=%.2f", transactionId); - - // reset stream, for header read completed. - stream->reset(); - if (header.is_amf3_command()) { - stream->skip(1); - } - - std::string request_name = protocol->get_request_name(transactionId); - if (request_name.empty()) { - ret = ERROR_RTMP_NO_REQUEST; - srs_error("decode AMF0/AMF3 request failed. ret=%d", ret); - return ret; - } - srs_verbose("AMF0/AMF3 request parsed. request_name=%s", request_name.c_str()); + int ret = ERROR_SUCCESS; + + srs_assert(payload != NULL); + srs_assert(size > 0); + + if (packet) { + srs_verbose("msg already decoded"); + return ret; + } + + if (!stream) { + srs_verbose("create decode stream for message."); + stream = new SrsStream(); + } + + // initialize the decode stream for all message, + // it's ok for the initialize if fast and without memory copy. + if ((ret = stream->initialize((char*)payload, size)) != ERROR_SUCCESS) { + srs_error("initialize stream failed. ret=%d", ret); + return ret; + } + srs_verbose("decode stream initialized success"); + + // decode specified packet type + if (header.is_amf0_command() || header.is_amf3_command() || header.is_amf0_data() || header.is_amf3_data()) { + srs_verbose("start to decode AMF0/AMF3 command message."); + + // skip 1bytes to decode the amf3 command. + if (header.is_amf3_command() && stream->require(1)) { + srs_verbose("skip 1bytes to decode AMF3 command"); + stream->skip(1); + } + + // amf0 command message. + // need to read the command name. + std::string command; + if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) { + srs_error("decode AMF0/AMF3 command name failed. ret=%d", ret); + return ret; + } + srs_verbose("AMF0/AMF3 command message, command_name=%s", command.c_str()); + + // result/error packet + if (command == RTMP_AMF0_COMMAND_RESULT || command == RTMP_AMF0_COMMAND_ERROR) { + double transactionId = 0.0; + if ((ret = srs_amf0_read_number(stream, transactionId)) != ERROR_SUCCESS) { + srs_error("decode AMF0/AMF3 transcationId failed. ret=%d", ret); + return ret; + } + srs_verbose("AMF0/AMF3 command id, transcationId=%.2f", transactionId); + + // reset stream, for header read completed. + stream->reset(); + if (header.is_amf3_command()) { + stream->skip(1); + } + + std::string request_name = protocol->get_request_name(transactionId); + if (request_name.empty()) { + ret = ERROR_RTMP_NO_REQUEST; + srs_error("decode AMF0/AMF3 request failed. ret=%d", ret); + return ret; + } + srs_verbose("AMF0/AMF3 request parsed. request_name=%s", request_name.c_str()); - if (request_name == RTMP_AMF0_COMMAND_CONNECT) { - srs_info("decode the AMF0/AMF3 response command(%s message).", request_name.c_str()); - packet = new SrsConnectAppResPacket(); - return packet->decode(stream); - } else if (request_name == RTMP_AMF0_COMMAND_CREATE_STREAM) { - srs_info("decode the AMF0/AMF3 response command(%s message).", request_name.c_str()); - packet = new SrsCreateStreamResPacket(0, 0); - return packet->decode(stream); - } else if (request_name == RTMP_AMF0_COMMAND_RELEASE_STREAM - || request_name == RTMP_AMF0_COMMAND_FC_PUBLISH - || request_name == RTMP_AMF0_COMMAND_UNPUBLISH) { - srs_info("decode the AMF0/AMF3 response command(%s message).", request_name.c_str()); - packet = new SrsFMLEStartResPacket(0); - return packet->decode(stream); - } else { - ret = ERROR_RTMP_NO_REQUEST; - srs_error("decode AMF0/AMF3 request failed. " - "request_name=%s, transactionId=%.2f, ret=%d", - request_name.c_str(), transactionId, ret); - return ret; - } - } - - // reset to zero(amf3 to 1) to restart decode. - stream->reset(); - if (header.is_amf3_command()) { - stream->skip(1); - } - - // decode command object. - if (command == RTMP_AMF0_COMMAND_CONNECT) { - srs_info("decode the AMF0/AMF3 command(connect vhost/app message)."); - packet = new SrsConnectAppPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_CREATE_STREAM) { - srs_info("decode the AMF0/AMF3 command(createStream message)."); - packet = new SrsCreateStreamPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_PLAY) { - srs_info("decode the AMF0/AMF3 command(paly message)."); - packet = new SrsPlayPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_PAUSE) { - srs_info("decode the AMF0/AMF3 command(pause message)."); - packet = new SrsPausePacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_RELEASE_STREAM) { - srs_info("decode the AMF0/AMF3 command(FMLE releaseStream message)."); - packet = new SrsFMLEStartPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_FC_PUBLISH) { - srs_info("decode the AMF0/AMF3 command(FMLE FCPublish message)."); - packet = new SrsFMLEStartPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_PUBLISH) { - srs_info("decode the AMF0/AMF3 command(publish message)."); - packet = new SrsPublishPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_COMMAND_UNPUBLISH) { - srs_info("decode the AMF0/AMF3 command(unpublish message)."); - packet = new SrsFMLEStartPacket(); - return packet->decode(stream); - } else if(command == RTMP_AMF0_DATA_SET_DATAFRAME || command == RTMP_AMF0_DATA_ON_METADATA) { - srs_info("decode the AMF0/AMF3 data(onMetaData message)."); - packet = new SrsOnMetaDataPacket(); - return packet->decode(stream); + if (request_name == RTMP_AMF0_COMMAND_CONNECT) { + srs_info("decode the AMF0/AMF3 response command(%s message).", request_name.c_str()); + packet = new SrsConnectAppResPacket(); + return packet->decode(stream); + } else if (request_name == RTMP_AMF0_COMMAND_CREATE_STREAM) { + srs_info("decode the AMF0/AMF3 response command(%s message).", request_name.c_str()); + packet = new SrsCreateStreamResPacket(0, 0); + return packet->decode(stream); + } else if (request_name == RTMP_AMF0_COMMAND_RELEASE_STREAM + || request_name == RTMP_AMF0_COMMAND_FC_PUBLISH + || request_name == RTMP_AMF0_COMMAND_UNPUBLISH) { + srs_info("decode the AMF0/AMF3 response command(%s message).", request_name.c_str()); + packet = new SrsFMLEStartResPacket(0); + return packet->decode(stream); + } else { + ret = ERROR_RTMP_NO_REQUEST; + srs_error("decode AMF0/AMF3 request failed. " + "request_name=%s, transactionId=%.2f, ret=%d", + request_name.c_str(), transactionId, ret); + return ret; + } + } + + // reset to zero(amf3 to 1) to restart decode. + stream->reset(); + if (header.is_amf3_command()) { + stream->skip(1); + } + + // decode command object. + if (command == RTMP_AMF0_COMMAND_CONNECT) { + srs_info("decode the AMF0/AMF3 command(connect vhost/app message)."); + packet = new SrsConnectAppPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_CREATE_STREAM) { + srs_info("decode the AMF0/AMF3 command(createStream message)."); + packet = new SrsCreateStreamPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_PLAY) { + srs_info("decode the AMF0/AMF3 command(paly message)."); + packet = new SrsPlayPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_PAUSE) { + srs_info("decode the AMF0/AMF3 command(pause message)."); + packet = new SrsPausePacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_RELEASE_STREAM) { + srs_info("decode the AMF0/AMF3 command(FMLE releaseStream message)."); + packet = new SrsFMLEStartPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_FC_PUBLISH) { + srs_info("decode the AMF0/AMF3 command(FMLE FCPublish message)."); + packet = new SrsFMLEStartPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_PUBLISH) { + srs_info("decode the AMF0/AMF3 command(publish message)."); + packet = new SrsPublishPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_COMMAND_UNPUBLISH) { + srs_info("decode the AMF0/AMF3 command(unpublish message)."); + packet = new SrsFMLEStartPacket(); + return packet->decode(stream); + } else if(command == RTMP_AMF0_DATA_SET_DATAFRAME || command == RTMP_AMF0_DATA_ON_METADATA) { + srs_info("decode the AMF0/AMF3 data(onMetaData message)."); + packet = new SrsOnMetaDataPacket(); + return packet->decode(stream); } else if(command == SRS_BW_CHECK_FINISHED - || command == SRS_BW_CHECK_PLAYING - || command == SRS_BW_CHECK_PUBLISHING - || command == SRS_BW_CHECK_STARTING_PLAY - || command == SRS_BW_CHECK_STARTING_PUBLISH - || command == SRS_BW_CHECK_START_PLAY - || command == SRS_BW_CHECK_START_PUBLISH - || command == SRS_BW_CHECK_STOPPED_PLAY - || command == SRS_BW_CHECK_STOP_PLAY - || command == SRS_BW_CHECK_STOP_PUBLISH - || command == SRS_BW_CHECK_STOPPED_PUBLISH - || command == SRS_BW_CHECK_FLASH_FINAL) + || command == SRS_BW_CHECK_PLAYING + || command == SRS_BW_CHECK_PUBLISHING + || command == SRS_BW_CHECK_STARTING_PLAY + || command == SRS_BW_CHECK_STARTING_PUBLISH + || command == SRS_BW_CHECK_START_PLAY + || command == SRS_BW_CHECK_START_PUBLISH + || command == SRS_BW_CHECK_STOPPED_PLAY + || command == SRS_BW_CHECK_STOP_PLAY + || command == SRS_BW_CHECK_STOP_PUBLISH + || command == SRS_BW_CHECK_STOPPED_PUBLISH + || command == SRS_BW_CHECK_FLASH_FINAL) { srs_info("decode the AMF0/AMF3 band width check message."); packet = new SrsBandwidthPacket(); @@ -1434,210 +1434,210 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) packet = new SrsCloseStreamPacket(); return packet->decode(stream); } - - // default packet to drop message. - srs_trace("drop the AMF0/AMF3 command message, command_name=%s", command.c_str()); - packet = new SrsPacket(); - return ret; - } else if(header.is_user_control_message()) { - srs_verbose("start to decode user control message."); - packet = new SrsUserControlPacket(); - return packet->decode(stream); - } else if(header.is_window_ackledgement_size()) { - srs_verbose("start to decode set ack window size message."); - packet = new SrsSetWindowAckSizePacket(); - return packet->decode(stream); - } else if(header.is_set_chunk_size()) { - srs_verbose("start to decode set chunk size message."); - packet = new SrsSetChunkSizePacket(); - return packet->decode(stream); - } else { - // default packet to drop message. - srs_trace("drop the unknown message, type=%d", header.message_type); - packet = new SrsPacket(); - } - - return ret; + + // default packet to drop message. + srs_trace("drop the AMF0/AMF3 command message, command_name=%s", command.c_str()); + packet = new SrsPacket(); + return ret; + } else if(header.is_user_control_message()) { + srs_verbose("start to decode user control message."); + packet = new SrsUserControlPacket(); + return packet->decode(stream); + } else if(header.is_window_ackledgement_size()) { + srs_verbose("start to decode set ack window size message."); + packet = new SrsSetWindowAckSizePacket(); + return packet->decode(stream); + } else if(header.is_set_chunk_size()) { + srs_verbose("start to decode set chunk size message."); + packet = new SrsSetChunkSizePacket(); + return packet->decode(stream); + } else { + // default packet to drop message. + srs_trace("drop the unknown message, type=%d", header.message_type); + packet = new SrsPacket(); + } + + return ret; } SrsPacket* SrsCommonMessage::get_packet() { - if (!packet) { - srs_error("the payload is raw/undecoded, invoke decode_packet to decode it."); - } - srs_assert(packet != NULL); - - return packet; + if (!packet) { + srs_error("the payload is raw/undecoded, invoke decode_packet to decode it."); + } + srs_assert(packet != NULL); + + return packet; } int SrsCommonMessage::get_perfer_cid() { - if (!packet) { - return RTMP_CID_ProtocolControl; - } - - // we donot use the complex basic header, - // ensure the basic header is 1bytes. - if (packet->get_perfer_cid() < 2) { - return packet->get_perfer_cid(); - } - - return packet->get_perfer_cid(); + if (!packet) { + return RTMP_CID_ProtocolControl; + } + + // we donot use the complex basic header, + // ensure the basic header is 1bytes. + if (packet->get_perfer_cid() < 2) { + return packet->get_perfer_cid(); + } + + return packet->get_perfer_cid(); } SrsCommonMessage* SrsCommonMessage::set_packet(SrsPacket* pkt, int stream_id) { - srs_freep(packet); + srs_freep(packet); - packet = pkt; - - header.message_type = packet->get_message_type(); - header.payload_length = packet->get_payload_length(); - header.stream_id = stream_id; - - return this; + packet = pkt; + + header.message_type = packet->get_message_type(); + header.payload_length = packet->get_payload_length(); + header.stream_id = stream_id; + + return this; } int SrsCommonMessage::encode_packet() { - int ret = ERROR_SUCCESS; - - if (packet == NULL) { - srs_warn("packet is empty, send out empty message."); - return ret; - } - // realloc the payload. - size = 0; - srs_freepa(payload); - - if ((ret = packet->encode(size, (char*&)payload)) != ERROR_SUCCESS) { - return ret; - } - - header.payload_length = size; - - return ret; + int ret = ERROR_SUCCESS; + + if (packet == NULL) { + srs_warn("packet is empty, send out empty message."); + return ret; + } + // realloc the payload. + size = 0; + srs_freepa(payload); + + if ((ret = packet->encode(size, (char*&)payload)) != ERROR_SUCCESS) { + return ret; + } + + header.payload_length = size; + + return ret; } SrsSharedPtrMessage::SrsSharedPtr::SrsSharedPtr() { - payload = NULL; - size = 0; - perfer_cid = 0; - shared_count = 0; + payload = NULL; + size = 0; + perfer_cid = 0; + shared_count = 0; } SrsSharedPtrMessage::SrsSharedPtr::~SrsSharedPtr() { - srs_freepa(payload); + srs_freepa(payload); } SrsSharedPtrMessage::SrsSharedPtrMessage() { - ptr = NULL; + ptr = NULL; } SrsSharedPtrMessage::~SrsSharedPtrMessage() { - if (ptr) { - if (ptr->shared_count == 0) { - srs_freep(ptr); - } else { - ptr->shared_count--; - } - } + if (ptr) { + if (ptr->shared_count == 0) { + srs_freep(ptr); + } else { + ptr->shared_count--; + } + } } bool SrsSharedPtrMessage::can_decode() { - return false; + return false; } int SrsSharedPtrMessage::initialize(SrsCommonMessage* source) { - int ret = ERROR_SUCCESS; - - if ((ret = initialize(&source->header, (char*)source->payload, source->size)) != ERROR_SUCCESS) { - return ret; - } - - // detach the payload from source - source->payload = NULL; - source->size = 0; - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = initialize(&source->header, (char*)source->payload, source->size)) != ERROR_SUCCESS) { + return ret; + } + + // detach the payload from source + source->payload = NULL; + source->size = 0; + + return ret; } int SrsSharedPtrMessage::initialize(SrsMessageHeader* source, char* payload, int size) { - int ret = ERROR_SUCCESS; - - srs_assert(source != NULL); - if (ptr) { - ret = ERROR_SYSTEM_ASSERT_FAILED; - srs_error("should not set the payload twice. ret=%d", ret); - srs_assert(false); - - return ret; - } - - header = *source; - header.payload_length = size; - - ptr = new SrsSharedPtr(); - - // direct attach the data of common message. - ptr->payload = payload; - ptr->size = size; - - if (source->is_video()) { - ptr->perfer_cid = RTMP_CID_Video; - } else if (source->is_audio()) { - ptr->perfer_cid = RTMP_CID_Audio; - } else { - ptr->perfer_cid = RTMP_CID_OverConnection2; - } - - super::payload = (int8_t*)ptr->payload; - super::size = ptr->size; - - return ret; + int ret = ERROR_SUCCESS; + + srs_assert(source != NULL); + if (ptr) { + ret = ERROR_SYSTEM_ASSERT_FAILED; + srs_error("should not set the payload twice. ret=%d", ret); + srs_assert(false); + + return ret; + } + + header = *source; + header.payload_length = size; + + ptr = new SrsSharedPtr(); + + // direct attach the data of common message. + ptr->payload = payload; + ptr->size = size; + + if (source->is_video()) { + ptr->perfer_cid = RTMP_CID_Video; + } else if (source->is_audio()) { + ptr->perfer_cid = RTMP_CID_Audio; + } else { + ptr->perfer_cid = RTMP_CID_OverConnection2; + } + + super::payload = (int8_t*)ptr->payload; + super::size = ptr->size; + + return ret; } SrsSharedPtrMessage* SrsSharedPtrMessage::copy() { - if (!ptr) { - srs_error("invoke initialize to initialize the ptr."); - srs_assert(false); - return NULL; - } - - SrsSharedPtrMessage* copy = new SrsSharedPtrMessage(); - - copy->header = header; - - copy->ptr = ptr; - ptr->shared_count++; - - copy->payload = (int8_t*)ptr->payload; - copy->size = ptr->size; - - return copy; + if (!ptr) { + srs_error("invoke initialize to initialize the ptr."); + srs_assert(false); + return NULL; + } + + SrsSharedPtrMessage* copy = new SrsSharedPtrMessage(); + + copy->header = header; + + copy->ptr = ptr; + ptr->shared_count++; + + copy->payload = (int8_t*)ptr->payload; + copy->size = ptr->size; + + return copy; } int SrsSharedPtrMessage::get_perfer_cid() { - if (!ptr) { - return 0; - } - - return ptr->perfer_cid; + if (!ptr) { + return 0; + } + + return ptr->perfer_cid; } int SrsSharedPtrMessage::encode_packet() { - srs_verbose("shared message ignore the encode method."); - return ERROR_SUCCESS; + srs_verbose("shared message ignore the encode method."); + return ERROR_SUCCESS; } SrsPacket::SrsPacket() @@ -1650,460 +1650,460 @@ SrsPacket::~SrsPacket() int SrsPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - srs_assert(stream != NULL); + int ret = ERROR_SUCCESS; + + srs_assert(stream != NULL); - ret = ERROR_SYSTEM_PACKET_INVALID; - srs_error("current packet is not support to decode. " - "paket=%s, ret=%d", get_class_name(), ret); - - return ret; + ret = ERROR_SYSTEM_PACKET_INVALID; + srs_error("current packet is not support to decode. " + "paket=%s, ret=%d", get_class_name(), ret); + + return ret; } int SrsPacket::get_perfer_cid() { - return 0; + return 0; } int SrsPacket::get_message_type() { - return 0; + return 0; } int SrsPacket::get_payload_length() { - return get_size(); + return get_size(); } int SrsPacket::encode(int& psize, char*& ppayload) { - int ret = ERROR_SUCCESS; - - int size = get_size(); - char* payload = NULL; - - SrsStream stream; - - if (size > 0) { - payload = new char[size]; - - if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { - srs_error("initialize the stream failed. ret=%d", ret); - srs_freepa(payload); - return ret; - } - } - - if ((ret = encode_packet(&stream)) != ERROR_SUCCESS) { - srs_error("encode the packet failed. ret=%d", ret); - srs_freepa(payload); - return ret; - } - - psize = size; - ppayload = payload; - srs_verbose("encode the packet success. size=%d", size); - - return ret; + int ret = ERROR_SUCCESS; + + int size = get_size(); + char* payload = NULL; + + SrsStream stream; + + if (size > 0) { + payload = new char[size]; + + if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { + srs_error("initialize the stream failed. ret=%d", ret); + srs_freepa(payload); + return ret; + } + } + + if ((ret = encode_packet(&stream)) != ERROR_SUCCESS) { + srs_error("encode the packet failed. ret=%d", ret); + srs_freepa(payload); + return ret; + } + + psize = size; + ppayload = payload; + srs_verbose("encode the packet success. size=%d", size); + + return ret; } int SrsPacket::get_size() { - return 0; + return 0; } int SrsPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - srs_assert(stream != NULL); + int ret = ERROR_SUCCESS; + + srs_assert(stream != NULL); - ret = ERROR_SYSTEM_PACKET_INVALID; - srs_error("current packet is not support to encode. " - "paket=%s, ret=%d", get_class_name(), ret); - - return ret; + ret = ERROR_SYSTEM_PACKET_INVALID; + srs_error("current packet is not support to encode. " + "paket=%s, ret=%d", get_class_name(), ret); + + return ret; } SrsConnectAppPacket::SrsConnectAppPacket() { - command_name = RTMP_AMF0_COMMAND_CONNECT; - transaction_id = 1; - command_object = SrsAmf0Any::object(); + command_name = RTMP_AMF0_COMMAND_CONNECT; + transaction_id = 1; + command_object = SrsAmf0Any::object(); } SrsConnectAppPacket::~SrsConnectAppPacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsConnectAppPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CONNECT) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode connect command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect transaction_id failed. ret=%d", ret); - return ret; - } - if (transaction_id != 1.0) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode connect transaction_id failed. " - "required=%.1f, actual=%.1f, ret=%d", 1.0, transaction_id, ret); - return ret; - } - - if ((ret = command_object->read(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect command_object failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode connect packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CONNECT) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode connect command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect transaction_id failed. ret=%d", ret); + return ret; + } + if (transaction_id != 1.0) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode connect transaction_id failed. " + "required=%.1f, actual=%.1f, ret=%d", 1.0, transaction_id, ret); + return ret; + } + + if ((ret = command_object->read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect command_object failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode connect packet success"); + + return ret; } int SrsConnectAppPacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsConnectAppPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsConnectAppPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::object(command_object); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::object(command_object); } int SrsConnectAppPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = command_object->write(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - srs_info("encode connect app request packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = command_object->write(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + srs_info("encode connect app request packet success."); + + return ret; } SrsConnectAppResPacket::SrsConnectAppResPacket() { - command_name = RTMP_AMF0_COMMAND_RESULT; - transaction_id = 1; - props = SrsAmf0Any::object(); - info = SrsAmf0Any::object(); + command_name = RTMP_AMF0_COMMAND_RESULT; + transaction_id = 1; + props = SrsAmf0Any::object(); + info = SrsAmf0Any::object(); } SrsConnectAppResPacket::~SrsConnectAppResPacket() { - srs_freep(props); - srs_freep(info); + srs_freep(props); + srs_freep(info); } int SrsConnectAppResPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode connect command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect transaction_id failed. ret=%d", ret); - return ret; - } - if (transaction_id != 1.0) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode connect transaction_id failed. " - "required=%.1f, actual=%.1f, ret=%d", 1.0, transaction_id, ret); - return ret; - } - - if ((ret = props->read(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect props failed. ret=%d", ret); - return ret; - } - - if ((ret = info->read(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode connect info failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode connect response packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode connect command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect transaction_id failed. ret=%d", ret); + return ret; + } + if (transaction_id != 1.0) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode connect transaction_id failed. " + "required=%.1f, actual=%.1f, ret=%d", 1.0, transaction_id, ret); + return ret; + } + + if ((ret = props->read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect props failed. ret=%d", ret); + return ret; + } + + if ((ret = info->read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect info failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode connect response packet success"); + + return ret; } int SrsConnectAppResPacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsConnectAppResPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsConnectAppResPacket::get_size() { return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::object(props) + SrsAmf0Size::object(info); + + SrsAmf0Size::object(props) + SrsAmf0Size::object(info); } int SrsConnectAppResPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + if ((ret = props->write(stream)) != ERROR_SUCCESS) { srs_error("encode props failed. ret=%d", ret); return ret; } - srs_verbose("encode props success."); - + srs_verbose("encode props success."); + if ((ret = info->write(stream)) != ERROR_SUCCESS) { srs_error("encode info failed. ret=%d", ret); return ret; } - srs_verbose("encode info success."); - - srs_info("encode connect app response packet success."); - - return ret; + srs_verbose("encode info success."); + + srs_info("encode connect app response packet success."); + + return ret; } SrsCreateStreamPacket::SrsCreateStreamPacket() { - command_name = RTMP_AMF0_COMMAND_CREATE_STREAM; - transaction_id = 2; - command_object = SrsAmf0Any::null(); + command_name = RTMP_AMF0_COMMAND_CREATE_STREAM; + transaction_id = 2; + command_object = SrsAmf0Any::null(); } SrsCreateStreamPacket::~SrsCreateStreamPacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsCreateStreamPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CREATE_STREAM) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode createStream command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream command_object failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode createStream packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CREATE_STREAM) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode createStream command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream command_object failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode createStream packet success"); + + return ret; } int SrsCreateStreamPacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsCreateStreamPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsCreateStreamPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null(); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null(); } int SrsCreateStreamPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - srs_info("encode create stream request packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + srs_info("encode create stream request packet success."); + + return ret; } SrsCreateStreamResPacket::SrsCreateStreamResPacket(double _transaction_id, double _stream_id) { - command_name = RTMP_AMF0_COMMAND_RESULT; - transaction_id = _transaction_id; - command_object = SrsAmf0Any::null(); - stream_id = _stream_id; + command_name = RTMP_AMF0_COMMAND_RESULT; + transaction_id = _transaction_id; + command_object = SrsAmf0Any::null(); + stream_id = _stream_id; } SrsCreateStreamResPacket::~SrsCreateStreamResPacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsCreateStreamResPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode createStream command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream command_object failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, stream_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode createStream stream_id failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode createStream response packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode createStream command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream command_object failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, stream_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode createStream stream_id failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode createStream response packet success"); + + return ret; } int SrsCreateStreamResPacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsCreateStreamResPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsCreateStreamResPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::number(); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::number(); } int SrsCreateStreamResPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - if ((ret = srs_amf0_write_number(stream, stream_id)) != ERROR_SUCCESS) { - srs_error("encode stream_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode stream_id success."); - - - srs_info("encode createStream response packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + if ((ret = srs_amf0_write_number(stream, stream_id)) != ERROR_SUCCESS) { + srs_error("encode stream_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode stream_id success."); + + + srs_info("encode createStream response packet success."); + + return ret; } SrsCloseStreamPacket::SrsCloseStreamPacket() @@ -2143,444 +2143,444 @@ int SrsCloseStreamPacket::decode(SrsStream* stream) SrsFMLEStartPacket::SrsFMLEStartPacket() { - command_name = RTMP_AMF0_COMMAND_RELEASE_STREAM; - transaction_id = 0; - command_object = SrsAmf0Any::null(); + command_name = RTMP_AMF0_COMMAND_RELEASE_STREAM; + transaction_id = 0; + command_object = SrsAmf0Any::null(); } SrsFMLEStartPacket::~SrsFMLEStartPacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsFMLEStartPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() - || (command_name != RTMP_AMF0_COMMAND_RELEASE_STREAM - && command_name != RTMP_AMF0_COMMAND_FC_PUBLISH - && command_name != RTMP_AMF0_COMMAND_UNPUBLISH) - ) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode FMLE start command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start command_object failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start stream_name failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode FMLE start packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() + || (command_name != RTMP_AMF0_COMMAND_RELEASE_STREAM + && command_name != RTMP_AMF0_COMMAND_FC_PUBLISH + && command_name != RTMP_AMF0_COMMAND_UNPUBLISH) + ) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode FMLE start command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start command_object failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start stream_name failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode FMLE start packet success"); + + return ret; } int SrsFMLEStartPacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsFMLEStartPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsFMLEStartPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::str(stream_name); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::str(stream_name); } int SrsFMLEStartPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - if ((ret = srs_amf0_write_string(stream, stream_name)) != ERROR_SUCCESS) { - srs_error("encode stream_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode stream_name success."); - - - srs_info("encode FMLE start response packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + if ((ret = srs_amf0_write_string(stream, stream_name)) != ERROR_SUCCESS) { + srs_error("encode stream_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode stream_name success."); + + + srs_info("encode FMLE start response packet success."); + + return ret; } SrsFMLEStartPacket* SrsFMLEStartPacket::create_release_stream(string stream) { - SrsFMLEStartPacket* pkt = new SrsFMLEStartPacket(); - - pkt->command_name = RTMP_AMF0_COMMAND_RELEASE_STREAM; - pkt->transaction_id = 2; - pkt->stream_name = stream; - - return pkt; + SrsFMLEStartPacket* pkt = new SrsFMLEStartPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_RELEASE_STREAM; + pkt->transaction_id = 2; + pkt->stream_name = stream; + + return pkt; } SrsFMLEStartPacket* SrsFMLEStartPacket::create_FC_publish(string stream) { - SrsFMLEStartPacket* pkt = new SrsFMLEStartPacket(); - - pkt->command_name = RTMP_AMF0_COMMAND_FC_PUBLISH; - pkt->transaction_id = 3; - pkt->stream_name = stream; - - return pkt; + SrsFMLEStartPacket* pkt = new SrsFMLEStartPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_FC_PUBLISH; + pkt->transaction_id = 3; + pkt->stream_name = stream; + + return pkt; } SrsFMLEStartResPacket::SrsFMLEStartResPacket(double _transaction_id) { - command_name = RTMP_AMF0_COMMAND_RESULT; - transaction_id = _transaction_id; - command_object = SrsAmf0Any::null(); - args = SrsAmf0Any::undefined(); + command_name = RTMP_AMF0_COMMAND_RESULT; + transaction_id = _transaction_id; + command_object = SrsAmf0Any::null(); + args = SrsAmf0Any::undefined(); } SrsFMLEStartResPacket::~SrsFMLEStartResPacket() { - srs_freep(command_object); - srs_freep(args); + srs_freep(command_object); + srs_freep(args); } int SrsFMLEStartResPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start response command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode FMLE start response command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start response transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start response command_object failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_undefined(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode FMLE start response stream_id failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode FMLE start packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start response command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode FMLE start response command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start response transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start response command_object failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_undefined(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode FMLE start response stream_id failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode FMLE start packet success"); + + return ret; } int SrsFMLEStartResPacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsFMLEStartResPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsFMLEStartResPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::undefined(); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::undefined(); } int SrsFMLEStartResPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - if ((ret = srs_amf0_write_undefined(stream)) != ERROR_SUCCESS) { - srs_error("encode args failed. ret=%d", ret); - return ret; - } - srs_verbose("encode args success."); - - - srs_info("encode FMLE start response packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + if ((ret = srs_amf0_write_undefined(stream)) != ERROR_SUCCESS) { + srs_error("encode args failed. ret=%d", ret); + return ret; + } + srs_verbose("encode args success."); + + + srs_info("encode FMLE start response packet success."); + + return ret; } SrsPublishPacket::SrsPublishPacket() { - command_name = RTMP_AMF0_COMMAND_PUBLISH; - transaction_id = 0; - command_object = SrsAmf0Any::null(); - type = "live"; + command_name = RTMP_AMF0_COMMAND_PUBLISH; + transaction_id = 0; + command_object = SrsAmf0Any::null(); + type = "live"; } SrsPublishPacket::~SrsPublishPacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsPublishPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode publish command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PUBLISH) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode publish command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode publish transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode publish command_object failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode publish stream_name failed. ret=%d", ret); - return ret; - } - - if (!stream->empty() && (ret = srs_amf0_read_string(stream, type)) != ERROR_SUCCESS) { - srs_error("amf0 decode publish type failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode publish packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode publish command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PUBLISH) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode publish command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode publish transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode publish command_object failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode publish stream_name failed. ret=%d", ret); + return ret; + } + + if (!stream->empty() && (ret = srs_amf0_read_string(stream, type)) != ERROR_SUCCESS) { + srs_error("amf0 decode publish type failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode publish packet success"); + + return ret; } int SrsPublishPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsPublishPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsPublishPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::str(stream_name) - + SrsAmf0Size::str(type); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::str(stream_name) + + SrsAmf0Size::str(type); } int SrsPublishPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - if ((ret = srs_amf0_write_string(stream, stream_name)) != ERROR_SUCCESS) { - srs_error("encode stream_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode stream_name success."); - - if ((ret = srs_amf0_write_string(stream, type)) != ERROR_SUCCESS) { - srs_error("encode type failed. ret=%d", ret); - return ret; - } - srs_verbose("encode type success."); - - srs_info("encode play request packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + if ((ret = srs_amf0_write_string(stream, stream_name)) != ERROR_SUCCESS) { + srs_error("encode stream_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode stream_name success."); + + if ((ret = srs_amf0_write_string(stream, type)) != ERROR_SUCCESS) { + srs_error("encode type failed. ret=%d", ret); + return ret; + } + srs_verbose("encode type success."); + + srs_info("encode play request packet success."); + + return ret; } SrsPausePacket::SrsPausePacket() { - command_name = RTMP_AMF0_COMMAND_PAUSE; - transaction_id = 0; - command_object = SrsAmf0Any::null(); + command_name = RTMP_AMF0_COMMAND_PAUSE; + transaction_id = 0; + command_object = SrsAmf0Any::null(); - time_ms = 0; - is_pause = true; + time_ms = 0; + is_pause = true; } SrsPausePacket::~SrsPausePacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsPausePacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode pause command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PAUSE) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode pause command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode pause transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode pause command_object failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_boolean(stream, is_pause)) != ERROR_SUCCESS) { - srs_error("amf0 decode pause is_pause failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, time_ms)) != ERROR_SUCCESS) { - srs_error("amf0 decode pause time_ms failed. ret=%d", ret); - return ret; - } - - srs_info("amf0 decode pause packet success"); - - return ret; + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode pause command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PAUSE) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode pause command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode pause transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode pause command_object failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_boolean(stream, is_pause)) != ERROR_SUCCESS) { + srs_error("amf0 decode pause is_pause failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, time_ms)) != ERROR_SUCCESS) { + srs_error("amf0 decode pause time_ms failed. ret=%d", ret); + return ret; + } + + srs_info("amf0 decode pause packet success"); + + return ret; } SrsPlayPacket::SrsPlayPacket() { - command_name = RTMP_AMF0_COMMAND_PLAY; - transaction_id = 0; - command_object = SrsAmf0Any::null(); + command_name = RTMP_AMF0_COMMAND_PLAY; + transaction_id = 0; + command_object = SrsAmf0Any::null(); - start = -2; - duration = -1; - reset = true; + start = -2; + duration = -1; + reset = true; } SrsPlayPacket::~SrsPlayPacket() { - srs_freep(command_object); + srs_freep(command_object); } int SrsPlayPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; + int ret = ERROR_SUCCESS; - if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode play command_name failed. ret=%d", ret); - return ret; - } - if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PLAY) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 decode play command_name failed. " - "command_name=%s, ret=%d", command_name.c_str(), ret); - return ret; - } - - if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("amf0 decode play transaction_id failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { - srs_error("amf0 decode play command_object failed. ret=%d", ret); - return ret; - } - - if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { - srs_error("amf0 decode play stream_name failed. ret=%d", ret); - return ret; - } - - if (!stream->empty() && (ret = srs_amf0_read_number(stream, start)) != ERROR_SUCCESS) { - srs_error("amf0 decode play start failed. ret=%d", ret); - return ret; - } - if (!stream->empty() && (ret = srs_amf0_read_number(stream, duration)) != ERROR_SUCCESS) { - srs_error("amf0 decode play duration failed. ret=%d", ret); - return ret; - } + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode play command_name failed. ret=%d", ret); + return ret; + } + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PLAY) { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 decode play command_name failed. " + "command_name=%s, ret=%d", command_name.c_str(), ret); + return ret; + } + + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("amf0 decode play transaction_id failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode play command_object failed. ret=%d", ret); + return ret; + } + + if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { + srs_error("amf0 decode play stream_name failed. ret=%d", ret); + return ret; + } + + if (!stream->empty() && (ret = srs_amf0_read_number(stream, start)) != ERROR_SUCCESS) { + srs_error("amf0 decode play start failed. ret=%d", ret); + return ret; + } + if (!stream->empty() && (ret = srs_amf0_read_number(stream, duration)) != ERROR_SUCCESS) { + srs_error("amf0 decode play duration failed. ret=%d", ret); + return ret; + } if (stream->empty()) { return ret; @@ -2595,337 +2595,337 @@ int SrsPlayPacket::decode(SrsStream* stream) SrsAutoFree(SrsAmf0Any, reset_value, false); if (reset_value) { - // check if the value is bool or number - // An optional Boolean value or number that specifies whether - // to flush any previous playlist - if (reset_value->is_boolean()) { - reset = reset_value->to_boolean(); - } else if (reset_value->is_number()) { - reset = (reset_value->to_number() == 0 ? false : true); - } else { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("amf0 invalid type=%#x, requires number or bool, ret=%d", reset_value->marker, ret); - return ret; - } + // check if the value is bool or number + // An optional Boolean value or number that specifies whether + // to flush any previous playlist + if (reset_value->is_boolean()) { + reset = reset_value->to_boolean(); + } else if (reset_value->is_number()) { + reset = (reset_value->to_number() == 0 ? false : true); + } else { + ret = ERROR_RTMP_AMF0_DECODE; + srs_error("amf0 invalid type=%#x, requires number or bool, ret=%d", reset_value->marker, ret); + return ret; + } } srs_info("amf0 decode play packet success"); - - return ret; + + return ret; } int SrsPlayPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsPlayPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsPlayPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::str(stream_name) - + SrsAmf0Size::number() + SrsAmf0Size::number() - + SrsAmf0Size::boolean(); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::str(stream_name) + + SrsAmf0Size::number() + SrsAmf0Size::number() + + SrsAmf0Size::boolean(); } int SrsPlayPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - if ((ret = srs_amf0_write_string(stream, stream_name)) != ERROR_SUCCESS) { - srs_error("encode stream_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode stream_name success."); - - if ((ret = srs_amf0_write_number(stream, start)) != ERROR_SUCCESS) { - srs_error("encode start failed. ret=%d", ret); - return ret; - } - srs_verbose("encode start success."); - - if ((ret = srs_amf0_write_number(stream, duration)) != ERROR_SUCCESS) { - srs_error("encode duration failed. ret=%d", ret); - return ret; - } - srs_verbose("encode duration success."); - - if ((ret = srs_amf0_write_boolean(stream, reset)) != ERROR_SUCCESS) { - srs_error("encode reset failed. ret=%d", ret); - return ret; - } - srs_verbose("encode reset success."); - - srs_info("encode play request packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + if ((ret = srs_amf0_write_string(stream, stream_name)) != ERROR_SUCCESS) { + srs_error("encode stream_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode stream_name success."); + + if ((ret = srs_amf0_write_number(stream, start)) != ERROR_SUCCESS) { + srs_error("encode start failed. ret=%d", ret); + return ret; + } + srs_verbose("encode start success."); + + if ((ret = srs_amf0_write_number(stream, duration)) != ERROR_SUCCESS) { + srs_error("encode duration failed. ret=%d", ret); + return ret; + } + srs_verbose("encode duration success."); + + if ((ret = srs_amf0_write_boolean(stream, reset)) != ERROR_SUCCESS) { + srs_error("encode reset failed. ret=%d", ret); + return ret; + } + srs_verbose("encode reset success."); + + srs_info("encode play request packet success."); + + return ret; } SrsPlayResPacket::SrsPlayResPacket() { - command_name = RTMP_AMF0_COMMAND_RESULT; - transaction_id = 0; - command_object = SrsAmf0Any::null(); - desc = SrsAmf0Any::object(); + command_name = RTMP_AMF0_COMMAND_RESULT; + transaction_id = 0; + command_object = SrsAmf0Any::null(); + desc = SrsAmf0Any::object(); } SrsPlayResPacket::~SrsPlayResPacket() { - srs_freep(command_object); - srs_freep(desc); + srs_freep(command_object); + srs_freep(desc); } int SrsPlayResPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsPlayResPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsPlayResPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::object(desc); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::object(desc); } int SrsPlayResPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode command_object failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_object success."); - - if ((ret = desc->write(stream)) != ERROR_SUCCESS) { - srs_error("encode desc failed. ret=%d", ret); - return ret; - } - srs_verbose("encode desc success."); - - - srs_info("encode play response packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode command_object failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_object success."); + + if ((ret = desc->write(stream)) != ERROR_SUCCESS) { + srs_error("encode desc failed. ret=%d", ret); + return ret; + } + srs_verbose("encode desc success."); + + + srs_info("encode play response packet success."); + + return ret; } SrsOnBWDonePacket::SrsOnBWDonePacket() { - command_name = RTMP_AMF0_COMMAND_ON_BW_DONE; - transaction_id = 0; - args = SrsAmf0Any::null(); + command_name = RTMP_AMF0_COMMAND_ON_BW_DONE; + transaction_id = 0; + args = SrsAmf0Any::null(); } SrsOnBWDonePacket::~SrsOnBWDonePacket() { - srs_freep(args); + srs_freep(args); } int SrsOnBWDonePacket::get_perfer_cid() { - return RTMP_CID_OverConnection; + return RTMP_CID_OverConnection; } int SrsOnBWDonePacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsOnBWDonePacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null(); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null(); } int SrsOnBWDonePacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode args failed. ret=%d", ret); - return ret; - } - srs_verbose("encode args success."); - - srs_info("encode onBWDone packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode args failed. ret=%d", ret); + return ret; + } + srs_verbose("encode args success."); + + srs_info("encode onBWDone packet success."); + + return ret; } SrsOnStatusCallPacket::SrsOnStatusCallPacket() { - command_name = RTMP_AMF0_COMMAND_ON_STATUS; - transaction_id = 0; - args = SrsAmf0Any::null(); - data = SrsAmf0Any::object(); + command_name = RTMP_AMF0_COMMAND_ON_STATUS; + transaction_id = 0; + args = SrsAmf0Any::null(); + data = SrsAmf0Any::object(); } SrsOnStatusCallPacket::~SrsOnStatusCallPacket() { - srs_freep(args); - srs_freep(data); + srs_freep(args); + srs_freep(data); } int SrsOnStatusCallPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsOnStatusCallPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsOnStatusCallPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::object(data); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::object(data); } int SrsOnStatusCallPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode args failed. ret=%d", ret); - return ret; - } - srs_verbose("encode args success.");; - - if ((ret = data->write(stream)) != ERROR_SUCCESS) { - srs_error("encode data failed. ret=%d", ret); - return ret; - } - srs_verbose("encode data success."); - - srs_info("encode onStatus(Call) packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode args failed. ret=%d", ret); + return ret; + } + srs_verbose("encode args success.");; + + if ((ret = data->write(stream)) != ERROR_SUCCESS) { + srs_error("encode data failed. ret=%d", ret); + return ret; + } + srs_verbose("encode data success."); + + srs_info("encode onStatus(Call) packet success."); + + return ret; } SrsBandwidthPacket::SrsBandwidthPacket() { - command_name = RTMP_AMF0_COMMAND_ON_STATUS; - transaction_id = 0; - args = SrsAmf0Any::null(); - data = SrsAmf0Any::object(); + command_name = RTMP_AMF0_COMMAND_ON_STATUS; + transaction_id = 0; + args = SrsAmf0Any::null(); + data = SrsAmf0Any::object(); } SrsBandwidthPacket::~SrsBandwidthPacket() { - srs_freep(args); - srs_freep(data); + srs_freep(args); + srs_freep(data); } int SrsBandwidthPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsBandwidthPacket::get_message_type() { - return RTMP_MSG_AMF0CommandMessage; + return RTMP_MSG_AMF0CommandMessage; } int SrsBandwidthPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::null() + SrsAmf0Size::object(data); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() + + SrsAmf0Size::null() + SrsAmf0Size::object(data); } int SrsBandwidthPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { - srs_error("encode transaction_id failed. ret=%d", ret); - return ret; - } - srs_verbose("encode transaction_id success."); - - if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { - srs_error("encode args failed. ret=%d", ret); - return ret; - } - srs_verbose("encode args success.");; - - if ((ret = data->write(stream)) != ERROR_SUCCESS) { - srs_error("encode data failed. ret=%d", ret); - return ret; - } - srs_verbose("encode data success."); - - srs_info("encode onStatus(Call) packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) { + srs_error("encode transaction_id failed. ret=%d", ret); + return ret; + } + srs_verbose("encode transaction_id success."); + + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) { + srs_error("encode args failed. ret=%d", ret); + return ret; + } + srs_verbose("encode args success.");; + + if ((ret = data->write(stream)) != ERROR_SUCCESS) { + srs_error("encode data failed. ret=%d", ret); + return ret; + } + srs_verbose("encode data success."); + + srs_info("encode onStatus(Call) packet success."); + + return ret; } int SrsBandwidthPacket::decode(SrsStream *stream) @@ -2956,124 +2956,124 @@ int SrsBandwidthPacket::decode(SrsStream *stream) bool SrsBandwidthPacket::is_starting_play() { - return command_name == SRS_BW_CHECK_STARTING_PLAY; + return command_name == SRS_BW_CHECK_STARTING_PLAY; } bool SrsBandwidthPacket::is_stopped_play() { - return command_name == SRS_BW_CHECK_STOPPED_PLAY; + return command_name == SRS_BW_CHECK_STOPPED_PLAY; } bool SrsBandwidthPacket::is_starting_publish() { - return command_name == SRS_BW_CHECK_STARTING_PUBLISH; + return command_name == SRS_BW_CHECK_STARTING_PUBLISH; } bool SrsBandwidthPacket::is_stopped_publish() { - return command_name == SRS_BW_CHECK_STOPPED_PUBLISH; + return command_name == SRS_BW_CHECK_STOPPED_PUBLISH; } bool SrsBandwidthPacket::is_flash_final() { - return command_name == SRS_BW_CHECK_FLASH_FINAL; + return command_name == SRS_BW_CHECK_FLASH_FINAL; } SrsBandwidthPacket* SrsBandwidthPacket::create_finish() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); - return pkt->set_command(SRS_BW_CHECK_FINISHED); + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_FINISHED); } SrsBandwidthPacket* SrsBandwidthPacket::create_start_play() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); - return pkt->set_command(SRS_BW_CHECK_START_PLAY); + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_START_PLAY); } SrsBandwidthPacket* SrsBandwidthPacket::create_playing() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); return pkt->set_command(SRS_BW_CHECK_PLAYING); } SrsBandwidthPacket* SrsBandwidthPacket::create_stop_play() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); - return pkt->set_command(SRS_BW_CHECK_STOP_PLAY); + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_STOP_PLAY); } SrsBandwidthPacket* SrsBandwidthPacket::create_start_publish() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); - return pkt->set_command(SRS_BW_CHECK_START_PUBLISH); + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_START_PUBLISH); } SrsBandwidthPacket* SrsBandwidthPacket::create_stop_publish() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); - return pkt->set_command(SRS_BW_CHECK_STOP_PUBLISH); + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_STOP_PUBLISH); } SrsBandwidthPacket* SrsBandwidthPacket::set_command(string command) { - command_name = command; - - return this; + command_name = command; + + return this; } SrsOnStatusDataPacket::SrsOnStatusDataPacket() { - command_name = RTMP_AMF0_COMMAND_ON_STATUS; - data = SrsAmf0Any::object(); + command_name = RTMP_AMF0_COMMAND_ON_STATUS; + data = SrsAmf0Any::object(); } SrsOnStatusDataPacket::~SrsOnStatusDataPacket() { - srs_freep(data); + srs_freep(data); } int SrsOnStatusDataPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsOnStatusDataPacket::get_message_type() { - return RTMP_MSG_AMF0DataMessage; + return RTMP_MSG_AMF0DataMessage; } int SrsOnStatusDataPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::object(data); + return SrsAmf0Size::str(command_name) + SrsAmf0Size::object(data); } int SrsOnStatusDataPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = data->write(stream)) != ERROR_SUCCESS) { - srs_error("encode data failed. ret=%d", ret); - return ret; - } - srs_verbose("encode data success."); - - srs_info("encode onStatus(Data) packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = data->write(stream)) != ERROR_SUCCESS) { + srs_error("encode data failed. ret=%d", ret); + return ret; + } + srs_verbose("encode data success."); + + srs_info("encode onStatus(Data) packet success."); + + return ret; } SrsSampleAccessPacket::SrsSampleAccessPacket() { - command_name = RTMP_AMF0_DATA_SAMPLE_ACCESS; - video_sample_access = false; - audio_sample_access = false; + command_name = RTMP_AMF0_DATA_SAMPLE_ACCESS; + video_sample_access = false; + audio_sample_access = false; } SrsSampleAccessPacket::~SrsSampleAccessPacket() @@ -3082,147 +3082,147 @@ SrsSampleAccessPacket::~SrsSampleAccessPacket() int SrsSampleAccessPacket::get_perfer_cid() { - return RTMP_CID_OverStream; + return RTMP_CID_OverStream; } int SrsSampleAccessPacket::get_message_type() { - return RTMP_MSG_AMF0DataMessage; + return RTMP_MSG_AMF0DataMessage; } int SrsSampleAccessPacket::get_size() { - return SrsAmf0Size::str(command_name) - + SrsAmf0Size::boolean() + SrsAmf0Size::boolean(); + return SrsAmf0Size::str(command_name) + + SrsAmf0Size::boolean() + SrsAmf0Size::boolean(); } int SrsSampleAccessPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { - srs_error("encode command_name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode command_name success."); - - if ((ret = srs_amf0_write_boolean(stream, video_sample_access)) != ERROR_SUCCESS) { - srs_error("encode video_sample_access failed. ret=%d", ret); - return ret; - } - srs_verbose("encode video_sample_access success."); - - if ((ret = srs_amf0_write_boolean(stream, audio_sample_access)) != ERROR_SUCCESS) { - srs_error("encode audio_sample_access failed. ret=%d", ret); - return ret; - } - srs_verbose("encode audio_sample_access success.");; - - srs_info("encode |RtmpSampleAccess packet success."); - - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) { + srs_error("encode command_name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode command_name success."); + + if ((ret = srs_amf0_write_boolean(stream, video_sample_access)) != ERROR_SUCCESS) { + srs_error("encode video_sample_access failed. ret=%d", ret); + return ret; + } + srs_verbose("encode video_sample_access success."); + + if ((ret = srs_amf0_write_boolean(stream, audio_sample_access)) != ERROR_SUCCESS) { + srs_error("encode audio_sample_access failed. ret=%d", ret); + return ret; + } + srs_verbose("encode audio_sample_access success.");; + + srs_info("encode |RtmpSampleAccess packet success."); + + return ret; } SrsOnMetaDataPacket::SrsOnMetaDataPacket() { - name = RTMP_AMF0_DATA_ON_METADATA; - metadata = SrsAmf0Any::object(); + name = RTMP_AMF0_DATA_ON_METADATA; + metadata = SrsAmf0Any::object(); } SrsOnMetaDataPacket::~SrsOnMetaDataPacket() { - srs_freep(metadata); + srs_freep(metadata); } int SrsOnMetaDataPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_read_string(stream, name)) != ERROR_SUCCESS) { - srs_error("decode metadata name failed. ret=%d", ret); - return ret; - } + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_read_string(stream, name)) != ERROR_SUCCESS) { + srs_error("decode metadata name failed. ret=%d", ret); + return ret; + } - // ignore the @setDataFrame - if (name == RTMP_AMF0_DATA_SET_DATAFRAME) { - if ((ret = srs_amf0_read_string(stream, name)) != ERROR_SUCCESS) { - srs_error("decode metadata name failed. ret=%d", ret); - return ret; - } - } - - srs_verbose("decode metadata name success. name=%s", name.c_str()); - - // the metadata maybe object or ecma array - SrsAmf0Any* any = NULL; - if ((ret = srs_amf0_read_any(stream, &any)) != ERROR_SUCCESS) { - srs_error("decode metadata metadata failed. ret=%d", ret); - return ret; - } - - srs_assert(any); - if (any->is_object()) { - srs_freep(metadata); - metadata = any->to_object(); - srs_info("decode metadata object success"); - return ret; - } - - SrsAutoFree(SrsAmf0Any, any, false); - - if (any->is_ecma_array()) { - SrsAmf0EcmaArray* arr = any->to_ecma_array(); - - // if ecma array, copy to object. - for (int i = 0; i < arr->count(); i++) { - metadata->set(arr->key_at(i), arr->value_at(i)); - } - - arr->clear(); - srs_info("decode metadata array success"); - } - - return ret; + // ignore the @setDataFrame + if (name == RTMP_AMF0_DATA_SET_DATAFRAME) { + if ((ret = srs_amf0_read_string(stream, name)) != ERROR_SUCCESS) { + srs_error("decode metadata name failed. ret=%d", ret); + return ret; + } + } + + srs_verbose("decode metadata name success. name=%s", name.c_str()); + + // the metadata maybe object or ecma array + SrsAmf0Any* any = NULL; + if ((ret = srs_amf0_read_any(stream, &any)) != ERROR_SUCCESS) { + srs_error("decode metadata metadata failed. ret=%d", ret); + return ret; + } + + srs_assert(any); + if (any->is_object()) { + srs_freep(metadata); + metadata = any->to_object(); + srs_info("decode metadata object success"); + return ret; + } + + SrsAutoFree(SrsAmf0Any, any, false); + + if (any->is_ecma_array()) { + SrsAmf0EcmaArray* arr = any->to_ecma_array(); + + // if ecma array, copy to object. + for (int i = 0; i < arr->count(); i++) { + metadata->set(arr->key_at(i), arr->value_at(i)); + } + + arr->clear(); + srs_info("decode metadata array success"); + } + + return ret; } int SrsOnMetaDataPacket::get_perfer_cid() { - return RTMP_CID_OverConnection2; + return RTMP_CID_OverConnection2; } int SrsOnMetaDataPacket::get_message_type() { - return RTMP_MSG_AMF0DataMessage; + return RTMP_MSG_AMF0DataMessage; } int SrsOnMetaDataPacket::get_size() { - return SrsAmf0Size::str(name) + SrsAmf0Size::object(metadata); + return SrsAmf0Size::str(name) + SrsAmf0Size::object(metadata); } int SrsOnMetaDataPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if ((ret = srs_amf0_write_string(stream, name)) != ERROR_SUCCESS) { - srs_error("encode name failed. ret=%d", ret); - return ret; - } - srs_verbose("encode name success."); - - if ((ret = metadata->write(stream)) != ERROR_SUCCESS) { - srs_error("encode metadata failed. ret=%d", ret); - return ret; - } - srs_verbose("encode metadata success."); - - srs_info("encode onMetaData packet success."); - return ret; + int ret = ERROR_SUCCESS; + + if ((ret = srs_amf0_write_string(stream, name)) != ERROR_SUCCESS) { + srs_error("encode name failed. ret=%d", ret); + return ret; + } + srs_verbose("encode name success."); + + if ((ret = metadata->write(stream)) != ERROR_SUCCESS) { + srs_error("encode metadata failed. ret=%d", ret); + return ret; + } + srs_verbose("encode metadata success."); + + srs_info("encode onMetaData packet success."); + return ret; } SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket() { - ackowledgement_window_size = 0; + ackowledgement_window_size = 0; } SrsSetWindowAckSizePacket::~SrsSetWindowAckSizePacket() @@ -3231,56 +3231,56 @@ SrsSetWindowAckSizePacket::~SrsSetWindowAckSizePacket() int SrsSetWindowAckSizePacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(4)) { - ret = ERROR_RTMP_MESSAGE_DECODE; - srs_error("decode ack window size failed. ret=%d", ret); - return ret; - } - - ackowledgement_window_size = stream->read_4bytes(); - srs_info("decode ack window size success"); - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_DECODE; + srs_error("decode ack window size failed. ret=%d", ret); + return ret; + } + + ackowledgement_window_size = stream->read_4bytes(); + srs_info("decode ack window size success"); + + return ret; } int SrsSetWindowAckSizePacket::get_perfer_cid() { - return RTMP_CID_ProtocolControl; + return RTMP_CID_ProtocolControl; } int SrsSetWindowAckSizePacket::get_message_type() { - return RTMP_MSG_WindowAcknowledgementSize; + return RTMP_MSG_WindowAcknowledgementSize; } int SrsSetWindowAckSizePacket::get_size() { - return 4; + return 4; } int SrsSetWindowAckSizePacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(4)) { - ret = ERROR_RTMP_MESSAGE_ENCODE; - srs_error("encode ack size packet failed. ret=%d", ret); - return ret; - } - - stream->write_4bytes(ackowledgement_window_size); - - srs_verbose("encode ack size packet " - "success. ack_size=%d", ackowledgement_window_size); - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("encode ack size packet failed. ret=%d", ret); + return ret; + } + + stream->write_4bytes(ackowledgement_window_size); + + srs_verbose("encode ack size packet " + "success. ack_size=%d", ackowledgement_window_size); + + return ret; } SrsAcknowledgementPacket::SrsAcknowledgementPacket() { - sequence_number = 0; + sequence_number = 0; } SrsAcknowledgementPacket::~SrsAcknowledgementPacket() @@ -3289,40 +3289,40 @@ SrsAcknowledgementPacket::~SrsAcknowledgementPacket() int SrsAcknowledgementPacket::get_perfer_cid() { - return RTMP_CID_ProtocolControl; + return RTMP_CID_ProtocolControl; } int SrsAcknowledgementPacket::get_message_type() { - return RTMP_MSG_Acknowledgement; + return RTMP_MSG_Acknowledgement; } int SrsAcknowledgementPacket::get_size() { - return 4; + return 4; } int SrsAcknowledgementPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(4)) { - ret = ERROR_RTMP_MESSAGE_ENCODE; - srs_error("encode acknowledgement packet failed. ret=%d", ret); - return ret; - } - - stream->write_4bytes(sequence_number); - - srs_verbose("encode acknowledgement packet " - "success. sequence_number=%d", sequence_number); - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("encode acknowledgement packet failed. ret=%d", ret); + return ret; + } + + stream->write_4bytes(sequence_number); + + srs_verbose("encode acknowledgement packet " + "success. sequence_number=%d", sequence_number); + + return ret; } SrsSetChunkSizePacket::SrsSetChunkSizePacket() { - chunk_size = RTMP_DEFAULT_CHUNK_SIZE; + chunk_size = RTMP_DEFAULT_CHUNK_SIZE; } SrsSetChunkSizePacket::~SrsSetChunkSizePacket() @@ -3331,69 +3331,69 @@ SrsSetChunkSizePacket::~SrsSetChunkSizePacket() int SrsSetChunkSizePacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(4)) { - ret = ERROR_RTMP_MESSAGE_DECODE; - srs_error("decode chunk size failed. ret=%d", ret); - return ret; - } - - chunk_size = stream->read_4bytes(); - srs_info("decode chunk size success. chunk_size=%d", chunk_size); - - if (chunk_size < RTMP_MIN_CHUNK_SIZE) { - ret = ERROR_RTMP_CHUNK_SIZE; - srs_error("invalid chunk size. min=%d, actual=%d, ret=%d", - ERROR_RTMP_CHUNK_SIZE, chunk_size, ret); - return ret; - } - if (chunk_size > RTMP_MAX_CHUNK_SIZE) { - ret = ERROR_RTMP_CHUNK_SIZE; - srs_error("invalid chunk size. max=%d, actual=%d, ret=%d", - RTMP_MAX_CHUNK_SIZE, chunk_size, ret); - return ret; - } - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_DECODE; + srs_error("decode chunk size failed. ret=%d", ret); + return ret; + } + + chunk_size = stream->read_4bytes(); + srs_info("decode chunk size success. chunk_size=%d", chunk_size); + + if (chunk_size < RTMP_MIN_CHUNK_SIZE) { + ret = ERROR_RTMP_CHUNK_SIZE; + srs_error("invalid chunk size. min=%d, actual=%d, ret=%d", + ERROR_RTMP_CHUNK_SIZE, chunk_size, ret); + return ret; + } + if (chunk_size > RTMP_MAX_CHUNK_SIZE) { + ret = ERROR_RTMP_CHUNK_SIZE; + srs_error("invalid chunk size. max=%d, actual=%d, ret=%d", + RTMP_MAX_CHUNK_SIZE, chunk_size, ret); + return ret; + } + + return ret; } int SrsSetChunkSizePacket::get_perfer_cid() { - return RTMP_CID_ProtocolControl; + return RTMP_CID_ProtocolControl; } int SrsSetChunkSizePacket::get_message_type() { - return RTMP_MSG_SetChunkSize; + return RTMP_MSG_SetChunkSize; } int SrsSetChunkSizePacket::get_size() { - return 4; + return 4; } int SrsSetChunkSizePacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(4)) { - ret = ERROR_RTMP_MESSAGE_ENCODE; - srs_error("encode chunk packet failed. ret=%d", ret); - return ret; - } - - stream->write_4bytes(chunk_size); - - srs_verbose("encode chunk packet success. ack_size=%d", chunk_size); - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("encode chunk packet failed. ret=%d", ret); + return ret; + } + + stream->write_4bytes(chunk_size); + + srs_verbose("encode chunk packet success. ack_size=%d", chunk_size); + + return ret; } SrsSetPeerBandwidthPacket::SrsSetPeerBandwidthPacket() { - bandwidth = 0; - type = 2; + bandwidth = 0; + type = 2; } SrsSetPeerBandwidthPacket::~SrsSetPeerBandwidthPacket() @@ -3402,43 +3402,43 @@ SrsSetPeerBandwidthPacket::~SrsSetPeerBandwidthPacket() int SrsSetPeerBandwidthPacket::get_perfer_cid() { - return RTMP_CID_ProtocolControl; + return RTMP_CID_ProtocolControl; } int SrsSetPeerBandwidthPacket::get_message_type() { - return RTMP_MSG_SetPeerBandwidth; + return RTMP_MSG_SetPeerBandwidth; } int SrsSetPeerBandwidthPacket::get_size() { - return 5; + return 5; } int SrsSetPeerBandwidthPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(5)) { - ret = ERROR_RTMP_MESSAGE_ENCODE; - srs_error("encode set bandwidth packet failed. ret=%d", ret); - return ret; - } - - stream->write_4bytes(bandwidth); - stream->write_1bytes(type); - - srs_verbose("encode set bandwidth packet " - "success. bandwidth=%d, type=%d", bandwidth, type); - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(5)) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("encode set bandwidth packet failed. ret=%d", ret); + return ret; + } + + stream->write_4bytes(bandwidth); + stream->write_1bytes(type); + + srs_verbose("encode set bandwidth packet " + "success. bandwidth=%d, type=%d", bandwidth, type); + + return ret; } SrsUserControlPacket::SrsUserControlPacket() { - event_type = 0; - event_data = 0; - extra_data = 0; + event_type = 0; + event_data = 0; + extra_data = 0; } SrsUserControlPacket::~SrsUserControlPacket() @@ -3447,75 +3447,75 @@ SrsUserControlPacket::~SrsUserControlPacket() int SrsUserControlPacket::decode(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(6)) { - ret = ERROR_RTMP_MESSAGE_DECODE; - srs_error("decode user control failed. ret=%d", ret); - return ret; - } - - event_type = stream->read_2bytes(); - event_data = stream->read_4bytes(); - - if (event_type == SrcPCUCSetBufferLength) { - if (!stream->require(4)) { - ret = ERROR_RTMP_MESSAGE_ENCODE; - srs_error("decode user control packet failed. ret=%d", ret); - return ret; - } - extra_data = stream->read_4bytes(); - } - - srs_info("decode user control success. " - "event_type=%d, event_data=%d, extra_data=%d", - event_type, event_data, extra_data); - - return ret; + int ret = ERROR_SUCCESS; + + if (!stream->require(6)) { + ret = ERROR_RTMP_MESSAGE_DECODE; + srs_error("decode user control failed. ret=%d", ret); + return ret; + } + + event_type = stream->read_2bytes(); + event_data = stream->read_4bytes(); + + if (event_type == SrcPCUCSetBufferLength) { + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("decode user control packet failed. ret=%d", ret); + return ret; + } + extra_data = stream->read_4bytes(); + } + + srs_info("decode user control success. " + "event_type=%d, event_data=%d, extra_data=%d", + event_type, event_data, extra_data); + + return ret; } int SrsUserControlPacket::get_perfer_cid() { - return RTMP_CID_ProtocolControl; + return RTMP_CID_ProtocolControl; } int SrsUserControlPacket::get_message_type() { - return RTMP_MSG_UserControlMessage; + return RTMP_MSG_UserControlMessage; } int SrsUserControlPacket::get_size() { - if (event_type == SrcPCUCSetBufferLength) { - return 2 + 4 + 4; - } else { - return 2 + 4; - } + if (event_type == SrcPCUCSetBufferLength) { + return 2 + 4 + 4; + } else { + return 2 + 4; + } } int SrsUserControlPacket::encode_packet(SrsStream* stream) { - int ret = ERROR_SUCCESS; - - if (!stream->require(get_size())) { - ret = ERROR_RTMP_MESSAGE_ENCODE; - srs_error("encode user control packet failed. ret=%d", ret); - return ret; - } - - stream->write_2bytes(event_type); - stream->write_4bytes(event_data); + int ret = ERROR_SUCCESS; + + if (!stream->require(get_size())) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("encode user control packet failed. ret=%d", ret); + return ret; + } + + stream->write_2bytes(event_type); + stream->write_4bytes(event_data); - // when event type is set buffer length, - // write the extra buffer length. - if (event_type == SrcPCUCSetBufferLength) { - stream->write_2bytes(extra_data); - srs_verbose("user control message, buffer_length=%d", extra_data); - } - - srs_verbose("encode user control packet success. " - "event_type=%d, event_data=%d", event_type, event_data); - - return ret; + // when event type is set buffer length, + // write the extra buffer length. + if (event_type == SrcPCUCSetBufferLength) { + stream->write_2bytes(extra_data); + srs_verbose("user control message, buffer_length=%d", extra_data); + } + + srs_verbose("encode user control packet success. " + "event_type=%d, event_data=%d", event_type, event_data); + + return ret; } diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp index d56348beb..801f2d0bc 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp +++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp @@ -94,16 +94,16 @@ class ISrsMessage; /** * max rtmp header size: -* 1bytes basic header, -* 11bytes message header, -* 4bytes timestamp header, +* 1bytes basic header, +* 11bytes message header, +* 4bytes timestamp header, * that is, 1+11+4=16bytes. */ #define RTMP_MAX_FMT0_HEADER_SIZE 16 /** * max rtmp header size: -* 1bytes basic header, -* 4bytes timestamp header, +* 1bytes basic header, +* 4bytes timestamp header, * that is, 1+4=5bytes. */ #define RTMP_MAX_FMT3_HEADER_SIZE 5 @@ -116,106 +116,106 @@ class ISrsMessage; class SrsProtocol { private: - struct AckWindowSize - { - int ack_window_size; - int64_t acked_size; - - AckWindowSize(); - }; + struct AckWindowSize + { + int ack_window_size; + int64_t acked_size; + + AckWindowSize(); + }; // peer in/out private: - ISrsProtocolReaderWriter* skt; - char* pp; - /** - * requests sent out, used to build the response. - * key: transactionId - * value: the request command name - */ - std::map requests; + ISrsProtocolReaderWriter* skt; + char* pp; + /** + * requests sent out, used to build the response. + * key: transactionId + * value: the request command name + */ + std::map requests; // peer in private: - std::map chunk_streams; - SrsBuffer* buffer; - int32_t in_chunk_size; - AckWindowSize in_ack_size; + std::map chunk_streams; + SrsBuffer* buffer; + int32_t in_chunk_size; + AckWindowSize in_ack_size; // peer out private: - char out_header_fmt0[RTMP_MAX_FMT0_HEADER_SIZE]; - char out_header_fmt3[RTMP_MAX_FMT3_HEADER_SIZE]; - int32_t out_chunk_size; + char out_header_fmt0[RTMP_MAX_FMT0_HEADER_SIZE]; + char out_header_fmt3[RTMP_MAX_FMT3_HEADER_SIZE]; + int32_t out_chunk_size; public: - /** - * use io to create the protocol stack, - * @param io, provides io interfaces, user must free it. - */ - SrsProtocol(ISrsProtocolReaderWriter* io); - virtual ~SrsProtocol(); + /** + * use io to create the protocol stack, + * @param io, provides io interfaces, user must free it. + */ + SrsProtocol(ISrsProtocolReaderWriter* io); + virtual ~SrsProtocol(); public: - std::string get_request_name(double transcationId); - /** - * set the timeout in us. - * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. - */ - virtual void set_recv_timeout(int64_t timeout_us); - virtual int64_t get_recv_timeout(); - virtual void set_send_timeout(int64_t timeout_us); - virtual int64_t get_send_timeout(); - virtual int64_t get_recv_bytes(); - virtual int64_t get_send_bytes(); - virtual int get_recv_kbps(); - virtual int get_send_kbps(); - /** - * recv a message with raw/undecoded payload from peer. - * the payload is not decoded, use srs_rtmp_expect_message if requires - * specifies message. - * @pmsg, user must free it. NULL if not success. - * @remark, only when success, user can use and must free the pmsg. - */ - virtual int recv_message(SrsCommonMessage** pmsg); - /** - * send out message with encoded payload to peer. - * use the message encode method to encode to payload, - * then sendout over socket. - * @msg this method will free it whatever return value. - */ - virtual int send_message(ISrsMessage* msg); + std::string get_request_name(double transcationId); + /** + * set the timeout in us. + * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. + */ + virtual void set_recv_timeout(int64_t timeout_us); + virtual int64_t get_recv_timeout(); + virtual void set_send_timeout(int64_t timeout_us); + virtual int64_t get_send_timeout(); + virtual int64_t get_recv_bytes(); + virtual int64_t get_send_bytes(); + virtual int get_recv_kbps(); + virtual int get_send_kbps(); + /** + * recv a message with raw/undecoded payload from peer. + * the payload is not decoded, use srs_rtmp_expect_message if requires + * specifies message. + * @pmsg, user must free it. NULL if not success. + * @remark, only when success, user can use and must free the pmsg. + */ + virtual int recv_message(SrsCommonMessage** pmsg); + /** + * send out message with encoded payload to peer. + * use the message encode method to encode to payload, + * then sendout over socket. + * @msg this method will free it whatever return value. + */ + virtual int send_message(ISrsMessage* msg); private: - /** - * when recv message, update the context. - */ - virtual int on_recv_message(SrsCommonMessage* msg); - virtual int response_acknowledgement_message(); - virtual int response_ping_message(int32_t timestamp); - /** - * when message sentout, update the context. - */ - virtual int on_send_message(ISrsMessage* msg); - /** - * try to recv interlaced message from peer, - * return error if error occur and nerver set the pmsg, - * return success and pmsg set to NULL if no entire message got, - * return success and pmsg set to entire message if got one. - */ - virtual int recv_interlaced_message(SrsCommonMessage** pmsg); - /** - * read the chunk basic header(fmt, cid) from chunk stream. - * user can discovery a SrsChunkStream by cid. - * @bh_size return the chunk basic header size, to remove the used bytes when finished. - */ - virtual int read_basic_header(char& fmt, int& cid, int& bh_size); - /** - * read the chunk message header(timestamp, payload_length, message_type, stream_id) - * from chunk stream and save to SrsChunkStream. - * @mh_size return the chunk message header size, to remove the used bytes when finished. - */ - virtual int read_message_header(SrsChunkStream* chunk, char fmt, int bh_size, int& mh_size); - /** - * read the chunk payload, remove the used bytes in buffer, - * if got entire message, set the pmsg. - * @payload_size read size in this roundtrip, generally a chunk size or left message size. - */ - virtual int read_message_payload(SrsChunkStream* chunk, int bh_size, int mh_size, int& payload_size, SrsCommonMessage** pmsg); + /** + * when recv message, update the context. + */ + virtual int on_recv_message(SrsCommonMessage* msg); + virtual int response_acknowledgement_message(); + virtual int response_ping_message(int32_t timestamp); + /** + * when message sentout, update the context. + */ + virtual int on_send_message(ISrsMessage* msg); + /** + * try to recv interlaced message from peer, + * return error if error occur and nerver set the pmsg, + * return success and pmsg set to NULL if no entire message got, + * return success and pmsg set to entire message if got one. + */ + virtual int recv_interlaced_message(SrsCommonMessage** pmsg); + /** + * read the chunk basic header(fmt, cid) from chunk stream. + * user can discovery a SrsChunkStream by cid. + * @bh_size return the chunk basic header size, to remove the used bytes when finished. + */ + virtual int read_basic_header(char& fmt, int& cid, int& bh_size); + /** + * read the chunk message header(timestamp, payload_length, message_type, stream_id) + * from chunk stream and save to SrsChunkStream. + * @mh_size return the chunk message header size, to remove the used bytes when finished. + */ + virtual int read_message_header(SrsChunkStream* chunk, char fmt, int bh_size, int& mh_size); + /** + * read the chunk payload, remove the used bytes in buffer, + * if got entire message, set the pmsg. + * @payload_size read size in this roundtrip, generally a chunk size or left message size. + */ + virtual int read_message_payload(SrsChunkStream* chunk, int bh_size, int mh_size, int& payload_size, SrsCommonMessage** pmsg); }; /** @@ -223,52 +223,52 @@ private: */ struct SrsMessageHeader { - /** - * One byte field to represent the message type. A range of type IDs - * (1-7) are reserved for protocol control messages. - */ - int8_t message_type; - /** - * Three-byte field that represents the size of the payload in bytes. - * It is set in big-endian format. - */ - int32_t payload_length; - /** - * Three-byte field that contains a timestamp delta of the message. - * The 4 bytes are packed in the big-endian order. - * @remark, only used for decoding message from chunk stream. - */ - int32_t timestamp_delta; - /** - * Three-byte field that identifies the stream of the message. These - * bytes are set in big-endian format. - */ - int32_t stream_id; - - /** - * Four-byte field that contains a timestamp of the message. - * The 4 bytes are packed in the big-endian order. - * @remark, used as calc timestamp when decode and encode time. - * @remark, we use 64bits for large time for jitter detect and hls. - */ - int64_t timestamp; - - SrsMessageHeader(); - virtual ~SrsMessageHeader(); + /** + * One byte field to represent the message type. A range of type IDs + * (1-7) are reserved for protocol control messages. + */ + int8_t message_type; + /** + * Three-byte field that represents the size of the payload in bytes. + * It is set in big-endian format. + */ + int32_t payload_length; + /** + * Three-byte field that contains a timestamp delta of the message. + * The 4 bytes are packed in the big-endian order. + * @remark, only used for decoding message from chunk stream. + */ + int32_t timestamp_delta; + /** + * Three-byte field that identifies the stream of the message. These + * bytes are set in big-endian format. + */ + int32_t stream_id; + + /** + * Four-byte field that contains a timestamp of the message. + * The 4 bytes are packed in the big-endian order. + * @remark, used as calc timestamp when decode and encode time. + * @remark, we use 64bits for large time for jitter detect and hls. + */ + int64_t timestamp; + + SrsMessageHeader(); + virtual ~SrsMessageHeader(); - bool is_audio(); - bool is_video(); - bool is_amf0_command(); - bool is_amf0_data(); - bool is_amf3_command(); - bool is_amf3_data(); - bool is_window_ackledgement_size(); - bool is_set_chunk_size(); - bool is_user_control_message(); - - void initialize_amf0_script(int size, int stream); - void initialize_audio(int size, u_int32_t time, int stream); - void initialize_video(int size, u_int32_t time, int stream); + bool is_audio(); + bool is_video(); + bool is_amf0_command(); + bool is_amf0_data(); + bool is_amf3_command(); + bool is_amf3_data(); + bool is_window_ackledgement_size(); + bool is_set_chunk_size(); + bool is_user_control_message(); + + void initialize_amf0_script(int size, int stream); + void initialize_audio(int size, u_int32_t time, int stream); + void initialize_video(int size, u_int32_t time, int stream); }; /** @@ -278,35 +278,35 @@ struct SrsMessageHeader class SrsChunkStream { public: - /** - * represents the basic header fmt, - * which used to identify the variant message header type. - */ - char fmt; - /** - * represents the basic header cid, - * which is the chunk stream id. - */ - int cid; - /** - * cached message header - */ - SrsMessageHeader header; - /** - * whether the chunk message header has extended timestamp. - */ - bool extended_timestamp; - /** - * partially read message. - */ - SrsCommonMessage* msg; - /** - * decoded msg count, to identify whether the chunk stream is fresh. - */ - int64_t msg_count; + /** + * represents the basic header fmt, + * which used to identify the variant message header type. + */ + char fmt; + /** + * represents the basic header cid, + * which is the chunk stream id. + */ + int cid; + /** + * cached message header + */ + SrsMessageHeader header; + /** + * whether the chunk message header has extended timestamp. + */ + bool extended_timestamp; + /** + * partially read message. + */ + SrsCommonMessage* msg; + /** + * decoded msg count, to identify whether the chunk stream is fresh. + */ + int64_t msg_count; public: - SrsChunkStream(int _cid); - virtual ~SrsChunkStream(); + SrsChunkStream(int _cid); + virtual ~SrsChunkStream(); }; /** @@ -316,39 +316,39 @@ class ISrsMessage { // 4.1. Message Header public: - SrsMessageHeader header; + SrsMessageHeader header; // 4.2. Message Payload public: - /** - * The other part which is the payload is the actual data that is - * contained in the message. For example, it could be some audio samples - * or compressed video data. The payload format and interpretation are - * beyond the scope of this document. - */ - int32_t size; - int8_t* payload; + /** + * The other part which is the payload is the actual data that is + * contained in the message. For example, it could be some audio samples + * or compressed video data. The payload format and interpretation are + * beyond the scope of this document. + */ + int32_t size; + int8_t* payload; public: - ISrsMessage(); - virtual ~ISrsMessage(); + ISrsMessage(); + virtual ~ISrsMessage(); public: - /** - * whether message canbe decoded. - * only update the context when message canbe decoded. - */ - virtual bool can_decode() = 0; + /** + * whether message canbe decoded. + * only update the context when message canbe decoded. + */ + virtual bool can_decode() = 0; /** * encode functions. */ public: - /** - * get the perfered cid(chunk stream id) which sendout over. - */ - virtual int get_perfer_cid() = 0; - /** - * encode the packet to message payload bytes. - * @remark there exists empty packet, so maybe the payload is NULL. - */ - virtual int encode_packet() = 0; + /** + * get the perfered cid(chunk stream id) which sendout over. + */ + virtual int get_perfer_cid() = 0; + /** + * encode the packet to message payload bytes. + * @remark there exists empty packet, so maybe the payload is NULL. + */ + virtual int encode_packet() = 0; }; /** @@ -358,52 +358,52 @@ public: class SrsCommonMessage : public ISrsMessage { private: - typedef ISrsMessage super; - disable_default_copy(SrsCommonMessage); + typedef ISrsMessage super; + disable_default_copy(SrsCommonMessage); // decoded message payload. private: - SrsStream* stream; - SrsPacket* packet; + SrsStream* stream; + SrsPacket* packet; public: - SrsCommonMessage(); - virtual ~SrsCommonMessage(); + SrsCommonMessage(); + virtual ~SrsCommonMessage(); public: - virtual bool can_decode(); + virtual bool can_decode(); /** * decode functions. */ public: - /** - * decode packet from message payload. - */ - // TODO: use protocol to decode it. - virtual int decode_packet(SrsProtocol* protocol); - /** - * get the decoded packet which decoded by decode_packet(). - * @remark, user never free the pkt, the message will auto free it. - */ - virtual SrsPacket* get_packet(); + /** + * decode packet from message payload. + */ + // TODO: use protocol to decode it. + virtual int decode_packet(SrsProtocol* protocol); + /** + * get the decoded packet which decoded by decode_packet(). + * @remark, user never free the pkt, the message will auto free it. + */ + virtual SrsPacket* get_packet(); /** * encode functions. */ public: - /** - * get the perfered cid(chunk stream id) which sendout over. - */ - virtual int get_perfer_cid(); - /** - * set the encoded packet to encode_packet() to payload. - * @stream_id, the id of stream which is created by createStream. - * @remark, user never free the pkt, the message will auto free it. - * @return message itself. - */ - // TODO: refine the send methods. - virtual SrsCommonMessage* set_packet(SrsPacket* pkt, int stream_id); - /** - * encode the packet to message payload bytes. - * @remark there exists empty packet, so maybe the payload is NULL. - */ - virtual int encode_packet(); + /** + * get the perfered cid(chunk stream id) which sendout over. + */ + virtual int get_perfer_cid(); + /** + * set the encoded packet to encode_packet() to payload. + * @stream_id, the id of stream which is created by createStream. + * @remark, user never free the pkt, the message will auto free it. + * @return message itself. + */ + // TODO: refine the send methods. + virtual SrsCommonMessage* set_packet(SrsPacket* pkt, int stream_id); + /** + * encode the packet to message payload bytes. + * @remark there exists empty packet, so maybe the payload is NULL. + */ + virtual int encode_packet(); }; /** @@ -414,108 +414,108 @@ public: class SrsSharedPtrMessage : public ISrsMessage { private: - typedef ISrsMessage super; + typedef ISrsMessage super; private: - struct SrsSharedPtr - { - char* payload; - int size; - int perfer_cid; - int shared_count; - - SrsSharedPtr(); - virtual ~SrsSharedPtr(); - }; - SrsSharedPtr* ptr; + struct SrsSharedPtr + { + char* payload; + int size; + int perfer_cid; + int shared_count; + + SrsSharedPtr(); + virtual ~SrsSharedPtr(); + }; + SrsSharedPtr* ptr; public: - SrsSharedPtrMessage(); - virtual ~SrsSharedPtrMessage(); + SrsSharedPtrMessage(); + virtual ~SrsSharedPtrMessage(); public: - virtual bool can_decode(); + virtual bool can_decode(); public: - /** - * set the shared payload. - * we will detach the payload of source, - * so ensure donot use it before. - */ - virtual int initialize(SrsCommonMessage* source); - /** - * set the shared payload. - * use source header, and specified param payload. - */ - virtual int initialize(SrsMessageHeader* source, char* payload, int size); - virtual SrsSharedPtrMessage* copy(); + /** + * set the shared payload. + * we will detach the payload of source, + * so ensure donot use it before. + */ + virtual int initialize(SrsCommonMessage* source); + /** + * set the shared payload. + * use source header, and specified param payload. + */ + virtual int initialize(SrsMessageHeader* source, char* payload, int size); + virtual SrsSharedPtrMessage* copy(); public: - /** - * get the perfered cid(chunk stream id) which sendout over. - */ - virtual int get_perfer_cid(); - /** - * ignored. - * for shared message, nothing should be done. - * use initialize() to set the data. - */ - virtual int encode_packet(); + /** + * get the perfered cid(chunk stream id) which sendout over. + */ + virtual int get_perfer_cid(); + /** + * ignored. + * for shared message, nothing should be done. + * use initialize() to set the data. + */ + virtual int encode_packet(); }; /** * the decoded message payload. * @remark we seperate the packet from message, -* for the packet focus on logic and domain data, -* the message bind to the protocol and focus on protocol, such as header. -* we can merge the message and packet, using OOAD hierachy, packet extends from message, -* it's better for me to use components -- the message use the packet as payload. +* for the packet focus on logic and domain data, +* the message bind to the protocol and focus on protocol, such as header. +* we can merge the message and packet, using OOAD hierachy, packet extends from message, +* it's better for me to use components -- the message use the packet as payload. */ class SrsPacket { protected: - /** - * subpacket must override to provide the right class name. - */ - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsPacket); - } + /** + * subpacket must override to provide the right class name. + */ + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsPacket); + } public: - SrsPacket(); - virtual ~SrsPacket(); + SrsPacket(); + virtual ~SrsPacket(); /** * decode functions. */ public: - /** - * subpacket must override to decode packet from stream. - * @remark never invoke the super.decode, it always failed. - */ - virtual int decode(SrsStream* stream); + /** + * subpacket must override to decode packet from stream. + * @remark never invoke the super.decode, it always failed. + */ + virtual int decode(SrsStream* stream); /** * encode functions. */ public: - virtual int get_perfer_cid(); - virtual int get_payload_length(); + virtual int get_perfer_cid(); + virtual int get_payload_length(); public: - /** - * subpacket must override to provide the right message type. - */ - virtual int get_message_type(); - /** - * the subpacket can override this encode, - * for example, video and audio will directly set the payload withou memory copy, - * other packet which need to serialize/encode to bytes by override the - * get_size and encode_packet. - */ - virtual int encode(int& size, char*& payload); + /** + * subpacket must override to provide the right message type. + */ + virtual int get_message_type(); + /** + * the subpacket can override this encode, + * for example, video and audio will directly set the payload withou memory copy, + * other packet which need to serialize/encode to bytes by override the + * get_size and encode_packet. + */ + virtual int encode(int& size, char*& payload); protected: - /** - * subpacket can override to calc the packet size. - */ - virtual int get_size(); - /** - * subpacket can override to encode the payload to stream. - * @remark never invoke the super.encode_packet, it always failed. - */ - virtual int encode_packet(SrsStream* stream); + /** + * subpacket can override to calc the packet size. + */ + virtual int get_size(); + /** + * subpacket can override to encode the payload to stream. + * @remark never invoke the super.encode_packet, it always failed. + */ + virtual int encode_packet(SrsStream* stream); }; /** @@ -526,28 +526,28 @@ protected: class SrsConnectAppPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsConnectAppPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsConnectAppPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Object* command_object; + std::string command_name; + double transaction_id; + SrsAmf0Object* command_object; public: - SrsConnectAppPacket(); - virtual ~SrsConnectAppPacket(); + SrsConnectAppPacket(); + virtual ~SrsConnectAppPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** * response for SrsConnectAppPacket. @@ -555,29 +555,29 @@ protected: class SrsConnectAppResPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsConnectAppResPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsConnectAppResPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Object* props; - SrsAmf0Object* info; + std::string command_name; + double transaction_id; + SrsAmf0Object* props; + SrsAmf0Object* info; public: - SrsConnectAppResPacket(); - virtual ~SrsConnectAppResPacket(); + SrsConnectAppResPacket(); + virtual ~SrsConnectAppResPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -590,28 +590,28 @@ protected: class SrsCreateStreamPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsCreateStreamPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsCreateStreamPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null public: - SrsCreateStreamPacket(); - virtual ~SrsCreateStreamPacket(); + SrsCreateStreamPacket(); + virtual ~SrsCreateStreamPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** * response for SrsCreateStreamPacket. @@ -619,29 +619,29 @@ protected: class SrsCreateStreamResPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsCreateStreamResPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsCreateStreamResPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - double stream_id; + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + double stream_id; public: - SrsCreateStreamResPacket(double _transaction_id, double _stream_id); - virtual ~SrsCreateStreamResPacket(); + SrsCreateStreamResPacket(double _transaction_id, double _stream_id); + virtual ~SrsCreateStreamResPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** * client close stream packet. @@ -672,32 +672,32 @@ public: class SrsFMLEStartPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsFMLEStartPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsFMLEStartPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - std::string stream_name; + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + std::string stream_name; public: - SrsFMLEStartPacket(); - virtual ~SrsFMLEStartPacket(); + SrsFMLEStartPacket(); + virtual ~SrsFMLEStartPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); public: - static SrsFMLEStartPacket* create_release_stream(std::string stream); - static SrsFMLEStartPacket* create_FC_publish(std::string stream); + static SrsFMLEStartPacket* create_release_stream(std::string stream); + static SrsFMLEStartPacket* create_FC_publish(std::string stream); }; /** * response for SrsFMLEStartPacket. @@ -705,29 +705,29 @@ public: class SrsFMLEStartResPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsFMLEStartResPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsFMLEStartResPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - SrsAmf0Any* args; // undefined + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + SrsAmf0Any* args; // undefined public: - SrsFMLEStartResPacket(double _transaction_id); - virtual ~SrsFMLEStartResPacket(); + SrsFMLEStartResPacket(double _transaction_id); + virtual ~SrsFMLEStartResPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -740,31 +740,31 @@ protected: class SrsPublishPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsPublishPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsPublishPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - std::string stream_name; - // optional, default to live. - std::string type; + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + std::string stream_name; + // optional, default to live. + std::string type; public: - SrsPublishPacket(); - virtual ~SrsPublishPacket(); + SrsPublishPacket(); + virtual ~SrsPublishPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -775,23 +775,23 @@ protected: class SrsPausePacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsPausePacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsPausePacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - bool is_pause; - double time_ms; + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + bool is_pause; + double time_ms; public: - SrsPausePacket(); - virtual ~SrsPausePacket(); + SrsPausePacket(); + virtual ~SrsPausePacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); }; /** @@ -801,32 +801,32 @@ public: class SrsPlayPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsPlayPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsPlayPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - std::string stream_name; - double start; - double duration; - bool reset; + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + std::string stream_name; + double start; + double duration; + bool reset; public: - SrsPlayPacket(); - virtual ~SrsPlayPacket(); + SrsPlayPacket(); + virtual ~SrsPlayPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** * response for SrsPlayPacket. @@ -835,27 +835,27 @@ protected: class SrsPlayResPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsPlayResPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsPlayResPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* command_object; // null - SrsAmf0Object* desc; + std::string command_name; + double transaction_id; + SrsAmf0Any* command_object; // null + SrsAmf0Object* desc; public: - SrsPlayResPacket(); - virtual ~SrsPlayResPacket(); + SrsPlayResPacket(); + virtual ~SrsPlayResPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -864,26 +864,26 @@ protected: class SrsOnBWDonePacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsOnBWDonePacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsOnBWDonePacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* args; // null + std::string command_name; + double transaction_id; + SrsAmf0Any* args; // null public: - SrsOnBWDonePacket(); - virtual ~SrsOnBWDonePacket(); + SrsOnBWDonePacket(); + virtual ~SrsOnBWDonePacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -893,27 +893,27 @@ protected: class SrsOnStatusCallPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsOnStatusCallPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsOnStatusCallPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* args; // null - SrsAmf0Object* data; + std::string command_name; + double transaction_id; + SrsAmf0Any* args; // null + SrsAmf0Object* data; public: - SrsOnStatusCallPacket(); - virtual ~SrsOnStatusCallPacket(); + SrsOnStatusCallPacket(); + virtual ~SrsOnStatusCallPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -925,44 +925,44 @@ protected: class SrsBandwidthPacket : public SrsPacket { private: - typedef SrsPacket super; - disable_default_copy(SrsBandwidthPacket); + typedef SrsPacket super; + disable_default_copy(SrsBandwidthPacket); protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsBandwidthPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsBandwidthPacket); + } public: - std::string command_name; - double transaction_id; - SrsAmf0Any* args; // null - SrsAmf0Object* data; + std::string command_name; + double transaction_id; + SrsAmf0Any* args; // null + SrsAmf0Object* data; public: - SrsBandwidthPacket(); - virtual ~SrsBandwidthPacket(); + SrsBandwidthPacket(); + virtual ~SrsBandwidthPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); public: virtual int decode(SrsStream* stream); public: - virtual bool is_starting_play(); - virtual bool is_stopped_play(); - virtual bool is_starting_publish(); - virtual bool is_stopped_publish(); - virtual bool is_flash_final(); - static SrsBandwidthPacket* create_finish(); - static SrsBandwidthPacket* create_start_play(); - static SrsBandwidthPacket* create_playing(); - static SrsBandwidthPacket* create_stop_play(); - static SrsBandwidthPacket* create_start_publish(); - static SrsBandwidthPacket* create_stop_publish(); + virtual bool is_starting_play(); + virtual bool is_stopped_play(); + virtual bool is_starting_publish(); + virtual bool is_stopped_publish(); + virtual bool is_flash_final(); + static SrsBandwidthPacket* create_finish(); + static SrsBandwidthPacket* create_start_play(); + static SrsBandwidthPacket* create_playing(); + static SrsBandwidthPacket* create_stop_play(); + static SrsBandwidthPacket* create_start_publish(); + static SrsBandwidthPacket* create_stop_publish(); private: - virtual SrsBandwidthPacket* set_command(std::string command); + virtual SrsBandwidthPacket* set_command(std::string command); }; /** @@ -972,25 +972,25 @@ private: class SrsOnStatusDataPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsOnStatusDataPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsOnStatusDataPacket); + } public: - std::string command_name; - SrsAmf0Object* data; + std::string command_name; + SrsAmf0Object* data; public: - SrsOnStatusDataPacket(); - virtual ~SrsOnStatusDataPacket(); + SrsOnStatusDataPacket(); + virtual ~SrsOnStatusDataPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1000,26 +1000,26 @@ protected: class SrsSampleAccessPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsSampleAccessPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsSampleAccessPacket); + } public: - std::string command_name; - bool video_sample_access; - bool audio_sample_access; + std::string command_name; + bool video_sample_access; + bool audio_sample_access; public: - SrsSampleAccessPacket(); - virtual ~SrsSampleAccessPacket(); + SrsSampleAccessPacket(); + virtual ~SrsSampleAccessPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1030,27 +1030,27 @@ protected: class SrsOnMetaDataPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsOnMetaDataPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsOnMetaDataPacket); + } public: - std::string name; - SrsAmf0Object* metadata; + std::string name; + SrsAmf0Object* metadata; public: - SrsOnMetaDataPacket(); - virtual ~SrsOnMetaDataPacket(); + SrsOnMetaDataPacket(); + virtual ~SrsOnMetaDataPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1061,26 +1061,26 @@ protected: class SrsSetWindowAckSizePacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsSetWindowAckSizePacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsSetWindowAckSizePacket); + } public: - int32_t ackowledgement_window_size; + int32_t ackowledgement_window_size; public: - SrsSetWindowAckSizePacket(); - virtual ~SrsSetWindowAckSizePacket(); + SrsSetWindowAckSizePacket(); + virtual ~SrsSetWindowAckSizePacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1091,24 +1091,24 @@ protected: class SrsAcknowledgementPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsAcknowledgementPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsAcknowledgementPacket); + } public: - int32_t sequence_number; + int32_t sequence_number; public: - SrsAcknowledgementPacket(); - virtual ~SrsAcknowledgementPacket(); + SrsAcknowledgementPacket(); + virtual ~SrsAcknowledgementPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1119,26 +1119,26 @@ protected: class SrsSetChunkSizePacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsSetChunkSizePacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsSetChunkSizePacket); + } public: - int32_t chunk_size; + int32_t chunk_size; public: - SrsSetChunkSizePacket(); - virtual ~SrsSetChunkSizePacket(); + SrsSetChunkSizePacket(); + virtual ~SrsSetChunkSizePacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1149,49 +1149,49 @@ protected: class SrsSetPeerBandwidthPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsSetPeerBandwidthPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsSetPeerBandwidthPacket); + } public: - int32_t bandwidth; - int8_t type; + int32_t bandwidth; + int8_t type; public: - SrsSetPeerBandwidthPacket(); - virtual ~SrsSetPeerBandwidthPacket(); + SrsSetPeerBandwidthPacket(); + virtual ~SrsSetPeerBandwidthPacket(); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; // 3.7. User Control message enum SrcPCUCEventType { - // generally, 4bytes event-data - SrcPCUCStreamBegin = 0x00, - SrcPCUCStreamEOF = 0x01, - SrcPCUCStreamDry = 0x02, - SrcPCUCSetBufferLength = 0x03, // 8bytes event-data - SrcPCUCStreamIsRecorded = 0x04, - SrcPCUCPingRequest = 0x06, - SrcPCUCPingResponse = 0x07, + // generally, 4bytes event-data + SrcPCUCStreamBegin = 0x00, + SrcPCUCStreamEOF = 0x01, + SrcPCUCStreamDry = 0x02, + SrcPCUCSetBufferLength = 0x03, // 8bytes event-data + SrcPCUCStreamIsRecorded = 0x04, + SrcPCUCPingRequest = 0x06, + SrcPCUCPingResponse = 0x07, }; /** * for the EventData is 4bytes. -* Stream Begin(=0) 4-bytes stream ID -* Stream EOF(=1) 4-bytes stream ID -* StreamDry(=2) 4-bytes stream ID -* SetBufferLength(=3) 8-bytes 4bytes stream ID, 4bytes buffer length. -* StreamIsRecorded(=4) 4-bytes stream ID -* PingRequest(=6) 4-bytes timestamp local server time -* PingResponse(=7) 4-bytes timestamp received ping request. +* Stream Begin(=0) 4-bytes stream ID +* Stream EOF(=1) 4-bytes stream ID +* StreamDry(=2) 4-bytes stream ID +* SetBufferLength(=3) 8-bytes 4bytes stream ID, 4bytes buffer length. +* StreamIsRecorded(=4) 4-bytes stream ID +* PingRequest(=6) 4-bytes timestamp local server time +* PingResponse(=7) 4-bytes timestamp received ping request. * * 3.7. User Control message * +------------------------------+------------------------- @@ -1202,32 +1202,32 @@ enum SrcPCUCEventType class SrsUserControlPacket : public SrsPacket { private: - typedef SrsPacket super; + typedef SrsPacket super; protected: - virtual const char* get_class_name() - { - return CLASS_NAME_STRING(SrsUserControlPacket); - } + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsUserControlPacket); + } public: - // @see: SrcPCUCEventType - int16_t event_type; - int32_t event_data; - /** - * 4bytes if event_type is SetBufferLength; otherwise 0. - */ - int32_t extra_data; + // @see: SrcPCUCEventType + int16_t event_type; + int32_t event_data; + /** + * 4bytes if event_type is SetBufferLength; otherwise 0. + */ + int32_t extra_data; public: - SrsUserControlPacket(); - virtual ~SrsUserControlPacket(); + SrsUserControlPacket(); + virtual ~SrsUserControlPacket(); public: - virtual int decode(SrsStream* stream); + virtual int decode(SrsStream* stream); public: - virtual int get_perfer_cid(); + virtual int get_perfer_cid(); public: - virtual int get_message_type(); + virtual int get_message_type(); protected: - virtual int get_size(); - virtual int encode_packet(SrsStream* stream); + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); }; /** @@ -1236,52 +1236,52 @@ protected: * @ppacket, store in the pmsg, user must never free it. NULL if not success. * @remark, only when success, user can use and must free the pmsg/ppacket. * for example: - SrsCommonMessage* msg = NULL; - SrsConnectAppResPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - return ret; - } - // use pkt + SrsCommonMessage* msg = NULL; + SrsConnectAppResPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + return ret; + } + // use pkt * user should never recv message and convert it, use this method instead. * if need to set timeout, use set timeout of SrsProtocol. */ template int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** ppacket) { - *pmsg = NULL; - *ppacket = NULL; - - int ret = ERROR_SUCCESS; - - while (true) { - SrsCommonMessage* msg = NULL; - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("recv message failed. ret=%d", ret); - return ret; - } - srs_verbose("recv message success."); - - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { - delete msg; - srs_error("decode message failed. ret=%d", ret); - return ret; - } - - T* pkt = dynamic_cast(msg->get_packet()); - if (!pkt) { - delete msg; - srs_trace("drop message(type=%d, size=%d, time=%"PRId64", sid=%d).", - msg->header.message_type, msg->header.payload_length, - msg->header.timestamp, msg->header.stream_id); - continue; - } - - *pmsg = msg; - *ppacket = pkt; - break; - } - - return ret; + *pmsg = NULL; + *ppacket = NULL; + + int ret = ERROR_SUCCESS; + + while (true) { + SrsCommonMessage* msg = NULL; + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("recv message failed. ret=%d", ret); + return ret; + } + srs_verbose("recv message success."); + + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { + delete msg; + srs_error("decode message failed. ret=%d", ret); + return ret; + } + + T* pkt = dynamic_cast(msg->get_packet()); + if (!pkt) { + delete msg; + srs_trace("drop message(type=%d, size=%d, time=%"PRId64", sid=%d).", + msg->header.message_type, msg->header.payload_length, + msg->header.timestamp, msg->header.stream_id); + continue; + } + + *pmsg = msg; + *ppacket = pkt; + break; + } + + return ret; } #endif diff --git a/trunk/src/rtmp/srs_protocol_utility.cpp b/trunk/src/rtmp/srs_protocol_utility.cpp index 00f60bfa6..b25d9e0aa 100644 --- a/trunk/src/rtmp/srs_protocol_utility.cpp +++ b/trunk/src/rtmp/srs_protocol_utility.cpp @@ -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) { - app = srs_replace(app, "...", "?"); - - size_t pos = 0; - if ((pos = app.find("?")) == std::string::npos) { - return; - } - - std::string query = app.substr(pos + 1); - app = app.substr(0, pos); - - 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 - ) { - query = query.substr(pos + 6); - if (!query.empty()) { - vhost = query; - } - } + app = srs_replace(app, "...", "?"); + + size_t pos = 0; + if ((pos = app.find("?")) == std::string::npos) { + return; + } + + std::string query = app.substr(pos + 1); + app = app.substr(0, pos); + + 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 + ) { + query = query.substr(pos + 6); + if (!query.empty()) { + vhost = query; + } + } } diff --git a/trunk/src/rtmp/srs_protocol_utility.hpp b/trunk/src/rtmp/srs_protocol_utility.hpp index d063a31d6..10aaf246d 100644 --- a/trunk/src/rtmp/srs_protocol_utility.hpp +++ b/trunk/src/rtmp/srs_protocol_utility.hpp @@ -36,8 +36,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // resolve the vhost in query string // @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); #endif diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index 83a8eb4bb..fc9fc3d4e 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -1,88 +1,88 @@ file - main readonly separator, - ..\main\srs_main_server.cpp, - ..\main\srs_main_bandcheck.cpp, - auto readonly separator, - ..\..\objs\srs_auto_headers.hpp, - libs readonly separator, - ..\libs\srs_librtmp.hpp, - ..\libs\srs_librtmp.cpp, - ..\libs\srs_lib_simple_socket.hpp, - ..\libs\srs_lib_simple_socket.cpp, - core readonly separator, - ..\core\srs_core.hpp, - ..\core\srs_core.cpp, - ..\core\srs_core_autofree.hpp, - ..\core\srs_core_autofree.cpp, - kernel readonly separator, - ..\kernel\srs_kernel_buffer.hpp, - ..\kernel\srs_kernel_buffer.cpp, - ..\kernel\srs_kernel_error.hpp, - ..\kernel\srs_kernel_error.cpp, - ..\kernel\srs_kernel_log.hpp, - ..\kernel\srs_kernel_log.cpp, - ..\kernel\srs_kernel_stream.hpp, - ..\kernel\srs_kernel_stream.cpp, - rtmp-protocol readonly separator, - ..\rtmp\srs_protocol_amf0.hpp, - ..\rtmp\srs_protocol_amf0.cpp, - ..\rtmp\srs_protocol_handshake.hpp, - ..\rtmp\srs_protocol_handshake.cpp, - ..\rtmp\srs_protocol_io.hpp, - ..\rtmp\srs_protocol_io.cpp, - ..\rtmp\srs_protocol_rtmp.hpp, - ..\rtmp\srs_protocol_rtmp.cpp, - ..\rtmp\srs_protocol_rtmp_stack.hpp, - ..\rtmp\srs_protocol_rtmp_stack.cpp, - ..\rtmp\srs_protocol_utility.hpp, - ..\rtmp\srs_protocol_utility.cpp, - app readonly separator, - ..\app\srs_app_bandwidth.hpp, - ..\app\srs_app_bandwidth.cpp, - ..\app\srs_app_client.hpp, - ..\app\srs_app_client.cpp, - ..\app\srs_app_codec.hpp, - ..\app\srs_app_codec.cpp, - ..\app\srs_app_conn.hpp, - ..\app\srs_app_conn.cpp, - ..\app\srs_app_config.hpp, - ..\app\srs_app_config.cpp, - ..\app\srs_app_encoder.hpp, - ..\app\srs_app_encoder.cpp, - ..\app\srs_app_forward.hpp, - ..\app\srs_app_forward.cpp, - ..\app\srs_app_hls.hpp, - ..\app\srs_app_hls.cpp, - ..\app\srs_app_http.hpp, - ..\app\srs_app_http.cpp, - ..\app\srs_app_log.hpp, - ..\app\srs_app_log.cpp, - ..\app\srs_app_refer.hpp, - ..\app\srs_app_refer.cpp, - ..\app\srs_app_reload.hpp, - ..\app\srs_app_reload.cpp, - ..\app\srs_app_pithy_print.hpp, - ..\app\srs_app_pithy_print.cpp, - ..\app\srs_app_thread.hpp, - ..\app\srs_app_thread.cpp, - ..\app\srs_app_server.hpp, - ..\app\srs_app_server.cpp, - ..\app\srs_app_st.hpp, - ..\app\srs_app_st.cpp, - ..\app\srs_app_socket.hpp, - ..\app\srs_app_socket.cpp, - ..\app\srs_app_source.hpp, - ..\app\srs_app_source.cpp, - utest readonly separator, - ..\utest\srs_utest.hpp, - ..\utest\srs_utest.cpp, - ..\utest\srs_utest_amf0.hpp, - ..\utest\srs_utest_amf0.cpp, - research readonly separator, - ..\..\research\librtmp\srs_play.c, - ..\..\research\librtmp\srs_publish.c, - ..\..\research\hls\ts_info.cc; + main readonly separator, + ..\main\srs_main_server.cpp, + ..\main\srs_main_bandcheck.cpp, + auto readonly separator, + ..\..\objs\srs_auto_headers.hpp, + libs readonly separator, + ..\libs\srs_librtmp.hpp, + ..\libs\srs_librtmp.cpp, + ..\libs\srs_lib_simple_socket.hpp, + ..\libs\srs_lib_simple_socket.cpp, + core readonly separator, + ..\core\srs_core.hpp, + ..\core\srs_core.cpp, + ..\core\srs_core_autofree.hpp, + ..\core\srs_core_autofree.cpp, + kernel readonly separator, + ..\kernel\srs_kernel_buffer.hpp, + ..\kernel\srs_kernel_buffer.cpp, + ..\kernel\srs_kernel_error.hpp, + ..\kernel\srs_kernel_error.cpp, + ..\kernel\srs_kernel_log.hpp, + ..\kernel\srs_kernel_log.cpp, + ..\kernel\srs_kernel_stream.hpp, + ..\kernel\srs_kernel_stream.cpp, + rtmp-protocol readonly separator, + ..\rtmp\srs_protocol_amf0.hpp, + ..\rtmp\srs_protocol_amf0.cpp, + ..\rtmp\srs_protocol_handshake.hpp, + ..\rtmp\srs_protocol_handshake.cpp, + ..\rtmp\srs_protocol_io.hpp, + ..\rtmp\srs_protocol_io.cpp, + ..\rtmp\srs_protocol_rtmp.hpp, + ..\rtmp\srs_protocol_rtmp.cpp, + ..\rtmp\srs_protocol_rtmp_stack.hpp, + ..\rtmp\srs_protocol_rtmp_stack.cpp, + ..\rtmp\srs_protocol_utility.hpp, + ..\rtmp\srs_protocol_utility.cpp, + app readonly separator, + ..\app\srs_app_bandwidth.hpp, + ..\app\srs_app_bandwidth.cpp, + ..\app\srs_app_client.hpp, + ..\app\srs_app_client.cpp, + ..\app\srs_app_codec.hpp, + ..\app\srs_app_codec.cpp, + ..\app\srs_app_conn.hpp, + ..\app\srs_app_conn.cpp, + ..\app\srs_app_config.hpp, + ..\app\srs_app_config.cpp, + ..\app\srs_app_encoder.hpp, + ..\app\srs_app_encoder.cpp, + ..\app\srs_app_forward.hpp, + ..\app\srs_app_forward.cpp, + ..\app\srs_app_hls.hpp, + ..\app\srs_app_hls.cpp, + ..\app\srs_app_http.hpp, + ..\app\srs_app_http.cpp, + ..\app\srs_app_log.hpp, + ..\app\srs_app_log.cpp, + ..\app\srs_app_refer.hpp, + ..\app\srs_app_refer.cpp, + ..\app\srs_app_reload.hpp, + ..\app\srs_app_reload.cpp, + ..\app\srs_app_pithy_print.hpp, + ..\app\srs_app_pithy_print.cpp, + ..\app\srs_app_thread.hpp, + ..\app\srs_app_thread.cpp, + ..\app\srs_app_server.hpp, + ..\app\srs_app_server.cpp, + ..\app\srs_app_st.hpp, + ..\app\srs_app_st.cpp, + ..\app\srs_app_socket.hpp, + ..\app\srs_app_socket.cpp, + ..\app\srs_app_source.hpp, + ..\app\srs_app_source.cpp, + utest readonly separator, + ..\utest\srs_utest.hpp, + ..\utest\srs_utest.cpp, + ..\utest\srs_utest_amf0.hpp, + ..\utest\srs_utest_amf0.cpp, + research readonly separator, + ..\..\research\librtmp\srs_play.c, + ..\..\research\librtmp\srs_publish.c, + ..\..\research\hls\ts_info.cc; mainconfig - "" = "MAIN"; + "" = "MAIN"; diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp index 3645bfac8..1a223dedd 100644 --- a/trunk/src/utest/srs_utest.cpp +++ b/trunk/src/utest/srs_utest.cpp @@ -39,30 +39,30 @@ SrsServer* _srs_server = NULL; // basic test and samples. VOID TEST(SampleTest, FastSampleInt64Test) { - EXPECT_EQ(1, (int)sizeof(int8_t)); - EXPECT_EQ(2, (int)sizeof(int16_t)); - EXPECT_EQ(4, (int)sizeof(int32_t)); - EXPECT_EQ(8, (int)sizeof(int64_t)); + EXPECT_EQ(1, (int)sizeof(int8_t)); + EXPECT_EQ(2, (int)sizeof(int16_t)); + EXPECT_EQ(4, (int)sizeof(int32_t)); + EXPECT_EQ(8, (int)sizeof(int64_t)); } VOID TEST(SampleTest, FastSampleMacrosTest) { - EXPECT_TRUE(1); - EXPECT_FALSE(0); - - EXPECT_EQ(1, 1); // == - EXPECT_NE(1, 2); // != - EXPECT_LE(1, 2); // <= - EXPECT_LT(1, 2); // < - EXPECT_GE(2, 1); // >= - EXPECT_GT(2, 1); // > + EXPECT_TRUE(1); + EXPECT_FALSE(0); + + EXPECT_EQ(1, 1); // == + EXPECT_NE(1, 2); // != + EXPECT_LE(1, 2); // <= + EXPECT_LT(1, 2); // < + EXPECT_GE(2, 1); // >= + EXPECT_GT(2, 1); // > - EXPECT_STREQ("winlin", "winlin"); - EXPECT_STRNE("winlin", "srs"); - EXPECT_STRCASEEQ("winlin", "Winlin"); - EXPECT_STRCASENE("winlin", "srs"); - - EXPECT_FLOAT_EQ(1.0, 1.000000000000001); - EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001); - EXPECT_NEAR(10, 15, 5); + EXPECT_STREQ("winlin", "winlin"); + EXPECT_STRNE("winlin", "srs"); + EXPECT_STRCASEEQ("winlin", "Winlin"); + EXPECT_STRCASENE("winlin", "srs"); + + EXPECT_FLOAT_EQ(1.0, 1.000000000000001); + EXPECT_DOUBLE_EQ(1.0, 1.0000000000000001); + EXPECT_NEAR(10, 15, 5); } diff --git a/trunk/src/utest/srs_utest_amf0.cpp b/trunk/src/utest/srs_utest_amf0.cpp index 0519d866f..b89890fc8 100644 --- a/trunk/src/utest/srs_utest_amf0.cpp +++ b/trunk/src/utest/srs_utest_amf0.cpp @@ -32,143 +32,143 @@ using namespace std; // user scenario: coding and decoding with amf0 VOID TEST(AMF0Test, ScenarioMain) { - // coded amf0 object - int nb_bytes = 0; - char* bytes = NULL; - - // coding data to binaries by amf0 - // for example, send connect app response to client. - if (true) { - // props: object - // fmsVer: string - // capabilities: number - // mode: number - // info: object - // level: string - // code: string - // descrption: string - // objectEncoding: number - // data: array - // version: string - // srs_sig: string - SrsAmf0Object* props = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, props, false); - props->set("fmsVer", SrsAmf0Any::str("FMS/3,5,3,888")); - props->set("capabilities", SrsAmf0Any::number(253)); - props->set("mode", SrsAmf0Any::number(123)); - - SrsAmf0Object* info = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, info, false); - info->set("level", SrsAmf0Any::str("info")); - info->set("code", SrsAmf0Any::str("NetStream.Connnect.Success")); - info->set("descrption", SrsAmf0Any::str("connected")); - info->set("objectEncoding", SrsAmf0Any::number(3)); - - SrsAmf0EcmaArray* data = SrsAmf0Any::ecma_array(); - info->set("data", data); - data->set("version", SrsAmf0Any::str("FMS/3,5,3,888")); - data->set("srs_sig", SrsAmf0Any::str("srs")); - - // buf store the serialized props/info - nb_bytes = props->total_size() + info->total_size(); - ASSERT_GT(nb_bytes, 0); - bytes = new char[nb_bytes]; - - // use SrsStream to write props/info to binary buf. - SrsStream s; - EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); - EXPECT_EQ(ERROR_SUCCESS, props->write(&s)); - EXPECT_EQ(ERROR_SUCCESS, info->write(&s)); - EXPECT_TRUE(s.empty()); - - // now, user can use the buf - EXPECT_EQ(0x03, bytes[0]); - EXPECT_EQ(0x09, bytes[nb_bytes - 1]); - } - SrsAutoFree(char, bytes, true); - - // decoding amf0 object from bytes - // when user know the schema - if (true) { - ASSERT_TRUE(NULL != bytes); - - // use SrsStream to assist amf0 object to read from bytes. - SrsStream s; - EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); - - // decoding - // if user know the schema, for instance, it's an amf0 object, - // user can use specified object to decoding. - SrsAmf0Object* props = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, props, false); - EXPECT_EQ(ERROR_SUCCESS, props->read(&s)); - - // user can use specified object to decoding. - SrsAmf0Object* info = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, info, false); - EXPECT_EQ(ERROR_SUCCESS, info->read(&s)); - - // use the decoded data. - SrsAmf0Any* prop = NULL; - - // if user requires specified property, use ensure of amf0 object - EXPECT_TRUE(NULL != (prop = props->ensure_property_string("fmsVer"))); - // the property can assert to string. - ASSERT_TRUE(prop->is_string()); - // get the prop string value. - EXPECT_STREQ("FMS/3,5,3,888", prop->to_str().c_str()); - - // get other type property value - EXPECT_TRUE(NULL != (prop = info->get_property("data"))); - // we cannot assert the property is ecma array - if (prop->is_ecma_array()) { - SrsAmf0EcmaArray* data = prop->to_ecma_array(); - // it must be a ecma array. - ASSERT_TRUE(NULL != data); - - // get property of array - EXPECT_TRUE(NULL != (prop = data->ensure_property_string("srs_sig"))); - ASSERT_TRUE(prop->is_string()); - EXPECT_STREQ("srs", prop->to_str().c_str()); - } - - // confidence about the schema - EXPECT_TRUE(NULL != (prop = info->ensure_property_string("level"))); - ASSERT_TRUE(prop->is_string()); - EXPECT_STREQ("info", prop->to_str().c_str()); - } - - // use any to decoding it, - // if user donot know the schema - if (true) { - ASSERT_TRUE(NULL != bytes); - - // use SrsStream to assist amf0 object to read from bytes. - SrsStream s; - EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); - - // decoding a amf0 any, for user donot know - SrsAmf0Any* any = NULL; - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &any)); - SrsAutoFree(SrsAmf0Any, any, false); - - // for amf0 object - if (any->is_object()) { - SrsAmf0Object* obj = any->to_object(); - ASSERT_TRUE(NULL != obj); - - // use foreach to process properties - for (int i = 0; i < obj->count(); ++i) { - string name = obj->key_at(i); - SrsAmf0Any* value = obj->value_at(i); - - // use the property name - EXPECT_TRUE("" != name); - // use the property value - EXPECT_TRUE(NULL != value); - } - } - } + // coded amf0 object + int nb_bytes = 0; + char* bytes = NULL; + + // coding data to binaries by amf0 + // for example, send connect app response to client. + if (true) { + // props: object + // fmsVer: string + // capabilities: number + // mode: number + // info: object + // level: string + // code: string + // descrption: string + // objectEncoding: number + // data: array + // version: string + // srs_sig: string + SrsAmf0Object* props = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, props, false); + props->set("fmsVer", SrsAmf0Any::str("FMS/3,5,3,888")); + props->set("capabilities", SrsAmf0Any::number(253)); + props->set("mode", SrsAmf0Any::number(123)); + + SrsAmf0Object* info = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, info, false); + info->set("level", SrsAmf0Any::str("info")); + info->set("code", SrsAmf0Any::str("NetStream.Connnect.Success")); + info->set("descrption", SrsAmf0Any::str("connected")); + info->set("objectEncoding", SrsAmf0Any::number(3)); + + SrsAmf0EcmaArray* data = SrsAmf0Any::ecma_array(); + info->set("data", data); + data->set("version", SrsAmf0Any::str("FMS/3,5,3,888")); + data->set("srs_sig", SrsAmf0Any::str("srs")); + + // buf store the serialized props/info + nb_bytes = props->total_size() + info->total_size(); + ASSERT_GT(nb_bytes, 0); + bytes = new char[nb_bytes]; + + // use SrsStream to write props/info to binary buf. + SrsStream s; + EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); + EXPECT_EQ(ERROR_SUCCESS, props->write(&s)); + EXPECT_EQ(ERROR_SUCCESS, info->write(&s)); + EXPECT_TRUE(s.empty()); + + // now, user can use the buf + EXPECT_EQ(0x03, bytes[0]); + EXPECT_EQ(0x09, bytes[nb_bytes - 1]); + } + SrsAutoFree(char, bytes, true); + + // decoding amf0 object from bytes + // when user know the schema + if (true) { + ASSERT_TRUE(NULL != bytes); + + // use SrsStream to assist amf0 object to read from bytes. + SrsStream s; + EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); + + // decoding + // if user know the schema, for instance, it's an amf0 object, + // user can use specified object to decoding. + SrsAmf0Object* props = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, props, false); + EXPECT_EQ(ERROR_SUCCESS, props->read(&s)); + + // user can use specified object to decoding. + SrsAmf0Object* info = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, info, false); + EXPECT_EQ(ERROR_SUCCESS, info->read(&s)); + + // use the decoded data. + SrsAmf0Any* prop = NULL; + + // if user requires specified property, use ensure of amf0 object + EXPECT_TRUE(NULL != (prop = props->ensure_property_string("fmsVer"))); + // the property can assert to string. + ASSERT_TRUE(prop->is_string()); + // get the prop string value. + EXPECT_STREQ("FMS/3,5,3,888", prop->to_str().c_str()); + + // get other type property value + EXPECT_TRUE(NULL != (prop = info->get_property("data"))); + // we cannot assert the property is ecma array + if (prop->is_ecma_array()) { + SrsAmf0EcmaArray* data = prop->to_ecma_array(); + // it must be a ecma array. + ASSERT_TRUE(NULL != data); + + // get property of array + EXPECT_TRUE(NULL != (prop = data->ensure_property_string("srs_sig"))); + ASSERT_TRUE(prop->is_string()); + EXPECT_STREQ("srs", prop->to_str().c_str()); + } + + // confidence about the schema + EXPECT_TRUE(NULL != (prop = info->ensure_property_string("level"))); + ASSERT_TRUE(prop->is_string()); + EXPECT_STREQ("info", prop->to_str().c_str()); + } + + // use any to decoding it, + // if user donot know the schema + if (true) { + ASSERT_TRUE(NULL != bytes); + + // use SrsStream to assist amf0 object to read from bytes. + SrsStream s; + EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); + + // decoding a amf0 any, for user donot know + SrsAmf0Any* any = NULL; + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &any)); + SrsAutoFree(SrsAmf0Any, any, false); + + // for amf0 object + if (any->is_object()) { + SrsAmf0Object* obj = any->to_object(); + ASSERT_TRUE(NULL != obj); + + // use foreach to process properties + for (int i = 0; i < obj->count(); ++i) { + string name = obj->key_at(i); + SrsAmf0Any* value = obj->value_at(i); + + // use the property name + EXPECT_TRUE("" != name); + // use the property value + EXPECT_TRUE(NULL != value); + } + } + } } VOID TEST(AMF0Test, ApiSize) @@ -429,623 +429,623 @@ VOID TEST(AMF0Test, ApiSize) VOID TEST(AMF0Test, ApiAnyElem) { - SrsAmf0Any* o = NULL; - - // string - if (true) { - o = SrsAmf0Any::str(); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_string()); - EXPECT_STREQ("", o->to_str().c_str()); - } - if (true) { - o = SrsAmf0Any::str("winlin"); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_string()); - EXPECT_STREQ("winlin", o->to_str().c_str()); - } - - // bool - if (true) { - o = SrsAmf0Any::boolean(); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_boolean()); - EXPECT_FALSE(o->to_boolean()); - } - if (true) { - o = SrsAmf0Any::boolean(false); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_boolean()); - EXPECT_FALSE(o->to_boolean()); - } - if (true) { - o = SrsAmf0Any::boolean(true); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_boolean()); - EXPECT_TRUE(o->to_boolean()); - } - - // number - if (true) { - o = SrsAmf0Any::number(); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_number()); - EXPECT_DOUBLE_EQ(0, o->to_number()); - } - if (true) { - o = SrsAmf0Any::number(100); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_number()); - EXPECT_DOUBLE_EQ(100, o->to_number()); - } - if (true) { - o = SrsAmf0Any::number(-100); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_number()); - EXPECT_DOUBLE_EQ(-100, o->to_number()); - } + SrsAmf0Any* o = NULL; + + // string + if (true) { + o = SrsAmf0Any::str(); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_string()); + EXPECT_STREQ("", o->to_str().c_str()); + } + if (true) { + o = SrsAmf0Any::str("winlin"); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_string()); + EXPECT_STREQ("winlin", o->to_str().c_str()); + } + + // bool + if (true) { + o = SrsAmf0Any::boolean(); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_boolean()); + EXPECT_FALSE(o->to_boolean()); + } + if (true) { + o = SrsAmf0Any::boolean(false); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_boolean()); + EXPECT_FALSE(o->to_boolean()); + } + if (true) { + o = SrsAmf0Any::boolean(true); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_boolean()); + EXPECT_TRUE(o->to_boolean()); + } + + // number + if (true) { + o = SrsAmf0Any::number(); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_number()); + EXPECT_DOUBLE_EQ(0, o->to_number()); + } + if (true) { + o = SrsAmf0Any::number(100); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_number()); + EXPECT_DOUBLE_EQ(100, o->to_number()); + } + if (true) { + o = SrsAmf0Any::number(-100); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_number()); + EXPECT_DOUBLE_EQ(-100, o->to_number()); + } - // null - if (true) { - o = SrsAmf0Any::null(); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_null()); - } + // null + if (true) { + o = SrsAmf0Any::null(); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_null()); + } - // undefined - if (true) { - o = SrsAmf0Any::undefined(); - SrsAutoFree(SrsAmf0Any, o, false); - ASSERT_TRUE(NULL != o); - EXPECT_TRUE(o->is_undefined()); - } + // undefined + if (true) { + o = SrsAmf0Any::undefined(); + SrsAutoFree(SrsAmf0Any, o, false); + ASSERT_TRUE(NULL != o); + EXPECT_TRUE(o->is_undefined()); + } } VOID TEST(AMF0Test, ApiAnyIO) { - SrsStream s; - SrsAmf0Any* o = NULL; - - char buf[1024]; - memset(buf, 0, sizeof(buf)); - EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); - - // object eof - if (true) { - s.reset(); - s.current()[2] = 0x09; - - o = SrsAmf0Any::object_eof(); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_EQ(3, s.pos()); - - s.reset(); - s.current()[0] = 0x01; - EXPECT_NE(ERROR_SUCCESS, o->read(&s)); - } - if (true) { - s.reset(); - - o = SrsAmf0Any::object_eof(); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_EQ(3, s.pos()); - - s.skip(-3); - EXPECT_EQ(0x09, s.read_3bytes()); - } - - // string - if (true) { - s.reset(); - - o = SrsAmf0Any::str("winlin"); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - - s.reset(); - EXPECT_EQ(2, s.read_1bytes()); - EXPECT_EQ(6, s.read_2bytes()); - EXPECT_EQ('w', s.current()[0]); - EXPECT_EQ('n', s.current()[5]); - - s.reset(); - s.current()[3] = 'x'; - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_STREQ("xinlin", o->to_str().c_str()); - } - - // number - if (true) { - s.reset(); - - o = SrsAmf0Any::number(10); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + SrsStream s; + SrsAmf0Any* o = NULL; + + char buf[1024]; + memset(buf, 0, sizeof(buf)); + EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); + + // object eof + if (true) { + s.reset(); + s.current()[2] = 0x09; + + o = SrsAmf0Any::object_eof(); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_EQ(3, s.pos()); + + s.reset(); + s.current()[0] = 0x01; + EXPECT_NE(ERROR_SUCCESS, o->read(&s)); + } + if (true) { + s.reset(); + + o = SrsAmf0Any::object_eof(); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_EQ(3, s.pos()); + + s.skip(-3); + EXPECT_EQ(0x09, s.read_3bytes()); + } + + // string + if (true) { + s.reset(); + + o = SrsAmf0Any::str("winlin"); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + + s.reset(); + EXPECT_EQ(2, s.read_1bytes()); + EXPECT_EQ(6, s.read_2bytes()); + EXPECT_EQ('w', s.current()[0]); + EXPECT_EQ('n', s.current()[5]); + + s.reset(); + s.current()[3] = 'x'; + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_STREQ("xinlin", o->to_str().c_str()); + } + + // number + if (true) { + s.reset(); + + o = SrsAmf0Any::number(10); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - EXPECT_EQ(0, s.read_1bytes()); - - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_DOUBLE_EQ(10, o->to_number()); - } - - // boolean - if (true) { - s.reset(); - - o = SrsAmf0Any::boolean(true); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + s.reset(); + EXPECT_EQ(0, s.read_1bytes()); + + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_DOUBLE_EQ(10, o->to_number()); + } + + // boolean + if (true) { + s.reset(); + + o = SrsAmf0Any::boolean(true); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - EXPECT_EQ(1, s.read_1bytes()); - - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_TRUE(o->to_boolean()); - } - if (true) { - s.reset(); - - o = SrsAmf0Any::boolean(false); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + s.reset(); + EXPECT_EQ(1, s.read_1bytes()); + + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_TRUE(o->to_boolean()); + } + if (true) { + s.reset(); + + o = SrsAmf0Any::boolean(false); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - EXPECT_EQ(1, s.read_1bytes()); - - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_FALSE(o->to_boolean()); - } - - // null - if (true) { - s.reset(); - - o = SrsAmf0Any::null(); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + s.reset(); + EXPECT_EQ(1, s.read_1bytes()); + + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_FALSE(o->to_boolean()); + } + + // null + if (true) { + s.reset(); + + o = SrsAmf0Any::null(); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - EXPECT_EQ(5, s.read_1bytes()); - - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_TRUE(o->is_null()); - } - - // undefined - if (true) { - s.reset(); - - o = SrsAmf0Any::undefined(); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + s.reset(); + EXPECT_EQ(5, s.read_1bytes()); + + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_TRUE(o->is_null()); + } + + // undefined + if (true) { + s.reset(); + + o = SrsAmf0Any::undefined(); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - EXPECT_EQ(6, s.read_1bytes()); - - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); - EXPECT_EQ(o->total_size(), s.pos()); - EXPECT_TRUE(o->is_undefined()); - } + s.reset(); + EXPECT_EQ(6, s.read_1bytes()); + + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); + EXPECT_EQ(o->total_size(), s.pos()); + EXPECT_TRUE(o->is_undefined()); + } - // any: string - if (true) { - s.reset(); - - o = SrsAmf0Any::str("winlin"); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + // any: string + if (true) { + s.reset(); + + o = SrsAmf0Any::str("winlin"); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - - SrsAmf0Any* po = NULL; - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - SrsAutoFree(SrsAmf0Any, po, false); - ASSERT_TRUE(po->is_string()); - EXPECT_STREQ("winlin", po->to_str().c_str()); - } + s.reset(); + + SrsAmf0Any* po = NULL; + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + SrsAutoFree(SrsAmf0Any, po, false); + ASSERT_TRUE(po->is_string()); + EXPECT_STREQ("winlin", po->to_str().c_str()); + } - // any: number - if (true) { - s.reset(); - - o = SrsAmf0Any::number(10); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + // any: number + if (true) { + s.reset(); + + o = SrsAmf0Any::number(10); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - - SrsAmf0Any* po = NULL; - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - SrsAutoFree(SrsAmf0Any, po, false); - ASSERT_TRUE(po->is_number()); - EXPECT_DOUBLE_EQ(10, po->to_number()); - } + s.reset(); + + SrsAmf0Any* po = NULL; + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + SrsAutoFree(SrsAmf0Any, po, false); + ASSERT_TRUE(po->is_number()); + EXPECT_DOUBLE_EQ(10, po->to_number()); + } - // any: boolean - if (true) { - s.reset(); - - o = SrsAmf0Any::boolean(true); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + // any: boolean + if (true) { + s.reset(); + + o = SrsAmf0Any::boolean(true); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - - SrsAmf0Any* po = NULL; - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - SrsAutoFree(SrsAmf0Any, po, false); - ASSERT_TRUE(po->is_boolean()); - EXPECT_TRUE(po->to_boolean()); - } + s.reset(); + + SrsAmf0Any* po = NULL; + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + SrsAutoFree(SrsAmf0Any, po, false); + ASSERT_TRUE(po->is_boolean()); + EXPECT_TRUE(po->to_boolean()); + } - // any: null - if (true) { - s.reset(); - - o = SrsAmf0Any::null(); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + // any: null + if (true) { + s.reset(); + + o = SrsAmf0Any::null(); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - - SrsAmf0Any* po = NULL; - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - SrsAutoFree(SrsAmf0Any, po, false); - ASSERT_TRUE(po->is_null()); - } + s.reset(); + + SrsAmf0Any* po = NULL; + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + SrsAutoFree(SrsAmf0Any, po, false); + ASSERT_TRUE(po->is_null()); + } - // any: undefined - if (true) { - s.reset(); - - o = SrsAmf0Any::undefined(); - SrsAutoFree(SrsAmf0Any, o, false); - - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(o->total_size(), s.pos()); + // any: undefined + if (true) { + s.reset(); + + o = SrsAmf0Any::undefined(); + SrsAutoFree(SrsAmf0Any, o, false); + + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(o->total_size(), s.pos()); - s.reset(); - - SrsAmf0Any* po = NULL; - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - SrsAutoFree(SrsAmf0Any, po, false); - ASSERT_TRUE(po->is_undefined()); - } - - // mixed any - if (true) { - s.reset(); - - o = SrsAmf0Any::str("winlin"); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - srs_freep(o); - - o = SrsAmf0Any::number(10); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - srs_freep(o); - - o = SrsAmf0Any::boolean(true); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - srs_freep(o); - - o = SrsAmf0Any::null(); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - srs_freep(o); - - o = SrsAmf0Any::undefined(); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - srs_freep(o); - - s.reset(); - SrsAmf0Any* po = NULL; - - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - ASSERT_TRUE(po->is_string()); - EXPECT_STREQ("winlin", po->to_str().c_str()); - srs_freep(po); - - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - ASSERT_TRUE(po->is_number()); - EXPECT_DOUBLE_EQ(10, po->to_number()); - srs_freep(po); - - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - ASSERT_TRUE(po->is_boolean()); - EXPECT_TRUE(po->to_boolean()); - srs_freep(po); - - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - ASSERT_TRUE(po->is_null()); - srs_freep(po); - - EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); - ASSERT_TRUE(NULL != po); - ASSERT_TRUE(po->is_undefined()); - srs_freep(po); - } + s.reset(); + + SrsAmf0Any* po = NULL; + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + SrsAutoFree(SrsAmf0Any, po, false); + ASSERT_TRUE(po->is_undefined()); + } + + // mixed any + if (true) { + s.reset(); + + o = SrsAmf0Any::str("winlin"); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + srs_freep(o); + + o = SrsAmf0Any::number(10); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + srs_freep(o); + + o = SrsAmf0Any::boolean(true); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + srs_freep(o); + + o = SrsAmf0Any::null(); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + srs_freep(o); + + o = SrsAmf0Any::undefined(); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + srs_freep(o); + + s.reset(); + SrsAmf0Any* po = NULL; + + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + ASSERT_TRUE(po->is_string()); + EXPECT_STREQ("winlin", po->to_str().c_str()); + srs_freep(po); + + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + ASSERT_TRUE(po->is_number()); + EXPECT_DOUBLE_EQ(10, po->to_number()); + srs_freep(po); + + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + ASSERT_TRUE(po->is_boolean()); + EXPECT_TRUE(po->to_boolean()); + srs_freep(po); + + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + ASSERT_TRUE(po->is_null()); + srs_freep(po); + + EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); + ASSERT_TRUE(NULL != po); + ASSERT_TRUE(po->is_undefined()); + srs_freep(po); + } } VOID TEST(AMF0Test, ApiAnyAssert) { - SrsStream s; - SrsAmf0Any* o = NULL; - - char buf[1024]; - memset(buf, 0, sizeof(buf)); - EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); - - // read any - if (true) { - s.reset(); - s.current()[0] = 0x12; - EXPECT_NE(ERROR_SUCCESS, srs_amf0_read_any(&s, &o)); - EXPECT_TRUE(NULL == o); - srs_freep(o); - } - - // any convert - if (true) { - o = SrsAmf0Any::str(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_string()); - } - if (true) { - o = SrsAmf0Any::number(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_number()); - } - if (true) { - o = SrsAmf0Any::boolean(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_boolean()); - } - if (true) { - o = SrsAmf0Any::null(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_null()); - } - if (true) { - o = SrsAmf0Any::undefined(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_undefined()); - } - if (true) { - o = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_object()); - } - if (true) { - o = SrsAmf0Any::ecma_array(); - SrsAutoFree(SrsAmf0Any, o, false); - EXPECT_TRUE(o->is_ecma_array()); - } - - // empty object - if (true) { - o = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Any, o, false); - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(1+3, s.pos()); - } - - // empty ecma array - if (true) { - o = SrsAmf0Any::ecma_array(); - SrsAutoFree(SrsAmf0Any, o, false); - s.reset(); - EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); - EXPECT_EQ(1+4+3, s.pos()); - } + SrsStream s; + SrsAmf0Any* o = NULL; + + char buf[1024]; + memset(buf, 0, sizeof(buf)); + EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); + + // read any + if (true) { + s.reset(); + s.current()[0] = 0x12; + EXPECT_NE(ERROR_SUCCESS, srs_amf0_read_any(&s, &o)); + EXPECT_TRUE(NULL == o); + srs_freep(o); + } + + // any convert + if (true) { + o = SrsAmf0Any::str(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_string()); + } + if (true) { + o = SrsAmf0Any::number(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_number()); + } + if (true) { + o = SrsAmf0Any::boolean(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_boolean()); + } + if (true) { + o = SrsAmf0Any::null(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_null()); + } + if (true) { + o = SrsAmf0Any::undefined(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_undefined()); + } + if (true) { + o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_object()); + } + if (true) { + o = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0Any, o, false); + EXPECT_TRUE(o->is_ecma_array()); + } + + // empty object + if (true) { + o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Any, o, false); + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(1+3, s.pos()); + } + + // empty ecma array + if (true) { + o = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0Any, o, false); + s.reset(); + EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); + EXPECT_EQ(1+4+3, s.pos()); + } } VOID TEST(AMF0Test, ApiObjectProps) { - SrsAmf0Object* o = NULL; - - // get/set property - if (true) { - o = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, o, false); - - EXPECT_TRUE(NULL == o->get_property("name")); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_TRUE(NULL != o->get_property("name")); - - EXPECT_TRUE(NULL == o->get_property("age")); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_TRUE(NULL != o->get_property("age")); - } - - // index property - if (true) { - o = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, o, false); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_STREQ("name", o->key_at(0).c_str()); - ASSERT_TRUE(o->value_at(0)->is_string()); - EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_STREQ("name", o->key_at(0).c_str()); - ASSERT_TRUE(o->value_at(0)->is_string()); - EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); - - EXPECT_STREQ("age", o->key_at(1).c_str()); - ASSERT_TRUE(o->value_at(1)->is_number()); - EXPECT_DOUBLE_EQ(100, o->value_at(1)->to_number()); - } - - // ensure property - if (true) { - o = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, o, false); - - EXPECT_TRUE(NULL == o->ensure_property_string("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("age")); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_TRUE(NULL != o->ensure_property_string("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("age")); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_TRUE(NULL != o->ensure_property_string("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("name")); - EXPECT_TRUE(NULL != o->ensure_property_number("age")); - EXPECT_TRUE(NULL == o->ensure_property_string("age")); - } + SrsAmf0Object* o = NULL; + + // get/set property + if (true) { + o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); + + EXPECT_TRUE(NULL == o->get_property("name")); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_TRUE(NULL != o->get_property("name")); + + EXPECT_TRUE(NULL == o->get_property("age")); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_TRUE(NULL != o->get_property("age")); + } + + // index property + if (true) { + o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_STREQ("name", o->key_at(0).c_str()); + ASSERT_TRUE(o->value_at(0)->is_string()); + EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_STREQ("name", o->key_at(0).c_str()); + ASSERT_TRUE(o->value_at(0)->is_string()); + EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); + + EXPECT_STREQ("age", o->key_at(1).c_str()); + ASSERT_TRUE(o->value_at(1)->is_number()); + EXPECT_DOUBLE_EQ(100, o->value_at(1)->to_number()); + } + + // ensure property + if (true) { + o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); + + EXPECT_TRUE(NULL == o->ensure_property_string("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("age")); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_TRUE(NULL != o->ensure_property_string("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("age")); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_TRUE(NULL != o->ensure_property_string("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("name")); + EXPECT_TRUE(NULL != o->ensure_property_number("age")); + EXPECT_TRUE(NULL == o->ensure_property_string("age")); + } - // count - if (true) { - o = SrsAmf0Any::object(); - SrsAutoFree(SrsAmf0Object, o, false); - - EXPECT_EQ(0, o->count()); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_EQ(1, o->count()); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_EQ(1, o->count()); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_EQ(2, o->count()); - } + // count + if (true) { + o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); + + EXPECT_EQ(0, o->count()); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_EQ(1, o->count()); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_EQ(1, o->count()); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_EQ(2, o->count()); + } } VOID TEST(AMF0Test, ApiEcmaArrayProps) { - SrsAmf0EcmaArray* o = NULL; - - // get/set property - if (true) { - o = SrsAmf0Any::ecma_array(); - SrsAutoFree(SrsAmf0EcmaArray, o, false); - - EXPECT_TRUE(NULL == o->get_property("name")); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_TRUE(NULL != o->get_property("name")); - - EXPECT_TRUE(NULL == o->get_property("age")); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_TRUE(NULL != o->get_property("age")); - } - - // index property - if (true) { - o = SrsAmf0Any::ecma_array(); - SrsAutoFree(SrsAmf0EcmaArray, o, false); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_STREQ("name", o->key_at(0).c_str()); - ASSERT_TRUE(o->value_at(0)->is_string()); - EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_STREQ("name", o->key_at(0).c_str()); - ASSERT_TRUE(o->value_at(0)->is_string()); - EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); - - EXPECT_STREQ("age", o->key_at(1).c_str()); - ASSERT_TRUE(o->value_at(1)->is_number()); - EXPECT_DOUBLE_EQ(100, o->value_at(1)->to_number()); - } - - // ensure property - if (true) { - o = SrsAmf0Any::ecma_array(); - SrsAutoFree(SrsAmf0EcmaArray, o, false); - - EXPECT_TRUE(NULL == o->ensure_property_string("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("age")); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_TRUE(NULL != o->ensure_property_string("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("age")); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_TRUE(NULL != o->ensure_property_string("name")); - EXPECT_TRUE(NULL == o->ensure_property_number("name")); - EXPECT_TRUE(NULL != o->ensure_property_number("age")); - EXPECT_TRUE(NULL == o->ensure_property_string("age")); - } + SrsAmf0EcmaArray* o = NULL; + + // get/set property + if (true) { + o = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); + + EXPECT_TRUE(NULL == o->get_property("name")); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_TRUE(NULL != o->get_property("name")); + + EXPECT_TRUE(NULL == o->get_property("age")); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_TRUE(NULL != o->get_property("age")); + } + + // index property + if (true) { + o = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_STREQ("name", o->key_at(0).c_str()); + ASSERT_TRUE(o->value_at(0)->is_string()); + EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_STREQ("name", o->key_at(0).c_str()); + ASSERT_TRUE(o->value_at(0)->is_string()); + EXPECT_STREQ("winlin", o->value_at(0)->to_str().c_str()); + + EXPECT_STREQ("age", o->key_at(1).c_str()); + ASSERT_TRUE(o->value_at(1)->is_number()); + EXPECT_DOUBLE_EQ(100, o->value_at(1)->to_number()); + } + + // ensure property + if (true) { + o = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); + + EXPECT_TRUE(NULL == o->ensure_property_string("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("age")); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_TRUE(NULL != o->ensure_property_string("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("age")); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_TRUE(NULL != o->ensure_property_string("name")); + EXPECT_TRUE(NULL == o->ensure_property_number("name")); + EXPECT_TRUE(NULL != o->ensure_property_number("age")); + EXPECT_TRUE(NULL == o->ensure_property_string("age")); + } - // count - if (true) { - o = SrsAmf0Any::ecma_array(); - SrsAutoFree(SrsAmf0EcmaArray, o, false); - - EXPECT_EQ(0, o->count()); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_EQ(1, o->count()); - - o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_EQ(1, o->count()); - - o->set("age", SrsAmf0Any::number(100)); - EXPECT_EQ(2, o->count()); - } + // count + if (true) { + o = SrsAmf0Any::ecma_array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); + + EXPECT_EQ(0, o->count()); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_EQ(1, o->count()); + + o->set("name", SrsAmf0Any::str("winlin")); + EXPECT_EQ(1, o->count()); + + o->set("age", SrsAmf0Any::number(100)); + EXPECT_EQ(2, o->count()); + } }