* Update the session layer to p4 37930

* Update the peerconnection_client in sync with updates on the libjingle side.
Review URL: http://webrtc-codereview.appspot.com/29008

git-svn-id: http://webrtc.googlecode.com/svn/trunk@34 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
ronghuawu@google.com
2011-06-01 18:50:40 +00:00
parent c16e32d346
commit e6988b9de5
16 changed files with 451 additions and 1700 deletions

View File

@ -1,798 +0,0 @@
/*
* libjingle
* Copyright 2004--2008, 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.
*/
#include "talk/session/phone/channelmanager.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <algorithm>
#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/sigslotrepeater.h"
#include "talk/base/stringencode.h"
#include "talk/session/phone/mediaengine.h"
#include "talk/session/phone/soundclip.h"
namespace cricket {
enum {
MSG_CREATEVOICECHANNEL = 1,
MSG_DESTROYVOICECHANNEL = 2,
MSG_SETAUDIOOPTIONS = 3,
MSG_GETOUTPUTVOLUME = 4,
MSG_SETOUTPUTVOLUME = 5,
MSG_SETLOCALMONITOR = 6,
MSG_SETVOICELOGGING = 7,
MSG_CREATEVIDEOCHANNEL = 11,
MSG_DESTROYVIDEOCHANNEL = 12,
MSG_SETVIDEOOPTIONS = 13,
MSG_SETLOCALRENDERER = 14,
MSG_SETDEFAULTVIDEOENCODERCONFIG = 15,
MSG_SETVIDEOLOGGING = 16,
MSG_CREATESOUNDCLIP = 17,
MSG_DESTROYSOUNDCLIP = 18,
MSG_CAMERASTARTED = 19,
MSG_SETVIDEOCAPTURE = 20,
};
struct CreationParams : public talk_base::MessageData {
CreationParams(BaseSession* session, const std::string& content_name,
bool rtcp, VoiceChannel* voice_channel)
: session(session),
content_name(content_name),
rtcp(rtcp),
voice_channel(voice_channel),
video_channel(NULL) {}
BaseSession* session;
std::string content_name;
bool rtcp;
VoiceChannel* voice_channel;
VideoChannel* video_channel;
};
struct AudioOptions : public talk_base::MessageData {
AudioOptions(int o, const Device* in, const Device* out)
: options(o), in_device(in), out_device(out) {}
int options;
const Device* in_device;
const Device* out_device;
bool result;
};
struct VolumeLevel : public talk_base::MessageData {
VolumeLevel() : level(-1), result(false) {}
explicit VolumeLevel(int l) : level(l), result(false) {}
int level;
bool result;
};
struct VideoOptions : public talk_base::MessageData {
explicit VideoOptions(const Device* d) : cam_device(d), result(false) {}
const Device* cam_device;
bool result;
};
struct DefaultVideoEncoderConfig : public talk_base::MessageData {
explicit DefaultVideoEncoderConfig(const VideoEncoderConfig& c)
: config(c), result(false) {}
VideoEncoderConfig config;
bool result;
};
struct LocalMonitor : public talk_base::MessageData {
explicit LocalMonitor(bool e) : enable(e), result(false) {}
bool enable;
bool result;
};
struct LocalRenderer : public talk_base::MessageData {
explicit LocalRenderer(VideoRenderer* r) : renderer(r), result(false) {}
VideoRenderer* renderer;
bool result;
};
struct LoggingOptions : public talk_base::MessageData {
explicit LoggingOptions(int lev, const char* f) : level(lev), filter(f) {}
int level;
std::string filter;
};
struct CaptureParams : public talk_base::MessageData {
explicit CaptureParams(bool c) : capture(c), result(CR_FAILURE) {}
bool capture;
CaptureResult result;
};
ChannelManager::ChannelManager(talk_base::Thread* worker_thread)
: media_engine_(MediaEngine::Create()),
device_manager_(new DeviceManager()),
initialized_(false),
main_thread_(talk_base::Thread::Current()),
worker_thread_(worker_thread),
audio_in_device_(DeviceManager::kDefaultDeviceName),
audio_out_device_(DeviceManager::kDefaultDeviceName),
audio_options_(MediaEngine::DEFAULT_AUDIO_OPTIONS),
local_renderer_(NULL),
capturing_(false),
monitoring_(false) {
Construct();
}
ChannelManager::ChannelManager(MediaEngine* me, DeviceManager* dm,
talk_base::Thread* worker_thread)
: media_engine_(me),
device_manager_(dm),
initialized_(false),
main_thread_(talk_base::Thread::Current()),
worker_thread_(worker_thread),
audio_in_device_(DeviceManager::kDefaultDeviceName),
audio_out_device_(DeviceManager::kDefaultDeviceName),
audio_options_(MediaEngine::DEFAULT_AUDIO_OPTIONS),
local_renderer_(NULL),
capturing_(false),
monitoring_(false) {
Construct();
}
void ChannelManager::Construct() {
// Init the device manager immediately, and set up our default video device.
SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
device_manager_->Init();
// Set camera_device_ to the name of the default video capturer.
SetVideoOptions(DeviceManager::kDefaultDeviceName);
// Camera is started asynchronously, request callbacks when startup
// completes to be able to forward them to the rendering manager.
media_engine_->SignalVideoCaptureResult.connect(
this, &ChannelManager::OnVideoCaptureResult);
}
ChannelManager::~ChannelManager() {
if (initialized_)
Terminate();
}
int ChannelManager::GetCapabilities() {
return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
}
void ChannelManager::GetSupportedAudioCodecs(
std::vector<AudioCodec>* codecs) const {
codecs->clear();
for (std::vector<AudioCodec>::const_iterator it =
media_engine_->audio_codecs().begin();
it != media_engine_->audio_codecs().end(); ++it) {
codecs->push_back(*it);
}
}
void ChannelManager::GetSupportedVideoCodecs(
std::vector<VideoCodec>* codecs) const {
codecs->clear();
std::vector<VideoCodec>::const_iterator it;
for (it = media_engine_->video_codecs().begin();
it != media_engine_->video_codecs().end(); ++it) {
codecs->push_back(*it);
}
}
bool ChannelManager::Init() {
ASSERT(!initialized_);
if (initialized_) {
return false;
}
ASSERT(worker_thread_ != NULL);
if (worker_thread_ && worker_thread_->started()) {
if (media_engine_->Init()) {
initialized_ = true;
// Now that we're initialized, apply any stored preferences. A preferred
// device might have been unplugged. In this case, we fallback to the
// default device but keep the user preferences. The preferences are
// changed only when the Javascript FE changes them.
const std::string preferred_audio_in_device = audio_in_device_;
const std::string preferred_audio_out_device = audio_out_device_;
const std::string preferred_camera_device = camera_device_;
Device device;
if (!device_manager_->GetAudioInputDevice(audio_in_device_, &device)) {
LOG(LS_WARNING) << "The preferred microphone '" << audio_in_device_
<< "' is unavailable. Fall back to the default.";
audio_in_device_ = DeviceManager::kDefaultDeviceName;
}
if (!device_manager_->GetAudioOutputDevice(audio_out_device_, &device)) {
LOG(LS_WARNING) << "The preferred speaker '" << audio_out_device_
<< "' is unavailable. Fall back to the default.";
audio_out_device_ = DeviceManager::kDefaultDeviceName;
}
if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
if (!camera_device_.empty()) {
LOG(LS_WARNING) << "The preferred camera '" << camera_device_
<< "' is unavailable. Fall back to the default.";
}
camera_device_ = DeviceManager::kDefaultDeviceName;
}
if (!SetAudioOptions(audio_in_device_, audio_out_device_,
audio_options_)) {
LOG(LS_WARNING) << "Failed to SetAudioOptions with"
<< " microphone: " << audio_in_device_
<< " speaker: " << audio_out_device_
<< " options: " << audio_options_;
}
if (!SetVideoOptions(camera_device_) && !camera_device_.empty()) {
LOG(LS_WARNING) << "Failed to SetVideoOptions with camera: "
<< camera_device_;
}
// Restore the user preferences.
audio_in_device_ = preferred_audio_in_device;
audio_out_device_ = preferred_audio_out_device;
camera_device_ = preferred_camera_device;
// Now apply the default video codec that has been set earlier.
if (default_video_encoder_config_.max_codec.id != 0) {
SetDefaultVideoEncoderConfig(default_video_encoder_config_);
}
// And the local renderer.
if (local_renderer_) {
SetLocalRenderer(local_renderer_);
}
}
}
return initialized_;
}
void ChannelManager::Terminate() {
ASSERT(initialized_);
if (!initialized_) {
return;
}
// Need to destroy the voice/video channels
while (!video_channels_.empty()) {
DestroyVideoChannel_w(video_channels_.back());
}
while (!voice_channels_.empty()) {
DestroyVoiceChannel_w(voice_channels_.back());
}
while (!soundclips_.empty()) {
DestroySoundclip_w(soundclips_.back());
}
media_engine_->Terminate();
initialized_ = false;
}
VoiceChannel* ChannelManager::CreateVoiceChannel(
BaseSession* session, const std::string& content_name, bool rtcp) {
CreationParams params(session, content_name, rtcp, NULL);
return (Send(MSG_CREATEVOICECHANNEL, &params)) ? params.voice_channel : NULL;
}
VoiceChannel* ChannelManager::CreateVoiceChannel_w(
BaseSession* session, const std::string& content_name, bool rtcp) {
talk_base::CritScope cs(&crit_);
// This is ok to alloc from a thread other than the worker thread
ASSERT(initialized_);
VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
if (media_channel == NULL)
return NULL;
VoiceChannel* voice_channel = new VoiceChannel(
worker_thread_, media_engine_.get(), media_channel,
session, content_name, rtcp);
voice_channels_.push_back(voice_channel);
return voice_channel;
}
void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
if (voice_channel) {
talk_base::TypedMessageData<VoiceChannel *> data(voice_channel);
Send(MSG_DESTROYVOICECHANNEL, &data);
}
}
void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
talk_base::CritScope cs(&crit_);
// Destroy voice channel.
ASSERT(initialized_);
VoiceChannels::iterator it = std::find(voice_channels_.begin(),
voice_channels_.end(), voice_channel);
ASSERT(it != voice_channels_.end());
if (it == voice_channels_.end())
return;
voice_channels_.erase(it);
delete voice_channel;
}
VideoChannel* ChannelManager::CreateVideoChannel(
BaseSession* session, const std::string& content_name, bool rtcp,
VoiceChannel* voice_channel) {
CreationParams params(session, content_name, rtcp, voice_channel);
return (Send(MSG_CREATEVIDEOCHANNEL, &params)) ? params.video_channel : NULL;
}
VideoChannel* ChannelManager::CreateVideoChannel_w(
BaseSession* session, const std::string& content_name, bool rtcp,
VoiceChannel* voice_channel) {
talk_base::CritScope cs(&crit_);
// This is ok to alloc from a thread other than the worker thread
ASSERT(initialized_);
VideoMediaChannel* media_channel =
// voice_channel can be NULL in case of NullVoiceEngine.
media_engine_->CreateVideoChannel(voice_channel ?
voice_channel->media_channel() : NULL);
if (media_channel == NULL)
return NULL;
VideoChannel* video_channel = new VideoChannel(
worker_thread_, media_engine_.get(), media_channel,
session, content_name, rtcp, voice_channel);
video_channels_.push_back(video_channel);
return video_channel;
}
void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
if (video_channel) {
talk_base::TypedMessageData<VideoChannel *> data(video_channel);
Send(MSG_DESTROYVIDEOCHANNEL, &data);
}
}
void ChannelManager::DestroyVideoChannel_w(VideoChannel *video_channel) {
talk_base::CritScope cs(&crit_);
// Destroy voice channel.
ASSERT(initialized_);
VideoChannels::iterator it = std::find(video_channels_.begin(),
video_channels_.end(), video_channel);
if (it == video_channels_.end())
return;
video_channels_.erase(it);
delete video_channel;
}
Soundclip* ChannelManager::CreateSoundclip() {
talk_base::TypedMessageData<Soundclip*> data(NULL);
Send(MSG_CREATESOUNDCLIP, &data);
return data.data();
}
Soundclip* ChannelManager::CreateSoundclip_w() {
talk_base::CritScope cs(&crit_);
ASSERT(initialized_);
ASSERT(worker_thread_ == talk_base::Thread::Current());
SoundclipMedia* soundclip_media = media_engine_->CreateSoundclip();
if (!soundclip_media) {
return NULL;
}
Soundclip* soundclip = new Soundclip(worker_thread_, soundclip_media);
soundclips_.push_back(soundclip);
return soundclip;
}
void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
if (soundclip) {
talk_base::TypedMessageData<Soundclip*> data(soundclip);
Send(MSG_DESTROYSOUNDCLIP, &data);
}
}
void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
talk_base::CritScope cs(&crit_);
// Destroy soundclip.
ASSERT(initialized_);
Soundclips::iterator it = std::find(soundclips_.begin(),
soundclips_.end(), soundclip);
ASSERT(it != soundclips_.end());
if (it == soundclips_.end())
return;
soundclips_.erase(it);
delete soundclip;
}
bool ChannelManager::GetAudioOptions(std::string* in_name,
std::string* out_name, int* opts) {
*in_name = audio_in_device_;
*out_name = audio_out_device_;
*opts = audio_options_;
return true;
}
bool ChannelManager::SetAudioOptions(const std::string& in_name,
const std::string& out_name, int opts) {
// Get device ids from DeviceManager.
Device in_dev, out_dev;
if (!device_manager_->GetAudioInputDevice(in_name, &in_dev)) {
LOG(LS_WARNING) << "Failed to GetAudioInputDevice: " << in_name;
return false;
}
if (!device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
LOG(LS_WARNING) << "Failed to GetAudioOutputDevice: " << out_name;
return false;
}
// If we're initialized, pass the settings to the media engine.
bool ret = true;
if (initialized_) {
AudioOptions options(opts, &in_dev, &out_dev);
ret = (Send(MSG_SETAUDIOOPTIONS, &options) && options.result);
}
// If all worked well, save the values for use in GetAudioOptions.
if (ret) {
audio_options_ = opts;
audio_in_device_ = in_name;
audio_out_device_ = out_name;
}
return ret;
}
bool ChannelManager::SetAudioOptions_w(int opts, const Device* in_dev,
const Device* out_dev) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
// Set audio options
bool ret = media_engine_->SetAudioOptions(opts);
// Set the audio devices
if (ret) {
talk_base::CritScope cs(&crit_);
ret = media_engine_->SetSoundDevices(in_dev, out_dev);
}
return ret;
}
bool ChannelManager::GetOutputVolume(int* level) {
VolumeLevel volume;
if (!Send(MSG_GETOUTPUTVOLUME, &volume) || !volume.result) {
return false;
}
*level = volume.level;
return true;
}
bool ChannelManager::GetOutputVolume_w(int* level) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
return media_engine_->GetOutputVolume(level);
}
bool ChannelManager::SetOutputVolume(int level) {
VolumeLevel volume(level);
return (Send(MSG_SETOUTPUTVOLUME, &volume) && volume.result);
}
bool ChannelManager::SetOutputVolume_w(int level) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
return media_engine_->SetOutputVolume(level);
}
bool ChannelManager::GetVideoOptions(std::string* cam_name) {
*cam_name = camera_device_;
return true;
}
bool ChannelManager::SetVideoOptions(const std::string& cam_name) {
Device device;
if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
if (!cam_name.empty()) {
LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
}
return false;
}
// If we're running, tell the media engine about it.
bool ret = true;
if (initialized_) {
VideoOptions options(&device);
ret = (Send(MSG_SETVIDEOOPTIONS, &options) && options.result);
}
// If everything worked, retain the name of the selected camera.
if (ret) {
camera_device_ = device.name;
}
return ret;
}
bool ChannelManager::SetVideoOptions_w(const Device* cam_device) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
// Set the video input device
return media_engine_->SetVideoCaptureDevice(cam_device);
}
bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
bool ret = true;
if (initialized_) {
DefaultVideoEncoderConfig config(c);
ret = Send(MSG_SETDEFAULTVIDEOENCODERCONFIG, &config) && config.result;
}
if (ret) {
default_video_encoder_config_ = c;
}
return ret;
}
bool ChannelManager::SetDefaultVideoEncoderConfig_w(
const VideoEncoderConfig& c) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
return media_engine_->SetDefaultVideoEncoderConfig(c);
}
bool ChannelManager::SetLocalMonitor(bool enable) {
LocalMonitor monitor(enable);
bool ret = Send(MSG_SETLOCALMONITOR, &monitor) && monitor.result;
if (ret) {
monitoring_ = enable;
}
return ret;
}
bool ChannelManager::SetLocalMonitor_w(bool enable) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
return media_engine_->SetLocalMonitor(enable);
}
bool ChannelManager::SetLocalRenderer(VideoRenderer* renderer) {
bool ret = true;
if (initialized_) {
LocalRenderer local(renderer);
ret = (Send(MSG_SETLOCALRENDERER, &local) && local.result);
}
if (ret) {
local_renderer_ = renderer;
}
return ret;
}
bool ChannelManager::SetLocalRenderer_w(VideoRenderer* renderer) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
return media_engine_->SetLocalRenderer(renderer);
}
CaptureResult ChannelManager::SetVideoCapture(bool capture) {
bool ret;
CaptureParams capture_params(capture);
ret = (Send(MSG_SETVIDEOCAPTURE, &capture_params) &&
(capture_params.result != CR_FAILURE));
if (ret) {
capturing_ = capture;
}
return capture_params.result;
}
CaptureResult ChannelManager::SetVideoCapture_w(bool capture) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
ASSERT(initialized_);
return media_engine_->SetVideoCapture(capture);
}
void ChannelManager::SetVoiceLogging(int level, const char* filter) {
SetMediaLogging(false, level, filter);
}
void ChannelManager::SetVideoLogging(int level, const char* filter) {
SetMediaLogging(true, level, filter);
}
void ChannelManager::SetMediaLogging(bool video, int level,
const char* filter) {
// Can be called before initialization; in this case, the worker function
// is simply called on the main thread.
if (initialized_) {
LoggingOptions options(level, filter);
Send((video) ? MSG_SETVIDEOLOGGING : MSG_SETVOICELOGGING, &options);
} else {
SetMediaLogging_w(video, level, filter);
}
}
void ChannelManager::SetMediaLogging_w(bool video, int level,
const char* filter) {
// Can be called before initialization
ASSERT(worker_thread_ == talk_base::Thread::Current() || !initialized_);
if (video) {
media_engine_->SetVideoLogging(level, filter);
} else {
media_engine_->SetVoiceLogging(level, filter);
}
}
bool ChannelManager::Send(uint32 id, talk_base::MessageData* data) {
if (!worker_thread_ || !initialized_) return false;
worker_thread_->Send(this, id, data);
return true;
}
void ChannelManager::OnVideoCaptureResult(CaptureResult result) {
capturing_ = result == CR_SUCCESS;
main_thread_->Post(this, MSG_CAMERASTARTED,
new talk_base::TypedMessageData<CaptureResult>(result));
}
void ChannelManager::OnMessage(talk_base::Message* message) {
talk_base::MessageData* data = message->pdata;
switch (message->message_id) {
case MSG_CREATEVOICECHANNEL: {
CreationParams* p = static_cast<CreationParams*>(data);
p->voice_channel =
CreateVoiceChannel_w(p->session, p->content_name, p->rtcp);
break;
}
case MSG_DESTROYVOICECHANNEL: {
VoiceChannel* p = static_cast<talk_base::TypedMessageData<VoiceChannel*>*>
(data)->data();
DestroyVoiceChannel_w(p);
break;
}
case MSG_CREATEVIDEOCHANNEL: {
CreationParams* p = static_cast<CreationParams*>(data);
p->video_channel = CreateVideoChannel_w(p->session, p->content_name,
p->rtcp, p->voice_channel);
break;
}
case MSG_DESTROYVIDEOCHANNEL: {
VideoChannel* p = static_cast<talk_base::TypedMessageData<VideoChannel*>*>
(data)->data();
DestroyVideoChannel_w(p);
break;
}
case MSG_CREATESOUNDCLIP: {
talk_base::TypedMessageData<Soundclip*> *p =
static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
p->data() = CreateSoundclip_w();
break;
}
case MSG_DESTROYSOUNDCLIP: {
talk_base::TypedMessageData<Soundclip*> *p =
static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
DestroySoundclip_w(p->data());
break;
}
case MSG_SETAUDIOOPTIONS: {
AudioOptions* p = static_cast<AudioOptions*>(data);
p->result = SetAudioOptions_w(p->options,
p->in_device, p->out_device);
break;
}
case MSG_GETOUTPUTVOLUME: {
VolumeLevel* p = static_cast<VolumeLevel*>(data);
p->result = GetOutputVolume_w(&p->level);
break;
}
case MSG_SETOUTPUTVOLUME: {
VolumeLevel* p = static_cast<VolumeLevel*>(data);
p->result = SetOutputVolume_w(p->level);
break;
}
case MSG_SETLOCALMONITOR: {
LocalMonitor* p = static_cast<LocalMonitor*>(data);
p->result = SetLocalMonitor_w(p->enable);
break;
}
case MSG_SETVIDEOOPTIONS: {
VideoOptions* p = static_cast<VideoOptions*>(data);
p->result = SetVideoOptions_w(p->cam_device);
break;
}
case MSG_SETDEFAULTVIDEOENCODERCONFIG: {
DefaultVideoEncoderConfig* p =
static_cast<DefaultVideoEncoderConfig*>(data);
p->result = SetDefaultVideoEncoderConfig_w(p->config);
break;
}
case MSG_SETLOCALRENDERER: {
LocalRenderer* p = static_cast<LocalRenderer*>(data);
p->result = SetLocalRenderer_w(p->renderer);
break;
}
case MSG_SETVIDEOCAPTURE: {
CaptureParams* p = static_cast<CaptureParams*>(data);
p->result = SetVideoCapture_w(p->capture);
break;
}
case MSG_SETVOICELOGGING:
case MSG_SETVIDEOLOGGING: {
LoggingOptions* p = static_cast<LoggingOptions*>(data);
bool video = (message->message_id == MSG_SETVIDEOLOGGING);
SetMediaLogging_w(video, p->level, p->filter.c_str());
break;
}
case MSG_CAMERASTARTED: {
talk_base::TypedMessageData<CaptureResult>* data =
static_cast<talk_base::TypedMessageData<CaptureResult>*>(
message->pdata);
SignalVideoCaptureResult(data->data());
delete data;
break;
}
}
}
static void GetDeviceNames(const std::vector<Device>& devs,
std::vector<std::string>* names) {
names->clear();
for (size_t i = 0; i < devs.size(); ++i) {
names->push_back(devs[i].name);
}
}
bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
names->clear();
std::vector<Device> devs;
bool ret = device_manager_->GetAudioInputDevices(&devs);
if (ret)
GetDeviceNames(devs, names);
return ret;
}
bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
names->clear();
std::vector<Device> devs;
bool ret = device_manager_->GetAudioOutputDevices(&devs);
if (ret)
GetDeviceNames(devs, names);
return ret;
}
bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
names->clear();
std::vector<Device> devs;
bool ret = device_manager_->GetVideoCaptureDevices(&devs);
if (ret)
GetDeviceNames(devs, names);
return ret;
}
} // namespace cricket

View File

@ -1,208 +0,0 @@
/*
* libjingle
* Copyright 2004--2008, 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_PHONE_CHANNELMANAGER_H_
#define TALK_SESSION_PHONE_CHANNELMANAGER_H_
#include <string>
#include <vector>
#include "talk/base/criticalsection.h"
#include "talk/base/sigslotrepeater.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/session.h"
#include "talk/session/phone/voicechannel.h"
#include "talk/session/phone/mediaengine.h"
#include "talk/session/phone/devicemanager.h"
namespace cricket {
class Soundclip;
class VoiceChannel;
// 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 talk_base::MessageHandler,
public sigslot::has_slots<> {
public:
// Creates the channel manager, and specifies the worker thread to use.
explicit ChannelManager(talk_base::Thread* worker);
// For testing purposes. Allows the media engine and dev manager to be mocks.
// The ChannelManager takes ownership of these objects.
ChannelManager(MediaEngine* me, DeviceManager* dm, talk_base::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.
talk_base::Thread* worker_thread() const { return worker_thread_; }
bool set_worker_thread(talk_base::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 GetSupportedVideoCodecs(std::vector<VideoCodec>* codecs) const;
// Indicates whether the media engine is started.
bool initialized() const { return initialized_; }
// Starts up the media engine.
bool Init();
// TODO: Remove this temporary API once Flute is updated.
bool Init(talk_base::Thread* thread) {
return set_worker_thread(thread) && 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);
// 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.
bool GetAudioOptions(std::string* wave_in_device,
std::string* wave_out_device, int* opts);
bool SetAudioOptions(const std::string& wave_in_device,
const std::string& wave_out_device, int opts);
bool GetOutputVolume(int* level);
bool SetOutputVolume(int level);
bool GetVideoOptions(std::string* cam_device);
bool SetVideoOptions(const std::string& cam_device);
bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config);
// 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);
// Starts and stops the local camera and renders it to the local renderer.
CaptureResult SetVideoCapture(bool capture);
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 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);
sigslot::repeater0<> SignalDevicesChange;
sigslot::signal1<CaptureResult> SignalVideoCaptureResult;
protected:
bool Send(uint32 id, talk_base::MessageData* pdata);
void OnMessage(talk_base::Message *message);
MediaEngine* media_engine() { return media_engine_.get(); }
private:
typedef std::vector<VoiceChannel*> VoiceChannels;
typedef std::vector<VideoChannel*> VideoChannels;
typedef std::vector<Soundclip*> Soundclips;
void Construct();
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);
Soundclip* CreateSoundclip_w();
void DestroySoundclip_w(Soundclip* soundclip);
bool SetAudioOptions_w(int opts, const Device* in_dev,
const Device* out_dev);
bool GetOutputVolume_w(int* level);
bool SetOutputVolume_w(int level);
bool SetLocalMonitor_w(bool enable);
bool SetVideoOptions_w(const Device* cam_device);
bool SetDefaultVideoEncoderConfig_w(const VideoEncoderConfig& config);
bool SetLocalRenderer_w(VideoRenderer* renderer);
CaptureResult SetVideoCapture_w(bool capture);
void SetMediaLogging(bool video, int level, const char* filter);
void SetMediaLogging_w(bool video, int level, const char* filter);
void OnVideoCaptureResult(CaptureResult result);
talk_base::CriticalSection crit_;
talk_base::scoped_ptr<MediaEngine> media_engine_;
talk_base::scoped_ptr<DeviceManager> device_manager_;
bool initialized_;
talk_base::Thread* main_thread_;
talk_base::Thread* worker_thread_;
VoiceChannels voice_channels_;
VideoChannels video_channels_;
Soundclips soundclips_;
std::string audio_in_device_;
std::string audio_out_device_;
int audio_options_;
std::string camera_device_;
VideoEncoderConfig default_video_encoder_config_;
VideoRenderer* local_renderer_;
bool capturing_;
bool monitoring_;
};
} // namespace cricket
#endif // TALK_SESSION_PHONE_CHANNELMANAGER_H_

View File

@ -1,328 +0,0 @@
/*
* libjingle
* Copyright 2004--2007, 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_PHONE_MEDIAENGINE_H_
#define TALK_SESSION_PHONE_MEDIAENGINE_H_
#ifdef OSX
#include <CoreAudio/CoreAudio.h>
#endif
#include <string>
#include <vector>
#include "talk/base/sigslotrepeater.h"
#include "talk/session/phone/codec.h"
#include "talk/session/phone/devicemanager.h"
#include "talk/session/phone/mediachannel.h"
#include "talk/session/phone/videocommon.h"
namespace cricket {
// A class for playing out soundclips.
class SoundclipMedia {
public:
enum SoundclipFlags {
SF_LOOP = 1,
};
virtual ~SoundclipMedia() {}
// Plays a sound out to the speakers with the given audio stream. The stream
// must be 16-bit little-endian 16 kHz PCM. If a stream is already playing
// on this SoundclipMedia, it is stopped. If clip is NULL, nothing is played.
// Returns whether it was successful.
virtual bool PlaySound(const char *clip, int len, int flags) = 0;
};
// MediaEngine is an abstraction of a media engine which can be subclassed
// to support different media componentry backends. It supports voice and
// video operations in the same class to facilitate proper synchronization
// between both media types.
class MediaEngine {
public:
// TODO: Move this to a global location (also used in DeviceManager)
// Capabilities of the media engine.
enum Capabilities {
AUDIO_RECV = 1 << 0,
AUDIO_SEND = 1 << 1,
VIDEO_RECV = 1 << 2,
VIDEO_SEND = 1 << 3,
};
// Bitmask flags for options that may be supported by the media engine
// implementation
enum AudioOptions {
ECHO_CANCELLATION = 1 << 0,
AUTO_GAIN_CONTROL = 1 << 1,
DEFAULT_AUDIO_OPTIONS = ECHO_CANCELLATION | AUTO_GAIN_CONTROL
};
enum VideoOptions {
};
virtual ~MediaEngine() {}
static MediaEngine* Create();
// Initialization
// Starts the engine.
virtual bool Init() = 0;
// Shuts down the engine.
virtual void Terminate() = 0;
// Returns what the engine is capable of, as a set of Capabilities, above.
virtual int GetCapabilities() = 0;
// MediaChannel creation
// Creates a voice media channel. Returns NULL on failure.
virtual VoiceMediaChannel *CreateChannel() = 0;
// Creates a video media channel, paired with the specified voice channel.
// Returns NULL on failure.
virtual VideoMediaChannel *CreateVideoChannel(
VoiceMediaChannel* voice_media_channel) = 0;
// Creates a soundclip object for playing sounds on. Returns NULL on failure.
virtual SoundclipMedia *CreateSoundclip() = 0;
// Configuration
// Sets global audio options. "options" are from AudioOptions, above.
virtual bool SetAudioOptions(int options) = 0;
// Sets global video options. "options" are from VideoOptions, above.
virtual bool SetVideoOptions(int options) = 0;
// Sets the default (maximum) codec/resolution and encoder option to capture
// and encode video.
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config)
= 0;
// Device selection
// TODO: Add method for selecting the soundclip device.
virtual bool SetSoundDevices(const Device* in_device,
const Device* out_device) = 0;
virtual bool SetVideoCaptureDevice(const Device* cam_device) = 0;
virtual bool SetVideoRenderer(int channel_id,
void* window,
unsigned int zOrder,
float left,
float top,
float right,
float bottom) = 0;
// Device configuration
// Gets the current speaker volume, as a value between 0 and 255.
virtual bool GetOutputVolume(int* level) = 0;
// Sets the current speaker volume, as a value between 0 and 255.
virtual bool SetOutputVolume(int level) = 0;
// Local monitoring
// Gets the current microphone level, as a value between 0 and 10.
virtual int GetInputLevel() = 0;
// Starts or stops the local microphone. Useful if local mic info is needed
// prior to a call being connected; the mic will be started automatically
// when a VoiceMediaChannel starts sending.
virtual bool SetLocalMonitor(bool enable) = 0;
// Installs a callback for raw frames from the local camera.
virtual bool SetLocalRenderer(VideoRenderer* renderer) = 0;
// Starts/stops local camera.
virtual CaptureResult SetVideoCapture(bool capture) = 0;
virtual const std::vector<AudioCodec>& audio_codecs() = 0;
virtual const std::vector<VideoCodec>& video_codecs() = 0;
// Logging control
virtual void SetVoiceLogging(int min_sev, const char* filter) = 0;
virtual void SetVideoLogging(int min_sev, const char* filter) = 0;
sigslot::repeater1<CaptureResult> SignalVideoCaptureResult;
};
// CompositeMediaEngine constructs a MediaEngine from separate
// voice and video engine classes.
template<class VOICE, class VIDEO>
class CompositeMediaEngine : public MediaEngine {
public:
CompositeMediaEngine() {}
virtual ~CompositeMediaEngine() {}
virtual bool Init() {
if (!voice_.Init())
return false;
if (!video_.Init()) {
voice_.Terminate();
return false;
}
SignalVideoCaptureResult.repeat(video_.SignalCaptureResult);
return true;
}
virtual void Terminate() {
video_.Terminate();
voice_.Terminate();
}
virtual int GetCapabilities() {
return (voice_.GetCapabilities() | video_.GetCapabilities());
}
virtual VoiceMediaChannel *CreateChannel() {
return voice_.CreateChannel();
}
virtual VideoMediaChannel *CreateVideoChannel(VoiceMediaChannel* channel) {
return video_.CreateChannel(channel);
}
virtual SoundclipMedia *CreateSoundclip() {
return voice_.CreateSoundclip();
}
virtual bool SetAudioOptions(int o) {
return voice_.SetOptions(o);
}
virtual bool SetVideoOptions(int o) {
return video_.SetOptions(o);
}
virtual bool SetDefaultVideoEncoderConfig(const VideoEncoderConfig& config) {
return video_.SetDefaultEncoderConfig(config);
}
virtual bool SetSoundDevices(const Device* in_device,
const Device* out_device) {
return voice_.SetDevices(in_device, out_device);
}
virtual bool SetVideoCaptureDevice(const Device* cam_device) {
return video_.SetCaptureDevice(cam_device);
}
virtual bool SetVideoRenderer(int channel_id,
void* window,
unsigned int zOrder,
float left,
float top,
float right,
float bottom) {
return video_.SetVideoRenderer(channel_id,
window,
zOrder,
left,
top,
right,
bottom);
}
virtual bool GetOutputVolume(int* level) {
return voice_.GetOutputVolume(level);
}
virtual bool SetOutputVolume(int level) {
return voice_.SetOutputVolume(level);
}
virtual int GetInputLevel() {
return voice_.GetInputLevel();
}
virtual bool SetLocalMonitor(bool enable) {
return voice_.SetLocalMonitor(enable);
}
virtual bool SetLocalRenderer(VideoRenderer* renderer) {
return video_.SetLocalRenderer(renderer);
}
virtual CaptureResult SetVideoCapture(bool capture) {
return video_.SetCapture(capture);
}
virtual const std::vector<AudioCodec>& audio_codecs() {
return voice_.codecs();
}
virtual const std::vector<VideoCodec>& video_codecs() {
return video_.codecs();
}
virtual void SetVoiceLogging(int min_sev, const char* filter) {
return voice_.SetLogging(min_sev, filter);
}
virtual void SetVideoLogging(int min_sev, const char* filter) {
return video_.SetLogging(min_sev, filter);
}
protected:
VOICE voice_;
VIDEO video_;
};
// NullVoiceEngine can be used with CompositeMediaEngine in the case where only
// a video engine is desired.
class NullVoiceEngine {
public:
bool Init() { return true; }
void Terminate() {}
int GetCapabilities() { return 0; }
// If you need this to return an actual channel, use FakeMediaEngine instead.
VoiceMediaChannel* CreateChannel() {
return NULL;
}
SoundclipMedia* CreateSoundclip() {
return NULL;
}
bool SetOptions(int opts) { return true; }
bool SetDevices(const Device* in_device, const Device* out_device) {
return true;
}
bool GetOutputVolume(int* level) { *level = 0; return true; }
bool SetOutputVolume(int level) { return true; }
int GetInputLevel() { return 0; }
bool SetLocalMonitor(bool enable) { return true; }
const std::vector<AudioCodec>& codecs() { return codecs_; }
void SetLogging(int min_sev, const char* filter) {}
private:
std::vector<AudioCodec> codecs_;
};
// NullVideoEngine can be used with CompositeMediaEngine in the case where only
// a voice engine is desired.
class NullVideoEngine {
public:
bool Init() { return true; }
void Terminate() {}
int GetCapabilities() { return 0; }
// If you need this to return an actual channel, use FakeMediaEngine instead.
VideoMediaChannel* CreateChannel(
VoiceMediaChannel* voice_media_channel) {
return NULL;
}
bool SetOptions(int opts) { return true; }
bool SetDefaultEncoderConfig(const VideoEncoderConfig& config) {
return true;
}
bool SetCaptureDevice(const Device* cam_device) { return true; }
bool SetLocalRenderer(VideoRenderer* renderer) { return true; }
CaptureResult SetCapture(bool capture) { return CR_SUCCESS; }
const std::vector<VideoCodec>& codecs() { return codecs_; }
void SetLogging(int min_sev, const char* filter) {}
sigslot::signal1<CaptureResult> SignalCaptureResult;
private:
std::vector<VideoCodec> codecs_;
};
typedef CompositeMediaEngine<NullVoiceEngine, NullVideoEngine> NullMediaEngine;
} // namespace cricket
#endif // TALK_SESSION_PHONE_MEDIAENGINE_H_