srs拉流的步骤前面几步和推流差不多,就不再赘述了。这边直接从playing函数调用开始开始讲起。srs推流的流程
在playing函数中,会启动一个新协程专门用来接受Message并且处理对饮的流程。旧协程会执行do_playing用于消费Message队列,往对端发送数据。
srs_error_t SrsRtmpConn::playing(SrsSource* source)
{
if (!info->edge && _srs_config->get_vhost_origin_cluster(req->vhost) && source->inactive()) {
/*这段代码是用来如果当前的源站没有流,去请求别的源站是否有流*/
}
/*用于接受Message并且进行处理*/
SrsQueueRecvThread trd(consumer, rtmp, SRS_PERF_MW_SLEEP, _srs_context->get_id());
if ((err = trd.start()) != srs_success) {
return srs_error_wrap(err, "rtmp: start receive thread");
}
/*消费Message队列*/
err = do_playing(source, consumer, &trd);
return err;
}
旧的协程会等待事件通知,在队列有数据时去消费Message,最后发送给对端。
srs_error_t SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, SrsQueueRecvThread* rtrd)
{
while (true) {
#ifdef SRS_PERF_QUEUE_COND_WAIT
// wait for message to incoming.
// 等待队列中有数据生产
consumer->wait(mw_msgs, mw_sleep);
#endif
// 获取数据
if ((err = consumer->dump_packets(&msgs, count)) != srs_success) {
return srs_error_wrap(err, "rtmp: consumer dump packets");
}
// 发送数据
if (user_specified_duration_to_stop) {
if (duration >= req->duration) {
return srs_error_new(ERROR_RTMP_DURATION_EXCEED, "rtmp: time %d up %d", srsu2msi(duration), srsu2msi(req->duration));
}
}
// apply the minimal interval for delivery stream in srs_utime_t.
if (send_min_interval > 0) {
srs_usleep(send_min_interval);
}
}
return err;
}