LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/rtp_rtcp/source - rtp_sender_audio.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 173 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2012 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 "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
      12             : 
      13             : #include <string.h>
      14             : 
      15             : #include <memory>
      16             : #include <utility>
      17             : 
      18             : #include "webrtc/base/logging.h"
      19             : #include "webrtc/base/timeutils.h"
      20             : #include "webrtc/base/trace_event.h"
      21             : #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
      22             : #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
      23             : #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
      24             : #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
      25             : 
      26             : namespace webrtc {
      27             : 
      28           0 : RTPSenderAudio::RTPSenderAudio(Clock* clock, RTPSender* rtp_sender)
      29             :     : clock_(clock),
      30           0 :       rtp_sender_(rtp_sender) {}
      31             : 
      32           0 : RTPSenderAudio::~RTPSenderAudio() {}
      33             : 
      34           0 : int32_t RTPSenderAudio::RegisterAudioPayload(
      35             :     const char payloadName[RTP_PAYLOAD_NAME_SIZE],
      36             :     const int8_t payload_type,
      37             :     const uint32_t frequency,
      38             :     const size_t channels,
      39             :     const uint32_t rate,
      40             :     RtpUtility::Payload** payload) {
      41           0 :   if (RtpUtility::StringCompare(payloadName, "cn", 2)) {
      42           0 :     rtc::CritScope cs(&send_audio_critsect_);
      43             :     //  we can have multiple CNG payload types
      44           0 :     switch (frequency) {
      45             :       case 8000:
      46           0 :         cngnb_payload_type_ = payload_type;
      47           0 :         break;
      48             :       case 16000:
      49           0 :         cngwb_payload_type_ = payload_type;
      50           0 :         break;
      51             :       case 32000:
      52           0 :         cngswb_payload_type_ = payload_type;
      53           0 :         break;
      54             :       case 48000:
      55           0 :         cngfb_payload_type_ = payload_type;
      56           0 :         break;
      57             :       default:
      58           0 :         return -1;
      59             :     }
      60           0 :   } else if (RtpUtility::StringCompare(payloadName, "telephone-event", 15)) {
      61           0 :     rtc::CritScope cs(&send_audio_critsect_);
      62             :     // Don't add it to the list
      63             :     // we dont want to allow send with a DTMF payloadtype
      64           0 :     dtmf_payload_type_ = payload_type;
      65           0 :     dtmf_payload_freq_ = frequency;
      66           0 :     return 0;
      67             :   }
      68           0 :   *payload = new RtpUtility::Payload;
      69           0 :   (*payload)->typeSpecific.Audio.frequency = frequency;
      70           0 :   (*payload)->typeSpecific.Audio.channels = channels;
      71           0 :   (*payload)->typeSpecific.Audio.rate = rate;
      72           0 :   (*payload)->audio = true;
      73           0 :   (*payload)->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0';
      74           0 :   strncpy((*payload)->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
      75           0 :   return 0;
      76             : }
      77             : 
      78           0 : bool RTPSenderAudio::MarkerBit(FrameType frame_type, int8_t payload_type) {
      79           0 :   rtc::CritScope cs(&send_audio_critsect_);
      80             :   // for audio true for first packet in a speech burst
      81           0 :   bool marker_bit = false;
      82           0 :   if (last_payload_type_ != payload_type) {
      83           0 :     if (payload_type != -1 && (cngnb_payload_type_ == payload_type ||
      84           0 :                                cngwb_payload_type_ == payload_type ||
      85           0 :                                cngswb_payload_type_ == payload_type ||
      86           0 :                                cngfb_payload_type_ == payload_type)) {
      87             :       // Only set a marker bit when we change payload type to a non CNG
      88           0 :       return false;
      89             :     }
      90             : 
      91             :     // payload_type differ
      92           0 :     if (last_payload_type_ == -1) {
      93           0 :       if (frame_type != kAudioFrameCN) {
      94             :         // first packet and NOT CNG
      95           0 :         return true;
      96             :       } else {
      97             :         // first packet and CNG
      98           0 :         inband_vad_active_ = true;
      99           0 :         return false;
     100             :       }
     101             :     }
     102             : 
     103             :     // not first packet AND
     104             :     // not CNG AND
     105             :     // payload_type changed
     106             : 
     107             :     // set a marker bit when we change payload type
     108           0 :     marker_bit = true;
     109             :   }
     110             : 
     111             :   // For G.723 G.729, AMR etc we can have inband VAD
     112           0 :   if (frame_type == kAudioFrameCN) {
     113           0 :     inband_vad_active_ = true;
     114           0 :   } else if (inband_vad_active_) {
     115           0 :     inband_vad_active_ = false;
     116           0 :     marker_bit = true;
     117             :   }
     118           0 :   return marker_bit;
     119             : }
     120             : 
     121           0 : bool RTPSenderAudio::SendAudio(FrameType frame_type,
     122             :                                int8_t payload_type,
     123             :                                uint32_t rtp_timestamp,
     124             :                                const uint8_t* payload_data,
     125             :                                size_t payload_size,
     126             :                                const RTPFragmentationHeader* fragmentation) {
     127             :   // From RFC 4733:
     128             :   // A source has wide latitude as to how often it sends event updates. A
     129             :   // natural interval is the spacing between non-event audio packets. [...]
     130             :   // Alternatively, a source MAY decide to use a different spacing for event
     131             :   // updates, with a value of 50 ms RECOMMENDED.
     132           0 :   constexpr int kDtmfIntervalTimeMs = 50;
     133           0 :   uint8_t audio_level_dbov = 0;
     134           0 :   uint32_t dtmf_payload_freq = 0;
     135             :   {
     136           0 :     rtc::CritScope cs(&send_audio_critsect_);
     137           0 :     audio_level_dbov = audio_level_dbov_;
     138           0 :     dtmf_payload_freq = dtmf_payload_freq_;
     139             :   }
     140             : 
     141             :   // Check if we have pending DTMFs to send
     142           0 :   if (!dtmf_event_is_on_ && dtmf_queue_.PendingDtmf()) {
     143           0 :     if ((clock_->TimeInMilliseconds() - dtmf_time_last_sent_) >
     144             :         kDtmfIntervalTimeMs) {
     145             :       // New tone to play
     146           0 :       dtmf_timestamp_ = rtp_timestamp;
     147           0 :       if (dtmf_queue_.NextDtmf(&dtmf_current_event_)) {
     148           0 :         dtmf_event_first_packet_sent_ = false;
     149           0 :         dtmf_length_samples_ =
     150           0 :             dtmf_current_event_.duration_ms * (dtmf_payload_freq / 1000);
     151           0 :         dtmf_event_is_on_ = true;
     152             :       }
     153             :     }
     154             :   }
     155             : 
     156             :   // A source MAY send events and coded audio packets for the same time
     157             :   // but we don't support it
     158           0 :   if (dtmf_event_is_on_) {
     159           0 :     if (frame_type == kEmptyFrame) {
     160             :       // kEmptyFrame is used to drive the DTMF when in CN mode
     161             :       // it can be triggered more frequently than we want to send the
     162             :       // DTMF packets.
     163             :       const unsigned int dtmf_interval_time_rtp =
     164           0 :           dtmf_payload_freq * kDtmfIntervalTimeMs / 1000;
     165           0 :       if ((rtp_timestamp - dtmf_timestamp_last_sent_) <
     166             :           dtmf_interval_time_rtp) {
     167             :         // not time to send yet
     168           0 :         return true;
     169             :       }
     170             :     }
     171           0 :     dtmf_timestamp_last_sent_ = rtp_timestamp;
     172           0 :     uint32_t dtmf_duration_samples = rtp_timestamp - dtmf_timestamp_;
     173           0 :     bool ended = false;
     174           0 :     bool send = true;
     175             : 
     176           0 :     if (dtmf_length_samples_ > dtmf_duration_samples) {
     177           0 :       if (dtmf_duration_samples <= 0) {
     178             :         // Skip send packet at start, since we shouldn't use duration 0
     179           0 :         send = false;
     180             :       }
     181             :     } else {
     182           0 :       ended = true;
     183           0 :       dtmf_event_is_on_ = false;
     184           0 :       dtmf_time_last_sent_ = clock_->TimeInMilliseconds();
     185             :     }
     186           0 :     if (send) {
     187           0 :       if (dtmf_duration_samples > 0xffff) {
     188             :         // RFC 4733 2.5.2.3 Long-Duration Events
     189           0 :         SendTelephoneEventPacket(ended, dtmf_timestamp_,
     190           0 :                                  static_cast<uint16_t>(0xffff), false);
     191             : 
     192             :         // set new timestap for this segment
     193           0 :         dtmf_timestamp_ = rtp_timestamp;
     194           0 :         dtmf_duration_samples -= 0xffff;
     195           0 :         dtmf_length_samples_ -= 0xffff;
     196             : 
     197           0 :         return SendTelephoneEventPacket(ended, dtmf_timestamp_,
     198           0 :             static_cast<uint16_t>(dtmf_duration_samples), false);
     199             :       } else {
     200           0 :         if (!SendTelephoneEventPacket(ended, dtmf_timestamp_,
     201             :                                       dtmf_duration_samples,
     202           0 :                                       !dtmf_event_first_packet_sent_)) {
     203           0 :           return false;
     204             :         }
     205           0 :         dtmf_event_first_packet_sent_ = true;
     206           0 :         return true;
     207             :       }
     208             :     }
     209           0 :     return true;
     210             :   }
     211           0 :   if (payload_size == 0 || payload_data == NULL) {
     212           0 :     if (frame_type == kEmptyFrame) {
     213             :       // we don't send empty audio RTP packets
     214             :       // no error since we use it to drive DTMF when we use VAD
     215           0 :       return true;
     216             :     }
     217           0 :     return false;
     218             :   }
     219             : 
     220           0 :   std::unique_ptr<RtpPacketToSend> packet = rtp_sender_->AllocatePacket();
     221           0 :   packet->SetMarker(MarkerBit(frame_type, payload_type));
     222           0 :   packet->SetPayloadType(payload_type);
     223           0 :   packet->SetTimestamp(rtp_timestamp);
     224           0 :   packet->set_capture_time_ms(clock_->TimeInMilliseconds());
     225             :   // Update audio level extension, if included.
     226           0 :   packet->SetExtension<AudioLevel>(frame_type == kAudioFrameSpeech,
     227           0 :                                    audio_level_dbov);
     228             : 
     229           0 :   if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
     230             :     // Use the fragment info if we have one.
     231             :     uint8_t* payload =
     232           0 :         packet->AllocatePayload(1 + fragmentation->fragmentationLength[0]);
     233           0 :     if (!payload)  // Too large payload buffer.
     234           0 :       return false;
     235           0 :     payload[0] = fragmentation->fragmentationPlType[0];
     236           0 :     memcpy(payload + 1, payload_data + fragmentation->fragmentationOffset[0],
     237           0 :            fragmentation->fragmentationLength[0]);
     238             :   } else {
     239           0 :     uint8_t* payload = packet->AllocatePayload(payload_size);
     240           0 :     if (!payload)  // Too large payload buffer.
     241           0 :       return false;
     242           0 :     memcpy(payload, payload_data, payload_size);
     243             :   }
     244             : 
     245           0 :   if (!rtp_sender_->AssignSequenceNumber(packet.get()))
     246           0 :     return false;
     247             : 
     248             :   {
     249           0 :     rtc::CritScope cs(&send_audio_critsect_);
     250           0 :     last_payload_type_ = payload_type;
     251             :   }
     252           0 :   TRACE_EVENT_ASYNC_END2("webrtc", "Audio", rtp_timestamp, "timestamp",
     253             :                          packet->Timestamp(), "seqnum",
     254             :                          packet->SequenceNumber());
     255           0 :   bool send_result = rtp_sender_->SendToNetwork(
     256           0 :       std::move(packet), kAllowRetransmission, RtpPacketSender::kHighPriority);
     257           0 :   if (first_packet_sent_()) {
     258           0 :     LOG(LS_INFO) << "First audio RTP packet sent to pacer";
     259             :   }
     260           0 :   return send_result;
     261             : }
     262             : 
     263             : // Audio level magnitude and voice activity flag are set for each RTP packet
     264           0 : int32_t RTPSenderAudio::SetAudioLevel(uint8_t level_dbov) {
     265           0 :   if (level_dbov > 127) {
     266           0 :     return -1;
     267             :   }
     268           0 :   rtc::CritScope cs(&send_audio_critsect_);
     269           0 :   audio_level_dbov_ = level_dbov;
     270           0 :   return 0;
     271             : }
     272             : 
     273             : // Send a TelephoneEvent tone using RFC 2833 (4733)
     274           0 : int32_t RTPSenderAudio::SendTelephoneEvent(uint8_t key,
     275             :                                            uint16_t time_ms,
     276             :                                            uint8_t level) {
     277           0 :   DtmfQueue::Event event;
     278             :   {
     279           0 :     rtc::CritScope lock(&send_audio_critsect_);
     280           0 :     if (dtmf_payload_type_ < 0) {
     281             :       // TelephoneEvent payloadtype not configured
     282           0 :       return -1;
     283             :     }
     284           0 :     event.payload_type = dtmf_payload_type_;
     285             :   }
     286           0 :   event.key = key;
     287           0 :   event.duration_ms = time_ms;
     288           0 :   event.level = level;
     289           0 :   return dtmf_queue_.AddDtmf(event) ? 0 : -1;
     290             : }
     291             : 
     292           0 : bool RTPSenderAudio::SendTelephoneEventPacket(bool ended,
     293             :                                               uint32_t dtmf_timestamp,
     294             :                                               uint16_t duration,
     295             :                                               bool marker_bit) {
     296           0 :   uint8_t send_count = 1;
     297           0 :   bool result = true;
     298             : 
     299           0 :   if (ended) {
     300             :     // resend last packet in an event 3 times
     301           0 :     send_count = 3;
     302             :   }
     303           0 :   do {
     304             :     // Send DTMF data.
     305           0 :     constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
     306           0 :     constexpr size_t kDtmfSize = 4;
     307             :     std::unique_ptr<RtpPacketToSend> packet(
     308           0 :         new RtpPacketToSend(kNoExtensions, kRtpHeaderSize + kDtmfSize));
     309           0 :     packet->SetPayloadType(dtmf_current_event_.payload_type);
     310           0 :     packet->SetMarker(marker_bit);
     311           0 :     packet->SetSsrc(rtp_sender_->SSRC());
     312           0 :     packet->SetTimestamp(dtmf_timestamp);
     313           0 :     packet->set_capture_time_ms(clock_->TimeInMilliseconds());
     314           0 :     if (!rtp_sender_->AssignSequenceNumber(packet.get()))
     315           0 :       return false;
     316             : 
     317             :     // Create DTMF data.
     318           0 :     uint8_t* dtmfbuffer = packet->AllocatePayload(kDtmfSize);
     319           0 :     RTC_DCHECK(dtmfbuffer);
     320             :     /*    From RFC 2833:
     321             :      0                   1                   2                   3
     322             :      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     323             :     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     324             :     |     event     |E|R| volume    |          duration             |
     325             :     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     326             :     */
     327             :     // R bit always cleared
     328           0 :     uint8_t R = 0x00;
     329           0 :     uint8_t volume = dtmf_current_event_.level;
     330             : 
     331             :     // First packet un-ended
     332           0 :     uint8_t E = ended ? 0x80 : 0x00;
     333             : 
     334             :     // First byte is Event number, equals key number
     335           0 :     dtmfbuffer[0] = dtmf_current_event_.key;
     336           0 :     dtmfbuffer[1] = E | R | volume;
     337           0 :     ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 2, duration);
     338             : 
     339           0 :     TRACE_EVENT_INSTANT2(
     340             :         TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Audio::SendTelephoneEvent",
     341             :         "timestamp", packet->Timestamp(), "seqnum", packet->SequenceNumber());
     342           0 :     result = rtp_sender_->SendToNetwork(std::move(packet), kAllowRetransmission,
     343           0 :                                         RtpPacketSender::kHighPriority);
     344           0 :     send_count--;
     345           0 :   } while (send_count > 0 && result);
     346             : 
     347           0 :   return result;
     348             : }
     349             : }  // namespace webrtc

Generated by: LCOV version 1.13