|
为什么要这样修改呢?当然是有特别的场景需要。比如某一个直播,推流中断。这时, 服务器直接用一个广告推流来替代。当直播恢复后,强行踢掉广告流。 因为主播流和广告流是使用的同一个直播地址,因此,需要这个踢流机制。 原来的播主网络恢复了,他要继续推流。如何处理呢?最好的办法不是发消息让广告进程停止注入。 而是强迫广告进程让出原来的播主频道。 srs原来提供了一个kickoff流的http-api。那是利用coroutine的机制来实现的,感觉非常危险。 容易易导致程序crash。并且,也没有必要那样做,只需要想办法exit rtmp-publishing处理线程 就可以了。关键算法程序如下: srs_error_t SrsRtmpConn::stream_service_cycle() { ... srs_trace("find a source for source-ip:%s, type=%d",ip.c_str(),info->type); int ret=0; SrsSource* source = NULL; if (info->type == SrsRtmpConnUnknown){ return srs_error_new(ERROR_RTMP_STREAM_NOT_FOUND, "rtmp: unknown stream"); } else if (info->type == SrsRtmpConnPlay){ ret = _srs_sources->find_for_play(req, server, &source); } else{ if ((ip == "127.0.0.1")){ _srs_sources->local_create(req, server, &source); }else{ srs_warn("%s/%s:Force local-publisher quit!",req->app.c_str(),req->stream.c_str()); string local_pusher_url = "127.0.0.1-" + req->app + "/" + req->stream; std::map<string,int>::iterator it; it = gRtmpConnExitFlagTbl.find(local_pusher_url); if (it != gRtmpConnExitFlagTbl.end()){ gRtmpConnExitFlagTbl.at(local_pusher_url) = 111111; //force quit if exist usleep(30000); } if ((ret = _srs_sources->fetch_or_create(req, server, &source)) <0) { return srs_error_new(ERROR_RTMP_ACCESS_DENIED, "rtmp: fetch source"); } } } ... } 经测试,播主和中断式广告相互切换非常流畅。 |