根据上一个章节的,我们知道了srt 每个链路创建SrsMpegtsSrtConn对象,SrsMpegtsSrtConn 调用do_cycle函数。do_sycle 函数推拉流调用不同处理函数。推流处理publishing及拉流处理playing
1. 分析推流数据处理流程。
-
- srs_error_t SrsMpegtsSrtConn::publishing()
- {
- srs_error_t err = srs_success;
-
- // We must do stat the client before hooks, because hooks depends on it.
- SrsStatistic* stat = SrsStatistic::instance();
- if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPublish)) != srs_success) {
- return srs_error_wrap(err, "srt: stat client");
- }
-
- // We must do hook after stat, because depends on it.
- if ((err = http_hooks_on_publish()) != srs_success) {
- return srs_error_wrap(err, "srt: callback on publish");
- }
-
- if ((err = acquire_publish()) == srs_success) {
- err = do_publishing();
- release_publish();
- }
-
- http_hooks_on_unpublish();
-
- return err;
- }
do_publishing 函数,调用srt_conn_->read 函数接收推流数据。
on_srt_packet 函数处理数据。
- srs_error_t SrsMpegtsSrtConn::do_publishing()
- {
- srs_error_t err = srs_success;
-
- SrsPithyPrint* pprint = SrsPithyPrint::create_srt_publish();
- SrsAutoFree(SrsPithyPrint, pprint);
-
- int nb_packets = 0;
-
- // Max udp packet size equal to 1500.
- char buf[1500];
- while (true) {
- if ((err = trd_->pull()) != srs_success) {
- return srs_error_wrap(err, "srt: thread quit");
- }
-
- pprint->elapse();
- if (pprint->can_print()) {
- SrsSrtStat s;
- if ((err = s.fetch(srt_fd_, true)) != srs_success) {
- srs_freep(err);
- } else {
- srs_trace("<- " SRS_CONSTS_LOG_SRT_PUBLISH " Transport Stats # pktRecv=%" PRId64 ", pktRcvLoss=%d, pktRcvRetrans=%d, pktRcvDrop=%d",
- s.pktRecv(), s.pktRcvLoss(), s.pktRcvRetrans(), s.pktRcvDrop());
- }
-
- kbps_->sample();
- srs_trace("<- " SRS_CONSTS_LOG_SRT_PUBLISH " time=%" PRId64 ", packets=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d",
- srsu2ms(pprint->age()), nb_packets, 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());
- nb_packets = 0;
- }
-
- ssize_t nb = 0;
- if ((err = srt_conn_->read(buf, sizeof(buf), &nb)) != srs_success) {
- return srs_error_wrap(err, "srt: recvmsg");
- }
-
- ++nb_packets;
-
- if ((err = on_srt_packet(buf, nb)) != srs_success) {
- return srs_error_wrap(err, "srt: process packet");
- }
- }
-
- return err;
- }
on_srt_packet 创建SrsSrtPacket 函数.执行 srt_source_->on_packet 。
- srs_error_t SrsMpegtsSrtConn::on_srt_packet(char* buf, int nb_buf)
- {
- srs_error_t err = srs_success;
-
- // Ignore if invalid length.
- if (nb_buf <= 0) {
- return err;
- }
-
- // Check srt payload, mpegts must be N times of SRS_TS_PACKET_SIZE
- if ((nb_buf % SRS_TS_PACKET_SIZE) != 0) {
- return srs_error_new(ERROR_SRT_CONN, "invalid ts packet len=%d", nb_buf);
- }
-
- // Check srt payload, the first byte must be 0x47
- if (buf[0] != 0x47) {
- return srs_error_new(ERROR_SRT_CONN, "invalid ts packet first=%#x", (uint8_t)buf[0]);
- }
-
- SrsSrtPacket* packet = new SrsSrtPacket();
- SrsAutoFree(SrsSrtPacket, packet);
- packet->wrap(buf, nb_buf);
-
- if ((err = srt_source_->on_packet(packet)) != srs_success) {
- return srs_error_wrap(err, "on srt packet");
- }
-
- return err;
- }
on_packet : srt 推流 给每个消费者 consumer->enqueue 推数据;
bridge_->on_packet :srt 转换其他协议的流数据。
- srs_error_t SrsSrtSource::on_packet(SrsSrtPacket* packet)
- {
- srs_error_t err = srs_success;
-
- for (int i = 0; i < (int)consumers.size(); i++) {
- SrsSrtConsumer* consumer = consumers.at(i);
- if ((err = consumer->enqueue(packet->copy())) != srs_success) {
- return srs_error_wrap(err, "consume ts packet");
- }
- }
-
- if ((err = bridge_->on_packet(packet)) != srs_success) {
- return srs_error_wrap(err, "bridge consume message");
- }
-
- return err;
- }
2. srs服务器处理srt拉流处理。
- srs_error_t SrsMpegtsSrtConn::playing()
- {
- srs_error_t err = srs_success;
-
- // We must do stat the client before hooks, because hooks depends on it.
- SrsStatistic* stat = SrsStatistic::instance();
- if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPlay)) != srs_success) {
- return srs_error_wrap(err, "rtmp: stat client");
- }
-
- // We must do hook after stat, because depends on it.
- if ((err = http_hooks_on_play()) != srs_success) {
- return srs_error_wrap(err, "rtmp: callback on play");
- }
-
- err = do_playing();
- http_hooks_on_stop();
-
- return err;
- }
do_playing() 函数:
consumer->dump_packet(&pkt);每个拉流消费者取出数据。
srt_conn_->write 发送数据。
- srs_error_t SrsMpegtsSrtConn::do_playing()
- {
- srs_error_t err = srs_success;
-
- SrsSrtConsumer* consumer = NULL;
- SrsAutoFree(SrsSrtConsumer, consumer);
- if ((err = srt_source_->create_consumer(consumer)) != srs_success) {
- return srs_error_wrap(err, "create consumer, ts source=%s", req_->get_stream_url().c_str());
- }
- srs_assert(consumer);
-
- // TODO: FIXME: Dumps the SPS/PPS from gop cache, without other frames.
- if ((err = srt_source_->consumer_dumps(consumer)) != srs_success) {
- return srs_error_wrap(err, "dumps consumer, url=%s", req_->get_stream_url().c_str());
- }
-
- SrsPithyPrint* pprint = SrsPithyPrint::create_srt_play();
- SrsAutoFree(SrsPithyPrint, pprint);
-
- SrsSrtRecvThread srt_recv_trd(srt_conn_);
- if ((err = srt_recv_trd.start()) != srs_success) {
- return srs_error_wrap(err, "start srt recv trd");
- }
-
- int nb_packets = 0;
-
- while (true) {
- if ((err = trd_->pull()) != srs_success) {
- return srs_error_wrap(err, "srt play thread");
- }
-
- if ((err = srt_recv_trd.get_recv_err()) != srs_success) {
- return srs_error_wrap(err, "srt play recv thread");
- }
-
- // Wait for amount of packets.
- SrsSrtPacket* pkt = NULL;
- SrsAutoFree(SrsSrtPacket, pkt);
- consumer->dump_packet(&pkt);
- if (!pkt) {
- // TODO: FIXME: We should check the quit event.
- consumer->wait(1, 1000 * SRS_UTIME_MILLISECONDS);
- continue;
- }
-
- ++nb_packets;
-
- // reportable
- pprint->elapse();
- if (pprint->can_print()) {
- SrsSrtStat s;
- if ((err = s.fetch(srt_fd_, true)) != srs_success) {
- srs_freep(err);
- } else {
- srs_trace("-> " SRS_CONSTS_LOG_SRT_PLAY " Transport Stats # pktSent=%" PRId64 ", pktSndLoss=%d, pktRetrans=%d, pktSndDrop=%d",
- s.pktSent(), s.pktSndLoss(), s.pktRetrans(), s.pktSndDrop());
- }
-
- kbps_->sample();
- srs_trace("-> " SRS_CONSTS_LOG_SRT_PLAY " time=%" PRId64 ", packets=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d",
- srsu2ms(pprint->age()), nb_packets, 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());
- nb_packets = 0;
- }
-
- ssize_t nb_write = 0;
- if ((err = srt_conn_->write(pkt->data(), pkt->size(), &nb_write)) != srs_success) {
- return srs_error_wrap(err, "srt send, size=%d", pkt->size());
- }
-
- // Yield to another coroutines.
- // @see https://github.com/ossrs/srs/issues/2194#issuecomment-777542162
- // TODO: FIXME: Please check whether SRT sendmsg causing clock deviation, see srs_thread_yield of SrsUdpMuxSocket::sendto
- }
-
- return err;
- }