Update to libjingle 0.6.2.
- Increase the video rtp buffer.
- Disable sound system for chromium build.
- Add basictype.h for NULL.
- Use the ref counted webrtc ADM/VCM.
- Add codereview.settings to use the webrtc codereview system.
git-svn-id: http://libjingle.googlecode.com/svn/trunk@86 dd674b97-3498-5ee5-1854-bdd07cd0ff33
diff --git a/CHANGELOG b/CHANGELOG
index f846076..1f64bb0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,13 @@
Libjingle
+0.6.2 - Oct 7, 2011
+ - Increase the video rtp buffer.
+ - Disable sound system for chromium build.
+ - Add basictype.h for NULL.
+ - Use the ref counted webrtc ADM/VCM.
+ - Add codereview.settings to use the webrtc codereview system.
+ - Add MediaSessionDescriptionFactory.
+
0.6.1 - Sep 15, 2011
- Add dummydevicemanager.
- Remove underscores from the files names for app/webrtc folder.
diff --git a/codereview.settings b/codereview.settings
new file mode 100644
index 0000000..b70057e
--- /dev/null
+++ b/codereview.settings
@@ -0,0 +1,9 @@
+# This file is used by gcl to get repository specific information.
+CODE_REVIEW_SERVER: webrtc-codereview.appspot.com
+#CC_LIST:
+#VIEW_VC:
+#STATUS:
+TRY_ON_UPLOAD: False
+#TRYSERVER_SVN_URL:
+#GITCL_PREUPLOAD:
+#GITCL_PREDCOMMIT:
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index 1048828..de414c5 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -76,7 +76,8 @@
setup_timeout_(kCallSetupTimeout),
signaling_thread_(signaling_thread),
incoming_(incoming),
- port_allocator_(allocator) {
+ port_allocator_(allocator),
+ desc_factory_(channel_manager_) {
}
WebRtcSession::~WebRtcSession() {
@@ -122,30 +123,32 @@
}
bool WebRtcSession::CreateVoiceChannel(const std::string& stream_id) {
- StreamInfo* stream_info = new StreamInfo(stream_id);
- stream_info->video = false;
- streams_.push_back(stream_info);
-
// RTCP disabled
cricket::VoiceChannel* voice_channel =
channel_manager_->CreateVoiceChannel(this, stream_id, true);
- ASSERT(voice_channel != NULL);
+ if (voice_channel == NULL) {
+ LOG(LERROR) << "Unable to create voice channel.";
+ return false;
+ }
+ StreamInfo* stream_info = new StreamInfo(stream_id);
stream_info->channel = voice_channel;
-
+ stream_info->video = false;
+ streams_.push_back(stream_info);
return true;
}
bool WebRtcSession::CreateVideoChannel(const std::string& stream_id) {
- StreamInfo* stream_info = new StreamInfo(stream_id);
- stream_info->video = true;
- streams_.push_back(stream_info);
-
// RTCP disabled
cricket::VideoChannel* video_channel =
channel_manager_->CreateVideoChannel(this, stream_id, true, NULL);
- ASSERT(video_channel != NULL);
+ if (video_channel == NULL) {
+ LOG(LERROR) << "Unable to create video channel.";
+ return false;
+ }
+ StreamInfo* stream_info = new StreamInfo(stream_id);
stream_info->channel = video_channel;
-
+ stream_info->video = true;
+ streams_.push_back(stream_info);
return true;
}
@@ -376,8 +379,15 @@
return false;
}
+ // Get capabilities from offer before generating an answer to it.
+ cricket::MediaSessionOptions options;
+ if (GetFirstAudioContent(offer))
+ options.has_audio = true;
+ if (GetFirstVideoContent(offer))
+ options.has_video = true;
+
talk_base::scoped_ptr<cricket::SessionDescription> answer;
- answer.reset(CreateAnswer(offer));
+ answer.reset(CreateAnswer(offer, options));
if (!answer.get()) {
return false;
@@ -479,106 +489,23 @@
}
cricket::SessionDescription* WebRtcSession::CreateOffer() {
- cricket::SessionDescription* offer = new cricket::SessionDescription();
- StreamMap::iterator iter;
+ cricket::MediaSessionOptions options;
+ options.has_audio = false; // disable default option
+ StreamMap::const_iterator iter;
for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
if ((*iter)->video) {
- // add video codecs, if there is video stream added
- cricket::VideoContentDescription* video =
- new cricket::VideoContentDescription();
- std::vector<cricket::VideoCodec> video_codecs;
- channel_manager_->GetSupportedVideoCodecs(&video_codecs);
- for (VideoCodecs::const_iterator codec = video_codecs.begin();
- codec != video_codecs.end(); ++codec) {
- video->AddCodec(*codec);
- }
-
- // enabling RTCP mux by default
- video->set_rtcp_mux(true);
- video->SortCodecs();
- offer->AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, video);
+ options.has_video = true;
} else {
- cricket::AudioContentDescription* audio =
- new cricket::AudioContentDescription();
-
- std::vector<cricket::AudioCodec> audio_codecs;
- channel_manager_->GetSupportedAudioCodecs(&audio_codecs);
- for (AudioCodecs::const_iterator codec = audio_codecs.begin();
- codec != audio_codecs.end(); ++codec) {
- audio->AddCodec(*codec);
- }
-
- // enabling RTCP mux by default.
- audio->set_rtcp_mux(true);
- audio->SortCodecs();
- offer->AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, audio);
+ options.has_audio = true;
}
}
- return offer;
+ return desc_factory_.CreateOffer(options);
}
cricket::SessionDescription* WebRtcSession::CreateAnswer(
- const cricket::SessionDescription* offer) {
- cricket::SessionDescription* answer = new cricket::SessionDescription();
-
- const cricket::ContentInfo* audio_content = GetFirstAudioContent(offer);
- if (audio_content) {
- const cricket::AudioContentDescription* audio_offer =
- static_cast<const cricket::AudioContentDescription*>(
- audio_content->description);
-
- cricket::AudioContentDescription* audio_accept =
- new cricket::AudioContentDescription();
- AudioCodecs audio_codecs;
- channel_manager_->GetSupportedAudioCodecs(&audio_codecs);
-
- for (AudioCodecs::const_iterator ours = audio_codecs.begin();
- ours != audio_codecs.end(); ++ours) {
- for (AudioCodecs::const_iterator theirs = audio_offer->codecs().begin();
- theirs != audio_offer->codecs().end(); ++theirs) {
- if (ours->Matches(*theirs)) {
- cricket::AudioCodec negotiated(*ours);
- negotiated.id = theirs->id;
- audio_accept->AddCodec(negotiated);
- }
- }
- }
-
- // RTCP mux is set based on what present in incoming offer
- audio_accept->set_rtcp_mux(audio_offer->rtcp_mux());
- audio_accept->SortCodecs();
- answer->AddContent(audio_content->name, audio_content->type, audio_accept);
- }
-
- const cricket::ContentInfo* video_content = GetFirstVideoContent(offer);
- if (video_content) {
- const cricket::VideoContentDescription* video_offer =
- static_cast<const cricket::VideoContentDescription*>(
- video_content->description);
-
- cricket::VideoContentDescription* video_accept =
- new cricket::VideoContentDescription();
- VideoCodecs video_codecs;
- channel_manager_->GetSupportedVideoCodecs(&video_codecs);
-
- for (VideoCodecs::const_iterator ours = video_codecs.begin();
- ours != video_codecs.end(); ++ours) {
- for (VideoCodecs::const_iterator theirs = video_offer->codecs().begin();
- theirs != video_offer->codecs().end(); ++theirs) {
- if (ours->Matches(*theirs)) {
- cricket::VideoCodec negotiated(*ours);
- negotiated.id = theirs->id;
- video_accept->AddCodec(negotiated);
- }
- }
- }
-
- // RTCP mux is set based on what present in incoming offer
- video_accept->set_rtcp_mux(video_offer->rtcp_mux());
- video_accept->SortCodecs();
- answer->AddContent(video_content->name, video_content->type, video_accept);
- }
- return answer;
+ const cricket::SessionDescription* offer,
+ const cricket::MediaSessionOptions& options) {
+ return desc_factory_.CreateAnswer(offer, options);
}
void WebRtcSession::SetError(Error error) {
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 11e389e..6338d25 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -38,6 +38,7 @@
#include "talk/p2p/base/session.h"
#include "talk/session/phone/channel.h"
#include "talk/session/phone/mediachannel.h"
+#include "talk/session/phone/mediasession.h"
namespace cricket {
class ChannelManager;
@@ -170,7 +171,8 @@
cricket::SessionDescription* CreateOffer();
cricket::SessionDescription* CreateAnswer(
- const cricket::SessionDescription* answer);
+ const cricket::SessionDescription* answer,
+ const cricket::MediaSessionOptions& options);
// from MessageHandler
virtual void OnMessage(talk_base::Message* message);
@@ -197,6 +199,7 @@
talk_base::Thread* signaling_thread_;
bool incoming_;
cricket::PortAllocator* port_allocator_;
+ cricket::MediaSessionDescriptionFactory desc_factory_;
};
} // namespace webrtc
diff --git a/talk/base/basictypes.h b/talk/base/basictypes.h
index d34cb39..4193ede 100644
--- a/talk/base/basictypes.h
+++ b/talk/base/basictypes.h
@@ -43,15 +43,6 @@
#ifndef INT_TYPES_DEFINED
#define INT_TYPES_DEFINED
#ifdef COMPILER_MSVC
-typedef __int64 int64;
-#else
-typedef long long int64;
-#endif /* COMPILER_MSVC */
-typedef int int32;
-typedef short int16;
-typedef char int8;
-
-#ifdef COMPILER_MSVC
typedef unsigned __int64 uint64;
typedef __int64 int64;
#ifndef INT64_C
@@ -61,7 +52,18 @@
#define UINT64_C(x) x ## UI64
#endif
#define INT64_F "I64"
-#else
+#else // COMPILER_MSVC
+#ifdef __LP64__
+typedef unsigned long uint64;
+typedef long int64;
+#ifndef INT64_C
+#define INT64_C(x) x ## L
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x ## UL
+#endif
+#define INT64_F "l"
+#else // __LP64__
typedef unsigned long long uint64;
typedef long long int64;
#ifndef INT64_C
@@ -71,10 +73,14 @@
#define UINT64_C(x) x ## ULL
#endif
#define INT64_F "ll"
-#endif /* COMPILER_MSVC */
+#endif // __LP64__
+#endif // COMPILER_MSVC
typedef unsigned int uint32;
+typedef int int32;
typedef unsigned short uint16;
+typedef short int16;
typedef unsigned char uint8;
+typedef char int8;
#endif // INT_TYPES_DEFINED
#ifdef WIN32
diff --git a/talk/base/common.h b/talk/base/common.h
index dc6106d..63de637 100644
--- a/talk/base/common.h
+++ b/talk/base/common.h
@@ -1,27 +1,27 @@
/*
* libjingle
- * Copyright 2004--2005, Google Inc.
+ * Copyright 2004 Google Inc.
*
- * Redistribution and use in source and binary forms, with or without
+ * 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,
+ * 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
+ * 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
+ * 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,
+ * 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
+ * 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.
*/
@@ -128,9 +128,11 @@
#define CTA_MAKE_NAME(line) CTA_MAKE_NAME2(line)
#define CTA_MAKE_NAME2(line) constraint_ ## line
-#ifdef __GNUC__
// Forces compiler to inline, even against its better judgement. Use wisely.
+#if defined(__GNUC__)
#define FORCE_INLINE __attribute__((always_inline))
+#elif defined(WIN32)
+#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE
#endif
diff --git a/talk/examples/call/call_main.cc b/talk/examples/call/call_main.cc
index 5af5474..b9f5696 100644
--- a/talk/examples/call/call_main.cc
+++ b/talk/examples/call/call_main.cc
@@ -212,6 +212,8 @@
std::vector<cricket::VideoCodec> video_codecs;
video_codecs.push_back(
cricket::VideoCodec(97, "H264", 320, 240, 30, 0));
+ video_codecs.push_back(
+ cricket::VideoCodec(99, "H264-SVC", 640, 360, 30, 0));
file_media_engine->set_video_codecs(video_codecs);
return file_media_engine;
diff --git a/talk/examples/call/callclient.cc b/talk/examples/call/callclient.cc
index c3a6490..3c65272 100644
--- a/talk/examples/call/callclient.cc
+++ b/talk/examples/call/callclient.cc
@@ -243,7 +243,7 @@
std::string to = GetWord(words, 1, "");
int bandwidth = GetInt(words, 2, cricket::kAutoBandwidth);
cricket::CallOptions options;
- options.is_video = true;
+ options.has_video = true;
options.video_bandwidth = bandwidth;
MakeCallTo(to, options);
} else if (command == "join") {
@@ -683,6 +683,7 @@
this, &CallClient::OnHangoutPublishRecordingError);
hangout_pubsub_client_->SignalRemoteMuteError.connect(
this, &CallClient::OnHangoutRemoteMuteError);
+ hangout_pubsub_client_->RequestAll();
}
}
diff --git a/talk/examples/call/presencepushtask.cc b/talk/examples/call/presencepushtask.cc
index 320b99c..fba3322 100644
--- a/talk/examples/call/presencepushtask.cc
+++ b/talk/examples/call/presencepushtask.cc
@@ -100,12 +100,13 @@
if (!stanza->HasAttr(QN_TYPE)) {
// We joined the MUC.
const XmlElement* elem = stanza->FirstNamed(QN_MUC_USER_X);
+ // Status code=110 or 100 is not guaranteed to be present, so we
+ // only check the item element and Muc join status.
if (elem) {
- elem = elem->FirstNamed(QN_MUC_USER_STATUS);
- }
- if (elem && (elem->Attr(QN_CODE) == "110" ||
- elem->Attr(QN_CODE) == "100")) {
- SignalMucJoined(muc->jid());
+ if (elem->FirstNamed(QN_MUC_USER_ITEM) &&
+ muc->state() == buzz::Muc::MUC_JOINING) {
+ SignalMucJoined(muc->jid());
+ }
}
} else {
// We've been kicked. Bye.
diff --git a/talk/main.scons b/talk/main.scons
index ae71b1d..b7d1c1c 100644
--- a/talk/main.scons
+++ b/talk/main.scons
@@ -69,10 +69,21 @@
# This is where we set common environments
#
-# Detect if running on 64 bit or 32 bit host.
-DeclareBit('platform_arch_64bit', 'Host Platform is 64 Bit')
+# Detect if building on 64-bit or 32-bit platform.
+DeclareBit('build_platform_64bit', 'Platform of the build machine is 64-bit')
if platform.architecture()[0] == "64bit":
- root_env.SetBits('platform_arch_64bit')
+ root_env.SetBits('build_platform_64bit')
+
+# This bit denotes that an env is for pure 64-bit builds. When set, all build
+# artifacts will be 64-bit. When unset, we will still produce some 64-bit
+# artifacts on 64-bit Linux via the legacy also64bit setting on our targets.
+# When the pure 64-bit build is considered stable, the also64bit setting will go
+# away.
+DeclareBit('host_platform_64bit', 'Platform of the host machine (where artifacts will execute) is 64-bit')
+
+def same_arch(env):
+ """Whether the host machine and build machine architectures match."""
+ return env.Bit('host_platform_64bit') == env.Bit('build_platform_64bit')
DeclareBit('use_static_openssl', 'Build OpenSSL as a static library')
@@ -297,13 +308,14 @@
mac_env.Append(
CPPDEFINES = [
'OSX',
- 'MAC_OS_X_VERSION_MIN_REQUIRED=1040',
],
CCFLAGS = [
'-m32',
'-arch', 'i386',
- '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk',
+ '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk',
'-fasm-blocks',
+ # Generate debugging info in the DWARF2 format.
+ '-gdwarf-2',
],
LINKFLAGS = [
'-Wl,-search_paths_first',
@@ -314,9 +326,10 @@
'-ObjC',
'-arch', 'i386',
'-mmacosx-version-min=10.5',
- '-isysroot', '/Developer/SDKs/MacOSX10.6.sdk',
+ '-isysroot', '/Developer/SDKs/MacOSX10.5.sdk',
'-m32',
'-dead-strip'
+ '-gdwarf-2',
],
FRAMEWORKS = [
'CoreServices',
@@ -409,53 +422,85 @@
'HAVE_DBUS_GLIB',
'dbus-glib-1')
+def linux_common_include_x86_32(env):
+ """Include x86-32 settings into an env based on linux_common."""
+ env.Append(
+ CCFLAGS = [
+ '-m32',
+ ],
+ LINKFLAGS = [
+ '-m32',
+ ],
+ )
+
+def linux_common_include_x86_64(env):
+ """Include x86-64 settings into an env based on linux_common."""
+ env.Append(
+ CCFLAGS = [
+ '-m64',
+ '-fPIC',
+ ],
+ LINKFLAGS = [
+ '-m64',
+ ],
+ )
+ env.SetBits('host_platform_64bit')
+
#-------------------------------------------------------------------------------
-# L I N U X -- T R A D I T I O N A L
+# L I N U X -- T R A D I T I O N A L -- X 8 6
#
-# Settings that are specific to our desktop Linux targets.
-linux_env = linux_common_env.Clone()
-# OpenSSL has infamously poor ABI stability, so that building against one
-# version and running against a different one often will not work. Since our
-# non-ChromeOS Linux builds are used on many different distros and distro
-# versions, this means we can't safely dynamically link to OpenSSL because the
-# product would end up being broken on any computer with a different version
-# installed. So instead we build it ourself and statically link to it.
-linux_env.SetBits('use_static_openssl')
-# Enable the optional PulseAudio code if the build machine has the required
-# dependency. (Not doing this for linux_common_env because we don't want
-# PulseAudio used on ChromeOS.)
-linux_env.EnableFeatureWherePackagePresent('have_libpulse',
- 'HAVE_LIBPULSE',
- 'libpulse')
-linux_env.Append(
- CCFLAGS = [
- '-m32',
- ],
- LINKFLAGS = [
- '-m32',
- ],
-)
+# Settings that are specific to our desktop Linux x86 targets.
+linux_x86_32_env = linux_common_env.Clone()
+linux_common_include_x86_32(linux_x86_32_env)
-linux_dbg_env = linux_env.Clone(
- BUILD_TYPE = 'dbg',
- BUILD_TYPE_DESCRIPTION = 'Linux debug build',
- BUILD_GROUPS = ['default', 'all'],
- tools = ['target_debug'],
-)
-# Remove -g set by hammer, which is not what we want (we have set -g3 above).
-linux_dbg_env.FilterOut(CCFLAGS = ['-g'])
-envs.append(linux_dbg_env)
+linux_x86_64_env = linux_common_env.Clone()
+linux_common_include_x86_64(linux_x86_64_env)
-linux_opt_env = linux_env.Clone(
- BUILD_TYPE = 'opt',
- BUILD_TYPE_DESCRIPTION = 'Linux optimized build',
- BUILD_GROUPS = ['all'],
- tools = ['target_optimized'],
-)
-# Remove -O2 set by hammer, which is not what we want.
-linux_opt_env.FilterOut(CCFLAGS = ['-O2'])
-linux_opt_env.Append(CCFLAGS = ['-Os'])
-envs.append(linux_opt_env)
+def gen_linux_x86(base_env, type_suffix, desc_suffix):
+ linux_env = base_env.Clone()
+ # OpenSSL has infamously poor ABI stability, so that building against one
+ # version and running against a different one often will not work. Since our
+ # non-ChromeOS Linux builds are used on many different distros and distro
+ # versions, this means we can't safely dynamically link to OpenSSL because the
+ # product would end up being broken on any computer with a different version
+ # installed. So instead we build it ourself and statically link to it.
+ linux_env.SetBits('use_static_openssl')
+ # Enable the optional PulseAudio code if the build machine has the required
+ # dependency. (Not doing this for linux_common_env because we don't want
+ # PulseAudio used on ChromeOS.)
+ linux_env.EnableFeatureWherePackagePresent('have_libpulse',
+ 'HAVE_LIBPULSE',
+ 'libpulse')
+ # Until the pure 64-bit build has had time to bake, we leave the funky mixed
+ # 32/64 build as the default.
+ #if same_arch(linux_env):
+ if not linux_env.Bit('host_platform_64bit'):
+ dbg_groups = ['default', 'all']
+ else:
+ dbg_groups = ['all']
+ linux_dbg_env = linux_env.Clone(
+ BUILD_TYPE = 'dbg' + type_suffix,
+ BUILD_TYPE_DESCRIPTION = 'Linux debug build' + desc_suffix,
+ BUILD_GROUPS = dbg_groups,
+ tools = ['target_debug'],
+ )
+ # Remove -g set by hammer, which is not what we want (we have set -g3 above).
+ linux_dbg_env.FilterOut(CCFLAGS = ['-g'])
+ envs.append(linux_dbg_env)
+
+ linux_opt_env = linux_env.Clone(
+ BUILD_TYPE = 'opt' + type_suffix,
+ BUILD_TYPE_DESCRIPTION = 'Linux optimized build' + desc_suffix,
+ BUILD_GROUPS = ['all'],
+ tools = ['target_optimized'],
+ )
+ # Remove -O2 set by hammer, which is not what we want.
+ linux_opt_env.FilterOut(CCFLAGS = ['-O2'])
+ linux_opt_env.Append(CCFLAGS = ['-Os'])
+ envs.append(linux_opt_env)
+
+gen_linux_x86(linux_x86_32_env, '', '')
+gen_linux_x86(linux_x86_64_env, '64', ' (64-bit)')
diff --git a/talk/p2p/base/session.cc b/talk/p2p/base/session.cc
index ef6737a..b5be361 100644
--- a/talk/p2p/base/session.cc
+++ b/talk/p2p/base/session.cc
@@ -1001,11 +1001,10 @@
bool Session::SendRejectMessage(const std::string& reason,
SessionError* error) {
- XmlElements elems;
- return SendMessage(ACTION_SESSION_REJECT, elems, error);
+ SessionTerminate term(reason);
+ return SendMessage(ACTION_SESSION_REJECT, term, error);
}
-
bool Session::SendTerminateMessage(const std::string& reason,
SessionError* error) {
SessionTerminate term(reason);
diff --git a/talk/session/phone/channel.cc b/talk/session/phone/channel.cc
index f41c2ad..9cc88ff 100644
--- a/talk/session/phone/channel.cc
+++ b/talk/session/phone/channel.cc
@@ -75,14 +75,14 @@
BaseChannel::BaseChannel(talk_base::Thread* thread,
MediaEngineInterface* media_engine,
MediaChannel* media_channel, BaseSession* session,
- const std::string& content_name,
- TransportChannel* transport_channel)
+ const std::string& content_name, bool rtcp)
: worker_thread_(thread),
media_engine_(media_engine),
session_(session),
media_channel_(media_channel),
content_name_(content_name),
- transport_channel_(transport_channel),
+ rtcp_(rtcp),
+ transport_channel_(NULL),
rtcp_transport_channel_(NULL),
enabled_(false),
writable_(false),
@@ -91,17 +91,7 @@
has_remote_content_(false),
muted_(false) {
ASSERT(worker_thread_ == talk_base::Thread::Current());
- media_channel_->SetInterface(this);
- transport_channel_->SignalWritableState.connect(
- this, &BaseChannel::OnWritableState);
- transport_channel_->SignalReadPacket.connect(
- this, &BaseChannel::OnChannelRead);
-
LOG(LS_INFO) << "Created channel";
-
- session->SignalState.connect(this, &BaseChannel::OnSessionState);
- session->SignalRemoteDescriptionUpdate.connect(this,
- &BaseChannel::OnRemoteDescriptionUpdate);
}
BaseChannel::~BaseChannel() {
@@ -119,6 +109,30 @@
LOG(LS_INFO) << "Destroyed channel";
}
+bool BaseChannel::Init(TransportChannel* transport_channel,
+ TransportChannel* rtcp_transport_channel) {
+ if (transport_channel == NULL) {
+ return false;
+ }
+ if (rtcp() && rtcp_transport_channel == NULL) {
+ return false;
+ }
+ transport_channel_ = transport_channel;
+ media_channel_->SetInterface(this);
+ transport_channel_->SignalWritableState.connect(
+ this, &BaseChannel::OnWritableState);
+ transport_channel_->SignalReadPacket.connect(
+ this, &BaseChannel::OnChannelRead);
+
+ session_->SignalState.connect(this, &BaseChannel::OnSessionState);
+ session_->SignalRemoteDescriptionUpdate.connect(this,
+ &BaseChannel::OnRemoteDescriptionUpdate);
+
+ OnSessionState(session(), session()->state());
+ set_rtcp_transport_channel(rtcp_transport_channel);
+ return true;
+}
+
bool BaseChannel::Enable(bool enable) {
// Can be called from thread other than worker thread
Send(enable ? MSG_ENABLE : MSG_DISABLE);
@@ -626,19 +640,8 @@
const std::string& content_name,
bool rtcp)
: BaseChannel(thread, media_engine, media_channel, session, content_name,
- session->CreateChannel(content_name, "rtp")),
+ rtcp),
received_media_(false) {
- if (rtcp) {
- set_rtcp_transport_channel(session->CreateChannel(content_name, "rtcp"));
- }
- // Can't go in BaseChannel because certain session states will
- // trigger pure virtual functions, such as GetFirstContent().
- OnSessionState(session, session->state());
-
- media_channel->SignalMediaError.connect(
- this, &VoiceChannel::OnVoiceChannelError);
- srtp_filter()->SignalSrtpError.connect(
- this, &VoiceChannel::OnSrtpError);
}
VoiceChannel::~VoiceChannel() {
@@ -648,6 +651,20 @@
DisableMedia_w();
}
+bool VoiceChannel::Init() {
+ TransportChannel* rtcp_channel = rtcp() ?
+ session()->CreateChannel(content_name(), "rtcp") : NULL;
+ if (!BaseChannel::Init(session()->CreateChannel(content_name(), "rtp"),
+ rtcp_channel)) {
+ return false;
+ }
+ media_channel()->SignalMediaError.connect(
+ this, &VoiceChannel::OnVoiceChannelError);
+ srtp_filter()->SignalSrtpError.connect(
+ this, &VoiceChannel::OnSrtpError);
+ return true;
+}
+
bool VoiceChannel::AddStream(uint32 ssrc) {
StreamMessageData data(ssrc, 0);
Send(MSG_ADDSTREAM, &data);
@@ -1007,20 +1024,23 @@
bool rtcp,
VoiceChannel* voice_channel)
: BaseChannel(thread, media_engine, media_channel, session, content_name,
- session->CreateChannel(content_name, "video_rtp")),
+ rtcp),
voice_channel_(voice_channel), renderer_(NULL) {
- if (rtcp) {
- set_rtcp_transport_channel(
- session->CreateChannel(content_name, "video_rtcp"));
- }
- // Can't go in BaseChannel because certain session states will
- // trigger pure virtual functions, such as GetFirstContent()
- OnSessionState(session, session->state());
+}
- media_channel->SignalMediaError.connect(
+bool VideoChannel::Init() {
+ TransportChannel* rtcp_channel = rtcp() ?
+ session()->CreateChannel(content_name(), "video_rtcp") : NULL;
+ if (!BaseChannel::Init(
+ session()->CreateChannel(content_name(), "video_rtp"),
+ rtcp_channel)) {
+ return false;
+ }
+ media_channel()->SignalMediaError.connect(
this, &VideoChannel::OnVideoChannelError);
srtp_filter()->SignalSrtpError.connect(
this, &VideoChannel::OnSrtpError);
+ return true;
}
void VoiceChannel::SendLastMediaError() {
diff --git a/talk/session/phone/channel.h b/talk/session/phone/channel.h
index a35ed86..324c35c 100644
--- a/talk/session/phone/channel.h
+++ b/talk/session/phone/channel.h
@@ -84,9 +84,10 @@
public:
BaseChannel(talk_base::Thread* thread, MediaEngineInterface* media_engine,
MediaChannel* channel, BaseSession* session,
- const std::string& content_name,
- TransportChannel* transport_channel);
+ const std::string& content_name, bool rtcp);
virtual ~BaseChannel();
+ bool Init(TransportChannel* transport_channel,
+ TransportChannel* rtcp_transport_channel);
talk_base::Thread* worker_thread() const { return worker_thread_; }
BaseSession* session() const { return session_; }
@@ -171,6 +172,7 @@
bool muted() const { return muted_; }
talk_base::Thread* signaling_thread() { return session_->signaling_thread(); }
SrtpFilter* srtp_filter() { return &srtp_filter_; }
+ bool rtcp() const { return rtcp_; }
void Send(uint32 id, talk_base::MessageData *pdata = NULL);
void Post(uint32 id, talk_base::MessageData *pdata = NULL);
@@ -270,6 +272,7 @@
MediaChannel *media_channel_;
std::string content_name_;
+ bool rtcp_;
TransportChannel *transport_channel_;
TransportChannel *rtcp_transport_channel_;
SrtpFilter srtp_filter_;
@@ -291,6 +294,7 @@
VoiceMediaChannel *channel, BaseSession *session,
const std::string& content_name, bool rtcp);
~VoiceChannel();
+ bool Init();
// downcasts a MediaChannel
virtual VoiceMediaChannel* media_channel() const {
@@ -423,6 +427,7 @@
const std::string& content_name, bool rtcp,
VoiceChannel *voice_channel);
~VideoChannel();
+ bool Init();
// downcasts a MediaChannel
virtual VideoMediaChannel* media_channel() const {
diff --git a/talk/session/phone/channelmanager.cc b/talk/session/phone/channelmanager.cc
index 98b8ded..8f8a0fc 100644
--- a/talk/session/phone/channelmanager.cc
+++ b/talk/session/phone/channelmanager.cc
@@ -313,6 +313,10 @@
VoiceChannel* voice_channel = new VoiceChannel(
worker_thread_, media_engine_.get(), media_channel,
session, content_name, rtcp);
+ if (!voice_channel->Init()) {
+ delete voice_channel;
+ return NULL;
+ }
voice_channels_.push_back(voice_channel);
return voice_channel;
}
@@ -362,6 +366,10 @@
VideoChannel* video_channel = new VideoChannel(
worker_thread_, media_engine_.get(), media_channel,
session, content_name, rtcp, voice_channel);
+ if (!video_channel->Init()) {
+ delete video_channel;
+ return NULL;
+ }
video_channels_.push_back(video_channel);
return video_channel;
}
diff --git a/talk/session/phone/devicemanager.cc b/talk/session/phone/devicemanager.cc
index a464dd1..6188461 100644
--- a/talk/session/phone/devicemanager.cc
+++ b/talk/session/phone/devicemanager.cc
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2008, Google Inc.
+ * 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:
@@ -35,6 +35,7 @@
#include <ksmedia.h>
#define INITGUID // For PKEY_AudioEndpoint_GUID
#include <mmdeviceapi.h>
+#include <mmsystem.h>
#include <functiondiscoverykeys_devpkey.h>
#include <uuids.h>
#include "talk/base/win32.h" // ToUtf8
@@ -52,10 +53,12 @@
#include "talk/base/stream.h"
#include "talk/session/phone/libudevsymboltable.h"
#include "talk/session/phone/v4llookup.h"
+#if !defined(NO_SOUND_SYSTEM)
#include "talk/sound/platformsoundsystem.h"
#include "talk/sound/platformsoundsystemfactory.h"
#include "talk/sound/sounddevicelocator.h"
#include "talk/sound/soundsysteminterface.h"
+#endif // !defined(NO_SOUND_SYSTEM)
#endif
#include "talk/base/logging.h"
@@ -153,7 +156,7 @@
need_couninitialize_(false),
#endif
watcher_(new DeviceWatcher(this))
-#ifdef LINUX
+#if defined(LINUX) && !defined(NO_SOUND_SYSTEM)
, sound_system_(new PlatformSoundSystemFactory())
#endif
{
@@ -330,7 +333,7 @@
std::vector<Device>* devs) {
devs->clear();
-#if defined(LINUX)
+#if defined(LINUX) && !defined(NO_SOUND_SYSTEM)
if (!sound_system_.get()) {
return false;
}
@@ -519,7 +522,7 @@
}
}
- if (!SUCCEEDED(hr)) {
+ if (FAILED(hr)) {
LOG(LS_WARNING) << "GetCoreAudioDevices failed with hr " << hr;
return false;
}
diff --git a/talk/session/phone/devicemanager.h b/talk/session/phone/devicemanager.h
index 38776fa..d846ee5 100644
--- a/talk/session/phone/devicemanager.h
+++ b/talk/session/phone/devicemanager.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2008, Google Inc.
+ * 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:
@@ -33,7 +33,17 @@
#include "talk/base/sigslot.h"
#include "talk/base/stringencode.h"
-#ifdef LINUX
+
+#ifdef BUILD_WITH_CHROMIUM
+// The SoundSystem related code refers to some definitions that are not
+// available in chromium. (LS_VERBOSE, DISALLOW_ASSIGN etc.)
+// For now, disable the sound system code from devicemanager.h/cc.
+// TODO: Split the DeviceManager implemenations out of
+// devicemanager.h/cc so that we can exclude the DeviceManager impls from
+// libjingle build when they are not needed.
+#define NO_SOUND_SYSTEM
+#endif
+#if defined(LINUX) && !defined(NO_SOUND_SYSTEM)
#include "talk/sound/soundsystemfactory.h"
#endif
@@ -128,7 +138,7 @@
bool need_couninitialize_;
#endif
DeviceWatcher* watcher_;
-#ifdef LINUX
+#if defined(LINUX) && !defined(NO_SOUND_SYSTEM)
SoundSystemHandle sound_system_;
#endif
};
diff --git a/talk/session/phone/filemediaengine.cc b/talk/session/phone/filemediaengine.cc
index f7a0461..2a7b8d8 100644
--- a/talk/session/phone/filemediaengine.cc
+++ b/talk/session/phone/filemediaengine.cc
@@ -127,6 +127,7 @@
// Called by media channel. Context: media channel thread.
bool SetSend(bool send);
+ void SetSendSsrc(uint32 ssrc);
void OnPacketReceived(talk_base::Buffer* packet);
// Override virtual method of parent MessageHandler. Context: Worker Thread.
@@ -191,6 +192,12 @@
return true;
}
+void RtpSenderReceiver::SetSendSsrc(uint32 ssrc) {
+ if (rtp_dump_reader_.get()) {
+ rtp_dump_reader_->SetSsrc(ssrc);
+ }
+}
+
void RtpSenderReceiver::OnPacketReceived(talk_base::Buffer* packet) {
if (rtp_dump_writer_.get()) {
rtp_dump_writer_->WriteRtpPacket(packet->data(), packet->length());
@@ -265,6 +272,10 @@
return rtp_sender_receiver_->SetSend(flag != SEND_NOTHING);
}
+void FileVoiceChannel::SetSendSsrc(uint32 ssrc) {
+ rtp_sender_receiver_->SetSendSsrc(ssrc);
+}
+
void FileVoiceChannel::OnPacketReceived(talk_base::Buffer* packet) {
rtp_sender_receiver_->OnPacketReceived(packet);
}
@@ -289,6 +300,10 @@
return rtp_sender_receiver_->SetSend(send);
}
+void FileVideoChannel::SetSendSsrc(uint32 ssrc) {
+ rtp_sender_receiver_->SetSendSsrc(ssrc);
+}
+
void FileVideoChannel::OnPacketReceived(talk_base::Buffer* packet) {
rtp_sender_receiver_->OnPacketReceived(packet);
}
diff --git a/talk/session/phone/filemediaengine.h b/talk/session/phone/filemediaengine.h
index 18f62ca..b20e0f2 100644
--- a/talk/session/phone/filemediaengine.h
+++ b/talk/session/phone/filemediaengine.h
@@ -165,7 +165,7 @@
// Implement pure virtual methods of MediaChannel.
virtual void OnPacketReceived(talk_base::Buffer* packet);
virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
- virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
+ virtual void SetSendSsrc(uint32 ssrc);
virtual bool SetRtcpCName(const std::string& cname) { return true; }
virtual bool Mute(bool on) { return false; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
@@ -209,7 +209,7 @@
// Implement pure virtual methods of MediaChannel.
virtual void OnPacketReceived(talk_base::Buffer* packet);
virtual void OnRtcpReceived(talk_base::Buffer* packet) {}
- virtual void SetSendSsrc(uint32 id) {} // TODO: change RTP packet?
+ virtual void SetSendSsrc(uint32 ssrc);
virtual bool SetRtcpCName(const std::string& cname) { return true; }
virtual bool Mute(bool on) { return false; }
virtual bool SetSendBandwidth(bool autobw, int bps) { return true; }
diff --git a/talk/session/phone/mediasession.cc b/talk/session/phone/mediasession.cc
index 8102d2a..b423708 100644
--- a/talk/session/phone/mediasession.cc
+++ b/talk/session/phone/mediasession.cc
@@ -117,7 +117,7 @@
const MediaSessionOptions& options) {
SessionDescription* offer = new SessionDescription();
- if (true) { // TODO: Allow audio to be optional
+ if (options.has_audio) {
AudioContentDescription* audio = new AudioContentDescription();
for (AudioCodecs::const_iterator codec = audio_codecs_.begin();
codec != audio_codecs_.end(); ++codec) {
@@ -148,7 +148,7 @@
}
// add video codecs, if this is a video call
- if (options.is_video) {
+ if (options.has_video) {
VideoContentDescription* video = new VideoContentDescription();
for (VideoCodecs::const_iterator codec = video_codecs_.begin();
codec != video_codecs_.end(); ++codec) {
@@ -190,7 +190,7 @@
SessionDescription* accept = new SessionDescription();
const ContentInfo* audio_content = GetFirstAudioContent(offer);
- if (audio_content) {
+ if (audio_content && options.has_audio) {
const AudioContentDescription* audio_offer =
static_cast<const AudioContentDescription*>(audio_content->description);
AudioContentDescription* audio_accept = new AudioContentDescription();
@@ -223,10 +223,12 @@
return NULL; // Fails the session setup.
}
accept->AddContent(audio_content->name, audio_content->type, audio_accept);
+ } else {
+ LOG(LS_INFO) << "Audio is not supported in answer";
}
const ContentInfo* video_content = GetFirstVideoContent(offer);
- if (video_content && options.is_video) {
+ if (video_content && options.has_video) {
const VideoContentDescription* video_offer =
static_cast<const VideoContentDescription*>(video_content->description);
VideoContentDescription* video_accept = new VideoContentDescription();
@@ -260,6 +262,8 @@
return NULL; // Fails the session setup.
}
accept->AddContent(video_content->name, video_content->type, video_accept);
+ } else {
+ LOG(LS_INFO) << "Video is not supported in answer";
}
return accept;
diff --git a/talk/session/phone/mediasession.h b/talk/session/phone/mediasession.h
index 9bfd84f..4e2a8fb 100644
--- a/talk/session/phone/mediasession.h
+++ b/talk/session/phone/mediasession.h
@@ -68,12 +68,14 @@
const int kAutoBandwidth = -1;
struct MediaSessionOptions {
MediaSessionOptions() :
- is_video(false),
+ has_audio(true), // Audio enabled by default.
+ has_video(false),
is_muc(false),
video_bandwidth(kAutoBandwidth) {
}
- bool is_video;
+ bool has_audio;
+ bool has_video;
bool is_muc;
// bps. -1 == auto.
int video_bandwidth;
diff --git a/talk/session/phone/rtpdump.cc b/talk/session/phone/rtpdump.cc
index 65381fd..50ebd2a 100644
--- a/talk/session/phone/rtpdump.cc
+++ b/talk/session/phone/rtpdump.cc
@@ -27,10 +27,10 @@
#include "talk/session/phone/rtpdump.h"
-#include <string>
#include <ctype.h>
-#include "talk/base/bytebuffer.h"
+#include <string>
+
#include "talk/base/byteorder.h"
#include "talk/base/logging.h"
#include "talk/base/time.h"
@@ -38,6 +38,8 @@
namespace cricket {
+static const int kRtpSsrcOffset = 8;
+
const char RtpDumpFileHeader::kFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n";
RtpDumpFileHeader::RtpDumpFileHeader(uint32 start_ms, uint32 s, uint16 p)
@@ -99,6 +101,12 @@
///////////////////////////////////////////////////////////////////////////
// Implementation of RtpDumpReader.
///////////////////////////////////////////////////////////////////////////
+void RtpDumpReader::SetSsrc(uint32 ssrc) {
+ // Convert ssrc to network endian for RTP packet.
+ ssrc_buffer_.Consume(ssrc_buffer_.Length());
+ ssrc_buffer_.WriteUInt32(ssrc);
+}
+
talk_base::StreamResult RtpDumpReader::ReadPacket(RtpDumpPacket* packet) {
if (!packet) return talk_base::SR_ERROR;
@@ -128,7 +136,17 @@
packet->data.resize(dump_packet_len - sizeof(header));
// Read the actual RTP or RTCP packet.
- return stream_->ReadAll(&packet->data[0], packet->data.size(), NULL, NULL);
+ res = stream_->ReadAll(&packet->data[0], packet->data.size(), NULL, NULL);
+ // If the packet is RTP and we have specified a ssrc, replace the RTP ssrc
+ // with the specified ssrc.
+ if (res == talk_base::SR_SUCCESS &&
+ packet->IsValidRtpPacket() &&
+ ssrc_buffer_.Length() == sizeof(uint32)) {
+ memcpy(&packet->data[kRtpSsrcOffset], ssrc_buffer_.Data(),
+ ssrc_buffer_.Length());
+ }
+
+ return res;
}
talk_base::StreamResult RtpDumpReader::ReadFileHeader() {
diff --git a/talk/session/phone/rtpdump.h b/talk/session/phone/rtpdump.h
index 57138b8..b120f12 100644
--- a/talk/session/phone/rtpdump.h
+++ b/talk/session/phone/rtpdump.h
@@ -33,12 +33,9 @@
#include <vector>
#include "talk/base/basictypes.h"
+#include "talk/base/bytebuffer.h"
#include "talk/base/stream.h"
-namespace talk_base {
-class ByteBuffer;
-}
-
namespace cricket {
// We use the RTP dump file format compatible to the format used by rtptools
@@ -109,6 +106,8 @@
}
virtual ~RtpDumpReader() {}
+ // Use the specified ssrc, rather than the ssrc from dump, for RTP packets.
+ void SetSsrc(uint32 ssrc);
virtual talk_base::StreamResult ReadPacket(RtpDumpPacket* packet);
protected:
@@ -125,6 +124,8 @@
bool file_header_read_;
size_t first_line_and_file_header_len_;
uint32 start_time_ms_;
+ talk_base::ByteBuffer ssrc_buffer_;
+
DISALLOW_COPY_AND_ASSIGN(RtpDumpReader);
};
diff --git a/talk/session/phone/videoframe.h b/talk/session/phone/videoframe.h
index 3fa533e..6f331d1 100644
--- a/talk/session/phone/videoframe.h
+++ b/talk/session/phone/videoframe.h
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004, Google Inc.
+ * Copyright 2004--2011, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -36,6 +36,14 @@
namespace cricket {
+// Simple rotation constants.
+enum {
+ ROTATION_0 = 0,
+ ROTATION_90 = 90,
+ ROTATION_180 = 180,
+ ROTATION_270 = 270
+};
+
// Represents a YUV420 (a.k.a. I420) video frame.
class VideoFrame {
friend class flute::MagicCamVideoRenderer;
@@ -71,6 +79,9 @@
virtual void SetElapsedTime(int64 elapsed_time) = 0;
virtual void SetTimeStamp(int64 time_stamp) = 0;
+ // Indicates the rotation angle in degrees.
+ virtual int GetRotation() const = 0;
+
// Make a shallow copy of the frame. The frame buffer itself is not copied.
// Both the current and new VideoFrame will share a single reference-counted
// frame buffer.
diff --git a/talk/session/phone/webrtcvideoengine.cc b/talk/session/phone/webrtcvideoengine.cc
index a65c264..d0d71ad 100644
--- a/talk/session/phone/webrtcvideoengine.cc
+++ b/talk/session/phone/webrtcvideoengine.cc
@@ -46,6 +46,7 @@
static const int kDefaultLogSeverity = talk_base::LS_WARNING;
static const int kStartVideoBitrate = 300;
static const int kMaxVideoBitrate = 1000;
+static const int kVideoRtpBufferSize = 65536;
class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
public:
@@ -67,7 +68,8 @@
if (renderer_ == NULL)
return 0;
WebRtcVideoFrame video_frame;
- video_frame.Attach(buffer, buffer_size, width_, height_, 0, time_stamp);
+ video_frame.Attach(buffer, buffer_size, width_, height_,
+ 1, 1, 0, time_stamp, 0);
int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1;
uint8* buffer_temp;
size_t buffer_size_temp;
@@ -129,6 +131,7 @@
initialized_ = false;
capture_id_ = -1;
capture_module_ = NULL;
+ external_capture_ = false;
log_level_ = kDefaultLogSeverity;
capture_started_ = false;
render_module_.reset(new WebRtcPassthroughRender());
@@ -158,7 +161,7 @@
Terminate();
vie_wrapper_.reset();
if (capture_module_) {
- webrtc::VideoCaptureModule::Destroy(capture_module_);
+ capture_module_->Release();
}
}
@@ -196,7 +199,7 @@
}
if (vie_wrapper_->render()->RegisterVideoRenderModule(
- *render_module_.get()) != 0) {
+ *render_module_.get()) != 0) {
LOG_RTCERR0(RegisterVideoRenderModule);
return false;
}
@@ -298,7 +301,7 @@
}
if (vie_wrapper_->render()->DeRegisterVideoRenderModule(
- *render_module_.get()) != 0)
+ *render_module_.get()) != 0)
LOG_RTCERR0(DeRegisterVideoRenderModule);
if ((vie_wrapper_->base()->DeregisterObserver()) != 0)
@@ -358,8 +361,9 @@
char device_name[256], device_id[256];
bool found = false;
for (int i = 0; i < vie_capture->NumberOfCaptureDevices(); ++i) {
- if (vie_capture->GetCaptureDevice(i, device_name, sizeof(device_name),
- device_id, sizeof(device_id)) == 0) {
+ if (vie_capture->GetCaptureDevice(i, device_name, ARRAY_SIZE(device_name),
+ device_id,
+ ARRAY_SIZE(device_id)) == 0) {
// TODO: We should only compare the device_id here,
// however the devicemanager and webrtc use different format for th v4l2
// device id. So here we also compare the device_name for now.
@@ -397,6 +401,8 @@
if (vie_capture->ConnectCaptureDevice(capture_id_,
channel->video_channel()) == 0) {
channel->set_connected(true);
+ } else {
+ LOG(LS_WARNING) << "SetCaptureDevice failed to ConnectCaptureDevice.";
}
}
SetCapture(true);
@@ -408,10 +414,18 @@
bool WebRtcVideoEngine::SetCaptureModule(webrtc::VideoCaptureModule* vcm) {
ReleaseCaptureDevice();
if (capture_module_) {
- webrtc::VideoCaptureModule::Destroy(capture_module_);
+ capture_module_->Release();
+ capture_module_ = NULL;
}
- capture_module_ = vcm;
- external_capture_ = true;
+
+ if (vcm) {
+ capture_module_ = vcm;
+ capture_module_->AddRef();
+ external_capture_ = true;
+ } else {
+ external_capture_ = false;
+ }
+
return true;
}
@@ -487,7 +501,8 @@
bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) {
for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
const VideoFormat& fmt = kVideoFormats[i];
- if (fmt.width == in.width && fmt.height == in.height) {
+ if ((in.width == 0 && in.height == 0) ||
+ (fmt.width == in.width && fmt.height == in.height)) {
for (int j = 0; j < ARRAY_SIZE(kVideoCodecPrefs); ++j) {
VideoCodec codec(kVideoCodecPrefs[j].payload_type,
kVideoCodecPrefs[j].name, 0, 0, 0, 0);
@@ -762,7 +777,7 @@
// connect it now.
if (!connected()) {
if (engine()->video_engine()->capture()->ConnectCaptureDevice(
- engine()->capture_id(), vie_channel_) != 0) {
+ engine()->capture_id(), vie_channel_) != 0) {
LOG_RTCERR2(ConnectCaptureDevice, engine()->capture_id(), vie_channel_);
ret = false;
} else {
@@ -969,6 +984,19 @@
return true;
}
+void WebRtcVideoMediaChannel::SetInterface(NetworkInterface* iface) {
+ MediaChannel::SetInterface(iface);
+ // Set the RTP recv/send buffer to a bigger size
+ if (network_interface_) {
+ network_interface_->SetOption(NetworkInterface::ST_RTP,
+ talk_base::Socket::OPT_RCVBUF,
+ kVideoRtpBufferSize);
+ network_interface_->SetOption(NetworkInterface::ST_RTP,
+ talk_base::Socket::OPT_SNDBUF,
+ kVideoRtpBufferSize);
+ }
+}
+
void WebRtcVideoMediaChannel::EnableRtcp() {
engine()->video_engine()->rtp()->SetRTCPStatus(
vie_channel_, webrtc::kRtcpCompound_RFC4585);
diff --git a/talk/session/phone/webrtcvideoengine.h b/talk/session/phone/webrtcvideoengine.h
index bb6b9c8..ffb6e7d 100644
--- a/talk/session/phone/webrtcvideoengine.h
+++ b/talk/session/phone/webrtcvideoengine.h
@@ -182,6 +182,7 @@
}
virtual bool SetSendBandwidth(bool autobw, int bps);
virtual bool SetOptions(int options);
+ virtual void SetInterface(NetworkInterface* iface);
WebRtcVideoEngine* engine() const { return engine_; }
VoiceMediaChannel* voice_channel() const { return voice_channel_; }
diff --git a/talk/session/phone/webrtcvideoengine_unittest.cc b/talk/session/phone/webrtcvideoengine_unittest.cc
index 8e985d7..ee42729 100644
--- a/talk/session/phone/webrtcvideoengine_unittest.cc
+++ b/talk/session/phone/webrtcvideoengine_unittest.cc
@@ -29,6 +29,33 @@
}
};
+class FakeNetworkInterface : public cricket::MediaChannel::NetworkInterface {
+ public:
+ FakeNetworkInterface()
+ : recv_buffer_size_(0),
+ send_buffer_size_(0) {
+ }
+ virtual bool SendPacket(talk_base::Buffer* packet) {
+ return true;
+ }
+ virtual bool SendRtcp(talk_base::Buffer* packet) {
+ return true;
+ }
+ virtual int SetOption(SocketType type, talk_base::Socket::Option opt,
+ int option) {
+ if (type == ST_RTP) {
+ if (opt == talk_base::Socket::OPT_RCVBUF)
+ recv_buffer_size_ = option;
+ else if (opt == talk_base::Socket::OPT_SNDBUF)
+ send_buffer_size_ = option;
+ }
+ return 0;
+ }
+ virtual ~FakeNetworkInterface() {}
+ int recv_buffer_size_;
+ int send_buffer_size_;
+};
+
class WebRtcVideoEngineTest : public testing::Test {
public:
class ChannelErrorListener : public sigslot::has_slots<> {
@@ -135,6 +162,11 @@
cricket::VideoCodec vp8_diff_res(104, "VP8", 320, 111, 30, 0);
EXPECT_FALSE(engine_.FindCodec(vp8_diff_res));
+
+ // PeerConnection doesn't negotiate the resolution at this point.
+ // Test that FindCodec can handle the case when width/height is 0.
+ cricket::VideoCodec vp8_zero_res(104, "VP8", 0, 0, 30, 0);
+ EXPECT_TRUE(engine_.FindCodec(vp8_zero_res));
}
// Test that we set our inbound codecs properly
@@ -160,6 +192,16 @@
EXPECT_STREQ(kVP8Codec.name.c_str(), gcodec.plName);
}
+// Tests that the rtp buffer is set properly after the SetInterface call.
+TEST_F(WebRtcVideoEngineTest, SetRtpBufferSize) {
+ EXPECT_TRUE(SetupEngine());
+ const int kExpectedVideoRtpBufferSize = 65536;
+ FakeNetworkInterface network_interface;
+ channel_->SetInterface(&network_interface);
+ EXPECT_EQ(kExpectedVideoRtpBufferSize, network_interface.recv_buffer_size_);
+ EXPECT_EQ(kExpectedVideoRtpBufferSize, network_interface.send_buffer_size_);
+}
+
// TODO: add tests for below interfaces
// bool SetOptions(int options);
// bool SetCaptureDevice(const Device* device);
diff --git a/talk/session/phone/webrtcvideoframe.cc b/talk/session/phone/webrtcvideoframe.cc
index c2a3470..8d2d6ca 100644
--- a/talk/session/phone/webrtcvideoframe.cc
+++ b/talk/session/phone/webrtcvideoframe.cc
@@ -28,6 +28,7 @@
#include "talk/session/phone/webrtcvideoframe.h"
#include "talk/base/logging.h"
+#include "talk/session/phone/videocapturer.h"
#include "talk/session/phone/videocommon.h"
#ifdef WEBRTC_RELATIVE_PATH
#include "common_video/vplib/main/interface/vplib.h"
@@ -36,14 +37,54 @@
#endif
namespace cricket {
+
WebRtcVideoFrame::WebRtcVideoFrame() {
}
WebRtcVideoFrame::~WebRtcVideoFrame() {
}
-void WebRtcVideoFrame::Attach(uint8* buffer, size_t buffer_size, size_t w,
- size_t h, int64 elapsed_time, int64 time_stamp) {
+bool WebRtcVideoFrame::Init(uint32 format, int w, int h, int dw, int dh,
+ uint8* sample, size_t sample_size,
+ size_t pixel_width, size_t pixel_height,
+ int64 elapsed_time, int64 time_stamp,
+ int rotation) {
+ // WebRtcVideoFrame currently doesn't support color conversion or rotation.
+ if (format != FOURCC_I420 || dw != w || dh != h || rotation != 0) {
+ return false;
+ }
+
+ uint8* buffer = new uint8[sample_size];
+ memcpy(buffer, sample, sample_size);
+ Attach(buffer, sample_size, w, h, pixel_width, pixel_height,
+ elapsed_time, time_stamp, rotation);
+ return true;
+}
+
+bool WebRtcVideoFrame::Init(const CapturedFrame* frame, int dw, int dh) {
+ return Init(frame->fourcc, frame->width, frame->height, dw, dh,
+ static_cast<uint8*>(frame->data), frame->data_size,
+ frame->pixel_width, frame->pixel_height,
+ frame->elapsed_time, frame->time_stamp, frame->rotation);
+}
+
+bool WebRtcVideoFrame::InitToBlack(int w, int h,
+ size_t pixel_width, size_t pixel_height,
+ int64 elapsed_time, int64 time_stamp) {
+ size_t buffer_size = VideoFrame::SizeOf(w, h);
+ uint8* buffer = new uint8[buffer_size];
+ Attach(buffer, buffer_size, w, h, pixel_width, pixel_height,
+ elapsed_time, time_stamp, 0);
+ memset(GetYPlane(), 16, w * h);
+ memset(GetUPlane(), 128, w * h / 4);
+ memset(GetVPlane(), 128, w * h / 4);
+ return true;
+}
+
+void WebRtcVideoFrame::Attach(uint8* buffer, size_t buffer_size, int w, int h,
+ size_t pixel_width, size_t pixel_height,
+ int64 elapsed_time, int64 time_stamp,
+ int rotation) {
video_frame_.Free();
WebRtc_UWord8* new_memory = buffer;
WebRtc_UWord32 new_length = buffer_size;
@@ -51,8 +92,11 @@
video_frame_.Swap(new_memory, new_length, new_size);
video_frame_.SetWidth(w);
video_frame_.SetHeight(h);
+ pixel_width_ = pixel_width;
+ pixel_height_ = pixel_height;
elapsed_time_ = elapsed_time;
video_frame_.SetTimeStamp(static_cast<WebRtc_UWord32>(time_stamp));
+ rotation_ = rotation;
}
void WebRtcVideoFrame::Detach(uint8** buffer, size_t* buffer_size) {
@@ -64,17 +108,6 @@
*buffer_size = new_size;
}
-bool WebRtcVideoFrame::InitToBlack(size_t w, size_t h,
- int64 elapsed_time, int64 time_stamp) {
- size_t buffer_size = w * h * 3 / 2;
- uint8* buffer = new uint8[buffer_size];
- Attach(buffer, buffer_size, w, h, elapsed_time, time_stamp);
- memset(GetYPlane(), 16, w * h);
- memset(GetUPlane(), 128, w * h / 4);
- memset(GetVPlane(), 128, w * h / 4);
- return true;
-}
-
size_t WebRtcVideoFrame::GetWidth() const {
return video_frame_.Width();
}
@@ -132,7 +165,8 @@
WebRtcVideoFrame* copy = new WebRtcVideoFrame();
copy->Attach(new_buffer, new_buffer_size,
video_frame_.Width(), video_frame_.Height(),
- elapsed_time_, video_frame_.TimeStamp());
+ pixel_width_, pixel_height_,
+ elapsed_time_, video_frame_.TimeStamp(), rotation_);
return copy;
}
@@ -142,8 +176,7 @@
return true;
}
-size_t WebRtcVideoFrame::CopyToBuffer(
- uint8* buffer, size_t size) const {
+size_t WebRtcVideoFrame::CopyToBuffer(uint8* buffer, size_t size) const {
if (!video_frame_.Buffer()) {
return 0;
}
@@ -174,20 +207,20 @@
return 0;
}
- webrtc::VideoType outgoingVideoType = webrtc::kUnknown;
+ webrtc::VideoType to_type = webrtc::kUnknown;
switch (to_fourcc) {
case FOURCC_ARGB:
- outgoingVideoType = webrtc::kARGB;
+ to_type = webrtc::kARGB;
break;
default:
LOG(LS_WARNING) << "RGB type not supported: " << to_fourcc;
return 0;
- break;
}
- if (outgoingVideoType != webrtc::kUnknown)
- webrtc::ConvertFromI420(outgoingVideoType, video_frame_.Buffer(),
- width, height, buffer);
+ if (to_type != webrtc::kUnknown) {
+ webrtc::ConvertFromI420(to_type, video_frame_.Buffer(),
+ width, height, buffer);
+ }
return needed;
}
@@ -241,4 +274,5 @@
// TODO: implement
return NULL;
}
+
} // namespace cricket
diff --git a/talk/session/phone/webrtcvideoframe.h b/talk/session/phone/webrtcvideoframe.h
index 6538fbc..3431969 100644
--- a/talk/session/phone/webrtcvideoframe.h
+++ b/talk/session/phone/webrtcvideoframe.h
@@ -38,16 +38,29 @@
#include "talk/session/phone/videoframe.h"
namespace cricket {
-// WebRtcVideoFrame only supports I420
+
+struct CapturedFrame;
+
class WebRtcVideoFrame : public VideoFrame {
public:
WebRtcVideoFrame();
~WebRtcVideoFrame();
- void Attach(uint8* buffer, size_t buffer_size,
- size_t w, size_t h, int64 elapsed_time, int64 time_stamp);
+ bool Init(uint32 format, int w, int h, int dw, int dh,
+ uint8* sample, size_t sample_size,
+ size_t pixel_width, size_t pixel_height,
+ int64 elapsed_time, int64 time_stamp, int rotation);
+
+ bool Init(const CapturedFrame* frame, int dw, int dh);
+
+ bool InitToBlack(int w, int h, size_t pixel_width, size_t pixel_height,
+ int64 elapsed_time, int64 time_stamp);
+
+ void Attach(uint8* buffer, size_t buffer_size, int w, int h,
+ size_t pixel_width, size_t pixel_height,
+ int64 elapsed_time, int64 time_stamp, int rotation);
void Detach(uint8** buffer, size_t* buffer_size);
- bool InitToBlack(size_t w, size_t h, int64 elapsed_time, int64 time_stamp);
+
bool HasImage() const { return video_frame_.Buffer() != NULL; }
virtual size_t GetWidth() const;
@@ -62,8 +75,8 @@
virtual int32 GetUPitch() const { return video_frame_.Width() / 2; }
virtual int32 GetVPitch() const { return video_frame_.Width() / 2; }
- virtual size_t GetPixelWidth() const { return 1; }
- virtual size_t GetPixelHeight() const { return 1; }
+ virtual size_t GetPixelWidth() const { return pixel_width_; }
+ virtual size_t GetPixelHeight() const { return pixel_height_; }
virtual int64 GetElapsedTime() const { return elapsed_time_; }
virtual int64 GetTimeStamp() const { return video_frame_.TimeStamp(); }
virtual void SetElapsedTime(int64 elapsed_time) {
@@ -73,6 +86,8 @@
video_frame_.SetTimeStamp(static_cast<WebRtc_UWord32>(time_stamp));
}
+ virtual int GetRotation() const { return rotation_; }
+
virtual VideoFrame* Copy() const;
virtual bool MakeExclusive();
virtual size_t CopyToBuffer(uint8* buffer, size_t size) const;
@@ -91,7 +106,10 @@
private:
webrtc::VideoFrame video_frame_;
+ size_t pixel_width_;
+ size_t pixel_height_;
int64 elapsed_time_;
+ int rotation_;
};
} // namespace cricket
diff --git a/talk/session/phone/webrtcvideoframe_unittest.cc b/talk/session/phone/webrtcvideoframe_unittest.cc
index 4bd9244..cd1f033 100644
--- a/talk/session/phone/webrtcvideoframe_unittest.cc
+++ b/talk/session/phone/webrtcvideoframe_unittest.cc
@@ -30,13 +30,11 @@
static const int kAlignment = 16;
static const std::string kImageFilename = "faces.1280x720_P420.yuv";
-DEFINE_int(yuvconverter_repeat, 1,
- "how many times to perform each conversion operation (for perf testing)");
-
class WebRtcVideoFrameTest : public testing::Test {
protected:
virtual void SetUp() {
- repeat_ = FLAG_yuvconverter_repeat;
+ // TODO: Fix (add a new flag) or remove repeat_.
+ repeat_ = 1;
}
public:
@@ -67,13 +65,11 @@
bool LoadFrame(uint8* sample, size_t sample_size, uint32 format,
int32 width, int32 height, WebRtcVideoFrame* frame,
int rotation) {
- // WebRtcVideoFrame only supporst I420 for now
- if (format != FOURCC_I420)
- return false;
for (int i = 0; i < repeat_; ++i) {
- uint8* new_buffer = new uint8[sample_size];
- memcpy(new_buffer, sample, sample_size);
- frame->Attach(new_buffer, sample_size, width, height, 0, 0);
+ if (!frame->Init(format, width, height, width, height,
+ sample, sample_size, 1, 1, 0, 0, 0)) {
+ return false;
+ }
}
return true;
}
@@ -177,7 +173,7 @@
start = start + stride * (height - 1);
stride = -stride;
}
- frame->InitToBlack(width, height, 0, 0);
+ frame->InitToBlack(width, height, 1, 1, 0, 0);
for (int32 y = 0; y < height; y += 2) {
for (int32 x = 0; x < width; x += 2) {
const uint8* rgb[4];
@@ -388,7 +384,7 @@
TEST_F(WebRtcVideoFrameTest, ConstructBlack) {
WebRtcVideoFrame frame;
for (int i = 0; i < repeat_; ++i) {
- EXPECT_TRUE(frame.InitToBlack(kWidth, kHeight, 0, 0));
+ EXPECT_TRUE(frame.InitToBlack(kWidth, kHeight, 1, 1, 0, 0));
}
EXPECT_TRUE(IsSize(frame, kWidth, kHeight));
EXPECT_EQ(16, *frame.GetYPlane());
diff --git a/talk/session/phone/webrtcvoiceengine.cc b/talk/session/phone/webrtcvoiceengine.cc
index 9135fb3..3dfad11 100644
--- a/talk/session/phone/webrtcvoiceengine.cc
+++ b/talk/session/phone/webrtcvoiceengine.cc
@@ -128,6 +128,12 @@
virtual ~WebRtcSoundclipMedia() {
engine_->UnregisterSoundclip(this);
if (webrtc_channel_ != -1) {
+ // We shouldn't have to call Disable() here. DeleteChannel() should call
+ // StopPlayout() while deleting the channel. We should fix the bug
+ // inside WebRTC and remove the Disable() call bellow. This work is
+ // tracked by bug http://b/issue?id=5382855.
+ PlaySound(NULL, 0, 0);
+ Disable();
if (engine_->voe_sc()->base()->DeleteChannel(webrtc_channel_)
== -1) {
LOG_RTCERR1(DeleteChannel, webrtc_channel_);
@@ -286,12 +292,12 @@
}
if (adm_) {
voe_wrapper_.reset();
- webrtc::AudioDeviceModule::Destroy(adm_);
+ adm_->Release();
adm_ = NULL;
}
if (adm_sc_) {
voe_wrapper_sc_.reset();
- webrtc::AudioDeviceModule::Destroy(adm_sc_);
+ adm_sc_->Release();
adm_sc_ = NULL;
}
@@ -317,21 +323,8 @@
static_cast<int>(talk_base::LS_INFO));
ApplyLogging("");
- if (adm_) {
- if (voe_wrapper_->base()->RegisterAudioDeviceModule(*adm_) == -1) {
- LOG_RTCERR0_EX(Init, voe_wrapper_->error());
- return false;
- }
- }
- if (adm_sc_) {
- if (voe_wrapper_sc_->base()->RegisterAudioDeviceModule(*adm_sc_) == -1) {
- LOG_RTCERR0_EX(Init, voe_wrapper_sc_->error());
- return false;
- }
- }
-
// Init WebRtc VoiceEngine, enabling AEC logging if specified in SetLogging.
- if (voe_wrapper_->base()->Init() == -1) {
+ if (voe_wrapper_->base()->Init(adm_) == -1) {
LOG_RTCERR0_EX(Init, voe_wrapper_->error());
return false;
}
@@ -371,7 +364,7 @@
#endif
// Initialize the VoiceEngine instance that we'll use to play out sound clips.
- if (voe_wrapper_sc_->base()->Init() == -1) {
+ if (voe_wrapper_sc_->base()->Init(adm_sc_) == -1) {
LOG_RTCERR0_EX(Init, voe_wrapper_sc_->error());
return false;
}
@@ -1000,8 +993,23 @@
LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init.";
return false;
}
- adm_ = adm;
- adm_sc_ = adm_sc;
+ if (adm_) {
+ adm_->Release();
+ adm_ = NULL;
+ }
+ if (adm) {
+ adm_ = adm;
+ adm_->AddRef();
+ }
+
+ if (adm_sc_) {
+ adm_sc_->Release();
+ adm_sc_ = NULL;
+ }
+ if (adm_sc) {
+ adm_sc_ = adm_sc;
+ adm_sc_->AddRef();
+ }
return true;
}
@@ -1317,13 +1325,6 @@
}
#endif // CHROMEOS
- // Tandberg-bridged conferences have an AGC target that is lower than
- // GTV-only levels.
- if ((channel_options_ & OPT_AGC_TANDBERG_LEVELS) && !agc_adjusted_) {
- if (engine()->AdjustAgcLevel(kTandbergDbAdjustment)) {
- agc_adjusted_ = true;
- }
- }
// VoiceEngine resets sequence number when StopSend is called. This
// sometimes causes libSRTP to complain about packets being
diff --git a/talk/site_scons/talk.py b/talk/site_scons/talk.py
index e2ac143..36fcf49 100644
--- a/talk/site_scons/talk.py
+++ b/talk/site_scons/talk.py
@@ -417,12 +417,11 @@
return merged
-# Linux can build both 32 and 64 bit on 64 bit host, but 32 bit host can
-# only build 32 bit. For 32 bit debian installer a 32 bit host is required.
-# ChromeOS (linux) ebuild don't support 64 bit and requires 32 bit build only
-# for now.
-def Allow64BitCompile(env):
- return (env.Bit('linux') and env.Bit('platform_arch_64bit')
+# Whether to enable extra 64-bit targets marked with the also64bit setting. Used
+# only for the legacy mixed 32/64 desktop Linux build.
+def EnableExtra64BitTargets(env):
+ return (env.Bit('linux') and env.Bit('build_platform_64bit') and
+ not env.Bit('host_platform_64bit')
)
@@ -524,7 +523,7 @@
env.Prepend(**{var : values})
# workaround for pulse stripping link flag for unknown reason
- if Allow64BitCompile(env):
+ if EnableExtra64BitTargets(env):
env['SHLINKCOM'] = ('$SHLINK -o $TARGET -m32 $SHLINKFLAGS $SOURCES '
'$_LIBDIRFLAGS $_LIBFLAGS')
env['LINKCOM'] = ('$LINK -o $TARGET -m32 $LINKFLAGS $SOURCES '
@@ -557,7 +556,7 @@
node = builder(name, srcs)
# make a parallel 64bit version if requested
- if Allow64BitCompile(env) and PopEntry(params, 'also64bit'):
+ if EnableExtra64BitTargets(env) and PopEntry(params, 'also64bit'):
env_64bit = env.Clone()
env_64bit.FilterOut(CCFLAGS = ['-m32'], LINKFLAGS = ['-m32'])
env_64bit.Prepend(CCFLAGS = ['-m64', '-fPIC'], LINKFLAGS = ['-m64'])
diff --git a/talk/sound/pulseaudiosoundsystem.cc b/talk/sound/pulseaudiosoundsystem.cc
index b4d17d1..3b45f8c 100644
--- a/talk/sound/pulseaudiosoundsystem.cc
+++ b/talk/sound/pulseaudiosoundsystem.cc
@@ -1,6 +1,6 @@
/*
* libjingle
- * Copyright 2004--2010, Google Inc.
+ * Copyright 2010, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -1467,7 +1467,8 @@
ssize_t bytes_per_sec = LATE(pa_bytes_per_second)(&spec);
latency = talk_base::_max(
latency,
- bytes_per_sec * kPlaybackLatencyMinimumMsecs / kMsecsPerSec);
+ static_cast<int>(
+ bytes_per_sec * kPlaybackLatencyMinimumMsecs / kMsecsPerSec));
FillPlaybackBufferAttr(latency, &attr);
pattr = &attr;
}
diff --git a/talk/sound/soundsystemproxy.h b/talk/sound/soundsystemproxy.h
index 07ea873..9ccace8 100644
--- a/talk/sound/soundsystemproxy.h
+++ b/talk/sound/soundsystemproxy.h
@@ -28,6 +28,7 @@
#ifndef TALK_SOUND_SOUNDSYSTEMPROXY_H_
#define TALK_SOUND_SOUNDSYSTEMPROXY_H_
+#include "talk/base/basictypes.h" // for NULL
#include "talk/sound/soundsysteminterface.h"
namespace cricket {