winlin

add publish edge framework

@@ -67,7 +67,7 @@ SrsEdgeIngester::~SrsEdgeIngester() @@ -67,7 +67,7 @@ SrsEdgeIngester::~SrsEdgeIngester()
67 srs_freep(pthread); 67 srs_freep(pthread);
68 } 68 }
69 69
70 -int SrsEdgeIngester::initialize(SrsSource* source, SrsEdge* edge, SrsRequest* req) 70 +int SrsEdgeIngester::initialize(SrsSource* source, SrsPlayEdge* edge, SrsRequest* req)
71 { 71 {
72 int ret = ERROR_SUCCESS; 72 int ret = ERROR_SUCCESS;
73 73
@@ -306,19 +306,226 @@ int SrsEdgeIngester::connect_server() @@ -306,19 +306,226 @@ int SrsEdgeIngester::connect_server()
306 return ret; 306 return ret;
307 } 307 }
308 308
309 -SrsEdge::SrsEdge() 309 +SrsEdgeForwarder::SrsEdgeForwarder()
  310 +{
  311 + io = NULL;
  312 + client = NULL;
  313 + _edge = NULL;
  314 + _req = NULL;
  315 + origin_index = 0;
  316 + stream_id = 0;
  317 + stfd = NULL;
  318 + pthread = new SrsThread(this, SRS_EDGE_INGESTER_SLEEP_US);
  319 +}
  320 +
  321 +SrsEdgeForwarder::~SrsEdgeForwarder()
  322 +{
  323 + stop();
  324 +
  325 + srs_freep(pthread);
  326 +}
  327 +
  328 +int SrsEdgeForwarder::initialize(SrsSource* source, SrsPublishEdge* edge, SrsRequest* req)
  329 +{
  330 + int ret = ERROR_SUCCESS;
  331 +
  332 + _source = source;
  333 + _edge = edge;
  334 + _req = req;
  335 +
  336 + return ret;
  337 +}
  338 +
  339 +int SrsEdgeForwarder::start()
  340 +{
  341 + return pthread->start();
  342 +}
  343 +
  344 +void SrsEdgeForwarder::stop()
  345 +{
  346 + pthread->stop();
  347 +
  348 + close_underlayer_socket();
  349 +
  350 + srs_freep(client);
  351 + srs_freep(io);
  352 +}
  353 +
  354 +int SrsEdgeForwarder::cycle()
  355 +{
  356 + int ret = ERROR_SUCCESS;
  357 +
  358 + if ((ret = connect_server()) != ERROR_SUCCESS) {
  359 + return ret;
  360 + }
  361 + srs_assert(client);
  362 +
  363 + client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
  364 + client->set_send_timeout(SRS_SEND_TIMEOUT_US);
  365 +
  366 + SrsRequest* req = _req;
  367 +
  368 + if ((ret = client->handshake()) != ERROR_SUCCESS) {
  369 + srs_error("handshake with server failed. ret=%d", ret);
  370 + return ret;
  371 + }
  372 + if ((ret = client->connect_app(req->app, req->tcUrl)) != ERROR_SUCCESS) {
  373 + srs_error("connect with server failed, tcUrl=%s. ret=%d", req->tcUrl.c_str(), ret);
  374 + return ret;
  375 + }
  376 + if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
  377 + srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
  378 + return ret;
  379 + }
  380 +
  381 + if ((ret = client->play(req->stream, stream_id)) != ERROR_SUCCESS) {
  382 + srs_error("connect with server failed, stream=%s, stream_id=%d. ret=%d",
  383 + req->stream.c_str(), stream_id, ret);
  384 + return ret;
  385 + }
  386 +
  387 + if ((ret = _source->on_publish()) != ERROR_SUCCESS) {
  388 + srs_error("edge ingester play stream then publish to edge failed. ret=%d", ret);
  389 + return ret;
  390 + }
  391 +
  392 + if ((ret = _edge->on_forward_publish()) != ERROR_SUCCESS) {
  393 + return ret;
  394 + }
  395 +
  396 + if ((ret = forward()) != ERROR_SUCCESS) {
  397 + return ret;
  398 + }
  399 +
  400 + return ret;
  401 +}
  402 +
  403 +int SrsEdgeForwarder::forward()
  404 +{
  405 + int ret = ERROR_SUCCESS;
  406 +
  407 + client->set_recv_timeout(SRS_EDGE_TIMEOUT_US);
  408 +
  409 + SrsPithyPrint pithy_print(SRS_STAGE_EDGE);
  410 +
  411 + while (pthread->can_loop()) {
  412 + // switch to other st-threads.
  413 + st_usleep(0);
  414 +
  415 + pithy_print.elapse();
  416 +
  417 + // pithy print
  418 + if (pithy_print.can_print()) {
  419 + srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
  420 + pithy_print.age(), client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
  421 + }
  422 +
  423 + // read from client.
  424 + SrsCommonMessage* msg = NULL;
  425 + if ((ret = client->recv_message(&msg)) != ERROR_SUCCESS) {
  426 + srs_error("recv origin server message failed. ret=%d", ret);
  427 + return ret;
  428 + }
  429 + srs_verbose("edge loop recv message. ret=%d", ret);
  430 +
  431 + srs_assert(msg);
  432 + SrsAutoFree(SrsCommonMessage, msg, false);
  433 + }
  434 +
  435 + return ret;
  436 +}
  437 +
  438 +void SrsEdgeForwarder::close_underlayer_socket()
  439 +{
  440 + srs_close_stfd(stfd);
  441 +}
  442 +
  443 +int SrsEdgeForwarder::connect_server()
  444 +{
  445 + int ret = ERROR_SUCCESS;
  446 +
  447 + // reopen
  448 + close_underlayer_socket();
  449 +
  450 + // TODO: FIXME: support reload
  451 + SrsConfDirective* conf = _srs_config->get_vhost_edge_origin(_req->vhost);
  452 + srs_assert(conf);
  453 +
  454 + // select the origin.
  455 + std::string server = conf->args.at(origin_index % conf->args.size());
  456 + origin_index = (origin_index + 1) % conf->args.size();
  457 +
  458 + std::string s_port = RTMP_DEFAULT_PORT;
  459 + int port = ::atoi(RTMP_DEFAULT_PORT);
  460 + size_t pos = server.find(":");
  461 + if (pos != std::string::npos) {
  462 + s_port = server.substr(pos + 1);
  463 + server = server.substr(0, pos);
  464 + port = ::atoi(s_port.c_str());
  465 + }
  466 +
  467 + // open socket.
  468 + srs_trace("connect edge stream=%s, tcUrl=%s to server=%s, port=%d",
  469 + _req->stream.c_str(), _req->tcUrl.c_str(), server.c_str(), port);
  470 +
  471 + // TODO: FIXME: extract utility method
  472 + int sock = socket(AF_INET, SOCK_STREAM, 0);
  473 + if(sock == -1){
  474 + ret = ERROR_SOCKET_CREATE;
  475 + srs_error("create socket error. ret=%d", ret);
  476 + return ret;
  477 + }
  478 +
  479 + srs_assert(!stfd);
  480 + stfd = st_netfd_open_socket(sock);
  481 + if(stfd == NULL){
  482 + ret = ERROR_ST_OPEN_SOCKET;
  483 + srs_error("st_netfd_open_socket failed. ret=%d", ret);
  484 + return ret;
  485 + }
  486 +
  487 + srs_freep(client);
  488 + srs_freep(io);
  489 +
  490 + io = new SrsSocket(stfd);
  491 + client = new SrsRtmpClient(io);
  492 +
  493 + // connect to server.
  494 + std::string ip = srs_dns_resolve(server);
  495 + if (ip.empty()) {
  496 + ret = ERROR_SYSTEM_IP_INVALID;
  497 + srs_error("dns resolve server error, ip empty. ret=%d", ret);
  498 + return ret;
  499 + }
  500 +
  501 + sockaddr_in addr;
  502 + addr.sin_family = AF_INET;
  503 + addr.sin_port = htons(port);
  504 + addr.sin_addr.s_addr = inet_addr(ip.c_str());
  505 +
  506 + if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
  507 + ret = ERROR_ST_CONNECT;
  508 + srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
  509 + return ret;
  510 + }
  511 + srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
  512 +
  513 + return ret;
  514 +}
  515 +
  516 +SrsPlayEdge::SrsPlayEdge()
310 { 517 {
311 state = SrsEdgeStateInit; 518 state = SrsEdgeStateInit;
312 user_state = SrsEdgeUserStateInit; 519 user_state = SrsEdgeUserStateInit;
313 ingester = new SrsEdgeIngester(); 520 ingester = new SrsEdgeIngester();
314 } 521 }
315 522
316 -SrsEdge::~SrsEdge() 523 +SrsPlayEdge::~SrsPlayEdge()
317 { 524 {
318 srs_freep(ingester); 525 srs_freep(ingester);
319 } 526 }
320 527
321 -int SrsEdge::initialize(SrsSource* source, SrsRequest* req) 528 +int SrsPlayEdge::initialize(SrsSource* source, SrsRequest* req)
322 { 529 {
323 int ret = ERROR_SUCCESS; 530 int ret = ERROR_SUCCESS;
324 531
@@ -329,7 +536,7 @@ int SrsEdge::initialize(SrsSource* source, SrsRequest* req) @@ -329,7 +536,7 @@ int SrsEdge::initialize(SrsSource* source, SrsRequest* req)
329 return ret; 536 return ret;
330 } 537 }
331 538
332 -int SrsEdge::on_client_play() 539 +int SrsPlayEdge::on_client_play()
333 { 540 {
334 int ret = ERROR_SUCCESS; 541 int ret = ERROR_SUCCESS;
335 542
@@ -350,7 +557,7 @@ int SrsEdge::on_client_play() @@ -350,7 +557,7 @@ int SrsEdge::on_client_play()
350 return ret; 557 return ret;
351 } 558 }
352 559
353 -void SrsEdge::on_all_client_stop() 560 +void SrsPlayEdge::on_all_client_stop()
354 { 561 {
355 // when all client disconnected, 562 // when all client disconnected,
356 // and edge is ingesting origin stream, abort it. 563 // and edge is ingesting origin stream, abort it.
@@ -365,7 +572,7 @@ void SrsEdge::on_all_client_stop() @@ -365,7 +572,7 @@ void SrsEdge::on_all_client_stop()
365 } 572 }
366 } 573 }
367 574
368 -int SrsEdge::on_ingest_play() 575 +int SrsPlayEdge::on_ingest_play()
369 { 576 {
370 int ret = ERROR_SUCCESS; 577 int ret = ERROR_SUCCESS;
371 578
@@ -382,3 +589,52 @@ int SrsEdge::on_ingest_play() @@ -382,3 +589,52 @@ int SrsEdge::on_ingest_play()
382 589
383 return ret; 590 return ret;
384 } 591 }
  592 +
  593 +SrsPublishEdge::SrsPublishEdge()
  594 +{
  595 + state = SrsEdgeStateInit;
  596 + user_state = SrsEdgeUserStateInit;
  597 + forwarder = new SrsEdgeForwarder();
  598 +}
  599 +
  600 +SrsPublishEdge::~SrsPublishEdge()
  601 +{
  602 + srs_freep(forwarder);
  603 +}
  604 +
  605 +int SrsPublishEdge::initialize(SrsSource* source, SrsRequest* req)
  606 +{
  607 + int ret = ERROR_SUCCESS;
  608 +
  609 + if ((ret = forwarder->initialize(source, this, req)) != ERROR_SUCCESS) {
  610 + return ret;
  611 + }
  612 +
  613 + return ret;
  614 +}
  615 +
  616 +int SrsPublishEdge::on_client_publish()
  617 +{
  618 + int ret = ERROR_SUCCESS;
  619 +
  620 + // error state.
  621 + if (user_state != SrsEdgeUserStateInit) {
  622 + ret = ERROR_RTMP_EDGE_PUBLISH_STATE;
  623 + srs_error("invalid state for client to play stream on edge. "
  624 + "state=%d, user_state=%d, ret=%d", state, user_state, ret);
  625 + return ret;
  626 + }
  627 +
  628 + // start ingest when init state.
  629 + if (state == SrsEdgeStateInit) {
  630 + state = SrsEdgeStatePublish;
  631 + }
  632 +
  633 + return ret;
  634 +}
  635 +
  636 +int SrsPublishEdge::on_forward_publish()
  637 +{
  638 + int ret = ERROR_SUCCESS;
  639 + return ret;
  640 +}
@@ -33,9 +33,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -33,9 +33,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #include <srs_app_st.hpp> 33 #include <srs_app_st.hpp>
34 #include <srs_app_thread.hpp> 34 #include <srs_app_thread.hpp>
35 35
36 -class SrsEdge;  
37 class SrsSource; 36 class SrsSource;
38 class SrsRequest; 37 class SrsRequest;
  38 +class SrsPlayEdge;
  39 +class SrsPublishEdge;
39 class SrsRtmpClient; 40 class SrsRtmpClient;
40 class SrsCommonMessage; 41 class SrsCommonMessage;
41 class ISrsProtocolReaderWriter; 42 class ISrsProtocolReaderWriter;
@@ -46,10 +47,14 @@ class ISrsProtocolReaderWriter; @@ -46,10 +47,14 @@ class ISrsProtocolReaderWriter;
46 enum SrsEdgeState 47 enum SrsEdgeState
47 { 48 {
48 SrsEdgeStateInit = 0, 49 SrsEdgeStateInit = 0,
  50 +
  51 + // for play edge
49 SrsEdgeStatePlay = 100, 52 SrsEdgeStatePlay = 100,
50 - SrsEdgeStatePublish,  
51 // play stream from origin, ingest stream 53 // play stream from origin, ingest stream
52 SrsEdgeStateIngestConnected, 54 SrsEdgeStateIngestConnected,
  55 +
  56 + // for publish edge
  57 + SrsEdgeStatePublish = 200,
53 // publish stream to edge, forward to origin 58 // publish stream to edge, forward to origin
54 SrsEdgeStateForwardConnected, 59 SrsEdgeStateForwardConnected,
55 }; 60 };
@@ -72,7 +77,7 @@ private: @@ -72,7 +77,7 @@ private:
72 int stream_id; 77 int stream_id;
73 private: 78 private:
74 SrsSource* _source; 79 SrsSource* _source;
75 - SrsEdge* _edge; 80 + SrsPlayEdge* _edge;
76 SrsRequest* _req; 81 SrsRequest* _req;
77 SrsThread* pthread; 82 SrsThread* pthread;
78 st_netfd_t stfd; 83 st_netfd_t stfd;
@@ -83,7 +88,7 @@ public: @@ -83,7 +88,7 @@ public:
83 SrsEdgeIngester(); 88 SrsEdgeIngester();
84 virtual ~SrsEdgeIngester(); 89 virtual ~SrsEdgeIngester();
85 public: 90 public:
86 - virtual int initialize(SrsSource* source, SrsEdge* edge, SrsRequest* req); 91 + virtual int initialize(SrsSource* source, SrsPlayEdge* edge, SrsRequest* req);
87 virtual int start(); 92 virtual int start();
88 virtual void stop(); 93 virtual void stop();
89 // interface ISrsThreadHandler 94 // interface ISrsThreadHandler
@@ -97,17 +102,50 @@ private: @@ -97,17 +102,50 @@ private:
97 }; 102 };
98 103
99 /** 104 /**
100 -* edge control service. 105 +* edge used to forward stream to origin.
  106 +*/
  107 +class SrsEdgeForwarder : public ISrsThreadHandler
  108 +{
  109 +private:
  110 + int stream_id;
  111 +private:
  112 + SrsSource* _source;
  113 + SrsPublishEdge* _edge;
  114 + SrsRequest* _req;
  115 + SrsThread* pthread;
  116 + st_netfd_t stfd;
  117 + ISrsProtocolReaderWriter* io;
  118 + SrsRtmpClient* client;
  119 + int origin_index;
  120 +public:
  121 + SrsEdgeForwarder();
  122 + virtual ~SrsEdgeForwarder();
  123 +public:
  124 + virtual int initialize(SrsSource* source, SrsPublishEdge* edge, SrsRequest* req);
  125 + virtual int start();
  126 + virtual void stop();
  127 +// interface ISrsThreadHandler
  128 +public:
  129 + virtual int cycle();
  130 +private:
  131 + virtual int forward();
  132 + virtual void close_underlayer_socket();
  133 + virtual int connect_server();
  134 +};
  135 +
  136 +/**
  137 +* play edge control service.
  138 +* downloading edge speed-up.
101 */ 139 */
102 -class SrsEdge 140 +class SrsPlayEdge
103 { 141 {
104 private: 142 private:
105 SrsEdgeState state; 143 SrsEdgeState state;
106 SrsEdgeUserState user_state; 144 SrsEdgeUserState user_state;
107 SrsEdgeIngester* ingester; 145 SrsEdgeIngester* ingester;
108 public: 146 public:
109 - SrsEdge();  
110 - virtual ~SrsEdge(); 147 + SrsPlayEdge();
  148 + virtual ~SrsPlayEdge();
111 public: 149 public:
112 virtual int initialize(SrsSource* source, SrsRequest* req); 150 virtual int initialize(SrsSource* source, SrsRequest* req);
113 /** 151 /**
@@ -125,4 +163,30 @@ public: @@ -125,4 +163,30 @@ public:
125 virtual int on_ingest_play(); 163 virtual int on_ingest_play();
126 }; 164 };
127 165
  166 +/**
  167 +* publish edge control service.
  168 +* uploading edge speed-up.
  169 +*/
  170 +class SrsPublishEdge
  171 +{
  172 +private:
  173 + SrsEdgeState state;
  174 + SrsEdgeUserState user_state;
  175 + SrsEdgeForwarder* forwarder;
  176 +public:
  177 + SrsPublishEdge();
  178 + virtual ~SrsPublishEdge();
  179 +public:
  180 + virtual int initialize(SrsSource* source, SrsRequest* req);
  181 + /**
  182 + * when client publish stream on edge.
  183 + */
  184 + virtual int on_client_publish();
  185 +public:
  186 + /**
  187 + * when forwarder start to publish stream.
  188 + */
  189 + virtual int on_forward_publish();
  190 +};
  191 +
128 #endif 192 #endif
@@ -321,6 +321,13 @@ int SrsRtmpConn::stream_service_cycle() @@ -321,6 +321,13 @@ int SrsRtmpConn::stream_service_cycle()
321 case SrsRtmpConnFMLEPublish: { 321 case SrsRtmpConnFMLEPublish: {
322 srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); 322 srs_verbose("FMLE start to publish stream %s.", req->stream.c_str());
323 323
  324 + if (vhost_is_edge) {
  325 + if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) {
  326 + srs_error("notice edge start publish stream failed. ret=%d", ret);
  327 + return ret;
  328 + }
  329 + }
  330 +
324 if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) { 331 if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) {
325 srs_error("start to publish stream failed. ret=%d", ret); 332 srs_error("start to publish stream failed. ret=%d", ret);
326 return ret; 333 return ret;
@@ -456,7 +456,8 @@ SrsSource::SrsSource(SrsRequest* req) @@ -456,7 +456,8 @@ SrsSource::SrsSource(SrsRequest* req)
456 frame_rate = sample_rate = 0; 456 frame_rate = sample_rate = 0;
457 _can_publish = true; 457 _can_publish = true;
458 458
459 - edge = new SrsEdge(); 459 + play_edge = new SrsPlayEdge();
  460 + publish_edge = new SrsPublishEdge();
460 gop_cache = new SrsGopCache(); 461 gop_cache = new SrsGopCache();
461 462
462 _srs_config->subscribe(this); 463 _srs_config->subscribe(this);
@@ -489,7 +490,8 @@ SrsSource::~SrsSource() @@ -489,7 +490,8 @@ SrsSource::~SrsSource()
489 srs_freep(cache_sh_video); 490 srs_freep(cache_sh_video);
490 srs_freep(cache_sh_audio); 491 srs_freep(cache_sh_audio);
491 492
492 - srs_freep(edge); 493 + srs_freep(play_edge);
  494 + srs_freep(publish_edge);
493 srs_freep(gop_cache); 495 srs_freep(gop_cache);
494 496
495 #ifdef SRS_AUTO_HLS 497 #ifdef SRS_AUTO_HLS
@@ -515,7 +517,10 @@ int SrsSource::initialize() @@ -515,7 +517,10 @@ int SrsSource::initialize()
515 } 517 }
516 #endif 518 #endif
517 519
518 - if ((ret = edge->initialize(this, _req)) != ERROR_SUCCESS) { 520 + if ((ret = play_edge->initialize(this, _req)) != ERROR_SUCCESS) {
  521 + return ret;
  522 + }
  523 + if ((ret = publish_edge->initialize(this, _req)) != ERROR_SUCCESS) {
519 return ret; 524 return ret;
520 } 525 }
521 526
@@ -1170,7 +1175,7 @@ void SrsSource::on_consumer_destroy(SrsConsumer* consumer) @@ -1170,7 +1175,7 @@ void SrsSource::on_consumer_destroy(SrsConsumer* consumer)
1170 srs_info("handle consumer destroy success."); 1175 srs_info("handle consumer destroy success.");
1171 1176
1172 if (consumers.empty()) { 1177 if (consumers.empty()) {
1173 - edge->on_all_client_stop(); 1178 + play_edge->on_all_client_stop();
1174 } 1179 }
1175 } 1180 }
1176 1181
@@ -1186,7 +1191,12 @@ bool SrsSource::is_atc() @@ -1186,7 +1191,12 @@ bool SrsSource::is_atc()
1186 1191
1187 int SrsSource::on_edge_start_play() 1192 int SrsSource::on_edge_start_play()
1188 { 1193 {
1189 - return edge->on_client_play(); 1194 + return play_edge->on_client_play();
  1195 +}
  1196 +
  1197 +int SrsSource::on_edge_start_publish()
  1198 +{
  1199 + return publish_edge->on_client_publish();
1190 } 1200 }
1191 1201
1192 int SrsSource::create_forwarders() 1202 int SrsSource::create_forwarders()
@@ -37,7 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,7 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #include <srs_app_st.hpp> 37 #include <srs_app_st.hpp>
38 #include <srs_app_reload.hpp> 38 #include <srs_app_reload.hpp>
39 39
40 -class SrsEdge; 40 +class SrsPlayEdge;
  41 +class SrsPublishEdge;
41 class SrsSource; 42 class SrsSource;
42 class SrsCommonMessage; 43 class SrsCommonMessage;
43 class SrsOnMetaDataPacket; 44 class SrsOnMetaDataPacket;
@@ -236,7 +237,8 @@ private: @@ -236,7 +237,8 @@ private:
236 SrsEncoder* encoder; 237 SrsEncoder* encoder;
237 #endif 238 #endif
238 // edge control service 239 // edge control service
239 - SrsEdge* edge; 240 + SrsPlayEdge* play_edge;
  241 + SrsPublishEdge* publish_edge;
240 // gop cache for client fast startup. 242 // gop cache for client fast startup.
241 SrsGopCache* gop_cache; 243 SrsGopCache* gop_cache;
242 // to forward stream to other servers 244 // to forward stream to other servers
@@ -314,6 +316,8 @@ public: @@ -314,6 +316,8 @@ public:
314 virtual bool is_atc(); 316 virtual bool is_atc();
315 // for edge, when play edge stream, check the state 317 // for edge, when play edge stream, check the state
316 virtual int on_edge_start_play(); 318 virtual int on_edge_start_play();
  319 + // for edge, when publish edge stream, check the state
  320 + virtual int on_edge_start_publish();
317 private: 321 private:
318 virtual int create_forwarders(); 322 virtual int create_forwarders();
319 virtual void destroy_forwarders(); 323 virtual void destroy_forwarders();
@@ -79,6 +79,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -79,6 +79,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
79 // edge specified errors 79 // edge specified errors
80 // invalid state for client to play edge stream. 80 // invalid state for client to play edge stream.
81 #define ERROR_RTMP_EDGE_PLAY_STATE 320 81 #define ERROR_RTMP_EDGE_PLAY_STATE 320
  82 +// invalid state for client to publish edge stream.
  83 +#define ERROR_RTMP_EDGE_PUBLISH_STATE 321
82 84
83 #define ERROR_SYSTEM_STREAM_INIT 400 85 #define ERROR_SYSTEM_STREAM_INIT 400
84 #define ERROR_SYSTEM_PACKET_INVALID 401 86 #define ERROR_SYSTEM_PACKET_INVALID 401