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 {