srs10流程图_SRS学习笔记10-SrsConnection及其子类分析

本文档详细解析了SRS服务器中SrsConnection及子类的处理流程,包括SrsRtmpConn的握手、连接建立、播放和发布流的过程。通过对不同类型的连接创建、管理及消息处理的介绍,展示了SRS在处理RTMP协议时的核心机制。
摘要由CSDN通过智能技术生成

SrsConnection* conn =NULL;if (type ==SrsListenerRtmpStream) {

conn= new SrsRtmpConn(this, client_stfd);

}else if (type ==SrsListenerHttpApi) {

#ifdef SRS_AUTO_HTTP_API

conn= new SrsHttpApi(this, client_stfd, http_api_mux);#elsesrs_warn("close http client for server not support http-api");

srs_close_stfd(client_stfd);returnret;#endif}else if (type ==SrsListenerHttpStream) {

#ifdef SRS_AUTO_HTTP_SERVER

conn= new SrsResponseOnlyHttpConn(this, client_stfd, http_server);#elsesrs_warn("close http client for server not support http-server");

srs_close_stfd(client_stfd);returnret;#endif}else{//TODO: FIXME: handler others

}

srs_assert(conn);

创建完成后调用 conn->start()启动,此后这个client的请求都在这个st thread 里完成

SrsConection类

/**

* the manager for connection.

* SrsServer类实现了这一接口,用来对SrsConnection类进行管理.*/

classIConnectionManager

{public:

IConnectionManager();virtual ~IConnectionManager();public:/**

* remove the specified connection.*/

virtual void remove(SrsConnection* c) = 0;

};/**

* the basic connection of SRS,

* all connections accept from listener must extends from this base class,

* server will add the connection to manager, and delete it when remove.*/

class SrsConnection : public virtual ISrsOneCycleThreadHandler, public virtualIKbpsDelta

{private:/**

* each connection start a green thread,

* when thread stop, the connection will be delete by server.

* 业务处理线程*/SrsOneCycleThread*pthread;/**

* the id of connection.*/

intid;protected:/**

* the manager object to manage the connection.*/IConnectionManager*manager;/**

* the underlayer st fd handler.*/st_netfd_t stfd;/**

* the ip of client.*/std::stringip;/**

* whether the connection is disposed,

* when disposed, connection should stop cycle and cleanup itself.*/

booldisposed;/**

* whether connection is expired, application definition.

* when expired, the connection must never be served and quit ASAP.*/

boolexpired;public:

SrsConnection(IConnectionManager*cm, st_netfd_t c);virtual ~SrsConnection();public:/**

* to dipose the connection.*/

virtual voiddispose();/**

* start the client green thread.

* when server get a client from listener,

* 1. server will create an concrete connection(for instance, RTMP connection),

* 2. then add connection to its connection manager,

* 3. start the client thread by invoke this start()

* when client cycle thread stop, invoke the on_thread_stop(), which will use server

* to remove the client by server->remove(this).*/

virtual intstart();//interface ISrsOneCycleThreadHandler

public:/**

* the thread cycle function,

* when serve connection completed, terminate the loop which will terminate the thread,

* thread will invoke the on_thread_stop() when it terminated.*/

virtual intcycle();/**

* when the thread cycle finished, thread will invoke the on_thread_stop(),

* which will remove self from server, server will remove the connection from manager

* then delete the connection.*/

virtual voidon_thread_stop();public:/**

* get the srs id which identify the client.*/

virtual intsrs_id();/**

* set connection to expired.*/

virtual voidexpire();protected:/**

* for concrete connection to do the cycle.

* 具体connection 的处理函数,参见SrsRtmpConn.*/

virtual int do_cycle() = 0;

};

intSrsConnection::start()

{

// 启动SrsOneCycleThread类return pthread->start();

}intSrsConnection::cycle()

{int ret =ERROR_SUCCESS;

//这是个全局的id生成器,也用来生成st thread的id

_srs_context->generate_id();

id= _srs_context->get_id();

// 取得客户端的ip地址

ip=srs_get_peer_ip(st_netfd_fileno(stfd));

// 调用子类如SrsRtmpConn的处理函数

ret=do_cycle();//if socket io error, set to closed.

if(srs_is_client_gracefully_close(ret)) {

ret=ERROR_SOCKET_CLOSED;

}//success.

if (ret ==ERROR_SUCCESS) {

srs_trace("client finished.");

}//client close peer.

if (ret ==ERROR_SOCKET_CLOSED) {

srs_warn("client disconnect peer. ret=%d", ret);

}returnERROR_SUCCESS;

}voidSrsConnection::on_thread_stop()

{//TODO: FIXME: never remove itself, use isolate thread to do cleanup.

// 用在SrsServer类的conns向量数组中删除此对象   manager->remove(this);

}intSrsConnection::srs_id()

{returnid;

}voidSrsConnection::expire()

{

expired= true;

}

SrsRtmpConn类

SrsRtmpConn::SrsRtmpConn(SrsServer*svr, st_netfd_t c)

: SrsConnection(svr, c)

{

server=svr;

req= newSrsRequest();

res= newSrsResponse();

skt= newSrsStSocket(c);//实现ISrsProtocolReaderWriter接口,即st socket的读写函数,以及读写超时,发送和接受到的字节数

rtmp= newSrsRtmpServer(skt);// 提供rtmp-command-protocol服务,是一个上层的面向协议,media stream的服务,

// 例如连接vhost/app,播放流,获取视频/音频数据,与之对应的是 SrsRtmpClient.

refer= newSrsRefer();

bandwidth= newSrsBandwidth();

security= newSrsSecurity();

duration= 0;

kbps= newSrsKbps();

kbps->set_io(skt, skt);

wakable=NULL;

mw_sleep=SRS_PERF_MW_SLEEP;

mw_enabled= false;

realtime=SRS_PERF_MIN_LATENCY_ENABLED;

send_min_interval= 0;

tcp_nodelay= false;

client_type=SrsRtmpConnUnknown;

// 在配置改变时,支持reload

_srs_config->subscribe(this);

}

构造函数初始化成员变量

//TODO: return detail message when error for client.

intSrsRtmpConn::do_cycle()

{int ret =ERROR_SUCCESS;

srs_trace("RTMP client ip=%s", ip.c_str());

// 设置SrsRtmpServer里面的底层数据通讯类SrsProtocol的读写超时

rtmp->set_recv_timeout(SRS_CONSTS_RTMP_RECV_TIMEOUT_US);

rtmp->set_send_timeout(SRS_CONSTS_RTMP_SEND_TIMEOUT_US);

// 握手if ((ret = rtmp->handshake()) !=ERROR_SUCCESS) {

srs_error("rtmp handshake failed. ret=%d", ret);returnret;

}

srs_verbose("rtmp handshake success");

// 获取连接的appif ((ret = rtmp->connect_app(req)) !=ERROR_SUCCESS) {

srs_error("rtmp connect vhost/app failed. ret=%d", ret);returnret;

}

srs_verbose("rtmp connect app success");//set client ip to request.

req->ip =ip;

// 假设推流地址 rtmp://192.168.151.151/live/marstv//discovery vhost, resolve the vhost from config

req->vhost 是192.168.151.151

SrsConfDirective* parsed_vhost = _srs_config->get_vhost(req->vhost);

// 没有设置 192.168.151.151 这样的vhost parsed_vhost是默认的vhostif(parsed_vhost) {

req->vhost = parsed_vhost->arg0();// req->vhost 是 __defaultVhost__

}

srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s",

req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str());if (req->schema.empty() || req->vhost.empty() || req->port.empty() || req->app.empty()) {

ret=ERROR_RTMP_REQ_TCURL;

srs_error("discovery tcUrl failed."

"tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d",

req->tcUrl.c_str(), req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str(), ret);returnret;

}//check vhost// 在 check_vhost里面会调用 http_hooks_on_connect

if ((ret = check_vhost()) !=ERROR_SUCCESS) {

srs_error("check vhost failed. ret=%d", ret);returnret;

}

srs_verbose("check vhost success.");

srs_trace("connect app,"

"tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, args=%s",

req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(),

req->schema.c_str(), req->vhost.c_str(), req->port.c_str(),

req->app.c_str(), (req->args? "(obj)":"null"));//show client identity

if(req->args) {

std::stringsrs_version;

std::stringsrs_server_ip;int srs_pid = 0;int srs_id = 0;

SrsAmf0Any* prop =NULL;if ((prop = req->args->ensure_property_string("srs_version")) !=NULL) {

srs_version= prop->to_str();

}if ((prop = req->args->ensure_property_string("srs_server_ip")) !=NULL) {

srs_server_ip= prop->to_str();

}if ((prop = req->args->ensure_property_number("srs_pid")) !=NULL) {

srs_pid= (int)prop->to_number();

}if ((prop = req->args->ensure_property_number("srs_id")) !=NULL) {

srs_id= (int)prop->to_number();

}

srs_info("edge-srs ip=%s, version=%s, pid=%d, id=%d",

srs_server_ip.c_str(), srs_version.c_str(), srs_pid, srs_id);if (srs_pid > 0) {

srs_trace("edge-srs ip=%s, version=%s, pid=%d, id=%d",

srs_server_ip.c_str(), srs_version.c_str(), srs_pid, srs_id);

}

}

ret=service_cycle();

http_hooks_on_close();returnret;

}

SrsRtmpConn::do_cycle最后调用 service_cycle函数,

service_cycle有一个循环调用 stream_service_recycle处理 client_type为 SrsRtmpConnPlay(调用playing函数),

SrsRtmpConnFMLEPublish,SrsRtmpConnHaivisionPublish,SrsRtmpConnFlashPublish,

intSrsRtmpConn::service_cycle()

{int ret =ERROR_SUCCESS;

//发送一个SrsSetWindowAckSizePacket类型的数据包if ((ret = rtmp->set_window_ack_size((int)(2.5 * 1000 * 1000))) !=ERROR_SUCCESS) {

srs_error("set window acknowledgement size failed. ret=%d", ret);returnret;

}

srs_verbose("set window acknowledgement size success");

//

发送一个SrsSetWindowAckSizePacket类型的数据包

if ((ret = rtmp->set_peer_bandwidth((int)(2.5 * 1000 * 1000), 2)) !=ERROR_SUCCESS) {

srs_error("set peer bandwidth failed. ret=%d", ret);returnret;

}

srs_verbose("set peer bandwidth success");//get the ip which client connected.

std::string local_ip =srs_get_local_ip(st_netfd_fileno(stfd));

// 检测虚拟主机的bandcheck指令//do bandwidth test if connect to the vhost which is for bandwidth check.

if (_srs_config->get_bw_check_enabled(req->vhost)) {return bandwidth->bandwidth_check(rtmp, skt, req, local_ip);

}//do token traverse before serve it.//@seehttps://github.com/ossrs/srs/pull/239

if (true) {bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost);bool edge_traverse = _srs_config->get_vhost_edge_token_traverse(req->vhost);if (vhost_is_edge &&edge_traverse) {if ((ret = check_edge_token_traverse_auth()) !=ERROR_SUCCESS) {

srs_warn("token auth failed, ret=%d", ret);returnret;

}

}

}//set chunk size to larger.//set the chunk size before any larger response greater than 128,//to make OBS happy, @seehttps://github.com/ossrs/srs/issues/454

int chunk_size = _srs_config->get_chunk_size(req->vhost);if ((ret = rtmp->set_chunk_size(chunk_size)) !=ERROR_SUCCESS) {

srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret);returnret;

}

//发送一个SrsSetChunkSizePacket类型的数据包

srs_info("set chunk_size=%d success", chunk_size);

//发送一个SrsConnectAppResPacket类型的数据包//response the client connect ok.

if ((ret = rtmp->response_connect_app(req, local_ip.c_str())) !=ERROR_SUCCESS) {

srs_error("response connect app failed. ret=%d", ret);returnret;

}

srs_verbose("response connect app success");

//发送一个SrsOnBWDonePacket类型的数据包if ((ret = rtmp->on_bw_done()) !=ERROR_SUCCESS) {

srs_error("on_bw_done failed. ret=%d", ret);returnret;

}

srs_verbose("on_bw_done success");while (!disposed) {

ret=stream_service_cycle();//stream service must terminated with error, never success.//when terminated with success, it's user required to stop.

if (ret ==ERROR_SUCCESS) {continue;

}//when not system control error, fatal error, return.

if (!srs_is_system_control_error(ret)) {if (ret != ERROR_SOCKET_TIMEOUT && !srs_is_client_gracefully_close(ret)) {

srs_error("stream service cycle failed. ret=%d", ret);

}returnret;

}//for republish, continue service

if (ret ==ERROR_CONTROL_REPUBLISH) {//set timeout to a larger value, wait for encoder to republish.

rtmp->set_send_timeout(SRS_REPUBLISH_RECV_TIMEOUT_US);

rtmp->set_recv_timeout(SRS_REPUBLISH_SEND_TIMEOUT_US);

srs_trace("control message(unpublish) accept, retry stream service.");continue;

}//for "some" system control error,//logical accept and retry stream service.

if (ret ==ERROR_CONTROL_RTMP_CLOSE) {//TODO: FIXME: use ping message to anti-death of socket.//@see:https://github.com/ossrs/srs/issues/39

//set timeout to a larger value, for user paused.

rtmp->set_recv_timeout(SRS_PAUSED_RECV_TIMEOUT_US);

rtmp->set_send_timeout(SRS_PAUSED_SEND_TIMEOUT_US);

srs_trace("control message(close) accept, retry stream service.");continue;

}//for other system control message, fatal error.

srs_error("control message(%d) reject as error. ret=%d", ret, ret);returnret;

}returnret;

}

intSrsRtmpConn::stream_service_cycle()

{int ret =ERROR_SUCCESS;

SrsRtmpConnType type;

//接受client的消息,是play 或 publishif ((ret = rtmp->identify_client(res->stream_id, type, req->stream, req->duration)) !=ERROR_SUCCESS) {if (!srs_is_client_gracefully_close(ret)) {

srs_error("identify client failed. ret=%d", ret);

}returnret;

}

req->strip();

srs_trace("client identified, type=%s, stream_name=%s, duration=%.2f",

srs_client_type_string(type).c_str(), req->stream.c_str(), req->duration);//security check

//根据ip地址对client进行过滤,位于srs_app_security.cpp:39//先检查allow规则,在检查deny规则,deny规则的优先级较高

if ((ret = security->check(type, ip, req)) !=ERROR_SUCCESS) {

srs_error("security check failed. ret=%d", ret);returnret;

}

srs_info("security check ok");//Never allow the empty stream name, for HLS may write to a file with empty name.//@seehttps://github.com/ossrs/srs/issues/834

if (req->stream.empty()) {

ret=ERROR_RTMP_STREAM_NAME_EMPTY;

srs_error("RTMP: Empty stream name not allowed, ret=%d", ret);returnret;

}//client is identified, set the timeout to service timeout.

rtmp->set_recv_timeout(SRS_CONSTS_RTMP_RECV_TIMEOUT_US);

rtmp->set_send_timeout(SRS_CONSTS_RTMP_SEND_TIMEOUT_US);//find a source to serve.

SrsSource* source =NULL;if ((ret = SrsSource::fetch_or_create(req, server, &source)) !=ERROR_SUCCESS) {returnret;

}

srs_assert(source!=NULL);//update the statistic when source disconveried.

SrsStatistic* stat =SrsStatistic::instance();if ((ret = stat->on_client(_srs_context->get_id(), req, this, type)) !=ERROR_SUCCESS) {

srs_error("stat client failed. ret=%d", ret);returnret;

}bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost);bool enabled_cache = _srs_config->get_gop_cache(req->vhost);

srs_trace("source url=%s, ip=%s, cache=%d, is_edge=%d, source_id=%d[%d]",

req->get_stream_url().c_str(), ip.c_str(), enabled_cache, vhost_is_edge,

source->source_id(), source->source_id());

source->set_cache(enabled_cache);

client_type=type;switch(type) {caseSrsRtmpConnPlay: {

srs_verbose("start to play stream %s.", req->stream.c_str());//response connection start play

if ((ret = rtmp->start_play(res->stream_id)) !=ERROR_SUCCESS) {

srs_error("start to play stream failed. ret=%d", ret);returnret;

}if ((ret = http_hooks_on_play()) !=ERROR_SUCCESS) {

srs_error("http hook on_play failed. ret=%d", ret);returnret;

}

srs_info("start to play stream %s success", req->stream.c_str());

ret=playing(source);

http_hooks_on_stop();returnret;

}caseSrsRtmpConnFMLEPublish: {

srs_verbose("FMLE start to publish stream %s.", req->stream.c_str());

//rtmp->start_fmle_publish功能

//1. 接收SrsFMLEStartPacket类型的数据包

// 将其中的transaction_id保存下来

// 2. 将transaction_id 作为参数构造SrsFMLEStartResPacket包返回给客户端

// 3. 接收SrsCreateStreamPacket类型的数据包

// 保存其中的transaction_id

//4. 用接收的transaction_id和服务端的stream_id初始化

// SrsCreateStreamResPacket包返回个publish client

// 5.接收SrsPublishPacket

//6. 回复SrsOnStatusCallPacket 参数

// command_name --> onFCPublish

// StatusCode --> NetStream.Publish.Start

// StatusDescription --> "Started publishing stream."

//7. 在回复一个SrsOnStatusCallPacket参数

// StatusLevel --> StatusLevelStatus

// StatusCode --> StatusCodePublishStart

// StatusDescription --> 同上

// StatusClientId --> RTMP_SIG_CLIENT_ID --> "ASAICiss"if ((ret = rtmp->start_fmle_publish(res->stream_id)) !=ERROR_SUCCESS) {

srs_error("start to publish stream failed. ret=%d", ret);returnret;

}returnpublishing(source);

}caseSrsRtmpConnHaivisionPublish: {

srs_verbose("Haivision start to publish stream %s.", req->stream.c_str());if ((ret = rtmp->start_haivision_publish(res->stream_id)) !=ERROR_SUCCESS) {

srs_error("start to publish stream failed. ret=%d", ret);returnret;

}returnpublishing(source);

}caseSrsRtmpConnFlashPublish: {

srs_verbose("flash start to publish stream %s.", req->stream.c_str());if ((ret = rtmp->start_flash_publish(res->stream_id)) !=ERROR_SUCCESS) {

srs_error("flash start to publish stream failed. ret=%d", ret);returnret;

}returnpublishing(source);

}default: {

ret=ERROR_SYSTEM_CLIENT_INVALID;

srs_info("invalid client type=%d. ret=%d", type, ret);returnret;

}

}returnret;

}

最后调用publishing函数,代码如下

int SrsRtmpConn::publishing(SrsSource*source)

{int ret =ERROR_SUCCESS;if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) !=ERROR_SUCCESS) {

srs_error("check publish_refer failed. ret=%d", ret);returnret;

}

srs_verbose("check publish_refer success.");if ((ret = http_hooks_on_publish()) !=ERROR_SUCCESS) {

srs_error("http hook on_publish failed. ret=%d", ret);returnret;

}bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost);if ((ret = acquire_publish(source, vhost_is_edge)) ==ERROR_SUCCESS) {//use isolate thread to recv,//@see:https://github.com/ossrs/srs/issues/237

SrsPublishRecvThread trd(rtmp, req,

st_netfd_fileno(stfd),0, this, source,

client_type!=SrsRtmpConnFlashPublish,

vhost_is_edge);

srs_info("start to publish stream %s success", req->stream.c_str());

ret= do_publishing(source, &trd);//stop isolate recv thread

trd.stop();

}//whatever the acquire publish, always release publish.//when the acquire error in the midlle-way, the publish state changed,//but failed, so we must cleanup it.//@seehttps://github.com/ossrs/srs/issues/474

//@remark when stream is busy, should never release it.

if (ret !=ERROR_SYSTEM_STREAM_BUSY) {

release_publish(source, vhost_is_edge);

}

http_hooks_on_unpublish();returnret;

}

主要功能如下:

1. 调用SrsRefer的check函数

2. 调用 http_hooks_on_publish函数

3. 调用 acquire_publish函数

4. 如果3 成功,新建SrsPublishRecvThread实例后,执行do_publishing函数

4. call http_hooks_on_unpublish函数

int SrsRtmpConn::do_publishing(SrsSource* source, SrsPublishRecvThread*trd)

{int ret =ERROR_SUCCESS;

SrsPithyPrint* pprint =SrsPithyPrint::create_rtmp_publish();

SrsAutoFree(SrsPithyPrint, pprint);//start isolate recv thread.

if ((ret = trd->start()) !=ERROR_SUCCESS) {

srs_error("start isolate recv thread failed. ret=%d", ret);returnret;

}//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;while (!disposed) {

pprint->elapse();//when source is set to expired, disconnect it.

if(expired) {

ret=ERROR_USER_DISCONNECT;

srs_error("connection expired. ret=%d", ret);returnret;

}//cond wait for timeout.

if (nb_msgs == 0) {//when not got msgs, wait for a larger timeout.//@seehttps://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);

}returnret;

}//when not got any messages, timeout.

if (trd->nb_msgs() <=nb_msgs) {

ret=ERROR_SOCKET_TIMEOUT;

srs_warn("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();//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("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

);

}

}returnret;

}

等待SrsPublishRecvThread结束

接受包的处理流程

SrsRecvThread::cycle()调用SrsRtmpServer的recv_message函数接收类型为SrsCommonMessage的消息

call handler->handle(msg)

也就是SrsPublishRecvThread的handle方法

在转到SrsRtmpConn的handle_publish_msg,检查消息头部,对命令的格式进行检查

在转到SrsRtmpConn的process_publish_msg

int SrsRtmpConn::process_publish_message(SrsSource* source, SrsCommonMessage* msg, boolvhost_is_edge)

{int ret =ERROR_SUCCESS;//for edge, directly proxy message to origin.

if(vhost_is_edge) {if ((ret = source->on_edge_proxy_publish(msg)) !=ERROR_SUCCESS) {

srs_error("edge publish proxy msg failed. ret=%d", ret);returnret;

}returnret;

}//process audio packet

if (msg->header.is_audio()) {if ((ret = source->on_audio(msg)) !=ERROR_SUCCESS) {

srs_error("source process audio message failed. ret=%d", ret);returnret;

}returnret;

}//process video packet

if (msg->header.is_video()) {if ((ret = source->on_video(msg)) !=ERROR_SUCCESS) {

srs_error("source process video message failed. ret=%d", ret);returnret;

}returnret;

}//process aggregate packet

if (msg->header.is_aggregate()) {if ((ret = source->on_aggregate(msg)) !=ERROR_SUCCESS) {

srs_error("source process aggregate message failed. ret=%d", ret);returnret;

}returnret;

}//process onMetaData

if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {

SrsPacket* pkt =NULL;if ((ret = rtmp->decode_message(msg, &pkt)) !=ERROR_SUCCESS) {

srs_error("decode onMetaData message failed. ret=%d", ret);returnret;

}

SrsAutoFree(SrsPacket, pkt);if (dynamic_cast(pkt)) {

SrsOnMetaDataPacket* metadata = dynamic_cast(pkt);if ((ret = source->on_meta_data(msg, metadata)) !=ERROR_SUCCESS) {

srs_error("source process onMetaData message failed. ret=%d", ret);returnret;

}

srs_info("process onMetaData message success.");returnret;

}

srs_info("ignore AMF0/AMF3 data message.");returnret;

}returnret;

}

根据vhost 是否是 edge

数据是 audio video  aggregate 调用 SrsSource类的

on_edge_proxy_publish

on_audio

on_video

on_aggregate

on_metadata

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值