1/*
2 * libjingle
3 * Copyright 2012, 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/mediastreamhandler.h"
29
30#include "talk/app/webrtc/localaudiosource.h"
31#include "talk/app/webrtc/videosource.h"
32#include "talk/app/webrtc/videosourceinterface.h"
33
34namespace webrtc {
35
36TrackHandler::TrackHandler(MediaStreamTrackInterface* track, uint32 ssrc)
37    : track_(track),
38      ssrc_(ssrc),
39      state_(track->state()),
40      enabled_(track->enabled()) {
41  track_->RegisterObserver(this);
42}
43
44TrackHandler::~TrackHandler() {
45  track_->UnregisterObserver(this);
46}
47
48void TrackHandler::OnChanged() {
49  if (state_ != track_->state()) {
50    state_ = track_->state();
51    OnStateChanged();
52  }
53  if (enabled_ != track_->enabled()) {
54    enabled_ = track_->enabled();
55    OnEnabledChanged();
56  }
57}
58
59LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(NULL) {}
60
61LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
62  talk_base::CritScope lock(&lock_);
63  if (sink_)
64    sink_->OnClose();
65}
66
67void LocalAudioSinkAdapter::OnData(const void* audio_data,
68                                   int bits_per_sample,
69                                   int sample_rate,
70                                   int number_of_channels,
71                                   int number_of_frames) {
72  talk_base::CritScope lock(&lock_);
73  if (sink_) {
74    sink_->OnData(audio_data, bits_per_sample, sample_rate,
75                  number_of_channels, number_of_frames);
76  }
77}
78
79void LocalAudioSinkAdapter::SetSink(cricket::AudioRenderer::Sink* sink) {
80  talk_base::CritScope lock(&lock_);
81  ASSERT(!sink || !sink_);
82  sink_ = sink;
83}
84
85LocalAudioTrackHandler::LocalAudioTrackHandler(
86    AudioTrackInterface* track,
87    uint32 ssrc,
88    AudioProviderInterface* provider)
89    : TrackHandler(track, ssrc),
90      audio_track_(track),
91      provider_(provider),
92      sink_adapter_(new LocalAudioSinkAdapter()) {
93  OnEnabledChanged();
94  track->AddSink(sink_adapter_.get());
95}
96
97LocalAudioTrackHandler::~LocalAudioTrackHandler() {
98}
99
100void LocalAudioTrackHandler::OnStateChanged() {
101  // TODO(perkj): What should happen when the state change?
102}
103
104void LocalAudioTrackHandler::Stop() {
105  audio_track_->RemoveSink(sink_adapter_.get());
106  cricket::AudioOptions options;
107  provider_->SetAudioSend(ssrc(), false, options, NULL);
108}
109
110void LocalAudioTrackHandler::OnEnabledChanged() {
111  cricket::AudioOptions options;
112  if (audio_track_->enabled() && audio_track_->GetSource()) {
113    // TODO(xians): Remove this static_cast since we should be able to connect
114    // a remote audio track to peer connection.
115    options = static_cast<LocalAudioSource*>(
116        audio_track_->GetSource())->options();
117  }
118
119  // Use the renderer if the audio track has one, otherwise use the sink
120  // adapter owned by this class.
121  cricket::AudioRenderer* renderer = audio_track_->GetRenderer() ?
122      audio_track_->GetRenderer() : sink_adapter_.get();
123  ASSERT(renderer != NULL);
124  provider_->SetAudioSend(ssrc(), audio_track_->enabled(), options, renderer);
125}
126
127RemoteAudioTrackHandler::RemoteAudioTrackHandler(
128    AudioTrackInterface* track,
129    uint32 ssrc,
130    AudioProviderInterface* provider)
131    : TrackHandler(track, ssrc),
132      audio_track_(track),
133      provider_(provider) {
134  track->GetSource()->RegisterAudioObserver(this);
135  OnEnabledChanged();
136}
137
138RemoteAudioTrackHandler::~RemoteAudioTrackHandler() {
139  audio_track_->GetSource()->UnregisterAudioObserver(this);
140}
141
142void RemoteAudioTrackHandler::Stop() {
143  provider_->SetAudioPlayout(ssrc(), false, NULL);
144}
145
146void RemoteAudioTrackHandler::OnStateChanged() {
147}
148
149void RemoteAudioTrackHandler::OnEnabledChanged() {
150  provider_->SetAudioPlayout(ssrc(), audio_track_->enabled(),
151                             audio_track_->GetRenderer());
152}
153
154void RemoteAudioTrackHandler::OnSetVolume(double volume) {
155  // When the track is disabled, the volume of the source, which is the
156  // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
157  // setting the volume to the source when the track is disabled.
158  if (audio_track_->enabled())
159    provider_->SetAudioPlayoutVolume(ssrc(), volume);
160}
161
162LocalVideoTrackHandler::LocalVideoTrackHandler(
163    VideoTrackInterface* track,
164    uint32 ssrc,
165    VideoProviderInterface* provider)
166    : TrackHandler(track, ssrc),
167      local_video_track_(track),
168      provider_(provider) {
169  VideoSourceInterface* source = local_video_track_->GetSource();
170  if (source)
171    provider_->SetCaptureDevice(ssrc, source->GetVideoCapturer());
172  OnEnabledChanged();
173}
174
175LocalVideoTrackHandler::~LocalVideoTrackHandler() {
176}
177
178void LocalVideoTrackHandler::OnStateChanged() {
179}
180
181void LocalVideoTrackHandler::Stop() {
182  provider_->SetCaptureDevice(ssrc(), NULL);
183  provider_->SetVideoSend(ssrc(), false, NULL);
184}
185
186void LocalVideoTrackHandler::OnEnabledChanged() {
187  const cricket::VideoOptions* options = NULL;
188  VideoSourceInterface* source = local_video_track_->GetSource();
189  if (local_video_track_->enabled() && source) {
190    options = source->options();
191  }
192  provider_->SetVideoSend(ssrc(), local_video_track_->enabled(), options);
193}
194
195RemoteVideoTrackHandler::RemoteVideoTrackHandler(
196    VideoTrackInterface* track,
197    uint32 ssrc,
198    VideoProviderInterface* provider)
199    : TrackHandler(track, ssrc),
200      remote_video_track_(track),
201      provider_(provider) {
202  OnEnabledChanged();
203  provider_->SetVideoPlayout(ssrc, true,
204                             remote_video_track_->GetSource()->FrameInput());
205}
206
207RemoteVideoTrackHandler::~RemoteVideoTrackHandler() {
208}
209
210void RemoteVideoTrackHandler::Stop() {
211  // Since cricket::VideoRenderer is not reference counted
212  // we need to remove the renderer before we are deleted.
213  provider_->SetVideoPlayout(ssrc(), false, NULL);
214}
215
216void RemoteVideoTrackHandler::OnStateChanged() {
217}
218
219void RemoteVideoTrackHandler::OnEnabledChanged() {
220}
221
222MediaStreamHandler::MediaStreamHandler(MediaStreamInterface* stream,
223                                       AudioProviderInterface* audio_provider,
224                                       VideoProviderInterface* video_provider)
225    : stream_(stream),
226      audio_provider_(audio_provider),
227      video_provider_(video_provider) {
228}
229
230MediaStreamHandler::~MediaStreamHandler() {
231  for (TrackHandlers::iterator it = track_handlers_.begin();
232       it != track_handlers_.end(); ++it) {
233    delete *it;
234  }
235}
236
237void MediaStreamHandler::RemoveTrack(MediaStreamTrackInterface* track) {
238  for (TrackHandlers::iterator it = track_handlers_.begin();
239       it != track_handlers_.end(); ++it) {
240    if ((*it)->track() == track) {
241      TrackHandler* track = *it;
242      track->Stop();
243      delete track;
244      track_handlers_.erase(it);
245      break;
246    }
247  }
248}
249
250TrackHandler* MediaStreamHandler::FindTrackHandler(
251    MediaStreamTrackInterface* track) {
252  TrackHandlers::iterator it = track_handlers_.begin();
253  for (; it != track_handlers_.end(); ++it) {
254    if ((*it)->track() == track) {
255      return *it;
256      break;
257    }
258  }
259  return NULL;
260}
261
262MediaStreamInterface* MediaStreamHandler::stream() {
263  return stream_.get();
264}
265
266void MediaStreamHandler::OnChanged() {
267}
268
269void MediaStreamHandler::Stop() {
270  for (TrackHandlers::const_iterator it = track_handlers_.begin();
271      it != track_handlers_.end(); ++it) {
272    (*it)->Stop();
273  }
274}
275
276LocalMediaStreamHandler::LocalMediaStreamHandler(
277    MediaStreamInterface* stream,
278    AudioProviderInterface* audio_provider,
279    VideoProviderInterface* video_provider)
280    : MediaStreamHandler(stream, audio_provider, video_provider) {
281}
282
283LocalMediaStreamHandler::~LocalMediaStreamHandler() {
284}
285
286void LocalMediaStreamHandler::AddAudioTrack(AudioTrackInterface* audio_track,
287                                            uint32 ssrc) {
288  ASSERT(!FindTrackHandler(audio_track));
289
290  TrackHandler* handler(new LocalAudioTrackHandler(audio_track, ssrc,
291                                                   audio_provider_));
292  track_handlers_.push_back(handler);
293}
294
295void LocalMediaStreamHandler::AddVideoTrack(VideoTrackInterface* video_track,
296                                            uint32 ssrc) {
297  ASSERT(!FindTrackHandler(video_track));
298
299  TrackHandler* handler(new LocalVideoTrackHandler(video_track, ssrc,
300                                                   video_provider_));
301  track_handlers_.push_back(handler);
302}
303
304RemoteMediaStreamHandler::RemoteMediaStreamHandler(
305    MediaStreamInterface* stream,
306    AudioProviderInterface* audio_provider,
307    VideoProviderInterface* video_provider)
308    : MediaStreamHandler(stream, audio_provider, video_provider) {
309}
310
311RemoteMediaStreamHandler::~RemoteMediaStreamHandler() {
312}
313
314void RemoteMediaStreamHandler::AddAudioTrack(AudioTrackInterface* audio_track,
315                                             uint32 ssrc) {
316  ASSERT(!FindTrackHandler(audio_track));
317  TrackHandler* handler(
318      new RemoteAudioTrackHandler(audio_track, ssrc, audio_provider_));
319  track_handlers_.push_back(handler);
320}
321
322void RemoteMediaStreamHandler::AddVideoTrack(VideoTrackInterface* video_track,
323                                             uint32 ssrc) {
324  ASSERT(!FindTrackHandler(video_track));
325  TrackHandler* handler(
326      new RemoteVideoTrackHandler(video_track, ssrc, video_provider_));
327  track_handlers_.push_back(handler);
328}
329
330MediaStreamHandlerContainer::MediaStreamHandlerContainer(
331    AudioProviderInterface* audio_provider,
332    VideoProviderInterface* video_provider)
333    : audio_provider_(audio_provider),
334      video_provider_(video_provider) {
335}
336
337MediaStreamHandlerContainer::~MediaStreamHandlerContainer() {
338  ASSERT(remote_streams_handlers_.empty());
339  ASSERT(local_streams_handlers_.empty());
340}
341
342void MediaStreamHandlerContainer::TearDown() {
343  for (StreamHandlerList::iterator it = remote_streams_handlers_.begin();
344       it != remote_streams_handlers_.end(); ++it) {
345    (*it)->Stop();
346    delete *it;
347  }
348  remote_streams_handlers_.clear();
349  for (StreamHandlerList::iterator it = local_streams_handlers_.begin();
350       it != local_streams_handlers_.end(); ++it) {
351    (*it)->Stop();
352    delete *it;
353  }
354  local_streams_handlers_.clear();
355}
356
357void MediaStreamHandlerContainer::RemoveRemoteStream(
358    MediaStreamInterface* stream) {
359  DeleteStreamHandler(&remote_streams_handlers_, stream);
360}
361
362void MediaStreamHandlerContainer::AddRemoteAudioTrack(
363    MediaStreamInterface* stream,
364    AudioTrackInterface* audio_track,
365    uint32 ssrc) {
366  MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_,
367                                                  stream);
368  if (handler == NULL) {
369    handler = CreateRemoteStreamHandler(stream);
370  }
371  handler->AddAudioTrack(audio_track, ssrc);
372}
373
374void MediaStreamHandlerContainer::AddRemoteVideoTrack(
375    MediaStreamInterface* stream,
376    VideoTrackInterface* video_track,
377    uint32 ssrc) {
378  MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_,
379                                                  stream);
380  if (handler == NULL) {
381    handler = CreateRemoteStreamHandler(stream);
382  }
383  handler->AddVideoTrack(video_track, ssrc);
384}
385
386void MediaStreamHandlerContainer::RemoveRemoteTrack(
387    MediaStreamInterface* stream,
388    MediaStreamTrackInterface* track) {
389  MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_,
390                                                  stream);
391  if (!VERIFY(handler != NULL)) {
392    LOG(LS_WARNING) << "Local MediaStreamHandler for stream  with id "
393                    << stream->label() << "doesnt't exist.";
394    return;
395  }
396  handler->RemoveTrack(track);
397}
398
399void MediaStreamHandlerContainer::RemoveLocalStream(
400    MediaStreamInterface* stream) {
401  DeleteStreamHandler(&local_streams_handlers_, stream);
402}
403
404void MediaStreamHandlerContainer::AddLocalAudioTrack(
405    MediaStreamInterface* stream,
406    AudioTrackInterface* audio_track,
407    uint32 ssrc) {
408  MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_,
409                                                  stream);
410  if (handler == NULL) {
411    handler = CreateLocalStreamHandler(stream);
412  }
413  handler->AddAudioTrack(audio_track, ssrc);
414}
415
416void MediaStreamHandlerContainer::AddLocalVideoTrack(
417    MediaStreamInterface* stream,
418    VideoTrackInterface* video_track,
419    uint32 ssrc) {
420  MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_,
421                                                  stream);
422  if (handler == NULL) {
423    handler = CreateLocalStreamHandler(stream);
424  }
425  handler->AddVideoTrack(video_track, ssrc);
426}
427
428void MediaStreamHandlerContainer::RemoveLocalTrack(
429    MediaStreamInterface* stream,
430    MediaStreamTrackInterface* track) {
431  MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_,
432                                                  stream);
433  if (!VERIFY(handler != NULL)) {
434    LOG(LS_WARNING) << "Remote MediaStreamHandler for stream with id "
435                    << stream->label() << "doesnt't exist.";
436    return;
437  }
438  handler->RemoveTrack(track);
439}
440
441MediaStreamHandler* MediaStreamHandlerContainer::CreateRemoteStreamHandler(
442    MediaStreamInterface* stream) {
443  ASSERT(!FindStreamHandler(remote_streams_handlers_, stream));
444
445  RemoteMediaStreamHandler* handler =
446      new RemoteMediaStreamHandler(stream, audio_provider_, video_provider_);
447  remote_streams_handlers_.push_back(handler);
448  return handler;
449}
450
451MediaStreamHandler* MediaStreamHandlerContainer::CreateLocalStreamHandler(
452    MediaStreamInterface* stream) {
453  ASSERT(!FindStreamHandler(local_streams_handlers_, stream));
454
455  LocalMediaStreamHandler* handler =
456      new LocalMediaStreamHandler(stream, audio_provider_, video_provider_);
457  local_streams_handlers_.push_back(handler);
458  return handler;
459}
460
461MediaStreamHandler* MediaStreamHandlerContainer::FindStreamHandler(
462    const StreamHandlerList& handlers,
463    MediaStreamInterface* stream) {
464  StreamHandlerList::const_iterator it = handlers.begin();
465  for (; it != handlers.end(); ++it) {
466    if ((*it)->stream() == stream) {
467      return *it;
468    }
469  }
470  return NULL;
471}
472
473void MediaStreamHandlerContainer::DeleteStreamHandler(
474    StreamHandlerList* streamhandlers, MediaStreamInterface* stream) {
475  StreamHandlerList::iterator it = streamhandlers->begin();
476  for (; it != streamhandlers->end(); ++it) {
477    if ((*it)->stream() == stream) {
478      (*it)->Stop();
479      delete *it;
480      streamhandlers->erase(it);
481      break;
482    }
483  }
484}
485
486}  // namespace webrtc
487