Rtmp协议规定:
(1)、 握手:固定步骤,RTMP连接都是以握手作为开始。
(2)、 建立连接:用于建立客户端和服务端之间的“网络连接”
(3)、 建立流:用于建立客户端和服务端之间的“网络流”,即多媒体通道。
(4)、 Publish/play:推流或者播放
int SrsRtmpConn::stream_service_cycle()
识别连接的类型,如pulish,play等。
int SrsRtmpConn::do_publishing(SrsSource* source, SrsPublishRecvThread* trd)
{
int ret = ERROR_SUCCESS;
SrsPithyPrint* pprint = SrsPithyPrint::create_rtmp_publish();
SrsAutoFree(SrsPithyPrint, pprint);
// 创建一个独立的接收线程,专门用于Rtmp协议的接受,因此,下一步进入rtmp接受线程至关重要。
// start isolate recv thread.
if ((ret = trd->start()) != ERROR_SUCCESS) {
srs_error("start isolate recv thread failed. ret=%d", ret);
return ret;
}
// change the isolate recv thread context id,
// merge its log to current thread.
int receive_thread_cid = trd->get_cid();
trd->set_cid(_srs_context->get_id());
// initialize the publish timeout.
publish_1stpkt_timeout = _srs_config->get_publish_1stpkt_timeout(req->vhost);
publish_normal_timeout = _srs_config->get_publish_normal_timeout(req->vhost);
// set the sock options.
set_sock_options();
if (true) {
bool mr = _srs_config->get_mr_enabled(req->vhost);
int mr_sleep = _srs_config->get_mr_sleep_ms(req->vhost);
srs_trace("start publish mr=%d/%d, p1stpt=%d, pnt=%d, tcp_nodelay=%d, rtcid=%d",
mr, mr_sleep, publish_1stpkt_timeout, publish_normal_timeout, tcp_nodelay,
receive_thread_cid);
}
int64_t nb_msgs = 0;
uint64_t nb_frames = 0;
while (!disposed) {
// 计算时间
pprint->elapse();
// 资源过期
// when source is set to expired, disconnect it.
if (expired) {
ret = ERROR_USER_DISCONNECT;
srs_trace("connection expired. ret=%d", ret);
return ret;
}
// 等待
// cond wait for timeout.
if (nb_msgs == 0) {
// when not got msgs, wait for a larger timeout.
// @see https://github.com/ossrs/srs/issues/441
trd->wait(publish_1stpkt_timeout);
} else {
trd->wait(publish_normal_timeout);
}
// 检测该线程出现问题
// check the thread error code.
if ((ret = trd->error_code()) != ERROR_SUCCESS) {
if (!srs_is_system_control_error(ret) && !srs_is_client_gracefully_close(ret)) {
srs_error("recv thread failed. ret=%d", ret);
}
return ret;
}
//上一次接受RTMP包数量如果等于现在接受的,说明本次没有接收到,publish超时
// when not got any messages, timeout.
if (trd->nb_msgs() <= nb_msgs) {
ret = ERROR_SOCKET_TIMEOUT;
srs_trace("publish timeout %dms, nb_msgs=%"PRId64", ret=%d",
nb_msgs? publish_normal_timeout : publish_1stpkt_timeout, nb_msgs, ret);
break;
}
nb_msgs = trd->nb_msgs();
// Update the stat for video fps.
// @remark https://github.com/ossrs/srs/issues/851
SrsStatistic* stat = SrsStatistic::instance();
if ((ret = stat->on_video_frames(req, (int)(trd->nb_video_frames() - nb_frames))) != ERROR_SUCCESS) {
return ret;
}
// 获取视频帧数量
nb_frames = trd->nb_video_frames();
// reportable
if (pprint->can_print()) {
kbps->sample();
bool mr = _srs_config->get_mr_enabled(req->vhost);
int mr_sleep = _srs_config->get_mr_sleep_ms(req->vhost);
srs_trace("<- "SRS_CONSTS_LOG_CLIENT_PUBLISH
" time=%"PRId64", okbps=%d,%d,%d, ikbps=%d,%d,%d, mr=%d/%d, p1stpt=%d, pnt=%d", pprint->age(),
kbps->get_send_kbps(), kbps->get_send_kbps_30s(), kbps->get_send_kbps_5m(),
kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m(),
mr, mr_sleep, publish_1stpkt_timeout, publish_normal_timeout
);
}
}
return ret;
}