tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

audio_egress.cc (7128B)


      1 /*
      2 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "audio/voip/audio_egress.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <memory>
     16 #include <utility>
     17 
     18 #include "api/array_view.h"
     19 #include "api/audio/audio_frame.h"
     20 #include "api/audio_codecs/audio_encoder.h"
     21 #include "api/audio_codecs/audio_format.h"
     22 #include "api/environment/environment.h"
     23 #include "api/sequence_checker.h"
     24 #include "api/task_queue/task_queue_factory.h"
     25 #include "audio/utility/audio_frame_operations.h"
     26 #include "modules/audio_coding/include/audio_coding_module.h"
     27 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
     28 #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h"
     29 #include "rtc_base/checks.h"
     30 #include "rtc_base/logging.h"
     31 #include "rtc_base/numerics/safe_conversions.h"
     32 
     33 namespace webrtc {
     34 
     35 AudioEgress::AudioEgress(const Environment& env, RtpRtcpInterface* rtp_rtcp)
     36    : rtp_rtcp_(rtp_rtcp),
     37      rtp_sender_audio_(&env.clock(), rtp_rtcp_->RtpSender()),
     38      audio_coding_(AudioCodingModule::Create()),
     39      encoder_queue_(env.task_queue_factory().CreateTaskQueue(
     40          "AudioEncoder",
     41          TaskQueueFactory::Priority::NORMAL)),
     42      encoder_queue_checker_(encoder_queue_.get()) {
     43  audio_coding_->RegisterTransportCallback(this);
     44 }
     45 
     46 AudioEgress::~AudioEgress() {
     47  audio_coding_->RegisterTransportCallback(nullptr);
     48 
     49  // Delete first to ensure that there are no running tasks when the other
     50  // members are destroyed.
     51  encoder_queue_ = nullptr;
     52 }
     53 
     54 bool AudioEgress::IsSending() const {
     55  return rtp_rtcp_->SendingMedia();
     56 }
     57 
     58 void AudioEgress::SetEncoder(int payload_type,
     59                             const SdpAudioFormat& encoder_format,
     60                             std::unique_ptr<AudioEncoder> encoder) {
     61  RTC_DCHECK_GE(payload_type, 0);
     62  RTC_DCHECK_LE(payload_type, 127);
     63 
     64  SetEncoderFormat(encoder_format);
     65 
     66  // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
     67  // as well as some other things, so we collect this info and send it along.
     68  rtp_rtcp_->RegisterSendPayloadFrequency(payload_type,
     69                                          encoder->RtpTimestampRateHz());
     70  rtp_sender_audio_.RegisterAudioPayload("audio", payload_type,
     71                                         encoder->RtpTimestampRateHz(),
     72                                         encoder->NumChannels(), 0);
     73 
     74  audio_coding_->SetEncoder(std::move(encoder));
     75 }
     76 
     77 bool AudioEgress::StartSend() {
     78  if (!GetEncoderFormat()) {
     79    RTC_DLOG(LS_WARNING) << "Send codec has not been set yet";
     80    return false;
     81  }
     82  rtp_rtcp_->SetSendingMediaStatus(true);
     83  return true;
     84 }
     85 
     86 void AudioEgress::StopSend() {
     87  rtp_rtcp_->SetSendingMediaStatus(false);
     88 }
     89 
     90 void AudioEgress::SendAudioData(std::unique_ptr<AudioFrame> audio_frame) {
     91  RTC_DCHECK_GT(audio_frame->samples_per_channel_, 0);
     92  RTC_DCHECK_LE(audio_frame->num_channels_, 8);
     93 
     94  encoder_queue_->PostTask(
     95      [this, audio_frame = std::move(audio_frame)]() mutable {
     96        RTC_DCHECK_RUN_ON(&encoder_queue_checker_);
     97        if (!rtp_rtcp_->SendingMedia()) {
     98          return;
     99        }
    100 
    101        double duration_seconds =
    102            static_cast<double>(audio_frame->samples_per_channel_) /
    103            audio_frame->sample_rate_hz_;
    104 
    105        input_audio_level_.ComputeLevel(*audio_frame, duration_seconds);
    106 
    107        AudioFrameOperations::Mute(audio_frame.get(),
    108                                   encoder_context_.previously_muted_,
    109                                   encoder_context_.mute_);
    110        encoder_context_.previously_muted_ = encoder_context_.mute_;
    111 
    112        audio_frame->timestamp_ = encoder_context_.frame_rtp_timestamp_;
    113 
    114        // This call will trigger AudioPacketizationCallback::SendData if
    115        // encoding is done and payload is ready for packetization and
    116        // transmission. Otherwise, it will return without invoking the
    117        // callback.
    118        if (audio_coding_->Add10MsData(*audio_frame) < 0) {
    119          RTC_DLOG(LS_ERROR) << "ACM::Add10MsData() failed.";
    120          return;
    121        }
    122 
    123        encoder_context_.frame_rtp_timestamp_ +=
    124            dchecked_cast<uint32_t>(audio_frame->samples_per_channel_);
    125      });
    126 }
    127 
    128 int32_t AudioEgress::SendData(AudioFrameType frame_type,
    129                              uint8_t payload_type,
    130                              uint32_t timestamp,
    131                              const uint8_t* payload_data,
    132                              size_t payload_size) {
    133  RTC_DCHECK_RUN_ON(&encoder_queue_checker_);
    134 
    135  ArrayView<const uint8_t> payload(payload_data, payload_size);
    136 
    137  // Currently we don't get a capture time from downstream modules (ADM,
    138  // AudioTransportImpl).
    139  // TODO(natim@webrtc.org): Integrate once it's ready.
    140  constexpr uint32_t kUndefinedCaptureTime = -1;
    141 
    142  // Push data from ACM to RTP/RTCP-module to deliver audio frame for
    143  // packetization.
    144  if (!rtp_rtcp_->OnSendingRtpFrame(timestamp, kUndefinedCaptureTime,
    145                                    payload_type,
    146                                    /*force_sender_report=*/false)) {
    147    return -1;
    148  }
    149 
    150  const uint32_t rtp_timestamp = timestamp + rtp_rtcp_->StartTimestamp();
    151 
    152  // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
    153  if (!rtp_sender_audio_.SendAudio({.type = frame_type,
    154                                    .payload = payload,
    155                                    .payload_id = payload_type,
    156                                    .rtp_timestamp = rtp_timestamp})) {
    157    RTC_DLOG(LS_ERROR)
    158        << "AudioEgress::SendData() failed to send data to RTP/RTCP module";
    159    return -1;
    160  }
    161 
    162  return 0;
    163 }
    164 
    165 void AudioEgress::RegisterTelephoneEventType(int rtp_payload_type,
    166                                             int sample_rate_hz) {
    167  RTC_DCHECK_GE(rtp_payload_type, 0);
    168  RTC_DCHECK_LE(rtp_payload_type, 127);
    169 
    170  rtp_rtcp_->RegisterSendPayloadFrequency(rtp_payload_type, sample_rate_hz);
    171  rtp_sender_audio_.RegisterAudioPayload("telephone-event", rtp_payload_type,
    172                                         sample_rate_hz, 0, 0);
    173 }
    174 
    175 bool AudioEgress::SendTelephoneEvent(int dtmf_event, int duration_ms) {
    176  RTC_DCHECK_GE(dtmf_event, 0);
    177  RTC_DCHECK_LE(dtmf_event, 255);
    178  RTC_DCHECK_GE(duration_ms, 0);
    179  RTC_DCHECK_LE(duration_ms, 65535);
    180 
    181  if (!IsSending()) {
    182    return false;
    183  }
    184 
    185  constexpr int kTelephoneEventAttenuationdB = 10;
    186 
    187  if (rtp_sender_audio_.SendTelephoneEvent(dtmf_event, duration_ms,
    188                                           kTelephoneEventAttenuationdB) != 0) {
    189    RTC_DLOG(LS_ERROR) << "SendTelephoneEvent() failed to send event";
    190    return false;
    191  }
    192  return true;
    193 }
    194 
    195 void AudioEgress::SetMute(bool mute) {
    196  encoder_queue_->PostTask([this, mute] {
    197    RTC_DCHECK_RUN_ON(&encoder_queue_checker_);
    198    encoder_context_.mute_ = mute;
    199  });
    200 }
    201 
    202 }  // namespace webrtc