summaryrefslogtreecommitdiff
path: root/session/media/channelmanager.h
blob: f7a289016e2b0d9c51ccbfa91652b3bfc0a95601 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/*
 * libjingle
 * Copyright 2004 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef TALK_SESSION_MEDIA_CHANNELMANAGER_H_
#define TALK_SESSION_MEDIA_CHANNELMANAGER_H_

#include <string>
#include <vector>

#include "talk/media/base/capturemanager.h"
#include "talk/media/base/mediaengine.h"
#include "talk/p2p/base/session.h"
#include "talk/session/media/voicechannel.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/sigslotrepeater.h"
#include "webrtc/base/thread.h"

namespace cricket {

const int kDefaultAudioDelayOffset = 0;

class Soundclip;
class VideoProcessor;
class VoiceChannel;
class VoiceProcessor;

// ChannelManager allows the MediaEngine to run on a separate thread, and takes
// care of marshalling calls between threads. It also creates and keeps track of
// voice and video channels; by doing so, it can temporarily pause all the
// channels when a new audio or video device is chosen. The voice and video
// channels are stored in separate vectors, to easily allow operations on just
// voice or just video channels.
// ChannelManager also allows the application to discover what devices it has
// using device manager.
class ChannelManager : public rtc::MessageHandler,
                       public sigslot::has_slots<> {
 public:
#if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
  // Creates the channel manager, and specifies the worker thread to use.
  explicit ChannelManager(rtc::Thread* worker);
#endif

  // For testing purposes. Allows the media engine and data media
  // engine and dev manager to be mocks.  The ChannelManager takes
  // ownership of these objects.
  ChannelManager(MediaEngineInterface* me,
                 DataEngineInterface* dme,
                 DeviceManagerInterface* dm,
                 CaptureManager* cm,
                 rtc::Thread* worker);
  // Same as above, but gives an easier default DataEngine.
  ChannelManager(MediaEngineInterface* me,
                 DeviceManagerInterface* dm,
                 rtc::Thread* worker);
  ~ChannelManager();

  // Accessors for the worker thread, allowing it to be set after construction,
  // but before Init. set_worker_thread will return false if called after Init.
  rtc::Thread* worker_thread() const { return worker_thread_; }
  bool set_worker_thread(rtc::Thread* thread) {
    if (initialized_) return false;
    worker_thread_ = thread;
    return true;
  }

  // Gets capabilities. Can be called prior to starting the media engine.
  int GetCapabilities();

  // Retrieves the list of supported audio & video codec types.
  // Can be called before starting the media engine.
  void GetSupportedAudioCodecs(std::vector<AudioCodec>* codecs) const;
  void GetSupportedAudioRtpHeaderExtensions(RtpHeaderExtensions* ext) const;
  void GetSupportedVideoCodecs(std::vector<VideoCodec>* codecs) const;
  void GetSupportedVideoRtpHeaderExtensions(RtpHeaderExtensions* ext) const;
  void GetSupportedDataCodecs(std::vector<DataCodec>* codecs) const;

  // Indicates whether the media engine is started.
  bool initialized() const { return initialized_; }
  // Starts up the media engine.
  bool Init();
  // Shuts down the media engine.
  void Terminate();

  // The operations below all occur on the worker thread.

  // Creates a voice channel, to be associated with the specified session.
  VoiceChannel* CreateVoiceChannel(
      BaseSession* session, const std::string& content_name, bool rtcp);
  // Destroys a voice channel created with the Create API.
  void DestroyVoiceChannel(VoiceChannel* voice_channel);
  // Creates a video channel, synced with the specified voice channel, and
  // associated with the specified session.
  VideoChannel* CreateVideoChannel(
      BaseSession* session, const std::string& content_name, bool rtcp,
      VoiceChannel* voice_channel);
  // Destroys a video channel created with the Create API.
  void DestroyVideoChannel(VideoChannel* video_channel);
  DataChannel* CreateDataChannel(
      BaseSession* session, const std::string& content_name,
      bool rtcp, DataChannelType data_channel_type);
  // Destroys a data channel created with the Create API.
  void DestroyDataChannel(DataChannel* data_channel);

  // Creates a soundclip.
  Soundclip* CreateSoundclip();
  // Destroys a soundclip created with the Create API.
  void DestroySoundclip(Soundclip* soundclip);

  // Indicates whether any channels exist.
  bool has_channels() const {
    return (!voice_channels_.empty() || !video_channels_.empty() ||
            !soundclips_.empty());
  }

  // Configures the audio and video devices. A null pointer can be passed to
  // GetAudioOptions() for any parameter of no interest.
  bool GetAudioOptions(std::string* wave_in_device,
                       std::string* wave_out_device,
                       AudioOptions* options);
  bool SetAudioOptions(const std::string& wave_in_device,
                       const std::string& wave_out_device,
                       const AudioOptions& options);
  // Sets Engine-specific audio options according to enabled experiments.
  bool SetEngineAudioOptions(const AudioOptions& options);
  bool GetOutputVolume(int* level);
  bool SetOutputVolume(int level);
  bool IsSameCapturer(const std::string& capturer_name,
                      VideoCapturer* capturer);
  // TODO(noahric): Nearly everything called "device" in this API is actually a
  // device name, so this should really be GetCaptureDeviceName, and the
  // next method should be GetCaptureDevice.
  bool GetCaptureDevice(std::string* cam_device);
  // Gets the current capture Device.
  bool GetVideoCaptureDevice(Device* device);
  // Create capturer based on what has been set in SetCaptureDevice().
  VideoCapturer* CreateVideoCapturer();
  // Create capturer from a screen.
  VideoCapturer* CreateScreenCapturer(const ScreencastId& screenid);
  bool SetCaptureDevice(const std::string& cam_device);
  bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config);
  // RTX will be enabled/disabled in engines that support it. The supporting
  // engines will start offering an RTX codec. Must be called before Init().
  bool SetVideoRtxEnabled(bool enable);

  // Starts/stops the local microphone and enables polling of the input level.
  bool SetLocalMonitor(bool enable);
  bool monitoring() const { return monitoring_; }
  // Sets the local renderer where to renderer the local camera.
  bool SetLocalRenderer(VideoRenderer* renderer);
  bool capturing() const { return capturing_; }

  // Configures the logging output of the mediaengine(s).
  void SetVoiceLogging(int level, const char* filter);
  void SetVideoLogging(int level, const char* filter);

  // The channel manager handles the Tx side for Video processing,
  // as well as Tx and Rx side for Voice processing.
  // (The Rx Video processing will go throug the simplerenderingmanager,
  //  to be implemented).
  bool RegisterVideoProcessor(VideoCapturer* capturer,
                              VideoProcessor* processor);
  bool UnregisterVideoProcessor(VideoCapturer* capturer,
                                VideoProcessor* processor);
  bool RegisterVoiceProcessor(uint32 ssrc,
                              VoiceProcessor* processor,
                              MediaProcessorDirection direction);
  bool UnregisterVoiceProcessor(uint32 ssrc,
                                VoiceProcessor* processor,
                                MediaProcessorDirection direction);
  // The following are done in the new "CaptureManager" style that
  // all local video capturers, processors, and managers should move to.
  // TODO(pthatcher): Make methods nicer by having start return a handle that
  // can be used for stop and restart, rather than needing to pass around
  // formats a a pseudo-handle.
  bool StartVideoCapture(VideoCapturer* video_capturer,
                         const VideoFormat& video_format);
  // When muting, produce black frames then pause the camera.
  // When unmuting, start the camera. Camera starts unmuted.
  bool MuteToBlackThenPause(VideoCapturer* video_capturer, bool muted);
  bool StopVideoCapture(VideoCapturer* video_capturer,
                        const VideoFormat& video_format);
  bool RestartVideoCapture(VideoCapturer* video_capturer,
                           const VideoFormat& previous_format,
                           const VideoFormat& desired_format,
                           CaptureManager::RestartOptions options);

  bool AddVideoRenderer(VideoCapturer* capturer, VideoRenderer* renderer);
  bool RemoveVideoRenderer(VideoCapturer* capturer, VideoRenderer* renderer);
  bool IsScreencastRunning() const;

  // The operations below occur on the main thread.

  bool GetAudioInputDevices(std::vector<std::string>* names);
  bool GetAudioOutputDevices(std::vector<std::string>* names);
  bool GetVideoCaptureDevices(std::vector<std::string>* names);
  void SetVideoCaptureDeviceMaxFormat(const std::string& usb_id,
                                      const VideoFormat& max_format);

  // Starts AEC dump using existing file.
  bool StartAecDump(rtc::PlatformFile file);

  sigslot::repeater0<> SignalDevicesChange;
  sigslot::signal2<VideoCapturer*, CaptureState> SignalVideoCaptureStateChange;

  // Returns the current selected device. Note: Subtly different from
  // GetCaptureDevice(). See member video_device_ for more details.
  // This API is mainly a hook used by unittests.
  const std::string& video_device_name() const { return video_device_name_; }

  // TODO(hellner): Remove this function once the engine capturer has been
  // removed.
  VideoFormat GetStartCaptureFormat();

 protected:
  // Adds non-transient parameters which can only be changed through the
  // options store.
  bool SetAudioOptions(const std::string& wave_in_device,
                       const std::string& wave_out_device,
                       const AudioOptions& options,
                       int delay_offset);
  int audio_delay_offset() const { return audio_delay_offset_; }
  // This is here so that ChannelManager subclasses can set the video
  // capturer factories to use.
  DeviceManagerInterface* device_manager() { return device_manager_.get(); }

 private:
  typedef std::vector<VoiceChannel*> VoiceChannels;
  typedef std::vector<VideoChannel*> VideoChannels;
  typedef std::vector<DataChannel*> DataChannels;
  typedef std::vector<Soundclip*> Soundclips;

  void Construct(MediaEngineInterface* me,
                 DataEngineInterface* dme,
                 DeviceManagerInterface* dm,
                 CaptureManager* cm,
                 rtc::Thread* worker_thread);
  void Terminate_w();
  VoiceChannel* CreateVoiceChannel_w(
      BaseSession* session, const std::string& content_name, bool rtcp);
  void DestroyVoiceChannel_w(VoiceChannel* voice_channel);
  VideoChannel* CreateVideoChannel_w(
      BaseSession* session, const std::string& content_name, bool rtcp,
      VoiceChannel* voice_channel);
  void DestroyVideoChannel_w(VideoChannel* video_channel);
  DataChannel* CreateDataChannel_w(
      BaseSession* session, const std::string& content_name,
      bool rtcp, DataChannelType data_channel_type);
  void DestroyDataChannel_w(DataChannel* data_channel);
  Soundclip* CreateSoundclip_w();
  void DestroySoundclip_w(Soundclip* soundclip);
  bool SetAudioOptions_w(const AudioOptions& options, int delay_offset,
                         const Device* in_dev, const Device* out_dev);
  bool SetEngineAudioOptions_w(const AudioOptions& options);
  bool SetCaptureDevice_w(const Device* cam_device);
  void OnVideoCaptureStateChange(VideoCapturer* capturer,
                                 CaptureState result);
  bool RegisterVideoProcessor_w(VideoCapturer* capturer,
                                VideoProcessor* processor);
  bool UnregisterVideoProcessor_w(VideoCapturer* capturer,
                                  VideoProcessor* processor);
  bool IsScreencastRunning_w() const;
  virtual void OnMessage(rtc::Message *message);

  rtc::scoped_ptr<MediaEngineInterface> media_engine_;
  rtc::scoped_ptr<DataEngineInterface> data_media_engine_;
  rtc::scoped_ptr<DeviceManagerInterface> device_manager_;
  rtc::scoped_ptr<CaptureManager> capture_manager_;
  bool initialized_;
  rtc::Thread* main_thread_;
  rtc::Thread* worker_thread_;

  VoiceChannels voice_channels_;
  VideoChannels video_channels_;
  DataChannels data_channels_;
  Soundclips soundclips_;

  std::string audio_in_device_;
  std::string audio_out_device_;
  AudioOptions audio_options_;
  int audio_delay_offset_;
  int audio_output_volume_;
  std::string camera_device_;
  VideoEncoderConfig default_video_encoder_config_;
  VideoRenderer* local_renderer_;
  bool enable_rtx_;

  bool capturing_;
  bool monitoring_;

  // String containing currently set device. Note that this string is subtly
  // different from camera_device_. E.g. camera_device_ will list unplugged
  // but selected devices while this sting will be empty or contain current
  // selected device.
  // TODO(hellner): refactor the code such that there is no need to keep two
  // strings for video devices that have subtle differences in behavior.
  std::string video_device_name_;
};

}  // namespace cricket

#endif  // TALK_SESSION_MEDIA_CHANNELMANAGER_H_