Home | History | Annotate | Download | only in webrtc
      1 /*
      2  * libjingle
      3  * Copyright 2015 Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "talk/app/webrtc/rtpsender.h"
     29 
     30 #include "talk/app/webrtc/localaudiosource.h"
     31 #include "talk/app/webrtc/videosourceinterface.h"
     32 #include "webrtc/base/helpers.h"
     33 
     34 namespace webrtc {
     35 
     36 LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
     37 
     38 LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
     39   rtc::CritScope lock(&lock_);
     40   if (sink_)
     41     sink_->OnClose();
     42 }
     43 
     44 void LocalAudioSinkAdapter::OnData(const void* audio_data,
     45                                    int bits_per_sample,
     46                                    int sample_rate,
     47                                    size_t number_of_channels,
     48                                    size_t number_of_frames) {
     49   rtc::CritScope lock(&lock_);
     50   if (sink_) {
     51     sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
     52                   number_of_frames);
     53   }
     54 }
     55 
     56 void LocalAudioSinkAdapter::SetSink(cricket::AudioRenderer::Sink* sink) {
     57   rtc::CritScope lock(&lock_);
     58   ASSERT(!sink || !sink_);
     59   sink_ = sink;
     60 }
     61 
     62 AudioRtpSender::AudioRtpSender(AudioTrackInterface* track,
     63                                const std::string& stream_id,
     64                                AudioProviderInterface* provider,
     65                                StatsCollector* stats)
     66     : id_(track->id()),
     67       stream_id_(stream_id),
     68       provider_(provider),
     69       stats_(stats),
     70       track_(track),
     71       cached_track_enabled_(track->enabled()),
     72       sink_adapter_(new LocalAudioSinkAdapter()) {
     73   RTC_DCHECK(provider != nullptr);
     74   track_->RegisterObserver(this);
     75   track_->AddSink(sink_adapter_.get());
     76 }
     77 
     78 AudioRtpSender::AudioRtpSender(AudioProviderInterface* provider,
     79                                StatsCollector* stats)
     80     : id_(rtc::CreateRandomUuid()),
     81       stream_id_(rtc::CreateRandomUuid()),
     82       provider_(provider),
     83       stats_(stats),
     84       sink_adapter_(new LocalAudioSinkAdapter()) {}
     85 
     86 AudioRtpSender::~AudioRtpSender() {
     87   Stop();
     88 }
     89 
     90 void AudioRtpSender::OnChanged() {
     91   RTC_DCHECK(!stopped_);
     92   if (cached_track_enabled_ != track_->enabled()) {
     93     cached_track_enabled_ = track_->enabled();
     94     if (can_send_track()) {
     95       SetAudioSend();
     96     }
     97   }
     98 }
     99 
    100 bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
    101   if (stopped_) {
    102     LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
    103     return false;
    104   }
    105   if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
    106     LOG(LS_ERROR) << "SetTrack called on audio RtpSender with " << track->kind()
    107                   << " track.";
    108     return false;
    109   }
    110   AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
    111 
    112   // Detach from old track.
    113   if (track_) {
    114     track_->RemoveSink(sink_adapter_.get());
    115     track_->UnregisterObserver(this);
    116   }
    117 
    118   if (can_send_track() && stats_) {
    119     stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
    120   }
    121 
    122   // Attach to new track.
    123   bool prev_can_send_track = can_send_track();
    124   track_ = audio_track;
    125   if (track_) {
    126     cached_track_enabled_ = track_->enabled();
    127     track_->RegisterObserver(this);
    128     track_->AddSink(sink_adapter_.get());
    129   }
    130 
    131   // Update audio provider.
    132   if (can_send_track()) {
    133     SetAudioSend();
    134     if (stats_) {
    135       stats_->AddLocalAudioTrack(track_.get(), ssrc_);
    136     }
    137   } else if (prev_can_send_track) {
    138     cricket::AudioOptions options;
    139     provider_->SetAudioSend(ssrc_, false, options, nullptr);
    140   }
    141   return true;
    142 }
    143 
    144 void AudioRtpSender::SetSsrc(uint32_t ssrc) {
    145   if (stopped_ || ssrc == ssrc_) {
    146     return;
    147   }
    148   // If we are already sending with a particular SSRC, stop sending.
    149   if (can_send_track()) {
    150     cricket::AudioOptions options;
    151     provider_->SetAudioSend(ssrc_, false, options, nullptr);
    152     if (stats_) {
    153       stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
    154     }
    155   }
    156   ssrc_ = ssrc;
    157   if (can_send_track()) {
    158     SetAudioSend();
    159     if (stats_) {
    160       stats_->AddLocalAudioTrack(track_.get(), ssrc_);
    161     }
    162   }
    163 }
    164 
    165 void AudioRtpSender::Stop() {
    166   // TODO(deadbeef): Need to do more here to fully stop sending packets.
    167   if (stopped_) {
    168     return;
    169   }
    170   if (track_) {
    171     track_->RemoveSink(sink_adapter_.get());
    172     track_->UnregisterObserver(this);
    173   }
    174   if (can_send_track()) {
    175     cricket::AudioOptions options;
    176     provider_->SetAudioSend(ssrc_, false, options, nullptr);
    177     if (stats_) {
    178       stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
    179     }
    180   }
    181   stopped_ = true;
    182 }
    183 
    184 void AudioRtpSender::SetAudioSend() {
    185   RTC_DCHECK(!stopped_ && can_send_track());
    186   cricket::AudioOptions options;
    187   if (track_->enabled() && track_->GetSource() &&
    188       !track_->GetSource()->remote()) {
    189     // TODO(xians): Remove this static_cast since we should be able to connect
    190     // a remote audio track to a peer connection.
    191     options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
    192   }
    193 
    194   // Use the renderer if the audio track has one, otherwise use the sink
    195   // adapter owned by this class.
    196   cricket::AudioRenderer* renderer =
    197       track_->GetRenderer() ? track_->GetRenderer() : sink_adapter_.get();
    198   ASSERT(renderer != nullptr);
    199   provider_->SetAudioSend(ssrc_, track_->enabled(), options, renderer);
    200 }
    201 
    202 VideoRtpSender::VideoRtpSender(VideoTrackInterface* track,
    203                                const std::string& stream_id,
    204                                VideoProviderInterface* provider)
    205     : id_(track->id()),
    206       stream_id_(stream_id),
    207       provider_(provider),
    208       track_(track),
    209       cached_track_enabled_(track->enabled()) {
    210   RTC_DCHECK(provider != nullptr);
    211   track_->RegisterObserver(this);
    212 }
    213 
    214 VideoRtpSender::VideoRtpSender(VideoProviderInterface* provider)
    215     : id_(rtc::CreateRandomUuid()),
    216       stream_id_(rtc::CreateRandomUuid()),
    217       provider_(provider) {}
    218 
    219 VideoRtpSender::~VideoRtpSender() {
    220   Stop();
    221 }
    222 
    223 void VideoRtpSender::OnChanged() {
    224   RTC_DCHECK(!stopped_);
    225   if (cached_track_enabled_ != track_->enabled()) {
    226     cached_track_enabled_ = track_->enabled();
    227     if (can_send_track()) {
    228       SetVideoSend();
    229     }
    230   }
    231 }
    232 
    233 bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
    234   if (stopped_) {
    235     LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
    236     return false;
    237   }
    238   if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
    239     LOG(LS_ERROR) << "SetTrack called on video RtpSender with " << track->kind()
    240                   << " track.";
    241     return false;
    242   }
    243   VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
    244 
    245   // Detach from old track.
    246   if (track_) {
    247     track_->UnregisterObserver(this);
    248   }
    249 
    250   // Attach to new track.
    251   bool prev_can_send_track = can_send_track();
    252   track_ = video_track;
    253   if (track_) {
    254     cached_track_enabled_ = track_->enabled();
    255     track_->RegisterObserver(this);
    256   }
    257 
    258   // Update video provider.
    259   if (can_send_track()) {
    260     VideoSourceInterface* source = track_->GetSource();
    261     // TODO(deadbeef): If SetTrack is called with a disabled track, and the
    262     // previous track was enabled, this could cause a frame from the new track
    263     // to slip out. Really, what we need is for SetCaptureDevice and
    264     // SetVideoSend
    265     // to be combined into one atomic operation, all the way down to
    266     // WebRtcVideoSendStream.
    267     provider_->SetCaptureDevice(ssrc_,
    268                                 source ? source->GetVideoCapturer() : nullptr);
    269     SetVideoSend();
    270   } else if (prev_can_send_track) {
    271     provider_->SetCaptureDevice(ssrc_, nullptr);
    272     provider_->SetVideoSend(ssrc_, false, nullptr);
    273   }
    274   return true;
    275 }
    276 
    277 void VideoRtpSender::SetSsrc(uint32_t ssrc) {
    278   if (stopped_ || ssrc == ssrc_) {
    279     return;
    280   }
    281   // If we are already sending with a particular SSRC, stop sending.
    282   if (can_send_track()) {
    283     provider_->SetCaptureDevice(ssrc_, nullptr);
    284     provider_->SetVideoSend(ssrc_, false, nullptr);
    285   }
    286   ssrc_ = ssrc;
    287   if (can_send_track()) {
    288     VideoSourceInterface* source = track_->GetSource();
    289     provider_->SetCaptureDevice(ssrc_,
    290                                 source ? source->GetVideoCapturer() : nullptr);
    291     SetVideoSend();
    292   }
    293 }
    294 
    295 void VideoRtpSender::Stop() {
    296   // TODO(deadbeef): Need to do more here to fully stop sending packets.
    297   if (stopped_) {
    298     return;
    299   }
    300   if (track_) {
    301     track_->UnregisterObserver(this);
    302   }
    303   if (can_send_track()) {
    304     provider_->SetCaptureDevice(ssrc_, nullptr);
    305     provider_->SetVideoSend(ssrc_, false, nullptr);
    306   }
    307   stopped_ = true;
    308 }
    309 
    310 void VideoRtpSender::SetVideoSend() {
    311   RTC_DCHECK(!stopped_ && can_send_track());
    312   const cricket::VideoOptions* options = nullptr;
    313   VideoSourceInterface* source = track_->GetSource();
    314   if (track_->enabled() && source) {
    315     options = source->options();
    316   }
    317   provider_->SetVideoSend(ssrc_, track_->enabled(), options);
    318 }
    319 
    320 }  // namespace webrtc
    321