webrtc 音频发送

线程启动:platform_thread.cc

void PlatformThread::Run() {
  if (!name_.empty())
    rtc::SetCurrentThreadName(name_.c_str());
  do {
    // The interface contract of Start/Stop is that for a successful call to
    // Start, there should be at least one call to the run function.  So we
    // call the function before checking |stop_|.
    if (!run_function_(obj_))
      break;
#if defined(WEBRTC_WIN)
    // Alertable sleep to permit RaiseFlag to run and update |stop_|.
    SleepEx(0, true);
  } while (!stop_);
#else
  } while (!stop_event_.Wait(0));
#endif  // defined(WEBRTC_WIN)
}

发送音频是有一个线程一直在循环发送:

process_thread_impl.cc

// static
bool ProcessThreadImpl::Run(void* obj) {
  return static_cast<ProcessThreadImpl*>(obj)->Process();
}


bool ProcessThreadImpl::Process() {
  int64_t now = rtc::TimeMillis();
  int64_t next_checkpoint = now + (1000 * 60);

  {
    rtc::CritScope lock(&lock_);
    if (stop_)
      return false;
    for (ModuleCallback& m : modules_) {
      // TODO(tommi): Would be good to measure the time TimeUntilNextProcess
      // takes and dcheck if it takes too long (e.g. >=10ms).  Ideally this
      // operation should not require taking a lock, so querying all modules
      // should run in a matter of nanoseconds.
      if (m.next_callback == 0)
        m.next_callback = GetNextCallbackTime(m.module, now);

      if (m.next_callback <= now ||
          m.next_callback == kCallProcessImmediately) {
        m.module->Process();//线程
        // Use a new 'now' reference to calculate when the next callback
        // should occur.  We'll continue to use 'now' above for the baseline
        // of calculating how long we should wait, to reduce variance.
        int64_t new_now = rtc::TimeMillis();
        m.next_callback = GetNextCallbackTime(m.module, new_now);
      }

      if (m.next_callback < next_checkpoint)
        next_checkpoint = m.next_callback;
    }

    while (!queue_.empty()) {
      rtc::QueuedTask* task = queue_.front();
      queue_.pop();
      lock_.Leave();
      task->Run();
      delete task;
      lock_.Enter();
    }
  }

  int64_t time_to_wait = next_checkpoint - rtc::TimeMillis();
  if (time_to_wait > 0)
    wake_up_->Wait(static_cast<unsigned long>(time_to_wait));

  return true;
}

paced_sender.cc

void PacedSender::Process() {
    while (!packets_->Empty()) {
    if (media_budget_->bytes_remaining() == 0 && !is_probing)
      return;

    // Since we need to release the lock in order to send, we first pop the
    // element from the priority queue but keep it in storage, so that we can
    // reinsert it if send fails.
    const paced_sender::Packet& packet = packets_->BeginPop();

    if (SendPacket(packet, probe_cluster_id)) { //发送
      // Send succeeded, remove it from the queue.
      packets_->FinalizePop(packet);
      if (is_probing)
        return;
    } else {
      // Send failed, put it back into the queue.
      packets_->CancelPop(packet);
      return;
    }
  }
}

bool PacedSender::SendPacket(const paced_sender::Packet& packet,
                             int probe_cluster_id) {
  // TODO(holmer): Because of this bug issue 5307 we have to send audio
  // packets even when the pacer is paused. Here we assume audio packets are
  // always high priority and that they are the only high priority packets.
  if (paused_ && packet.priority != kHighPriority)
    return false;
  critsect_->Leave();
  const bool success = packet_sender_->TimeToSendPacket(
      packet.ssrc, packet.sequence_number, packet.capture_time_ms,
      packet.retransmission, probe_cluster_id);
  critsect_->Enter();

  if (success) {
    prober_->PacketSent(clock_->TimeInMilliseconds(), packet.bytes);
    // TODO(holmer): High priority packets should only be accounted for if we
    // are allocating bandwidth for audio.
    if (packet.priority != kHighPriority) {
      // Update media bytes sent.
      media_budget_->UseBudget(packet.bytes);
      padding_budget_->UseBudget(packet.bytes);
    }
  }

  return success;
}

rtp_sender.cc

// Called from pacer when we can send the packet.
bool RTPSender::TimeToSendPacket(uint16_t sequence_number,
                                 int64_t capture_time_ms,
                                 bool retransmission,
                                 int probe_cluster_id) {
  size_t length = IP_PACKET_SIZE;
  uint8_t data_buffer[IP_PACKET_SIZE];
  int64_t stored_time_ms;

  if (!packet_history_.GetPacketAndSetSendTime(sequence_number,
                                               0,
                                               retransmission,
                                               data_buffer,
                                               &length,
                                               &stored_time_ms)) {
    // Packet cannot be found. Allow sending to continue.
    return true;
  }

  int rtx;
  {
    rtc::CritScope lock(&send_critsect_);
    rtx = rtx_;
  }
  return PrepareAndSendPacket(data_buffer, length, capture_time_ms,
                              retransmission && (rtx & kRtxRetransmitted) > 0,
                              retransmission, probe_cluster_id);
}

bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
                                     size_t length,
                                     int64_t capture_time_ms,
                                     bool send_over_rtx,
                                     bool is_retransmit,
                                     int probe_cluster_id) {
  uint8_t* buffer_to_send_ptr = buffer;

  RtpUtility::RtpHeaderParser rtp_parser(buffer, length);
  RTPHeader rtp_header;
  rtp_parser.Parse(&rtp_header);
  if (!is_retransmit && rtp_header.markerBit) {
    TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PacedSend",
                           capture_time_ms);
  }

  TRACE_EVENT_INSTANT2(
      TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PrepareAndSendPacket",
      "timestamp", rtp_header.timestamp, "seqnum", rtp_header.sequenceNumber);

  uint8_t data_buffer_rtx[IP_PACKET_SIZE];
  if (send_over_rtx) {
    BuildRtxPacket(buffer, &length, data_buffer_rtx);
    buffer_to_send_ptr = data_buffer_rtx;
  }

  int64_t now_ms = clock_->TimeInMilliseconds();
  int64_t diff_ms = now_ms - capture_time_ms;
  UpdateTransmissionTimeOffset(buffer_to_send_ptr, length, rtp_header,
                               diff_ms);
  UpdateAbsoluteSendTime(buffer_to_send_ptr, length, rtp_header, now_ms);

  PacketOptions options;
  if (AllocateTransportSequenceNumber(&options.packet_id)) {
    if (UpdateTransportSequenceNumber(options.packet_id, buffer_to_send_ptr,
                                      length, rtp_header)) {
      if (transport_feedback_observer_)
        transport_feedback_observer_->AddPacket(options.packet_id, length,
                                                probe_cluster_id);
    }
  }

  if (!is_retransmit && !send_over_rtx) {
    UpdateDelayStatistics(capture_time_ms, now_ms);
    UpdateOnSendPacket(options.packet_id, capture_time_ms, rtp_header.ssrc);
  }

  bool ret = SendPacketToNetwork(buffer_to_send_ptr, length, options);
  if (ret) {
    rtc::CritScope lock(&send_critsect_);
    media_has_been_sent_ = true;
  }
  UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx,
                 is_retransmit);
  return ret;
}


bool RTPSender::SendPacketToNetwork(const uint8_t* packet,
                                    size_t size,
                                    const PacketOptions& options) {
  int bytes_sent = -1;
  if (transport_) {
    //发送rtp
    bytes_sent = transport_->SendRtp(packet, size, options)
                     ? static_cast<int>(size)
                     : -1;
    if (event_log_ && bytes_sent > 0) {
      event_log_->LogRtpHeader(kOutgoingPacket, MediaType::ANY, packet, size);
    }
  }
  TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
                       "RTPSender::SendPacketToNetwork", "size", size, "sent",
                       bytes_sent);
  // TODO(pwestin): Add a separate bitrate for sent bitrate after pacer.
  if (bytes_sent <= 0) {
    LOG(LS_WARNING) << "Transport failed to send packet";
    return false;
  }
  return true;
}

channel.cc

bool Channel::SendRtp(const uint8_t* data,
                      size_t len,
                      const PacketOptions& options) {
  WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
               "Channel::SendPacket(channel=%d, len=%" PRIuS ")", len);

  rtc::CritScope cs(&_callbackCritSect);

  if (_transportPtr == NULL) {
    WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
                 "Channel::SendPacket() failed to send RTP packet due to"
                 " invalid transport object");
    return false;
  }

  uint8_t* bufferToSendPtr = (uint8_t*)data;
  size_t bufferLength = len;

  //发送rtp
  if (!_transportPtr->SendRtp(bufferToSendPtr, bufferLength, options)) {
    std::string transport_name =
        _externalTransport ? "external transport" : "WebRtc sockets";
    WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
                 "Channel::SendPacket() RTP transmission using %s failed",
                 transport_name.c_str());
    return false;
  }
  return true;
}

webrtcvoiceengine.h

  bool SendRtp(const uint8_t* data,
               size_t len,
               const webrtc::PacketOptions& options) override {
    rtc::CopyOnWriteBuffer packet(data, len, kMaxRtpPacketLen);
    rtc::PacketOptions rtc_options;
    rtc_options.packet_id = options.packet_id;
    return VoiceMediaChannel::SendPacket(&packet, rtc_options);//发送
  }

mediachannel.h

  // Base method to send packet using NetworkInterface.
  bool SendPacket(rtc::CopyOnWriteBuffer* packet,
                  const rtc::PacketOptions& options) {
    return DoSendPacket(packet, false, options);
  }


  bool DoSendPacket(rtc::CopyOnWriteBuffer* packet,
                    bool rtcp,
                    const rtc::PacketOptions& options) {
    rtc::CritScope cs(&network_interface_crit_);
    if (!network_interface_)
      return false;

    return (!rtcp) ? network_interface_->SendPacket(packet, options)
                   : network_interface_->SendRtcp(packet, options);
  }

channel.cpp

bool BaseChannel::SendPacket(bool rtcp,
                             rtc::CopyOnWriteBuffer* packet,
                             const rtc::PacketOptions& options) {
  // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
  // If the thread is not our network thread, we will post to our network
  // so that the real work happens on our network. This avoids us having to
  // synchronize access to all the pieces of the send path, including
  // SRTP and the inner workings of the transport channels.
  // The only downside is that we can't return a proper failure code if
  // needed. Since UDP is unreliable anyway, this should be a non-issue.
  if (!network_thread_->IsCurrent()) {
    // Avoid a copy by transferring the ownership of the packet data.
    int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
    SendPacketMessageData* data = new SendPacketMessageData;
    data->packet = std::move(*packet);
    data->options = options;
    network_thread_->Post(RTC_FROM_HERE, this, message_id, data);//
    return true;
  }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值