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

for #742, refine the object live cycle. 3.0.15

This commit is contained in:
winlin 2017-01-17 10:44:13 +08:00
parent f4c0af8bfc
commit dca9749f37
19 changed files with 286 additions and 226 deletions

View file

@ -183,6 +183,7 @@ Please select your language:
### V3 changes ### V3 changes
* v3.0, 2017-01-17, for [#742][bug #742] refine source, timeout, live cycle. 3.0.15
* v3.0, 2017-01-11, fix [#735][bug #735] config transform refer_publish invalid. 3.0.14 * v3.0, 2017-01-11, fix [#735][bug #735] config transform refer_publish invalid. 3.0.14
* v3.0, 2017-01-06, for [#730][bug #730] support config in/out ack size. 3.0.13 * v3.0, 2017-01-06, for [#730][bug #730] support config in/out ack size. 3.0.13
* v3.0, 2017-01-06, for [#711][bug #711] support perfile for transcode. 3.0.12 * v3.0, 2017-01-06, for [#711][bug #711] support perfile for transcode. 3.0.12
@ -1365,7 +1366,8 @@ Winlin
[bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx
[bug #735]: https://github.com/ossrs/srs/issues/735 [bug #735]: https://github.com/ossrs/srs/issues/735
[bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [bug #742]: https://github.com/ossrs/srs/issues/742
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
[exo #828]: https://github.com/google/ExoPlayer/pull/828 [exo #828]: https://github.com/google/ExoPlayer/pull/828

View file

@ -120,7 +120,7 @@ int SrsAppCasterFlv::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
SrsDynamicHttpConn::SrsDynamicHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m, string cip) SrsDynamicHttpConn::SrsDynamicHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m, string cip)
: SrsHttpConn(cm, fd, m, cip) : SrsHttpConn(cm, fd, m, cip)
{ {
sdk = new SrsSimpleRtmpClient(); sdk = NULL;
pprint = SrsPithyPrint::create_caster(); pprint = SrsPithyPrint::create_caster();
} }
@ -181,9 +181,13 @@ int SrsDynamicHttpConn::do_proxy(ISrsHttpResponseReader* rr, SrsFlvDecoder* dec)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
srs_freep(sdk);
int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US; int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US;
int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US;
if ((ret = sdk->connect(output, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(output, cto / 1000, sto / 1000);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
srs_error("flv: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", output.c_str(), cto, sto, ret); srs_error("flv: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", output.c_str(), cto, sto, ret);
return ret; return ret;
} }

View file

@ -73,14 +73,12 @@ SrsEdgeUpstream::~SrsEdgeUpstream()
SrsEdgeRtmpUpstream::SrsEdgeRtmpUpstream(string r) SrsEdgeRtmpUpstream::SrsEdgeRtmpUpstream(string r)
{ {
redirect = r; redirect = r;
sdk = new SrsSimpleRtmpClient(); sdk = NULL;
} }
SrsEdgeRtmpUpstream::~SrsEdgeRtmpUpstream() SrsEdgeRtmpUpstream::~SrsEdgeRtmpUpstream()
{ {
close(); close();
srs_freep(sdk);
} }
int SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb) int SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb)
@ -126,9 +124,12 @@ int SrsEdgeRtmpUpstream::connect(SrsRequest* r, SrsLbRoundRobin* lb)
url = srs_generate_rtmp_url(server, port, vhost, req->app, req->stream); url = srs_generate_rtmp_url(server, port, vhost, req->app, req->stream);
} }
srs_freep(sdk);
int64_t cto = SRS_EDGE_INGESTER_TIMEOUT_US; int64_t cto = SRS_EDGE_INGESTER_TIMEOUT_US;
int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US;
if ((ret = sdk->connect(url, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(url, cto/1000, sto/1000);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
srs_error("edge pull %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret); srs_error("edge pull %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret);
return ret; return ret;
} }
@ -153,7 +154,7 @@ int SrsEdgeRtmpUpstream::decode_message(SrsCommonMessage* msg, SrsPacket** ppack
void SrsEdgeRtmpUpstream::close() void SrsEdgeRtmpUpstream::close()
{ {
sdk->close(); srs_freep(sdk);
} }
void SrsEdgeRtmpUpstream::set_recv_timeout(int64_t timeout) void SrsEdgeRtmpUpstream::set_recv_timeout(int64_t timeout)
@ -406,7 +407,7 @@ SrsEdgeForwarder::SrsEdgeForwarder()
req = NULL; req = NULL;
send_error_code = ERROR_SUCCESS; send_error_code = ERROR_SUCCESS;
sdk = new SrsSimpleRtmpClient(); sdk = NULL;
lb = new SrsLbRoundRobin(); lb = new SrsLbRoundRobin();
pthread = new SrsReusableThread2("edge-fwr", this, SRS_EDGE_FORWARDER_SLEEP_US); pthread = new SrsReusableThread2("edge-fwr", this, SRS_EDGE_FORWARDER_SLEEP_US);
queue = new SrsMessageQueue(); queue = new SrsMessageQueue();
@ -416,7 +417,6 @@ SrsEdgeForwarder::~SrsEdgeForwarder()
{ {
stop(); stop();
srs_freep(sdk);
srs_freep(lb); srs_freep(lb);
srs_freep(pthread); srs_freep(pthread);
srs_freep(queue); srs_freep(queue);
@ -464,9 +464,12 @@ int SrsEdgeForwarder::start()
} }
// open socket. // open socket.
srs_freep(sdk);
int64_t cto = SRS_EDGE_FORWARDER_TIMEOUT_US; int64_t cto = SRS_EDGE_FORWARDER_TIMEOUT_US;
int64_t sto = SRS_CONSTS_RTMP_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_TIMEOUT_US;
if ((ret = sdk->connect(url, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(url, cto/1000, sto/1000);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
srs_warn("edge push %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret); srs_warn("edge push %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret);
return ret; return ret;
} }
@ -482,8 +485,9 @@ int SrsEdgeForwarder::start()
void SrsEdgeForwarder::stop() void SrsEdgeForwarder::stop()
{ {
pthread->stop(); pthread->stop();
sdk->close();
queue->clear(); queue->clear();
srs_freep(sdk);
} }
#define SYS_MAX_EDGE_SEND_MSGS 128 #define SYS_MAX_EDGE_SEND_MSGS 128

View file

@ -57,7 +57,7 @@ SrsForwarder::SrsForwarder(SrsSource* s)
req = NULL; req = NULL;
sh_video = sh_audio = NULL; sh_video = sh_audio = NULL;
sdk = new SrsSimpleRtmpClient(); sdk = NULL;
pthread = new SrsReusableThread2("forward", this, SRS_FORWARDER_SLEEP_US); pthread = new SrsReusableThread2("forward", this, SRS_FORWARDER_SLEEP_US);
queue = new SrsMessageQueue(); queue = new SrsMessageQueue();
jitter = new SrsRtmpJitter(); jitter = new SrsRtmpJitter();
@ -236,9 +236,12 @@ int SrsForwarder::cycle()
url = srs_generate_rtmp_url(server, port, req->vhost, req->app, req->stream); url = srs_generate_rtmp_url(server, port, req->vhost, req->app, req->stream);
} }
srs_freep(sdk);
int64_t cto = SRS_FORWARDER_SLEEP_US; int64_t cto = SRS_FORWARDER_SLEEP_US;
int64_t sto = SRS_CONSTS_RTMP_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_TIMEOUT_US;
if ((ret = sdk->connect(url, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(url, cto, sto);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
srs_warn("forward failed, url=%s, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret); srs_warn("forward failed, url=%s, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret);
return ret; return ret;
} }

View file

@ -40,7 +40,7 @@ using namespace std;
SrsHttpClient::SrsHttpClient() SrsHttpClient::SrsHttpClient()
{ {
transport = new SrsTcpClient(); transport = NULL;
kbps = new SrsKbps(); kbps = new SrsKbps();
parser = NULL; parser = NULL;
timeout_us = 0; timeout_us = 0;
@ -52,19 +52,14 @@ SrsHttpClient::~SrsHttpClient()
disconnect(); disconnect();
srs_freep(kbps); srs_freep(kbps);
srs_freep(transport);
srs_freep(parser); srs_freep(parser);
} }
// TODO: FIXME: use ms for timeout.
int SrsHttpClient::initialize(string h, int p, int64_t t_us) int SrsHttpClient::initialize(string h, int p, int64_t t_us)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// disconnect first when h:p changed.
if ((!host.empty() && host != h) || (port != 0 && port != p)) {
disconnect();
}
srs_freep(parser); srs_freep(parser);
parser = new SrsHttpParser(); parser = new SrsHttpParser();
@ -73,9 +68,11 @@ int SrsHttpClient::initialize(string h, int p, int64_t t_us)
return ret; return ret;
} }
// Always disconnect the transport.
host = h; host = h;
port = p; port = p;
timeout_us = t_us; timeout_us = t_us;
disconnect();
// ep used for host in header. // ep used for host in header.
string ep = host; string ep = host;
@ -83,7 +80,7 @@ int SrsHttpClient::initialize(string h, int p, int64_t t_us)
ep += ":" + srs_int2str(port); ep += ":" + srs_int2str(port);
} }
// set default value for headers. // Set default value for headers.
headers["Host"] = ep; headers["Host"] = ep;
headers["Connection"] = "Keep-Alive"; headers["Connection"] = "Keep-Alive";
headers["User-Agent"] = RTMP_SIG_SRS_SERVER; headers["User-Agent"] = RTMP_SIG_SRS_SERVER;
@ -126,9 +123,8 @@ int SrsHttpClient::post(string path, string req, ISrsHttpMessage** ppmsg)
std::string data = ss.str(); std::string data = ss.str();
if ((ret = transport->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { if ((ret = transport->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) {
// disconnect when error. // Disconnect the transport when channel error, reconnect for next operation.
disconnect(); disconnect();
srs_error("write http post failed. ret=%d", ret); srs_error("write http post failed. ret=%d", ret);
return ret; return ret;
} }
@ -138,9 +134,13 @@ int SrsHttpClient::post(string path, string req, ISrsHttpMessage** ppmsg)
srs_error("parse http post response failed. ret=%d", ret); srs_error("parse http post response failed. ret=%d", ret);
return ret; return ret;
} }
srs_assert(msg); srs_assert(msg);
*ppmsg = msg;
if (ppmsg) {
*ppmsg = msg;
} else {
srs_freep(msg);
}
srs_info("parse http post response success."); srs_info("parse http post response success.");
return ret; return ret;
@ -173,9 +173,8 @@ int SrsHttpClient::get(string path, string req, ISrsHttpMessage** ppmsg)
std::string data = ss.str(); std::string data = ss.str();
if ((ret = transport->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { if ((ret = transport->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) {
// disconnect when error. // Disconnect the transport when channel error, reconnect for next operation.
disconnect(); disconnect();
srs_error("write http get failed. ret=%d", ret); srs_error("write http get failed. ret=%d", ret);
return ret; return ret;
} }
@ -187,7 +186,11 @@ int SrsHttpClient::get(string path, string req, ISrsHttpMessage** ppmsg)
} }
srs_assert(msg); srs_assert(msg);
*ppmsg = msg; if (ppmsg) {
*ppmsg = msg;
} else {
srs_freep(msg);
}
srs_info("parse http get response success."); srs_info("parse http get response success.");
return ret; return ret;
@ -215,23 +218,24 @@ void SrsHttpClient::kbps_sample(const char* label, int64_t age)
void SrsHttpClient::disconnect() void SrsHttpClient::disconnect()
{ {
kbps->set_io(NULL, NULL); kbps->set_io(NULL, NULL);
transport->close(); transport->close();
srs_freep(transport);
} }
int SrsHttpClient::connect() int SrsHttpClient::connect()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (transport->connected()) { // When transport connected, ignore.
if (transport) {
return ret; return ret;
} }
disconnect(); transport = new SrsTcpClient(host, port, timeout_us / 1000);
if ((ret = transport->connect()) != ERROR_SUCCESS) {
// open socket. disconnect();
if ((ret = transport->connect(host, port, timeout_us)) != ERROR_SUCCESS) { srs_warn("http client failed, server=%s, port=%d, timeout=%"PRId64", ret=%d", host.c_str(), port, timeout_us, ret);
srs_warn("http client failed, server=%s, port=%d, timeout=%"PRId64", ret=%d",
host.c_str(), port, timeout_us, ret);
return ret; return ret;
} }
srs_info("connect to server success. server=%s, port=%d", host.c_str(), port); srs_info("connect to server success. server=%s, port=%d", host.c_str(), port);

View file

@ -46,11 +46,19 @@ class SrsKbps;
#define SRS_HTTP_CLIENT_TIMEOUT_US (int64_t)(30*1000*1000LL) #define SRS_HTTP_CLIENT_TIMEOUT_US (int64_t)(30*1000*1000LL)
/** /**
* http client to GET/POST/PUT/DELETE uri * The client to GET/POST/PUT/DELETE over HTTP.
*/ * @remark We will reuse the TCP transport until initialize or channel error,
* such as send/recv failed.
* Usage:
* SrsHttpClient hc;
* hc.initialize("127.0.0.1", 80, 9000);
* hc.post("/api/v1/version", "Hello world!", NULL);
*/
class SrsHttpClient class SrsHttpClient
{ {
private: private:
// The underlayer TCP transport, set to NULL when disconnect, or never not NULL when connected.
// We will disconnect transport when initialize or channel error, such as send/recv error.
SrsTcpClient* transport; SrsTcpClient* transport;
SrsHttpParser* parser; SrsHttpParser* parser;
std::map<std::string, std::string> headers; std::map<std::string, std::string> headers;
@ -65,12 +73,13 @@ public:
virtual ~SrsHttpClient(); virtual ~SrsHttpClient();
public: public:
/** /**
* initialize the client, connect to host and port. * Initliaze the client, disconnect the transport, renew the HTTP parser.
* @remark we will set default values in headers, which can be override by set_header. * @remark we will set default values in headers, which can be override by set_header.
*/ */
virtual int initialize(std::string h, int p, int64_t t_us = SRS_HTTP_CLIENT_TIMEOUT_US); virtual int initialize(std::string h, int p, int64_t t_us = SRS_HTTP_CLIENT_TIMEOUT_US);
/** /**
* set the header[k]=v and return the client itself. * Set HTTP request header in header[k]=v.
* @return the HTTP client itself.
*/ */
virtual SrsHttpClient* set_header(std::string k, std::string v); virtual SrsHttpClient* set_header(std::string k, std::string v);
public: public:

View file

@ -135,14 +135,13 @@ SrsKafkaPartition::SrsKafkaPartition()
id = broker = 0; id = broker = 0;
port = SRS_CONSTS_KAFKA_DEFAULT_PORT; port = SRS_CONSTS_KAFKA_DEFAULT_PORT;
transport = new SrsTcpClient(); transport = NULL;
kafka = new SrsKafkaClient(transport); kafka = NULL;
} }
SrsKafkaPartition::~SrsKafkaPartition() SrsKafkaPartition::~SrsKafkaPartition()
{ {
srs_freep(kafka); disconnect();
srs_freep(transport);
} }
string SrsKafkaPartition::hostport() string SrsKafkaPartition::hostport()
@ -158,13 +157,15 @@ int SrsKafkaPartition::connect()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (transport->connected()) { if (transport) {
return ret; return ret;
} }
transport = new SrsTcpClient(host, port, SRS_KAFKA_PRODUCER_TIMEOUT);
kafka = new SrsKafkaClient(transport);
int64_t timeout = SRS_KAFKA_PRODUCER_TIMEOUT * 1000; if ((ret = transport->connect()) != ERROR_SUCCESS) {
if ((ret = transport->connect(host, port, timeout)) != ERROR_SUCCESS) { disconnect();
srs_error("connect to %s partition=%d failed, timeout=%"PRId64". ret=%d", hostport().c_str(), id, timeout, ret); srs_error("connect to %s partition=%d failed. ret=%d", hostport().c_str(), id, ret);
return ret; return ret;
} }
@ -178,6 +179,12 @@ int SrsKafkaPartition::flush(SrsKafkaPartitionCache* pc)
return kafka->write_messages(topic, id, *pc); return kafka->write_messages(topic, id, *pc);
} }
void SrsKafkaPartition::disconnect()
{
srs_freep(kafka);
srs_freep(transport);
}
SrsKafkaMessage::SrsKafkaMessage(SrsKafkaProducer* p, int k, SrsJsonObject* j) SrsKafkaMessage::SrsKafkaMessage(SrsKafkaProducer* p, int k, SrsJsonObject* j)
{ {
producer = p; producer = p;
@ -562,12 +569,6 @@ int SrsKafkaProducer::request_metadata()
return ret; return ret;
} }
SrsTcpClient* transport = new SrsTcpClient();
SrsAutoFree(SrsTcpClient, transport);
SrsKafkaClient* kafka = new SrsKafkaClient(transport);
SrsAutoFree(SrsKafkaClient, kafka);
std::string server; std::string server;
int port = SRS_CONSTS_KAFKA_DEFAULT_PORT; int port = SRS_CONSTS_KAFKA_DEFAULT_PORT;
if (true) { if (true) {
@ -584,8 +585,14 @@ int SrsKafkaProducer::request_metadata()
senabled.c_str(), sbrokers.c_str(), lb->current(), server.c_str(), port, topic.c_str()); senabled.c_str(), sbrokers.c_str(), lb->current(), server.c_str(), port, topic.c_str());
} }
SrsTcpClient* transport = new SrsTcpClient(server, port, SRS_CONSTS_KAFKA_TIMEOUT_US / 1000);
SrsAutoFree(SrsTcpClient, transport);
SrsKafkaClient* kafka = new SrsKafkaClient(transport);
SrsAutoFree(SrsKafkaClient, kafka);
// reconnect to kafka server. // reconnect to kafka server.
if ((ret = transport->connect(server, port, SRS_CONSTS_KAFKA_TIMEOUT_US)) != ERROR_SUCCESS) { if ((ret = transport->connect()) != ERROR_SUCCESS) {
srs_error("kafka connect %s:%d failed. ret=%d", server.c_str(), port, ret); srs_error("kafka connect %s:%d failed. ret=%d", server.c_str(), port, ret);
return ret; return ret;
} }

View file

@ -57,6 +57,7 @@ struct SrsKafkaPartition
{ {
private: private:
std::string ep; std::string ep;
// Not NULL when connected.
SrsTcpClient* transport; SrsTcpClient* transport;
SrsKafkaClient* kafka; SrsKafkaClient* kafka;
public: public:
@ -73,6 +74,8 @@ public:
virtual std::string hostport(); virtual std::string hostport();
virtual int connect(); virtual int connect();
virtual int flush(SrsKafkaPartitionCache* pc); virtual int flush(SrsKafkaPartitionCache* pc);
private:
virtual void disconnect();
}; };
/** /**

View file

@ -133,8 +133,7 @@ SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
buffer = new SrsSimpleStream(); buffer = new SrsSimpleStream();
output = _srs_config->get_stream_caster_output(c); output = _srs_config->get_stream_caster_output(c);
req = NULL; sdk = NULL;
sdk = new SrsSimpleRtmpClient();
avc = new SrsRawH264Stream(); avc = new SrsRawH264Stream();
aac = new SrsRawAacStream(); aac = new SrsRawAacStream();
@ -149,7 +148,6 @@ SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
{ {
close(); close();
srs_freep(sdk);
srs_freep(buffer); srs_freep(buffer);
srs_freep(stream); srs_freep(stream);
srs_freep(context); srs_freep(context);
@ -570,6 +568,10 @@ int SrsMpegtsOverUdp::rtmp_write_packet(char type, u_int32_t timestamp, char* da
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = connect()) != ERROR_SUCCESS) {
return ret;
}
SrsSharedPtrMessage* msg = NULL; SrsSharedPtrMessage* msg = NULL;
if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != ERROR_SUCCESS) {
@ -597,6 +599,7 @@ int SrsMpegtsOverUdp::rtmp_write_packet(char type, u_int32_t timestamp, char* da
// send out encoded msg. // send out encoded msg.
if ((ret = sdk->send_and_free_message(msg)) != ERROR_SUCCESS) { if ((ret = sdk->send_and_free_message(msg)) != ERROR_SUCCESS) {
close();
return ret; return ret;
} }
} }
@ -608,20 +611,23 @@ int SrsMpegtsOverUdp::connect()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when ok, ignore. // Ignore when connected.
// TODO: FIXME: should reconnect when disconnected. if (sdk) {
if (sdk->connected()) {
return ret; return ret;
} }
int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US; int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US;
int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US;
if ((ret = sdk->connect(output, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(output, cto/1000, sto/1000);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
close();
srs_error("mpegts: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", output.c_str(), cto, sto, ret); srs_error("mpegts: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", output.c_str(), cto, sto, ret);
return ret; return ret;
} }
if ((ret = sdk->publish()) != ERROR_SUCCESS) { if ((ret = sdk->publish()) != ERROR_SUCCESS) {
close();
srs_error("mpegts: publish failed. ret=%d", ret); srs_error("mpegts: publish failed. ret=%d", ret);
return ret; return ret;
} }
@ -631,8 +637,7 @@ int SrsMpegtsOverUdp::connect()
void SrsMpegtsOverUdp::close() void SrsMpegtsOverUdp::close()
{ {
srs_freep(req); srs_freep(sdk);
sdk->close();
} }
#endif #endif

View file

@ -86,7 +86,6 @@ private:
SrsSimpleStream* buffer; SrsSimpleStream* buffer;
std::string output; std::string output;
private: private:
SrsRequest* req;
SrsSimpleRtmpClient* sdk; SrsSimpleRtmpClient* sdk;
private: private:
SrsRawH264Stream* avc; SrsRawH264Stream* avc;
@ -121,10 +120,9 @@ private:
private: private:
virtual int rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size); virtual int rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size);
private: private:
// connect to rtmp output url. // Connect to RTMP server.
// @remark ignore when not connected, reconnect when disconnected.
virtual int connect(); virtual int connect();
// close the connected io and rtmp to ready to be re-connect. // Close the connection to RTMP server.
virtual void close(); virtual void close();
}; };

View file

@ -77,51 +77,45 @@ using namespace std;
// when edge timeout, retry next. // when edge timeout, retry next.
#define SRS_EDGE_TOKEN_TRAVERSE_TIMEOUT_US (int64_t)(3*1000*1000LL) #define SRS_EDGE_TOKEN_TRAVERSE_TIMEOUT_US (int64_t)(3*1000*1000LL)
SrsSimpleRtmpClient::SrsSimpleRtmpClient() SrsSimpleRtmpClient::SrsSimpleRtmpClient(string u, int64_t ctm, int64_t stm)
{ {
req = NULL;
client = NULL;
kbps = new SrsKbps(); kbps = new SrsKbps();
transport = new SrsTcpClient(); url = u;
connect_timeout = ctm;
stream_timeout = stm;
req = new SrsRequest();
srs_parse_rtmp_url(url, req->tcUrl, req->stream);
srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->port, req->param);
transport = NULL;
client = NULL;
stream_id = 0; stream_id = 0;
} }
SrsSimpleRtmpClient::~SrsSimpleRtmpClient() SrsSimpleRtmpClient::~SrsSimpleRtmpClient()
{ {
close(); close();
srs_freep(kbps); srs_freep(kbps);
srs_freep(transport);
srs_freep(client);
} }
int SrsSimpleRtmpClient::connect(string url, int64_t connect_timeout, int64_t stream_timeout) int SrsSimpleRtmpClient::connect()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when ok, ignore. close();
// TODO: FIXME: should reconnect when disconnected.
if (transport->connected()) {
return ret;
}
// parse uri transport = new SrsTcpClient(req->host, req->port, connect_timeout);
srs_freep(req);
req = new SrsRequest();
srs_parse_rtmp_url(url, req->tcUrl, req->stream);
srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->port, req->param);
// connect host.
if ((ret = transport->connect(req->host, req->port, connect_timeout)) != ERROR_SUCCESS) {
return ret;
}
srs_freep(client);
client = new SrsRtmpClient(transport); client = new SrsRtmpClient(transport);
kbps->set_io(transport, transport); kbps->set_io(transport, transport);
if ((ret = transport->connect()) != ERROR_SUCCESS) {
close();
return ret;
}
client->set_recv_timeout(stream_timeout); client->set_recv_timeout(stream_timeout);
client->set_send_timeout(stream_timeout); client->set_send_timeout(stream_timeout);
@ -142,6 +136,13 @@ int SrsSimpleRtmpClient::connect(string url, int64_t connect_timeout, int64_t st
return ret; return ret;
} }
void SrsSimpleRtmpClient::close()
{
srs_freep(client);
srs_freep(transport);
kbps->set_io(NULL, NULL);
}
int SrsSimpleRtmpClient::connect_app() int SrsSimpleRtmpClient::connect_app()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -197,19 +198,6 @@ int SrsSimpleRtmpClient::connect_app()
return ret; return ret;
} }
bool SrsSimpleRtmpClient::connected()
{
return transport->connected();
}
void SrsSimpleRtmpClient::close()
{
transport->close();
srs_freep(client);
srs_freep(req);
}
int SrsSimpleRtmpClient::publish() int SrsSimpleRtmpClient::publish()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -1464,48 +1452,35 @@ int SrsRtmpConn::check_edge_token_traverse_auth()
srs_assert(req); srs_assert(req);
SrsTcpClient* transport = new SrsTcpClient();
SrsAutoFree(SrsTcpClient, transport);
vector<string> args = _srs_config->get_vhost_edge_origin(req->vhost)->args; vector<string> args = _srs_config->get_vhost_edge_origin(req->vhost)->args;
if (args.empty()) {
return ret;
}
for (int i = 0; i < (int)args.size(); i++) { for (int i = 0; i < (int)args.size(); i++) {
string hostport = args.at(i); string hostport = args.at(i);
if ((ret = connect_server(hostport, transport)) == ERROR_SUCCESS) {
break; // select the origin.
string server;
int port = SRS_CONSTS_RTMP_DEFAULT_PORT;
srs_parse_hostport(hostport, server, port);
SrsTcpClient* transport = new SrsTcpClient(server, port, SRS_EDGE_TOKEN_TRAVERSE_TIMEOUT_US / 1000);
SrsAutoFree(SrsTcpClient, transport);
if ((ret = transport->connect()) != ERROR_SUCCESS) {
srs_warn("Illegal edge token, tcUrl=%s to server=%s, port=%d. ret=%d", req->tcUrl.c_str(), server.c_str(), port, ret);
continue;
} }
}
if (ret != ERROR_SUCCESS) { SrsRtmpClient* client = new SrsRtmpClient(transport);
srs_warn("token traverse connect failed. ret=%d", ret); SrsAutoFree(SrsRtmpClient, client);
return ret;
return do_token_traverse_auth(client);
} }
SrsRtmpClient* client = new SrsRtmpClient(transport); ret = ERROR_EDGE_PORT_INVALID;
SrsAutoFree(SrsRtmpClient, client); srs_error("Illegal edge token, server=%d. ret=%d", (int)args.size(), ret);
return do_token_traverse_auth(client);
}
int SrsRtmpConn::connect_server(string hostport, SrsTcpClient* transport)
{
int ret = ERROR_SUCCESS;
SrsConfDirective* conf = _srs_config->get_vhost_edge_origin(req->vhost);
srs_assert(conf);
// select the origin.
string server;
int port = SRS_CONSTS_RTMP_DEFAULT_PORT;
srs_parse_hostport(hostport, server, port);
// open socket.
int64_t timeout = SRS_EDGE_TOKEN_TRAVERSE_TIMEOUT_US;
if ((ret = transport->connect(server, port, timeout)) != ERROR_SUCCESS) {
srs_warn("edge token traverse failed, tcUrl=%s to server=%s, port=%d, timeout=%"PRId64", ret=%d",
req->tcUrl.c_str(), server.c_str(), port, timeout, ret);
return ret;
}
srs_info("edge token auth connected, url=%s/%s, server=%s:%d", req->tcUrl.c_str(), req->stream.c_str(), server.c_str(), port);
return ret; return ret;
} }

View file

@ -63,10 +63,20 @@ class ISrsKafkaCluster;
#endif #endif
/** /**
* the simple rtmp client stub, use SrsRtmpClient and provides high level APIs. * The simple RTMP client, provides friendly APIs.
* @remark Should never use client when closed.
* Usage:
* SrsSimpleRtmpClient client("rtmp://127.0.0.1:1935/live/livestream", 3000, 9000);
* client.connect();
* client.play();
* client.close();
*/ */
class SrsSimpleRtmpClient class SrsSimpleRtmpClient
{ {
private:
std::string url;
int64_t connect_timeout;
int64_t stream_timeout;
private: private:
SrsRequest* req; SrsRequest* req;
SrsTcpClient* transport; SrsTcpClient* transport;
@ -74,15 +84,19 @@ private:
SrsKbps* kbps; SrsKbps* kbps;
int stream_id; int stream_id;
public: public:
SrsSimpleRtmpClient(); // Constructor.
// @param u The RTMP url, for example, rtmp://ip:port/app/stream?domain=vhost
// @param ctm The timeout in ms to connect to server.
// @param stm The timeout in ms to delivery A/V stream.
SrsSimpleRtmpClient(std::string u, int64_t ctm, int64_t stm);
virtual ~SrsSimpleRtmpClient(); virtual ~SrsSimpleRtmpClient();
public: public:
virtual int connect(std::string url, int64_t connect_timeout, int64_t stream_timeout); // Connect, handshake and connect app to RTMP server.
// @remark We always close the transport.
virtual int connect();
virtual void close();
private: private:
virtual int connect_app(); virtual int connect_app();
public:
virtual bool connected();
virtual void close();
public: public:
virtual int publish(); virtual int publish();
virtual int play(); virtual int play();
@ -175,8 +189,8 @@ private:
virtual void set_sock_options(); virtual void set_sock_options();
private: private:
virtual int check_edge_token_traverse_auth(); virtual int check_edge_token_traverse_auth();
virtual int connect_server(std::string hostport, SrsTcpClient* transport);
virtual int do_token_traverse_auth(SrsRtmpClient* client); virtual int do_token_traverse_auth(SrsRtmpClient* client);
private:
/** /**
* when the connection disconnect, call this method. * when the connection disconnect, call this method.
* e.g. log msg of connection and report to other system. * e.g. log msg of connection and report to other system.

View file

@ -197,7 +197,7 @@ SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o)
trd = new SrsOneCycleThread("rtsp", this); trd = new SrsOneCycleThread("rtsp", this);
req = NULL; req = NULL;
sdk = new SrsSimpleRtmpClient(); sdk = NULL;
vjitter = new SrsRtspJitter(); vjitter = new SrsRtspJitter();
ajitter = new SrsRtspJitter(); ajitter = new SrsRtspJitter();
@ -209,6 +209,8 @@ SrsRtspConn::SrsRtspConn(SrsRtspCaster* c, st_netfd_t fd, std::string o)
SrsRtspConn::~SrsRtspConn() SrsRtspConn::~SrsRtspConn()
{ {
close();
srs_close_stfd(stfd); srs_close_stfd(stfd);
srs_freep(video_rtp); srs_freep(video_rtp);
@ -623,6 +625,10 @@ int SrsRtspConn::rtmp_write_packet(char type, u_int32_t timestamp, char* data, i
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = connect()) != ERROR_SUCCESS) {
return ret;
}
SrsSharedPtrMessage* msg = NULL; SrsSharedPtrMessage* msg = NULL;
if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != ERROR_SUCCESS) {
@ -633,20 +639,19 @@ int SrsRtspConn::rtmp_write_packet(char type, u_int32_t timestamp, char* data, i
// send out encoded msg. // send out encoded msg.
if ((ret = sdk->send_and_free_message(msg)) != ERROR_SUCCESS) { if ((ret = sdk->send_and_free_message(msg)) != ERROR_SUCCESS) {
close();
return ret; return ret;
} }
return ret; return ret;
} }
// TODO: FIXME: merge all client code.
int SrsRtspConn::connect() int SrsRtspConn::connect()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when ok, ignore. // Ignore when connected.
// TODO: FIXME: support reconnect. if (sdk) {
if (sdk->connected()) {
return ret; return ret;
} }
@ -666,13 +671,17 @@ int SrsRtspConn::connect()
// connect host. // connect host.
int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US; int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US;
int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US;
if ((ret = sdk->connect(url, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(url, cto/1000, sto/1000);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
close();
srs_error("rtsp: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret); srs_error("rtsp: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret);
return ret; return ret;
} }
// publish. // publish.
if ((ret = sdk->publish()) != ERROR_SUCCESS) { if ((ret = sdk->publish()) != ERROR_SUCCESS) {
close();
srs_error("rtsp: publish %s failed. ret=%d", url.c_str(), ret); srs_error("rtsp: publish %s failed. ret=%d", url.c_str(), ret);
return ret; return ret;
} }
@ -680,6 +689,11 @@ int SrsRtspConn::connect()
return write_sequence_header(); return write_sequence_header();
} }
void SrsRtspConn::close()
{
srs_freep(sdk);
}
SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c) SrsRtspCaster::SrsRtspCaster(SrsConfDirective* c)
{ {
// TODO: FIXME: support reload. // TODO: FIXME: support reload.

View file

@ -177,9 +177,10 @@ private:
virtual int write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, u_int32_t dts); virtual int write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, u_int32_t dts);
virtual int rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size); virtual int rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size);
private: private:
// connect to rtmp output url. // Connect to RTMP server.
// @remark ignore when not connected, reconnect when disconnected.
virtual int connect(); virtual int connect();
// Close the connection to RTMP server.
virtual void close();
}; };
/** /**

View file

@ -421,10 +421,14 @@ int SrsStSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
return ret; return ret;
} }
SrsTcpClient::SrsTcpClient() SrsTcpClient::SrsTcpClient(string h, int p, int64_t tm)
{ {
io = NULL; io = NULL;
stfd = NULL; stfd = NULL;
host = h;
port = p;
timeout = tm;
} }
SrsTcpClient::~SrsTcpClient() SrsTcpClient::~SrsTcpClient()
@ -432,26 +436,19 @@ SrsTcpClient::~SrsTcpClient()
close(); close();
} }
bool SrsTcpClient::connected() int SrsTcpClient::connect()
{
return io;
}
int SrsTcpClient::connect(string host, int port, int64_t timeout)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when connected, ignore. close();
if (io) {
return ret; srs_assert(stfd == NULL);
} if ((ret = srs_socket_connect(host, port, timeout * 1000, &stfd)) != ERROR_SUCCESS) {
srs_error("connect tcp://%s:%d failed, to=%"PRId64"ms. ret=%d", host.c_str(), port, timeout, ret);
// connect host.
if ((ret = srs_socket_connect(host, port, timeout, &stfd)) != ERROR_SUCCESS) {
srs_error("connect server %s:%d failed. ret=%d", host.c_str(), port, ret);
return ret; return ret;
} }
srs_assert(io == NULL);
io = new SrsStSocket(stfd); io = new SrsStSocket(stfd);
return ret; return ret;
@ -459,7 +456,7 @@ int SrsTcpClient::connect(string host, int port, int64_t timeout)
void SrsTcpClient::close() void SrsTcpClient::close()
{ {
// when closed, ignore. // Ignore when already closed.
if (!io) { if (!io) {
return; return;
} }

View file

@ -205,34 +205,41 @@ public:
}; };
/** /**
* the common tcp client, to connect to specified TCP server, * The client to connect to server over TCP.
* reconnect and close the connection. * User must never reuse the client when close it.
* Usage:
* SrsTcpClient client("127.0.0.1", 1935,9000);
* client.connect();
* client.write("Hello world!", 12, NULL);
* client.read(buf, 4096, NULL);
*/ */
class SrsTcpClient : public ISrsProtocolReaderWriter class SrsTcpClient : public ISrsProtocolReaderWriter
{ {
private: private:
st_netfd_t stfd; st_netfd_t stfd;
SrsStSocket* io; SrsStSocket* io;
private:
std::string host;
int port;
int64_t timeout;
public: public:
SrsTcpClient(); /**
* Constructor.
* @param h the ip or hostname of server.
* @param p the port to connect to.
* @param tm the timeout in ms.
*/
SrsTcpClient(std::string h, int p, int64_t tm);
virtual ~SrsTcpClient(); virtual ~SrsTcpClient();
public: public:
/** /**
* whether connected to server. * Connect to server over TCP.
* @remark We will close the exists connection before do connect.
*/ */
virtual bool connected(); virtual int connect();
public:
/** /**
* connect to server over TCP. * Close the connection to server.
* @param host the ip or hostname of server. * @remark User should never use the client when close it.
* @param port the port to connect to.
* @param timeout the timeout in us.
* @remark ignore when connected.
*/
virtual int connect(std::string host, int port, int64_t timeout);
/**
* close the connection.
* @remark ignore when closed.
*/ */
virtual void close(); virtual void close();
// interface ISrsProtocolReaderWriter // interface ISrsProtocolReaderWriter

View file

@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version // current release version
#define VERSION_MAJOR 3 #define VERSION_MAJOR 3
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 14 #define VERSION_REVISION 15
// generated by configure, only macros. // generated by configure, only macros.
#include <srs_auto_headers.hpp> #include <srs_auto_headers.hpp>

View file

@ -69,6 +69,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// to avoid death connection. // to avoid death connection.
// the common io timeout, for both recv and send. // the common io timeout, for both recv and send.
// TODO: FIXME: use ms for timeout.
#define SRS_CONSTS_RTMP_TIMEOUT_US (int64_t)(30*1000*1000LL) #define SRS_CONSTS_RTMP_TIMEOUT_US (int64_t)(30*1000*1000LL)
// the timeout to wait for client control message, // the timeout to wait for client control message,
@ -409,6 +410,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_CONSTS_KAFKA_DEFAULT_PORT 9092 #define SRS_CONSTS_KAFKA_DEFAULT_PORT 9092
// the common io timeout, for both recv and send. // the common io timeout, for both recv and send.
// TODO: FIXME: use ms for timeout.
#define SRS_CONSTS_KAFKA_TIMEOUT_US (int64_t)(30*1000*1000LL) #define SRS_CONSTS_KAFKA_TIMEOUT_US (int64_t)(30*1000*1000LL)
#endif #endif

View file

@ -647,34 +647,8 @@ private:
SrsRawAacStream* aac; SrsRawAacStream* aac;
std::string aac_specific_config; std::string aac_specific_config;
public: public:
SrsIngestSrsOutput(SrsHttpUri* rtmp) { SrsIngestSrsOutput(SrsHttpUri* rtmp);
out_rtmp = rtmp; virtual ~SrsIngestSrsOutput();
disconnected = false;
raw_aac_dts = srs_update_system_time_ms();
req = NULL;
sdk = new SrsSimpleRtmpClient();
avc = new SrsRawH264Stream();
aac = new SrsRawAacStream();
h264_sps_changed = false;
h264_pps_changed = false;
h264_sps_pps_sent = false;
}
virtual ~SrsIngestSrsOutput() {
close();
srs_freep(sdk);
srs_freep(avc);
srs_freep(aac);
std::multimap<int64_t, SrsTsMessage*>::iterator it;
for (it = queue.begin(); it != queue.end(); ++it) {
SrsTsMessage* msg = it->second;
srs_freep(msg);
}
queue.clear();
}
// interface ISrsTsHandler // interface ISrsTsHandler
public: public:
virtual int on_ts_message(SrsTsMessage* msg); virtual int on_ts_message(SrsTsMessage* msg);
@ -705,6 +679,37 @@ private:
virtual void close(); virtual void close();
}; };
SrsIngestSrsOutput::SrsIngestSrsOutput(SrsHttpUri* rtmp)
{
out_rtmp = rtmp;
disconnected = false;
raw_aac_dts = srs_update_system_time_ms();
req = NULL;
sdk = NULL;
avc = new SrsRawH264Stream();
aac = new SrsRawAacStream();
h264_sps_changed = false;
h264_pps_changed = false;
h264_sps_pps_sent = false;
}
SrsIngestSrsOutput::~SrsIngestSrsOutput()
{
close();
srs_freep(avc);
srs_freep(aac);
std::multimap<int64_t, SrsTsMessage*>::iterator it;
for (it = queue.begin(); it != queue.end(); ++it) {
SrsTsMessage* msg = it->second;
srs_freep(msg);
}
queue.clear();
}
int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg) int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -1184,6 +1189,10 @@ int SrsIngestSrsOutput::rtmp_write_packet(char type, u_int32_t timestamp, char*
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if ((ret = connect()) != ERROR_SUCCESS) {
return ret;
}
SrsSharedPtrMessage* msg = NULL; SrsSharedPtrMessage* msg = NULL;
if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != ERROR_SUCCESS) { if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != ERROR_SUCCESS) {
@ -1196,6 +1205,7 @@ int SrsIngestSrsOutput::rtmp_write_packet(char type, u_int32_t timestamp, char*
// send out encoded msg. // send out encoded msg.
if ((ret = sdk->send_and_free_message(msg)) != ERROR_SUCCESS) { if ((ret = sdk->send_and_free_message(msg)) != ERROR_SUCCESS) {
close();
srs_error("send RTMP type=%d, dts=%d, size=%d failed. ret=%d", type, timestamp, size, ret); srs_error("send RTMP type=%d, dts=%d, size=%d failed. ret=%d", type, timestamp, size, ret);
return ret; return ret;
} }
@ -1207,9 +1217,8 @@ int SrsIngestSrsOutput::connect()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when ok, ignore. // Ignore when connected.
// TODO: FIXME: should reconnect when disconnected. if (sdk) {
if (sdk->connected()) {
return ret; return ret;
} }
@ -1219,13 +1228,17 @@ int SrsIngestSrsOutput::connect()
// connect host. // connect host.
int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US; int64_t cto = SRS_CONSTS_RTMP_TIMEOUT_US;
int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US; int64_t sto = SRS_CONSTS_RTMP_PULSE_TIMEOUT_US;
if ((ret = sdk->connect(url, cto, sto)) != ERROR_SUCCESS) { sdk = new SrsSimpleRtmpClient(url, cto/1000, sto/1000);
if ((ret = sdk->connect()) != ERROR_SUCCESS) {
close();
srs_error("mpegts: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret); srs_error("mpegts: connect %s failed, cto=%"PRId64", sto=%"PRId64". ret=%d", url.c_str(), cto, sto, ret);
return ret; return ret;
} }
// publish. // publish.
if ((ret = sdk->publish()) != ERROR_SUCCESS) { if ((ret = sdk->publish()) != ERROR_SUCCESS) {
close();
srs_error("mpegts: publish %s failed. ret=%d", url.c_str(), ret); srs_error("mpegts: publish %s failed. ret=%d", url.c_str(), ret);
return ret; return ret;
} }
@ -1235,11 +1248,9 @@ int SrsIngestSrsOutput::connect()
void SrsIngestSrsOutput::close() void SrsIngestSrsOutput::close()
{ {
srs_trace("close output=%s", out_rtmp->get_url().c_str());
h264_sps_pps_sent = false; h264_sps_pps_sent = false;
srs_freep(req); srs_freep(req);
sdk->close(); srs_freep(sdk);
} }
// the context for ingest hls stream. // the context for ingest hls stream.