winlin

use kernel utility int2str and float2str

@@ -44,6 +44,7 @@ using namespace std; @@ -44,6 +44,7 @@ using namespace std;
44 #include <srs_app_utility.hpp> 44 #include <srs_app_utility.hpp>
45 #include <srs_protocol_amf0.hpp> 45 #include <srs_protocol_amf0.hpp>
46 #include <srs_kernel_utility.hpp> 46 #include <srs_kernel_utility.hpp>
  47 +#include <srs_kernel_balance.hpp>
47 48
48 // when error, edge ingester sleep for a while and retry. 49 // when error, edge ingester sleep for a while and retry.
49 #define SRS_EDGE_INGESTER_SLEEP_US (int64_t)(1*1000*1000LL) 50 #define SRS_EDGE_INGESTER_SLEEP_US (int64_t)(1*1000*1000LL)
@@ -67,10 +68,9 @@ SrsEdgeIngester::SrsEdgeIngester() @@ -67,10 +68,9 @@ SrsEdgeIngester::SrsEdgeIngester()
67 client = NULL; 68 client = NULL;
68 _edge = NULL; 69 _edge = NULL;
69 _req = NULL; 70 _req = NULL;
70 - origin_index = 0;  
71 stream_id = 0; 71 stream_id = 0;
72 stfd = NULL; 72 stfd = NULL;
73 - curr_origin_server = ""; 73 + lb = new SrsLbRoundRobin();
74 pthread = new SrsReusableThread2("edge-igs", this, SRS_EDGE_INGESTER_SLEEP_US); 74 pthread = new SrsReusableThread2("edge-igs", this, SRS_EDGE_INGESTER_SLEEP_US);
75 } 75 }
76 76
@@ -78,6 +78,7 @@ SrsEdgeIngester::~SrsEdgeIngester() @@ -78,6 +78,7 @@ SrsEdgeIngester::~SrsEdgeIngester()
78 { 78 {
79 stop(); 79 stop();
80 80
  81 + srs_freep(lb);
81 srs_freep(pthread); 82 srs_freep(pthread);
82 srs_freep(kbps); 83 srs_freep(kbps);
83 } 84 }
@@ -121,7 +122,7 @@ void SrsEdgeIngester::stop() @@ -121,7 +122,7 @@ void SrsEdgeIngester::stop()
121 122
122 string SrsEdgeIngester::get_curr_origin() 123 string SrsEdgeIngester::get_curr_origin()
123 { 124 {
124 - return curr_origin_server; 125 + return lb->selected();
125 } 126 }
126 127
127 int SrsEdgeIngester::cycle() 128 int SrsEdgeIngester::cycle()
@@ -130,7 +131,8 @@ int SrsEdgeIngester::cycle() @@ -130,7 +131,8 @@ int SrsEdgeIngester::cycle()
130 131
131 _source->on_source_id_changed(_srs_context->get_id()); 132 _source->on_source_id_changed(_srs_context->get_id());
132 133
133 - std::string ep_server, ep_port; 134 + std::string ep_server;
  135 + int ep_port;
134 if ((ret = connect_server(ep_server, ep_port)) != ERROR_SUCCESS) { 136 if ((ret = connect_server(ep_server, ep_port)) != ERROR_SUCCESS) {
135 return ret; 137 return ret;
136 } 138 }
@@ -216,7 +218,7 @@ int SrsEdgeIngester::ingest() @@ -216,7 +218,7 @@ int SrsEdgeIngester::ingest()
216 } 218 }
217 219
218 // TODO: FIXME: refine the connect_app. 220 // TODO: FIXME: refine the connect_app.
219 -int SrsEdgeIngester::connect_app(string ep_server, string ep_port) 221 +int SrsEdgeIngester::connect_app(string ep_server, int ep_port)
220 { 222 {
221 int ret = ERROR_SUCCESS; 223 int ret = ERROR_SUCCESS;
222 224
@@ -258,7 +260,7 @@ int SrsEdgeIngester::connect_app(string ep_server, string ep_port) @@ -258,7 +260,7 @@ int SrsEdgeIngester::connect_app(string ep_server, string ep_port)
258 // generate the tcUrl 260 // generate the tcUrl
259 std::string param = ""; 261 std::string param = "";
260 std::string tc_url = srs_generate_tc_url(ep_server, vhost, req->app, ep_port, param); 262 std::string tc_url = srs_generate_tc_url(ep_server, vhost, req->app, ep_port, param);
261 - srs_trace("edge ingest from %s:%s at %s", ep_server.c_str(), ep_port.c_str(), tc_url.c_str()); 263 + srs_trace("edge ingest from %s:%d at %s", ep_server.c_str(), ep_port, tc_url.c_str());
262 264
263 // replace the tcUrl in request, 265 // replace the tcUrl in request,
264 // which will replace the tc_url in client.connect_app(). 266 // which will replace the tc_url in client.connect_app().
@@ -339,7 +341,7 @@ void SrsEdgeIngester::close_underlayer_socket() @@ -339,7 +341,7 @@ void SrsEdgeIngester::close_underlayer_socket()
339 srs_close_stfd(stfd); 341 srs_close_stfd(stfd);
340 } 342 }
341 343
342 -int SrsEdgeIngester::connect_server(string& ep_server, string& ep_port) 344 +int SrsEdgeIngester::connect_server(string& ep_server, int& ep_port)
343 { 345 {
344 int ret = ERROR_SUCCESS; 346 int ret = ERROR_SUCCESS;
345 347
@@ -358,21 +360,13 @@ int SrsEdgeIngester::connect_server(string& ep_server, string& ep_port) @@ -358,21 +360,13 @@ int SrsEdgeIngester::connect_server(string& ep_server, string& ep_port)
358 } 360 }
359 361
360 // select the origin. 362 // select the origin.
361 - std::string server = curr_origin_server = conf->args.at(origin_index % conf->args.size());  
362 - origin_index = (origin_index + 1) % conf->args.size();  
363 -  
364 - std::string s_port = SRS_CONSTS_RTMP_DEFAULT_PORT; 363 + std::string server = lb->select(conf->args);
365 int port = ::atoi(SRS_CONSTS_RTMP_DEFAULT_PORT); 364 int port = ::atoi(SRS_CONSTS_RTMP_DEFAULT_PORT);
366 - size_t pos = server.find(":");  
367 - if (pos != std::string::npos) {  
368 - s_port = server.substr(pos + 1);  
369 - server = server.substr(0, pos);  
370 - port = ::atoi(s_port.c_str());  
371 - } 365 + srs_parse_hostport(server, server, port);
372 366
373 // output the connected server and port. 367 // output the connected server and port.
374 ep_server = server; 368 ep_server = server;
375 - ep_port = s_port; 369 + ep_port = port;
376 370
377 // open socket. 371 // open socket.
378 int64_t timeout = SRS_EDGE_INGESTER_TIMEOUT_US; 372 int64_t timeout = SRS_EDGE_INGESTER_TIMEOUT_US;
@@ -46,6 +46,7 @@ class SrsCommonMessage; @@ -46,6 +46,7 @@ class SrsCommonMessage;
46 class SrsMessageQueue; 46 class SrsMessageQueue;
47 class ISrsProtocolReaderWriter; 47 class ISrsProtocolReaderWriter;
48 class SrsKbps; 48 class SrsKbps;
  49 +class SrsLbRoundRobin;
49 50
50 /** 51 /**
51 * the state of edge, auto machine 52 * the state of edge, auto machine
@@ -88,9 +89,7 @@ private: @@ -88,9 +89,7 @@ private:
88 ISrsProtocolReaderWriter* io; 89 ISrsProtocolReaderWriter* io;
89 SrsKbps* kbps; 90 SrsKbps* kbps;
90 SrsRtmpClient* client; 91 SrsRtmpClient* client;
91 - int origin_index;  
92 - // current origin server of current source.  
93 - std::string curr_origin_server; 92 + SrsLbRoundRobin* lb;
94 public: 93 public:
95 SrsEdgeIngester(); 94 SrsEdgeIngester();
96 virtual ~SrsEdgeIngester(); 95 virtual ~SrsEdgeIngester();
@@ -105,8 +104,8 @@ public: @@ -105,8 +104,8 @@ public:
105 private: 104 private:
106 virtual int ingest(); 105 virtual int ingest();
107 virtual void close_underlayer_socket(); 106 virtual void close_underlayer_socket();
108 - virtual int connect_server(std::string& ep_server, std::string& ep_port);  
109 - virtual int connect_app(std::string ep_server, std::string ep_port); 107 + virtual int connect_server(std::string& ep_server, int& ep_port);
  108 + virtual int connect_app(std::string ep_server, int ep_port);
110 virtual int process_publish_message(SrsCommonMessage* msg); 109 virtual int process_publish_message(SrsCommonMessage* msg);
111 }; 110 };
112 111
@@ -43,6 +43,7 @@ using namespace std; @@ -43,6 +43,7 @@ using namespace std;
43 #include <srs_app_utility.hpp> 43 #include <srs_app_utility.hpp>
44 #include <srs_app_process.hpp> 44 #include <srs_app_process.hpp>
45 #include <srs_core_autofree.hpp> 45 #include <srs_core_autofree.hpp>
  46 +#include <srs_kernel_utility.hpp>
46 47
47 #ifdef SRS_AUTO_FFMPEG_STUB 48 #ifdef SRS_AUTO_FFMPEG_STUB
48 49
@@ -248,12 +249,6 @@ int SrsFFMPEG::start() @@ -248,12 +249,6 @@ int SrsFFMPEG::start()
248 return ret; 249 return ret;
249 } 250 }
250 251
251 - // prepare exec params  
252 - // @remark we should never use stack variable, use heap to alloc to make lldb happy.  
253 - #define SRS_TMP_SIZE 512  
254 - char* tmp = new char[SRS_TMP_SIZE];  
255 - SrsAutoFree(char, tmp);  
256 -  
257 // the argv for process. 252 // the argv for process.
258 params.clear(); 253 params.clear();
259 254
@@ -300,33 +295,28 @@ int SrsFFMPEG::start() @@ -300,33 +295,28 @@ int SrsFFMPEG::start()
300 if (vcodec != SRS_RTMP_ENCODER_COPY && vcodec != SRS_RTMP_ENCODER_NO_VIDEO) { 295 if (vcodec != SRS_RTMP_ENCODER_COPY && vcodec != SRS_RTMP_ENCODER_NO_VIDEO) {
301 if (vbitrate > 0) { 296 if (vbitrate > 0) {
302 params.push_back("-b:v"); 297 params.push_back("-b:v");
303 - snprintf(tmp, SRS_TMP_SIZE, "%d", vbitrate * 1000);  
304 - params.push_back(tmp); 298 + params.push_back(srs_int2str(vbitrate * 1000));
305 } 299 }
306 300
307 if (vfps > 0) { 301 if (vfps > 0) {
308 params.push_back("-r"); 302 params.push_back("-r");
309 - snprintf(tmp, SRS_TMP_SIZE, "%.2f", vfps);  
310 - params.push_back(tmp); 303 + params.push_back(srs_float2str(vfps));
311 } 304 }
312 305
313 if (vwidth > 0 && vheight > 0) { 306 if (vwidth > 0 && vheight > 0) {
314 params.push_back("-s"); 307 params.push_back("-s");
315 - snprintf(tmp, SRS_TMP_SIZE, "%dx%d", vwidth, vheight);  
316 - params.push_back(tmp); 308 + params.push_back(srs_int2str(vwidth) + "x" + srs_int2str(vheight));
317 } 309 }
318 310
319 // TODO: add aspect if needed. 311 // TODO: add aspect if needed.
320 if (vwidth > 0 && vheight > 0) { 312 if (vwidth > 0 && vheight > 0) {
321 params.push_back("-aspect"); 313 params.push_back("-aspect");
322 - snprintf(tmp, SRS_TMP_SIZE, "%d:%d", vwidth, vheight);  
323 - params.push_back(tmp); 314 + params.push_back(srs_int2str(vwidth) + ":" + srs_int2str(vheight));
324 } 315 }
325 316
326 if (vthreads > 0) { 317 if (vthreads > 0) {
327 params.push_back("-threads"); 318 params.push_back("-threads");
328 - snprintf(tmp, SRS_TMP_SIZE, "%d", vthreads);  
329 - params.push_back(tmp); 319 + params.push_back(srs_int2str(vthreads));
330 } 320 }
331 321
332 params.push_back("-profile:v"); 322 params.push_back("-profile:v");
@@ -360,20 +350,17 @@ int SrsFFMPEG::start() @@ -360,20 +350,17 @@ int SrsFFMPEG::start()
360 if (acodec != SRS_RTMP_ENCODER_COPY) { 350 if (acodec != SRS_RTMP_ENCODER_COPY) {
361 if (abitrate > 0) { 351 if (abitrate > 0) {
362 params.push_back("-b:a"); 352 params.push_back("-b:a");
363 - snprintf(tmp, SRS_TMP_SIZE, "%d", abitrate * 1000);  
364 - params.push_back(tmp); 353 + params.push_back(srs_int2str(abitrate * 1000));
365 } 354 }
366 355
367 if (asample_rate > 0) { 356 if (asample_rate > 0) {
368 params.push_back("-ar"); 357 params.push_back("-ar");
369 - snprintf(tmp, SRS_TMP_SIZE, "%d", asample_rate);  
370 - params.push_back(tmp); 358 + params.push_back(srs_int2str(asample_rate));
371 } 359 }
372 360
373 if (achannels > 0) { 361 if (achannels > 0) {
374 params.push_back("-ac"); 362 params.push_back("-ac");
375 - snprintf(tmp, SRS_TMP_SIZE, "%d", achannels);  
376 - params.push_back(tmp); 363 + params.push_back(srs_int2str(achannels));
377 } 364 }
378 365
379 // aparams 366 // aparams
@@ -98,7 +98,7 @@ int SrsKafkaProducer::request_metadata() @@ -98,7 +98,7 @@ int SrsKafkaProducer::request_metadata()
98 } 98 }
99 99
100 srs_assert(!brokers->args.empty()); 100 srs_assert(!brokers->args.empty());
101 - std::string broker = lb->select<string>(brokers->args); 101 + std::string broker = lb->select(brokers->args);
102 102
103 if (true) { 103 if (true) {
104 std::string senabled = srs_bool2switch(enabled); 104 std::string senabled = srs_bool2switch(enabled);
@@ -720,15 +720,12 @@ int SrsServer::acquire_pid_file() @@ -720,15 +720,12 @@ int SrsServer::acquire_pid_file()
720 srs_error("truncate pid file %s error! ret=%#x", pid_file.c_str(), ret); 720 srs_error("truncate pid file %s error! ret=%#x", pid_file.c_str(), ret);
721 return ret; 721 return ret;
722 } 722 }
723 -  
724 - int pid = (int)getpid();  
725 723
726 // write the pid 724 // write the pid
727 - char buf[512];  
728 - snprintf(buf, sizeof(buf), "%d", pid);  
729 - if (write(fd, buf, strlen(buf)) != (int)strlen(buf)) { 725 + string pid = srs_int2str(getpid());
  726 + if (write(fd, pid.c_str(), pid.length()) != pid.length()) {
730 ret = ERROR_SYSTEM_PID_WRITE_FILE; 727 ret = ERROR_SYSTEM_PID_WRITE_FILE;
731 - srs_error("write our pid error! pid=%d file=%s ret=%#x", pid, pid_file.c_str(), ret); 728 + srs_error("write our pid error! pid=%s file=%s ret=%#x", pid.c_str(), pid_file.c_str(), ret);
732 return ret; 729 return ret;
733 } 730 }
734 731
@@ -746,7 +743,7 @@ int SrsServer::acquire_pid_file() @@ -746,7 +743,7 @@ int SrsServer::acquire_pid_file()
746 return ret; 743 return ret;
747 } 744 }
748 745
749 - srs_trace("write pid=%d to %s success!", pid, pid_file.c_str()); 746 + srs_trace("write pid=%s to %s success!", pid.c_str(), pid_file.c_str());
750 pid_fd = fd; 747 pid_fd = fd;
751 748
752 return ret; 749 return ret;
@@ -204,8 +204,7 @@ string srs_path_build_timestamp(string template_path) @@ -204,8 +204,7 @@ string srs_path_build_timestamp(string template_path)
204 // [timestamp],replace this const to current UNIX timestamp in ms. 204 // [timestamp],replace this const to current UNIX timestamp in ms.
205 if (true) { 205 if (true) {
206 int64_t now_us = ((int64_t)tv.tv_sec) * 1000 * 1000 + (int64_t)tv.tv_usec; 206 int64_t now_us = ((int64_t)tv.tv_sec) * 1000 * 1000 + (int64_t)tv.tv_usec;
207 - snprintf(buf, sizeof(buf), "%"PRId64, now_us / 1000);  
208 - path = srs_string_replace(path, "[timestamp]", buf); 207 + path = srs_string_replace(path, "[timestamp]", srs_int2str(now_us / 1000));
209 } 208 }
210 209
211 return path; 210 return path;
@@ -23,6 +23,8 @@ @@ -23,6 +23,8 @@
23 23
24 #include <srs_kernel_balance.hpp> 24 #include <srs_kernel_balance.hpp>
25 25
  26 +using namespace std;
  27 +
26 SrsLbRoundRobin::SrsLbRoundRobin() 28 SrsLbRoundRobin::SrsLbRoundRobin()
27 { 29 {
28 index = -1; 30 index = -1;
@@ -38,3 +40,18 @@ u_int32_t SrsLbRoundRobin::current() @@ -38,3 +40,18 @@ u_int32_t SrsLbRoundRobin::current()
38 return index; 40 return index;
39 } 41 }
40 42
  43 +string SrsLbRoundRobin::selected()
  44 +{
  45 + return elem;
  46 +}
  47 +
  48 +string SrsLbRoundRobin::select(const vector<string>& servers)
  49 +{
  50 + srs_assert(!servers.empty());
  51 +
  52 + index = (int)(count++ % servers.size());
  53 + elem = servers.at(index);
  54 +
  55 + return elem;
  56 +}
  57 +
@@ -30,6 +30,7 @@ @@ -30,6 +30,7 @@
30 #include <srs_core.hpp> 30 #include <srs_core.hpp>
31 31
32 #include <vector> 32 #include <vector>
  33 +#include <string>
33 34
34 /** 35 /**
35 * the round-robin load balance algorithm, 36 * the round-robin load balance algorithm,
@@ -42,21 +43,15 @@ private: @@ -42,21 +43,15 @@ private:
42 int index; 43 int index;
43 // total scheduled count. 44 // total scheduled count.
44 u_int32_t count; 45 u_int32_t count;
  46 + // current selected server.
  47 + std::string elem;
45 public: 48 public:
46 SrsLbRoundRobin(); 49 SrsLbRoundRobin();
47 virtual ~SrsLbRoundRobin(); 50 virtual ~SrsLbRoundRobin();
48 public: 51 public:
49 virtual u_int32_t current(); 52 virtual u_int32_t current();
50 -public:  
51 - template<typename T>  
52 - const T& select(const std::vector<T>& servers)  
53 - {  
54 - srs_assert(!servers.empty());  
55 -  
56 - index = (int)(count++ % servers.size());  
57 -  
58 - return servers.at(index);  
59 - } 53 + virtual std::string selected();
  54 + virtual std::string select(const std::vector<std::string>& servers);
60 }; 55 };
61 56
62 #endif 57 #endif
@@ -169,14 +169,43 @@ string srs_dns_resolve(string host) @@ -169,14 +169,43 @@ string srs_dns_resolve(string host)
169 169
170 char ipv4[16]; 170 char ipv4[16];
171 memset(ipv4, 0, sizeof(ipv4)); 171 memset(ipv4, 0, sizeof(ipv4));
172 - for (int i = 0; i < answer->h_length; i++) {  
173 - inet_ntop(AF_INET, answer->h_addr_list[i], ipv4, sizeof(ipv4));  
174 - break; 172 +
  173 + // covert the first entry to ip.
  174 + if (answer->h_length > 0) {
  175 + inet_ntop(AF_INET, answer->h_addr_list[0], ipv4, sizeof(ipv4));
175 } 176 }
176 177
177 return ipv4; 178 return ipv4;
178 } 179 }
179 180
  181 +void srs_parse_hostport(const string& hostport, string& host, int& port)
  182 +{
  183 + host = hostport;
  184 +
  185 + size_t pos = hostport.find(":");
  186 + if (pos != std::string::npos) {
  187 + string p = hostport.substr(pos + 1);
  188 + host = hostport.substr(0, pos);
  189 + port = ::atoi(p.c_str());
  190 + }
  191 +}
  192 +
  193 +string srs_int2str(int64_t value)
  194 +{
  195 + // len(max int64_t) is 20, plus one "+-."
  196 + char tmp[22];
  197 + snprintf(tmp, 22, "%"PRId64, value);
  198 + return tmp;
  199 +}
  200 +
  201 +string srs_float2str(double value)
  202 +{
  203 + // len(max int64_t) is 20, plus one "+-."
  204 + char tmp[22];
  205 + snprintf(tmp, 22, "%.2f", value);
  206 + return tmp;
  207 +}
  208 +
180 bool srs_is_little_endian() 209 bool srs_is_little_endian()
181 { 210 {
182 // convert to network(big-endian) order, if not equals, 211 // convert to network(big-endian) order, if not equals,
@@ -52,6 +52,13 @@ extern int64_t srs_update_system_time_ms(); @@ -52,6 +52,13 @@ extern int64_t srs_update_system_time_ms();
52 52
53 // dns resolve utility, return the resolved ip address. 53 // dns resolve utility, return the resolved ip address.
54 extern std::string srs_dns_resolve(std::string host); 54 extern std::string srs_dns_resolve(std::string host);
  55 +// split the host:port to host and port.
  56 +extern void srs_parse_hostport(const std::string& hostport, std::string& host, int& port);
  57 +
  58 +// parse the int64 value to string.
  59 +extern std::string srs_int2str(int64_t value);
  60 +// parse the float value to string, precise is 2.
  61 +extern std::string srs_float2str(double value);
55 62
56 // whether system is little endian 63 // whether system is little endian
57 extern bool srs_is_little_endian(); 64 extern bool srs_is_little_endian();
@@ -174,9 +174,7 @@ int64_t SrsHttpHeader::content_length() @@ -174,9 +174,7 @@ int64_t SrsHttpHeader::content_length()
174 174
175 void SrsHttpHeader::set_content_length(int64_t size) 175 void SrsHttpHeader::set_content_length(int64_t size)
176 { 176 {
177 - char buf[64];  
178 - snprintf(buf, sizeof(buf), "%"PRId64, size);  
179 - set("Content-Length", buf); 177 + set("Content-Length", srs_int2str(size));
180 } 178 }
181 179
182 string SrsHttpHeader::content_type() 180 string SrsHttpHeader::content_type()
@@ -28,6 +28,7 @@ using namespace std; @@ -28,6 +28,7 @@ using namespace std;
28 28
29 #include <srs_kernel_log.hpp> 29 #include <srs_kernel_log.hpp>
30 #include <srs_protocol_amf0.hpp> 30 #include <srs_protocol_amf0.hpp>
  31 +#include <srs_kernel_utility.hpp>
31 32
32 /* json encode 33 /* json encode
33 cout<< SRS_JOBJECT_START 34 cout<< SRS_JOBJECT_START
@@ -328,10 +329,7 @@ string SrsJsonAny::dumps() @@ -328,10 +329,7 @@ string SrsJsonAny::dumps()
328 return to_boolean()? "true":"false"; 329 return to_boolean()? "true":"false";
329 } 330 }
330 case SRS_JSON_Integer: { 331 case SRS_JSON_Integer: {
331 - // len(max int64_t) is 20, plus one "+-."  
332 - char tmp[22];  
333 - snprintf(tmp, 22, "%"PRId64, to_integer());  
334 - return tmp; 332 + return srs_int2str(to_integer());
335 } 333 }
336 case SRS_JSON_Number: { 334 case SRS_JSON_Number: {
337 // len(max int64_t) is 20, plus one "+-." 335 // len(max int64_t) is 20, plus one "+-."
@@ -125,6 +125,11 @@ void srs_random_generate(char* bytes, int size) @@ -125,6 +125,11 @@ void srs_random_generate(char* bytes, int size)
125 } 125 }
126 } 126 }
127 127
  128 +string srs_generate_tc_url(string ip, string vhost, string app, int port, string param)
  129 +{
  130 + return srs_generate_tc_url(ip, vhost, app, srs_int2str(port), param);
  131 +}
  132 +
128 string srs_generate_tc_url(string ip, string vhost, string app, string port, string param) 133 string srs_generate_tc_url(string ip, string vhost, string app, string port, string param)
129 { 134 {
130 string tcUrl = "rtmp://"; 135 string tcUrl = "rtmp://";
@@ -89,6 +89,10 @@ extern std::string srs_generate_tc_url( @@ -89,6 +89,10 @@ extern std::string srs_generate_tc_url(
89 std::string ip, std::string vhost, std::string app, std::string port, 89 std::string ip, std::string vhost, std::string app, std::string port,
90 std::string param 90 std::string param
91 ); 91 );
  92 +extern std::string srs_generate_tc_url(
  93 + std::string ip, std::string vhost, std::string app, int port,
  94 + std::string param
  95 +);
92 96
93 /** 97 /**
94 * compare the memory in bytes. 98 * compare the memory in bytes.