1 /* 2 * libjingle 3 * Copyright 2004--2007, 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 #ifndef TALK_SESSION_PHONE_MEDIAENGINE_H_ 29 #define TALK_SESSION_PHONE_MEDIAENGINE_H_ 30 31 #ifdef OSX 32 #include <CoreAudio/CoreAudio.h> 33 #endif 34 35 #include <string> 36 #include <vector> 37 38 #include "talk/base/sigslotrepeater.h" 39 #include "talk/session/phone/codec.h" 40 #include "talk/session/phone/devicemanager.h" 41 #include "talk/session/phone/mediachannel.h" 42 #include "talk/session/phone/videocommon.h" 43 44 namespace cricket { 45 46 // A class for playing out soundclips. 47 class SoundclipMedia { 48 public: 49 enum SoundclipFlags { 50 SF_LOOP = 1, 51 }; 52 ~SoundclipMedia()53 virtual ~SoundclipMedia() {} 54 55 // Plays a sound out to the speakers with the given audio stream. The stream 56 // must be 16-bit little-endian 16 kHz PCM. If a stream is already playing 57 // on this SoundclipMedia, it is stopped. If clip is NULL, nothing is played. 58 // Returns whether it was successful. 59 virtual bool PlaySound(const char *clip, int len, int flags) = 0; 60 }; 61 62 // MediaEngine is an abstraction of a media engine which can be subclassed 63 // to support different media componentry backends. It supports voice and 64 // video operations in the same class to facilitate proper synchronization 65 // between both media types. 66 class MediaEngine { 67 public: 68 // TODO: Move this to a global location (also used in DeviceManager) 69 // Capabilities of the media engine. 70 enum Capabilities { 71 AUDIO_RECV = 1 << 0, 72 AUDIO_SEND = 1 << 1, 73 VIDEO_RECV = 1 << 2, 74 VIDEO_SEND = 1 << 3, 75 }; 76 77 // Bitmask flags for options that may be supported by the media engine 78 // implementation 79 enum AudioOptions { 80 ECHO_CANCELLATION = 1 << 0, 81 AUTO_GAIN_CONTROL = 1 << 1, 82 DEFAULT_AUDIO_OPTIONS = ECHO_CANCELLATION | AUTO_GAIN_CONTROL 83 }; 84 enum VideoOptions { 85 }; 86 ~MediaEngine()87 virtual ~MediaEngine() {} 88 static MediaEngine* Create(); 89 90 // Initialization 91 // Starts the engine. 92 virtual bool Init() = 0; 93 // Shuts down the engine. 94 virtual void Terminate() = 0; 95 // Returns what the engine is capable of, as a set of Capabilities, above. 96 virtual int GetCapabilities() = 0; 97 98 // MediaChannel creation 99 // Creates a voice media channel. Returns NULL on failure. 100 virtual VoiceMediaChannel *CreateChannel() = 0; 101 // Creates a video media channel, paired with the specified voice channel. 102 // Returns NULL on failure. 103 virtual VideoMediaChannel *CreateVideoChannel( 104 VoiceMediaChannel* voice_media_channel) = 0; 105 106 // Creates a soundclip object for playing sounds on. Returns NULL on failure. 107 virtual SoundclipMedia *CreateSoundclip() = 0; 108 109 // Configuration 110 // Sets global audio options. "options" are from AudioOptions, above. 111 virtual bool SetAudioOptions(int options) = 0; 112 // Sets global video options. "options" are from VideoOptions, above. 113 virtual bool SetVideoOptions(int options) = 0; 114 // Sets the default (maximum) codec/resolution and encoder option to capture 115 // and encode video. 116 virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) 117 = 0; 118 119 // Device selection 120 // TODO: Add method for selecting the soundclip device. 121 virtual bool SetSoundDevices(const Device* in_device, 122 const Device* out_device) = 0; 123 virtual bool SetVideoCaptureDevice(const Device* cam_device) = 0; 124 125 // Device configuration 126 // Sets the current speaker volume, as a value between 0 and 255. 127 virtual bool SetOutputVolume(int level) = 0; 128 129 // Local monitoring 130 // Gets the current microphone level, as a value between 0 and 10. 131 virtual int GetInputLevel() = 0; 132 // Starts or stops the local microphone. Useful if local mic info is needed 133 // prior to a call being connected; the mic will be started automatically 134 // when a VoiceMediaChannel starts sending. 135 virtual bool SetLocalMonitor(bool enable) = 0; 136 // Installs a callback for raw frames from the local camera. 137 virtual bool SetLocalRenderer(VideoRenderer* renderer) = 0; 138 // Starts/stops local camera. 139 virtual CaptureResult SetVideoCapture(bool capture) = 0; 140 141 virtual const std::vector<AudioCodec>& audio_codecs() = 0; 142 virtual const std::vector<VideoCodec>& video_codecs() = 0; 143 virtual bool FindAudioCodec(const AudioCodec &codec) = 0; 144 virtual bool FindVideoCodec(const VideoCodec &codec) = 0; 145 146 // Logging control 147 virtual void SetVoiceLogging(int min_sev, const char* filter) = 0; 148 virtual void SetVideoLogging(int min_sev, const char* filter) = 0; 149 150 sigslot::repeater1<CaptureResult> SignalVideoCaptureResult; 151 }; 152 153 // CompositeMediaEngine constructs a MediaEngine from separate 154 // voice and video engine classes. 155 template<class VOICE, class VIDEO> 156 class CompositeMediaEngine : public MediaEngine { 157 public: CompositeMediaEngine()158 CompositeMediaEngine() {} Init()159 virtual bool Init() { 160 if (!voice_.Init()) 161 return false; 162 if (!video_.Init()) { 163 voice_.Terminate(); 164 return false; 165 } 166 SignalVideoCaptureResult.repeat(video_.SignalCaptureResult); 167 return true; 168 } Terminate()169 virtual void Terminate() { 170 video_.Terminate(); 171 voice_.Terminate(); 172 } 173 GetCapabilities()174 virtual int GetCapabilities() { 175 return (voice_.GetCapabilities() | video_.GetCapabilities()); 176 } CreateChannel()177 virtual VoiceMediaChannel *CreateChannel() { 178 return voice_.CreateChannel(); 179 } CreateVideoChannel(VoiceMediaChannel * channel)180 virtual VideoMediaChannel *CreateVideoChannel(VoiceMediaChannel* channel) { 181 return video_.CreateChannel(channel); 182 } CreateSoundclip()183 virtual SoundclipMedia *CreateSoundclip() { 184 return voice_.CreateSoundclip(); 185 } 186 SetAudioOptions(int o)187 virtual bool SetAudioOptions(int o) { 188 return voice_.SetOptions(o); 189 } SetVideoOptions(int o)190 virtual bool SetVideoOptions(int o) { 191 return video_.SetOptions(o); 192 } SetDefaultVideoEncoderConfig(const VideoEncoderConfig & config)193 virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) { 194 return video_.SetDefaultEncoderConfig(config); 195 } 196 SetSoundDevices(const Device * in_device,const Device * out_device)197 virtual bool SetSoundDevices(const Device* in_device, 198 const Device* out_device) { 199 return voice_.SetDevices(in_device, out_device); 200 } SetVideoCaptureDevice(const Device * cam_device)201 virtual bool SetVideoCaptureDevice(const Device* cam_device) { 202 return video_.SetCaptureDevice(cam_device); 203 } 204 SetOutputVolume(int level)205 virtual bool SetOutputVolume(int level) { 206 return voice_.SetOutputVolume(level); 207 } 208 GetInputLevel()209 virtual int GetInputLevel() { 210 return voice_.GetInputLevel(); 211 } SetLocalMonitor(bool enable)212 virtual bool SetLocalMonitor(bool enable) { 213 return voice_.SetLocalMonitor(enable); 214 } SetLocalRenderer(VideoRenderer * renderer)215 virtual bool SetLocalRenderer(VideoRenderer* renderer) { 216 return video_.SetLocalRenderer(renderer); 217 } SetVideoCapture(bool capture)218 virtual CaptureResult SetVideoCapture(bool capture) { 219 return video_.SetCapture(capture); 220 } 221 audio_codecs()222 virtual const std::vector<AudioCodec>& audio_codecs() { 223 return voice_.codecs(); 224 } video_codecs()225 virtual const std::vector<VideoCodec>& video_codecs() { 226 return video_.codecs(); 227 } 228 FindAudioCodec(const AudioCodec & codec)229 virtual bool FindAudioCodec(const AudioCodec &codec) { 230 return voice_.FindCodec(codec); 231 } FindVideoCodec(const VideoCodec & codec)232 virtual bool FindVideoCodec(const VideoCodec &codec) { 233 return video_.FindCodec(codec); 234 } 235 SetVoiceLogging(int min_sev,const char * filter)236 virtual void SetVoiceLogging(int min_sev, const char* filter) { 237 return voice_.SetLogging(min_sev, filter); 238 } SetVideoLogging(int min_sev,const char * filter)239 virtual void SetVideoLogging(int min_sev, const char* filter) { 240 return video_.SetLogging(min_sev, filter); 241 } 242 243 private: 244 VOICE voice_; 245 VIDEO video_; 246 }; 247 248 class NullVoiceMediaChannel : public VoiceMediaChannel { 249 public: NullVoiceMediaChannel()250 explicit NullVoiceMediaChannel() {} ~NullVoiceMediaChannel()251 ~NullVoiceMediaChannel() {} 252 // MediaChannel implementations OnPacketReceived(talk_base::Buffer * packet)253 virtual void OnPacketReceived(talk_base::Buffer* packet) {} OnRtcpReceived(talk_base::Buffer * packet)254 virtual void OnRtcpReceived(talk_base::Buffer* packet) {} SetSendSsrc(uint32 id)255 virtual void SetSendSsrc(uint32 id) {} SetRtcpCName(const std::string & cname)256 virtual bool SetRtcpCName(const std::string& cname) { return true; } Mute(bool on)257 virtual bool Mute(bool on) { return true; } SetSendBandwidth(bool autobw,int bps)258 virtual bool SetSendBandwidth(bool autobw, int bps) { return true; } SetOptions(int options)259 virtual bool SetOptions(int options) { return true; } 260 // VoiceMediaChannel implementations SetRecvCodecs(const std::vector<AudioCodec> & codecs)261 virtual bool SetRecvCodecs(const std::vector<AudioCodec> &codecs) { 262 return true; 263 } SetSendCodecs(const std::vector<AudioCodec> & codecs)264 virtual bool SetSendCodecs(const std::vector<AudioCodec> &codecs) { 265 return true; 266 } SetPlayout(bool playout)267 virtual bool SetPlayout(bool playout) { return true; } SetSend(SendFlags flag)268 virtual bool SetSend(SendFlags flag) { return true; } AddStream(uint32 ssrc)269 virtual bool AddStream(uint32 ssrc) { return true; } RemoveStream(uint32 ssrc)270 virtual bool RemoveStream(uint32 ssrc) { return true; } GetActiveStreams(AudioInfo::StreamList * streams)271 virtual bool GetActiveStreams(AudioInfo::StreamList* streams) { return true; } GetOutputLevel()272 virtual int GetOutputLevel() { return 0; } SetRingbackTone(const char * buf,int len)273 virtual void SetRingbackTone(const char *buf, int len) {} PlayRingbackTone(bool play,bool loop)274 virtual bool PlayRingbackTone(bool play, bool loop) { return true; } PressDTMF(int event,bool playout)275 virtual bool PressDTMF(int event, bool playout) { return true; } GetStats(VoiceMediaInfo * info)276 virtual bool GetStats(VoiceMediaInfo* info) { return false; } 277 }; 278 279 // NullVoiceEngine can be used with CompositeMediaEngine in the case where only 280 // a video engine is desired. 281 class NullVoiceEngine { 282 public: Init()283 bool Init() { return true; } Terminate()284 void Terminate() {} GetCapabilities()285 int GetCapabilities() { return 0; } CreateChannel()286 VoiceMediaChannel* CreateChannel() { 287 // TODO: See if we can make things work without requiring 288 // allocation of a channel. 289 return new NullVoiceMediaChannel(); 290 } CreateSoundclip()291 SoundclipMedia* CreateSoundclip() { 292 return NULL; 293 } SetOptions(int opts)294 bool SetOptions(int opts) { return true; } SetDevices(const Device * in_device,const Device * out_device)295 bool SetDevices(const Device* in_device, const Device* out_device) { 296 return true; 297 } SetOutputVolume(int level)298 bool SetOutputVolume(int level) { return true; } GetInputLevel()299 int GetInputLevel() { return 0; } SetLocalMonitor(bool enable)300 bool SetLocalMonitor(bool enable) { return true; } codecs()301 const std::vector<AudioCodec>& codecs() { return codecs_; } FindCodec(const AudioCodec &)302 bool FindCodec(const AudioCodec&) { return false; } SetLogging(int min_sev,const char * filter)303 void SetLogging(int min_sev, const char* filter) {} 304 private: 305 std::vector<AudioCodec> codecs_; 306 }; 307 308 // NullVideoEngine can be used with CompositeMediaEngine in the case where only 309 // a voice engine is desired. 310 class NullVideoEngine { 311 public: Init()312 bool Init() { return true; } Terminate()313 void Terminate() {} GetCapabilities()314 int GetCapabilities() { return 0; } CreateChannel(VoiceMediaChannel * voice_media_channel)315 VideoMediaChannel* CreateChannel(VoiceMediaChannel* voice_media_channel) { 316 return NULL; 317 } SetOptions(int opts)318 bool SetOptions(int opts) { return true; } SetDefaultEncoderConfig(const VideoEncoderConfig & config)319 bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) { 320 return true; 321 } SetCaptureDevice(const Device * cam_device)322 bool SetCaptureDevice(const Device* cam_device) { return true; } SetLocalRenderer(VideoRenderer * renderer)323 bool SetLocalRenderer(VideoRenderer* renderer) { return true; } SetCapture(bool capture)324 CaptureResult SetCapture(bool capture) { return CR_SUCCESS; } codecs()325 const std::vector<VideoCodec>& codecs() { return codecs_; } FindCodec(const VideoCodec &)326 bool FindCodec(const VideoCodec&) { return false; } SetLogging(int min_sev,const char * filter)327 void SetLogging(int min_sev, const char* filter) {} 328 sigslot::signal1<CaptureResult> SignalCaptureResult; 329 private: 330 std::vector<VideoCodec> codecs_; 331 }; 332 333 typedef CompositeMediaEngine<NullVoiceEngine, NullVideoEngine> NullMediaEngine; 334 335 } // namespace cricket 336 337 #endif // TALK_SESSION_PHONE_MEDIAENGINE_H_ 338