Updated stable to r2879.

git-svn-id: http://webrtc.googlecode.com/svn/stable/src@2881 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/common_audio/signal_processing/include/spl_inl_armv7.h b/common_audio/signal_processing/include/spl_inl_armv7.h
index 2eff496..8461474 100644
--- a/common_audio/signal_processing/include/spl_inl_armv7.h
+++ b/common_audio/signal_processing/include/spl_inl_armv7.h
@@ -64,6 +64,7 @@
   return tmp;
 }
 
+// TODO(kma): add unit test.
 static __inline int32_t WebRtc_MulAccumW16(int16_t a,
                                           int16_t b,
                                           int32_t c) {
@@ -124,7 +125,12 @@
 static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
   WebRtc_Word32 tmp = 0;
 
-  if (a <= 0) a ^= 0xFFFFFFFF;
+  if (a == 0) {
+    return 0;
+  }
+  else if (a < 0) {
+    a ^= 0xFFFFFFFF;
+  }
 
   __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
 
@@ -144,13 +150,19 @@
 static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
   WebRtc_Word32 tmp = 0;
 
-  if (a <= 0) a ^= 0xFFFFFFFF;
+  if (a == 0) {
+    return 0;
+  }
+  else if (a < 0) {
+    a ^= 0xFFFFFFFF;
+  }
 
   __asm __volatile ("clz %0, %1":"=r"(tmp):"r"(a));
 
   return tmp - 17;
 }
 
+// TODO(kma): add unit test.
 static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) {
   WebRtc_Word16 out16 = 0;
 
@@ -158,4 +170,5 @@
 
   return out16;
 }
+
 #endif  // WEBRTC_SPL_SPL_INL_ARMV7_H_
diff --git a/common_audio/signal_processing/signal_processing_unittest.cc b/common_audio/signal_processing/signal_processing_unittest.cc
index 4acef5b..d5026fb 100644
--- a/common_audio/signal_processing/signal_processing_unittest.cc
+++ b/common_audio/signal_processing/signal_processing_unittest.cc
@@ -138,8 +138,20 @@
     char bVersion[8];
 
     EXPECT_EQ(17, WebRtcSpl_GetSizeInBits(a32));
+
+    EXPECT_EQ(0, WebRtcSpl_NormW32(0));
+    EXPECT_EQ(31, WebRtcSpl_NormW32(-1));
+    EXPECT_EQ(0, WebRtcSpl_NormW32(WEBRTC_SPL_WORD32_MIN));
     EXPECT_EQ(14, WebRtcSpl_NormW32(a32));
+
+    EXPECT_EQ(0, WebRtcSpl_NormW16(0));
+    EXPECT_EQ(15, WebRtcSpl_NormW16(-1));
+    EXPECT_EQ(0, WebRtcSpl_NormW16(WEBRTC_SPL_WORD16_MIN));
     EXPECT_EQ(4, WebRtcSpl_NormW16(b32));
+
+    EXPECT_EQ(0, WebRtcSpl_NormU32(0));
+    EXPECT_EQ(0, WebRtcSpl_NormU32(-1));
+    EXPECT_EQ(0, WebRtcSpl_NormU32(WEBRTC_SPL_WORD32_MIN));
     EXPECT_EQ(15, WebRtcSpl_NormU32(a32));
 
     EXPECT_EQ(104, WebRtcSpl_AddSatW16(a16, b16));
@@ -147,6 +159,7 @@
 
     EXPECT_EQ(109410, WebRtcSpl_AddSatW32(a32, b32));
     EXPECT_EQ(112832, WebRtcSpl_SubSatW32(a32, b32));
+
     a32 = 0x80000000;
     b32 = 0x80000000;
     // Cast to signed int to avoid compiler complaint on gtest.h.
@@ -505,14 +518,23 @@
   const int kStep = 1;
   const int kSeqDimension = 6;
 
-  const int16_t vector16_b[kVector16Size] = {1, 4323, 1963,
+  const int16_t kVector16[kVector16Size] = {1, 4323, 1963,
     WEBRTC_SPL_WORD16_MAX, WEBRTC_SPL_WORD16_MIN + 5, -3333, -876, 8483, 142};
-  const int32_t expected[3] = {-266947903, -15579555, -171282001};
   int32_t vector32[kCrossCorrelationDimension] = {0};
 
-  WebRtcSpl_CrossCorrelation(vector32, vector16, vector16_b, kSeqDimension,
+  WebRtcSpl_CrossCorrelation(vector32, vector16, kVector16, kSeqDimension,
                              kCrossCorrelationDimension, kShift, kStep);
 
+  // WebRtcSpl_CrossCorrelationC() and WebRtcSpl_CrossCorrelationNeon()
+  // are not bit-exact.
+  const int32_t kExpected[kCrossCorrelationDimension] =
+      {-266947903, -15579555, -171282001};
+  const int32_t kExpectedNeon[kCrossCorrelationDimension] =
+      {-266947901, -15579553, -171281999};
+  const int32_t* expected = kExpected;
+  if (WebRtcSpl_CrossCorrelation != WebRtcSpl_CrossCorrelationC) {
+    expected = kExpectedNeon;
+  }
   for (int i = 0; i < kCrossCorrelationDimension; ++i) {
     EXPECT_EQ(expected[i], vector32[i]);
   }
diff --git a/common_audio/signal_processing/spl_init.c b/common_audio/signal_processing/spl_init.c
index 1021d1b..595a5ce 100644
--- a/common_audio/signal_processing/spl_init.c
+++ b/common_audio/signal_processing/spl_init.c
@@ -14,10 +14,6 @@
  * Some code came from common/rtcd.c in the WebM project.
  */
 
-/* TODO(kma): Add calls to WebRtcSpl_Init() in all related modules
- * (AEC, NS, codecs etc.).
- */
-
 #include "common_audio/signal_processing/include/real_fft.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "system_wrappers/interface/cpu_features_wrapper.h"
diff --git a/common_audio/vad/webrtc_vad.c b/common_audio/vad/webrtc_vad.c
index 034f99b..6999211 100644
--- a/common_audio/vad/webrtc_vad.c
+++ b/common_audio/vad/webrtc_vad.c
@@ -37,6 +37,8 @@
     return -1;
   }
 
+  WebRtcSpl_Init();
+
   self->init_flag = 0;
 
   return 0;
@@ -54,7 +56,6 @@
 
 // TODO(bjornv): Move WebRtcVad_InitCore() code here.
 int WebRtcVad_Init(VadInst* handle) {
-  WebRtcSpl_Init();
   // Initialize the core VAD component.
   return WebRtcVad_InitCore((VadInstT*) handle);
 }
diff --git a/common_video/i420_video_frame.cc b/common_video/i420_video_frame.cc
index f7ae456..ca709ef 100644
--- a/common_video/i420_video_frame.cc
+++ b/common_video/i420_video_frame.cc
@@ -38,9 +38,9 @@
   return 0;
 }
 
-int I420VideoFrame::CreateFrame(int size_y, const uint8_t& buffer_y,
-                                int size_u, const uint8_t& buffer_u,
-                                int size_v, const uint8_t& buffer_v,
+int I420VideoFrame::CreateFrame(int size_y, const uint8_t* buffer_y,
+                                int size_u, const uint8_t* buffer_u,
+                                int size_v, const uint8_t* buffer_v,
                                 int width, int height,
                                 int stride_y, int stride_u, int stride_v) {
   if (size_y < 1 || size_u < 1 || size_v < 1)
@@ -56,9 +56,9 @@
 }
 
 int I420VideoFrame::CopyFrame(const I420VideoFrame& videoFrame) {
-  int ret = CreateFrame(videoFrame.size(kYPlane), *videoFrame.buffer(kYPlane),
-                        videoFrame.size(kUPlane), *videoFrame.buffer(kUPlane),
-                        videoFrame.size(kVPlane), *videoFrame.buffer(kVPlane),
+  int ret = CreateFrame(videoFrame.size(kYPlane), videoFrame.buffer(kYPlane),
+                        videoFrame.size(kUPlane), videoFrame.buffer(kUPlane),
+                        videoFrame.size(kVPlane), videoFrame.buffer(kVPlane),
                         videoFrame.width_, videoFrame.height_,
                         videoFrame.stride(kYPlane), videoFrame.stride(kUPlane),
                         videoFrame.stride(kVPlane));
@@ -79,6 +79,13 @@
   std::swap(render_time_ms_, videoFrame->render_time_ms_);
 }
 
+uint8_t* I420VideoFrame::buffer(PlaneType type) {
+  Plane* plane_ptr = GetPlane(type);
+  if (plane_ptr)
+    return plane_ptr->buffer();
+  return NULL;
+}
+
 const uint8_t* I420VideoFrame::buffer(PlaneType type) const {
   const Plane* plane_ptr = GetPlane(type);
   if (plane_ptr)
@@ -141,5 +148,19 @@
   return NULL;
 }
 
+Plane* I420VideoFrame::GetPlane(PlaneType type) {
+  switch (type) {
+    case kYPlane :
+      return &y_plane_;
+    case kUPlane :
+      return &u_plane_;
+    case kVPlane :
+      return &v_plane_;
+    default:
+      assert(false);
+  }
+  return NULL;
+}
+
 
 }  // namespace webrtc
diff --git a/common_video/i420_video_frame_unittest.cc b/common_video/i420_video_frame_unittest.cc
index 07dca79..e0d22a5 100644
--- a/common_video/i420_video_frame_unittest.cc
+++ b/common_video/i420_video_frame_unittest.cc
@@ -87,9 +87,9 @@
   memset(buffer_y, 16, kSizeY);
   memset(buffer_u, 8, kSizeU);
   memset(buffer_v, 4, kSizeV);
-  frame2.CreateFrame(kSizeY, *buffer_y,
-                     kSizeU, *buffer_u,
-                     kSizeV, *buffer_v,
+  frame2.CreateFrame(kSizeY, buffer_y,
+                     kSizeU, buffer_u,
+                     kSizeV, buffer_v,
                      width + 5, height + 5, stride_y + 5, stride_u, stride_v);
   // Frame of smaller dimensions - allocated sizes should not vary.
   EXPECT_EQ(0, frame1.CopyFrame(frame2));
@@ -119,9 +119,9 @@
   memset(buffer_y, 16, kSizeY);
   memset(buffer_u, 8, kSizeUv);
   memset(buffer_v, 4, kSizeUv);
-  frame2.CreateFrame(kSizeY, *buffer_y,
-                     kSizeUv, *buffer_u,
-                     kSizeUv, *buffer_v,
+  frame2.CreateFrame(kSizeY, buffer_y,
+                     kSizeUv, buffer_u,
+                     kSizeUv, buffer_v,
                      width, height, stride_y, stride_uv, stride_uv);
   // Copy memory (at least allocated size).
   EXPECT_EQ(memcmp(buffer_y, frame2.buffer(kYPlane), kSizeY), 0);
@@ -167,9 +167,9 @@
   memset(buffer_y1, 2, kSizeY1);
   memset(buffer_u1, 4, kSizeU1);
   memset(buffer_v1, 8, kSizeV1);
-  frame1.CreateFrame(kSizeY1, *buffer_y1,
-                     kSizeU1, *buffer_u1,
-                     kSizeV1, *buffer_v1,
+  frame1.CreateFrame(kSizeY1, buffer_y1,
+                     kSizeU1, buffer_u1,
+                     kSizeV1, buffer_v1,
                      width1, height1, stride_y1, stride_u1, stride_v1);
   // Initialize frame2 values.
   EXPECT_EQ(0, frame2.CreateEmptyFrame(width2, height2,
@@ -183,9 +183,9 @@
   memset(buffer_y2, 0, kSizeY2);
   memset(buffer_u2, 1, kSizeU2);
   memset(buffer_v2, 2, kSizeV2);
-  frame2.CreateFrame(kSizeY2, *buffer_y2,
-                     kSizeU2, *buffer_u2,
-                     kSizeV2, *buffer_v2,
+  frame2.CreateFrame(kSizeY2, buffer_y2,
+                     kSizeU2, buffer_u2,
+                     kSizeV2, buffer_v2,
                      width2, height2, stride_y2, stride_u2, stride_v2);
   // Copy frames for subsequent comparison.
   I420VideoFrame frame1_copy, frame2_copy;
diff --git a/common_video/interface/i420_video_frame.h b/common_video/interface/i420_video_frame.h
index 4dd3fb9..9c7f83a 100644
--- a/common_video/interface/i420_video_frame.h
+++ b/common_video/interface/i420_video_frame.h
@@ -43,9 +43,9 @@
   // CreateFrame: Sets the frame's members and buffers. If required size is
   // bigger than allocated one, new buffers of adequate size will be allocated.
   // Return value: 0 on success ,-1 on error.
-  int CreateFrame(int size_y, const uint8_t& buffer_y,
-                  int size_u, const uint8_t& buffer_u,
-                  int size_v, const uint8_t& buffer_v,
+  int CreateFrame(int size_y, const uint8_t* buffer_y,
+                  int size_u, const uint8_t* buffer_u,
+                  int size_v, const uint8_t* buffer_v,
                   int width, int height,
                   int stride_y, int stride_u, int stride_v);
 
@@ -58,6 +58,8 @@
   void SwapFrame(I420VideoFrame* videoFrame);
 
   // Get pointer to buffer per plane.
+  uint8_t* buffer(PlaneType type);
+  // Overloading with const.
   const uint8_t* buffer(PlaneType type) const;
 
   // Get allocated size per plane.
@@ -98,6 +100,8 @@
                       int stride_y, int stride_u, int stride_v);
   // Get the pointer to a specific plane.
   const Plane* GetPlane(PlaneType type) const;
+  // Overloading with non-const.
+  Plane* GetPlane(PlaneType type);
 
   Plane y_plane_;
   Plane u_plane_;
diff --git a/common_video/libyuv/include/webrtc_libyuv.h b/common_video/libyuv/include/webrtc_libyuv.h
index c6e9571..bd8ff0b 100644
--- a/common_video/libyuv/include/webrtc_libyuv.h
+++ b/common_video/libyuv/include/webrtc_libyuv.h
@@ -139,10 +139,18 @@
                      VideoFrame* dst_frame);
 
 // Compute PSNR for an I420 frame (all planes).
+double I420PSNR(const VideoFrame* ref_frame,
+                const VideoFrame* test_frame);
+// Compute SSIM for an I420 frame (all planes).
+double I420SSIM(const VideoFrame* ref_frame,
+                const VideoFrame* test_frame);
+
+// TODO(mikhal): Remove these functions and keep only the above functionality.
+// Compute PSNR for an I420 buffer (all planes).
 double I420PSNR(const uint8_t* ref_frame,
                 const uint8_t* test_frame,
                 int width, int height);
-// Compute SSIM for an I420 frame (all planes).
+// Compute SSIM for an I420 buffer (all planes).
 double I420SSIM(const uint8_t* ref_frame,
                 const uint8_t* test_frame,
                 int width, int height);
diff --git a/common_video/libyuv/libyuv_unittest.cc b/common_video/libyuv/libyuv_unittest.cc
index 5ab8c11..6c2bba8 100644
--- a/common_video/libyuv/libyuv_unittest.cc
+++ b/common_video/libyuv/libyuv_unittest.cc
@@ -158,8 +158,7 @@
              output_file) != static_cast<unsigned int>(frame_length_)) {
     return;
   }
-  psnr = I420PSNR(orig_frame.Buffer(), res_i420_frame.Buffer(),
-                  width_, height_);
+  psnr = I420PSNR(&orig_frame, &res_i420_frame);
   // Optimization Speed- quality trade-off => 45 dB only (platform dependant).
   EXPECT_GT(ceil(psnr), 44);
   j++;
@@ -171,8 +170,7 @@
                                kUYVY, 0, out_uyvy_buffer));
   EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer, 0, 0, width_, height_,
             0, kRotateNone, &res_i420_frame));
-  psnr = I420PSNR(orig_frame.Buffer(), res_i420_frame.Buffer(),
-                  width_, height_);
+  psnr = I420PSNR(&orig_frame, &res_i420_frame);
   EXPECT_EQ(48.0, psnr);
   if (fwrite(res_i420_frame.Buffer(), 1, frame_length_,
              output_file) !=  static_cast<unsigned int>(frame_length_)) {
@@ -211,8 +209,7 @@
     return;
   }
 
-  psnr = I420PSNR(orig_frame.Buffer(), res_i420_frame.Buffer(),
-                  width_, height_);
+  psnr = I420PSNR(&orig_frame, &res_i420_frame);
   EXPECT_EQ(48.0, psnr);
   j++;
   delete [] outYV120Buffer;
@@ -229,8 +226,7 @@
              output_file) !=  static_cast<unsigned int>(frame_length_)) {
     return;
   }
-  psnr = I420PSNR(orig_frame.Buffer(), res_i420_frame.Buffer(),
-                  width_, height_);
+  psnr = I420PSNR(&orig_frame, &res_i420_frame);
   EXPECT_EQ(48.0, psnr);
 
   // printf("\nConvert #%d I420 <-> RGB565\n", j);
@@ -245,8 +241,7 @@
              output_file) !=  static_cast<unsigned int>(frame_length_)) {
     return;
   }
-  psnr = I420PSNR(orig_frame.Buffer(), res_i420_frame.Buffer(),
-                  width_, height_);
+  psnr = I420PSNR(&orig_frame, &res_i420_frame);
   // TODO(leozwang) Investigate the right psnr should be set for I420ToRGB565,
   // Another example is I420ToRGB24, the psnr is 44
   EXPECT_GT(ceil(psnr), 40);
@@ -263,8 +258,7 @@
              output_file) !=  static_cast<unsigned int>(frame_length_)) {
     return;
   }
-  psnr = I420PSNR(orig_frame.Buffer(), res_i420_frame.Buffer(),
-                  width_, height_);
+  psnr = I420PSNR(&orig_frame, &res_i420_frame);
   // TODO(leozwang) Investigate the right psnr should be set for I420ToARGB8888,
   EXPECT_GT(ceil(psnr), 42);
 
diff --git a/common_video/libyuv/webrtc_libyuv.cc b/common_video/libyuv/webrtc_libyuv.cc
index 82dc4a3..7a7d1d1 100644
--- a/common_video/libyuv/webrtc_libyuv.cc
+++ b/common_video/libyuv/webrtc_libyuv.cc
@@ -285,6 +285,69 @@
 }
 
 // Compute PSNR for an I420 frame (all planes)
+double I420PSNR(const VideoFrame* ref_frame,
+                const VideoFrame* test_frame) {
+  if (!ref_frame || !test_frame)
+    return -1;
+  else if ((ref_frame->Width() !=  test_frame->Width()) ||
+          (ref_frame->Height() !=  test_frame->Height()))
+    return -1;
+  else if (ref_frame->Width() == 0u || ref_frame->Height() == 0u)
+    return -1;
+  int height = ref_frame->Height() ;
+  int width = ref_frame->Width();
+  int half_width = (width + 1) >> 1;
+  int half_height = (height + 1) >> 1;
+  const uint8_t* src_y_a = ref_frame->Buffer();
+  const uint8_t* src_u_a = src_y_a + width * height;
+  const uint8_t* src_v_a = src_u_a + half_width * half_height;
+  const uint8_t* src_y_b = test_frame->Buffer();
+  const uint8_t* src_u_b = src_y_b + width * height;
+  const uint8_t* src_v_b = src_u_b + half_width * half_height;
+  // In the following: stride is determined by width.
+  double psnr = libyuv::I420Psnr(src_y_a, width,
+                                 src_u_a, half_width,
+                                 src_v_a, half_width,
+                                 src_y_b, width,
+                                 src_u_b, half_width,
+                                 src_v_b, half_width,
+                                 width, height);
+  // LibYuv sets the max psnr value to 128, we restrict it to 48.
+  // In case of 0 mse in one frame, 128 can skew the results significantly.
+  return (psnr > 48.0) ? 48.0 : psnr;
+}
+// Compute SSIM for an I420 frame (all planes)
+double I420SSIM(const VideoFrame* ref_frame,
+                const VideoFrame* test_frame) {
+  if (!ref_frame || !test_frame)
+    return -1;
+  else if ((ref_frame->Width() !=  test_frame->Width()) ||
+          (ref_frame->Height() !=  test_frame->Height()))
+    return -1;
+  else if (ref_frame->Width() == 0u || ref_frame->Height() == 0u)
+    return -1;
+  int height = ref_frame->Height() ;
+  int width = ref_frame->Width();
+  int half_width = (width + 1) >> 1;
+  int half_height = (height + 1) >> 1;
+  const uint8_t* src_y_a = ref_frame->Buffer();
+  const uint8_t* src_u_a = src_y_a + width * height;
+  const uint8_t* src_v_a = src_u_a + half_width * half_height;
+  const uint8_t* src_y_b = test_frame->Buffer();
+  const uint8_t* src_u_b = src_y_b + width * height;
+  const uint8_t* src_v_b = src_u_b + half_width * half_height;
+  int stride_y = width;
+  int stride_uv = half_width;
+  return libyuv::I420Ssim(src_y_a, stride_y,
+                          src_u_a, stride_uv,
+                          src_v_a, stride_uv,
+                          src_y_b, stride_y,
+                          src_u_b, stride_uv,
+                          src_v_b, stride_uv,
+                          width, height);
+}
+
+// Compute PSNR for an I420 frame (all planes)
 double I420PSNR(const uint8_t* ref_frame,
                 const uint8_t* test_frame,
                 int width, int height) {
diff --git a/common_video/plane.cc b/common_video/plane.cc
index 21fa87c..e47208f 100644
--- a/common_video/plane.cc
+++ b/common_video/plane.cc
@@ -57,10 +57,10 @@
   return 0;
 }
 
-int Plane::Copy(int size, int stride, const uint8_t& buffer) {
+int Plane::Copy(int size, int stride, const uint8_t* buffer) {
   if (MaybeResize(size) < 0)
     return -1;
-  memcpy(buffer_.get(), &buffer, size);
+  memcpy(buffer_.get(), buffer, size);
   plane_size_ = size;
   stride_ = stride;
   return 0;
diff --git a/common_video/plane.h b/common_video/plane.h
index 3a3f97e..795f800 100644
--- a/common_video/plane.h
+++ b/common_video/plane.h
@@ -35,7 +35,7 @@
   // Copy buffer: If current size is smaller
   // than current size, then a buffer of sufficient size will be allocated.
   // Return value: 0 on success ,-1 on error.
-  int Copy(int size, int stride, const uint8_t& buffer);
+  int Copy(int size, int stride, const uint8_t* buffer);
 
   // Swap plane data.
   void Swap(Plane& plane);
@@ -48,6 +48,8 @@
 
   // Return data pointer.
   const uint8_t* buffer() const {return buffer_.get();}
+  // Overloading with non-const.
+  uint8_t* buffer() {return buffer_.get();}
 
  private:
   // Resize when needed: If current allocated size is less than new_size, buffer
diff --git a/common_video/plane_unittest.cc b/common_video/plane_unittest.cc
index 15d2a7c..301f690 100644
--- a/common_video/plane_unittest.cc
+++ b/common_video/plane_unittest.cc
@@ -56,7 +56,7 @@
   uint8_t buffer1[100];
   size1 = 80;
   memset(&buffer1, 0, size1);
-  plane2.Copy(size1, stride1, *buffer1);
+  plane2.Copy(size1, stride1, buffer1);
   EXPECT_GE(plane2.allocated_size(), size1);
   EXPECT_EQ(0, memcmp(buffer1, plane2.buffer(), size1));
 }
diff --git a/modules/audio_coding/codecs/ilbc/ilbc.c b/modules/audio_coding/codecs/ilbc/ilbc.c
index dbd32d1..9a93d61 100644
--- a/modules/audio_coding/codecs/ilbc/ilbc.c
+++ b/modules/audio_coding/codecs/ilbc/ilbc.c
@@ -48,6 +48,7 @@
 WebRtc_Word16 WebRtcIlbcfix_EncoderCreate(iLBC_encinst_t **iLBC_encinst) {
   *iLBC_encinst=(iLBC_encinst_t*)malloc(sizeof(iLBC_Enc_Inst_t));
   if (*iLBC_encinst!=NULL) {
+    WebRtcSpl_Init();
     return(0);
   } else {
     return(-1);
@@ -57,6 +58,7 @@
 WebRtc_Word16 WebRtcIlbcfix_DecoderCreate(iLBC_decinst_t **iLBC_decinst) {
   *iLBC_decinst=(iLBC_decinst_t*)malloc(sizeof(iLBC_Dec_Inst_t));
   if (*iLBC_decinst!=NULL) {
+    WebRtcSpl_Init();
     return(0);
   } else {
     return(-1);
diff --git a/modules/audio_coding/codecs/ilbc/init_decode.c b/modules/audio_coding/codecs/ilbc/init_decode.c
index 7e51d0f..ea16a32 100644
--- a/modules/audio_coding/codecs/ilbc/init_decode.c
+++ b/modules/audio_coding/codecs/ilbc/init_decode.c
@@ -29,8 +29,6 @@
     int use_enhancer) {  /* (i) 1: use enhancer, 0: no enhancer */
   int i;
 
-  WebRtcSpl_Init();
-
   iLBCdec_inst->mode = mode;
 
   /* Set all the variables that are dependent on the frame size mode */
diff --git a/modules/audio_coding/codecs/ilbc/init_encode.c b/modules/audio_coding/codecs/ilbc/init_encode.c
index 79b3231..e1c0fc6 100644
--- a/modules/audio_coding/codecs/ilbc/init_encode.c
+++ b/modules/audio_coding/codecs/ilbc/init_encode.c
@@ -26,8 +26,6 @@
 WebRtc_Word16 WebRtcIlbcfix_InitEncode(  /* (o) Number of bytes encoded */
     iLBC_Enc_Inst_t *iLBCenc_inst,  /* (i/o) Encoder instance */
     WebRtc_Word16 mode) {  /* (i) frame size mode */
-  WebRtcSpl_Init();
-
   iLBCenc_inst->mode = mode;
 
   /* Set all the variables that are dependent on the frame size mode */
diff --git a/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/modules/audio_coding/codecs/isac/fix/source/isacfix.c
index 890cd27..5ea5b96 100644
--- a/modules/audio_coding/codecs/isac/fix/source/isacfix.c
+++ b/modules/audio_coding/codecs/isac/fix/source/isacfix.c
@@ -86,6 +86,7 @@
     (*(ISACFIX_SubStruct**)ISAC_main_inst)->errorcode = 0;
     (*(ISACFIX_SubStruct**)ISAC_main_inst)->initflag = 0;
     (*(ISACFIX_SubStruct**)ISAC_main_inst)->ISACenc_obj.SaveEnc_ptr = NULL;
+    WebRtcSpl_Init();
     return(0);
   } else {
     return(-1);
@@ -217,8 +218,6 @@
   /* flag encoder init */
   ISAC_inst->initflag |= 2;
 
-  WebRtcSpl_Init();
-
   if (CodingMode == 0)
     /* Adaptive mode */
     ISAC_inst->ISACenc_obj.new_framelength  = INITIAL_FRAMESAMPLES;
@@ -529,8 +528,6 @@
   /* flag decoder init */
   ISAC_inst->initflag |= 1;
 
-  WebRtcSpl_Init();
-
   WebRtcIsacfix_InitMaskingDec(&ISAC_inst->ISACdec_obj.maskfiltstr_obj);
   WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACdec_obj.postfiltbankstr_obj);
   WebRtcIsacfix_InitPitchFilter(&ISAC_inst->ISACdec_obj.pitchfiltstr_obj);
diff --git a/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.cc b/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.cc
index e8d153b..d37cd64 100644
--- a/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.cc
+++ b/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.cc
@@ -14,6 +14,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <algorithm>  // max
+
 #ifdef WIN32
 #include <winsock2.h>
 #else
@@ -56,17 +58,18 @@
     length = (WebRtc_UWord16) (length - _kRDHeaderLen);
 
     // check buffer size
-    if (_datagram && _memSize < length)
+    if (_datagram && _memSize < length + 1)
     {
         reset();
     }
 
     if (!_datagram)
     {
-        _datagram = new WebRtc_UWord8[length];
-        _memSize = length;
+        // Add one extra byte, to be able to fake a dummy payload of one byte.
+        _datagram = new WebRtc_UWord8[length + 1];
+        _memSize = length + 1;
     }
-    memset(_datagram, 0, length);
+    memset(_datagram, 0, length + 1);
 
     if (length == 0)
     {
@@ -75,7 +78,7 @@
     }
 
     // Read basic header
-    if (fread((unsigned short *) _datagram, 1, _kBasicHeaderLen, fp)
+    if (fread(_datagram, 1, _kBasicHeaderLen, fp)
         != (size_t)_kBasicHeaderLen)
     {
         reset();
@@ -83,6 +86,7 @@
     }
     _receiveTime = receiveTime;
     _datagramLen = _kBasicHeaderLen;
+    int header_length = _kBasicHeaderLen;
 
     // Parse the basic header
     WebRtcNetEQ_RTPInfo tempRTPinfo;
@@ -93,17 +97,18 @@
     if (X != 0 || CC != 0)
     {
         int newLen = _kBasicHeaderLen + CC * 4 + X * 4;
-        assert(_memSize >= newLen);
+        assert(_memSize >= newLen + 1);
 
         // Read extension from file
         size_t readLen = newLen - _kBasicHeaderLen;
-        if (fread((unsigned short *) _datagram + _kBasicHeaderLen, 1, readLen,
+        if (fread(_datagram + _kBasicHeaderLen, 1, readLen,
             fp) != readLen)
         {
             reset();
             return -1;
         }
         _datagramLen = newLen;
+        header_length = newLen;
 
         if (X != 0)
         {
@@ -112,16 +117,19 @@
 
             // Read extension from file
             size_t readLen = totHdrLen - newLen;
-            if (fread((unsigned short *) _datagram + newLen, 1, readLen, fp)
+            if (fread(_datagram + newLen, 1, readLen, fp)
                 != readLen)
             {
                 reset();
                 return -1;
             }
             _datagramLen = totHdrLen;
+            header_length = totHdrLen;
         }
     }
-    _datagramLen = length;
+    // Make sure that we have at least one byte of dummy payload.
+    _datagramLen = std::max(static_cast<int>(length), header_length + 1);
+    assert(_datagramLen <= _memSize);
 
     if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
     {
@@ -129,6 +137,12 @@
         return readFromFile(fp);
     }
 
+    if (_filterSSRC && _selectSSRC != SSRC())
+    {
+        // Discard this payload.
+        return(readFromFile(fp));
+    }
+
     return packetLen;
 
 }
diff --git a/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc b/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc
index fdc9662..ecca018 100644
--- a/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc
+++ b/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc
@@ -32,7 +32,9 @@
 _payloadLen(0),
 _rtpParsed(false),
 _receiveTime(0),
-_lost(false)
+_lost(false),
+_selectSSRC(0),
+_filterSSRC(false)
 {
     memset(&_rtpInfo, 0, sizeof(_rtpInfo));
     _blockList.clear();
@@ -157,6 +159,12 @@
         return(readFromFile(fp));
     }
 
+    if (_filterSSRC && _selectSSRC != SSRC())
+    {
+        // Discard this payload.
+        return(readFromFile(fp));
+    }
+
     return(packetLen);
 
 }
@@ -250,6 +258,11 @@
     _blockList[pt] = true;
 }
 
+void NETEQTEST_RTPpacket::selectSSRC(uint32_t ssrc)
+{
+    _selectSSRC = ssrc;
+    _filterSSRC = true;
+}
 
 void NETEQTEST_RTPpacket::parseHeader()
 {
diff --git a/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h b/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h
index a6d32dc..8ce04c5 100644
--- a/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h
+++ b/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h
@@ -36,6 +36,7 @@
     int readFixedFromFile(FILE *fp, size_t len);
     virtual int writeToFile(FILE *fp);
     void blockPT(WebRtc_UWord8 pt);
+    void selectSSRC(uint32_t ssrc);
     //WebRtc_Word16 payloadType();
     void parseHeader();
     void parseHeader(WebRtcNetEQ_RTPInfo & rtpInfo);
@@ -79,6 +80,8 @@
     WebRtc_UWord32        _receiveTime;
     bool                _lost;
     std::map<WebRtc_UWord8, bool> _blockList;
+    uint32_t            _selectSSRC;
+    bool                _filterSSRC;
 
 protected:
     static const int _kRDHeaderLen;
diff --git a/modules/audio_coding/neteq/test/NetEqRTPplay.cc b/modules/audio_coding/neteq/test/NetEqRTPplay.cc
index 7811be3..8aa88d8 100644
--- a/modules/audio_coding/neteq/test/NetEqRTPplay.cc
+++ b/modules/audio_coding/neteq/test/NetEqRTPplay.cc
@@ -185,6 +185,8 @@
     std::map<WebRtc_UWord8, decoderStruct> decoders;
     bool dummyRtp = false;
     bool noDecode = false;
+    bool filterSSRC = false;
+    uint32_t ssrc;
 
 #ifdef DEF_BUILD_DATE
     printf("Build time: %s\n", __BUILD_DATE);
@@ -224,6 +226,7 @@
         printf("\t-rtponly packLenBytes  : input file consists of constant size RTP packets without RTPplay headers\n");
         printf("\t-dummyrtp              : input file contains only RTP headers\n");
         printf("\t-nodecode              : no decoding will be done\n");
+        printf("\t-ssrc 0xNNNNNNNN       : discard all other SSRCs\n");
         //printf("\t-switchms              : switch from mono to stereo (copy channel) after 10 seconds\n");
         //printf("\t-duplicate             : use two instances with identical input (2-channel mono)\n");
 
@@ -321,6 +324,17 @@
             argIx++;
             noDecode = true;
         }
+        else if (strcmp(argv[argIx], "-ssrc") == 0)
+        {
+            argIx++;
+            filterSSRC = true;
+            if (sscanf(argv[argIx], "%X", &ssrc) != 1)
+            {
+                printf("Could not read SSRC argument.\n");
+                exit(1);
+            }
+            argIx++;
+        }
         //else if( strcmp(argv[argIx], "-switchms") == 0 ) {
         //    argIx++;
         //    switchMS = true;
@@ -407,6 +421,15 @@
         slaveRtp = new NETEQTEST_DummyRTPpacket();
     }
 
+    /* Uncomment and edit the line(s) below to block some payload types. */
+    //rtp->blockPT(72);
+    //rtp->blockPT(23);
+
+    /* Select a specific SSRC. */
+    if (filterSSRC) {
+        rtp->selectSSRC(ssrc);
+    }
+
     if (!rtpOnly)
     {
         while (rtp->readFromFile(in_file) >= 0)
@@ -440,11 +463,6 @@
 
     fseek(in_file, tempFilePos, SEEK_SET /* from beginning */);
 
-
-    /* block some payload types */
-    //rtp->blockPT(72);
-    //rtp->blockPT(23);
-
     /* read first packet */
     if (!rtpOnly)
     {
diff --git a/modules/audio_coding/neteq/test/RTPanalyze.cc b/modules/audio_coding/neteq/test/RTPanalyze.cc
index 4d7d573..6a4c6b1 100644
--- a/modules/audio_coding/neteq/test/RTPanalyze.cc
+++ b/modules/audio_coding/neteq/test/RTPanalyze.cc
@@ -37,7 +37,7 @@
   printf("Output file: %s\n\n", argv[2]);
 
   // Print file header.
-  fprintf(out_file, "SeqNo  TimeStamp   SendTime  Size    PT  M\n");
+  fprintf(out_file, "SeqNo  TimeStamp   SendTime  Size    PT  M       SSRC\n");
 
   // Read file header.
   NETEQTEST_RTPpacket::skipFileHeader(in_file);
@@ -49,9 +49,10 @@
 
   while (packet.readFromFile(in_file) >= 0) {
     // Write packet data to file.
-    fprintf(out_file, "%5u %10u %10u %5i %5i %2i\n",
+    fprintf(out_file, "%5u %10u %10u %5i %5i %2i %#08X\n",
             packet.sequenceNumber(), packet.timeStamp(), packet.time(),
-            packet.dataLen(), packet.payloadType(), packet.markerBit());
+            packet.dataLen(), packet.payloadType(), packet.markerBit(),
+            packet.SSRC());
     if (packet.payloadType() == kRedPayloadType) {
       WebRtcNetEQ_RTPInfo red_header;
       int len;
diff --git a/modules/audio_coding/neteq/test/RTPchange.cc b/modules/audio_coding/neteq/test/RTPchange.cc
index 259a773..bdd5ade 100644
--- a/modules/audio_coding/neteq/test/RTPchange.cc
+++ b/modules/audio_coding/neteq/test/RTPchange.cc
@@ -59,7 +59,7 @@
   uint32_t send_time;
 
   while (fscanf(stat_file,
-                "%hu %u %u %*i %*i\n", &seq_no, &ts, &send_time) == 3) {
+                "%hu %u %u %*i %*i %*i %*x\n", &seq_no, &ts, &send_time) == 3) {
     std::pair<uint16_t, uint32_t>
         temp_pair = std::pair<uint16_t, uint32_t>(seq_no, ts);
 
diff --git a/modules/audio_coding/neteq/webrtc_neteq.c b/modules/audio_coding/neteq/webrtc_neteq.c
index 47355c0..c9ca4c1 100644
--- a/modules/audio_coding/neteq/webrtc_neteq.c
+++ b/modules/audio_coding/neteq/webrtc_neteq.c
@@ -290,6 +290,9 @@
     MainInst_t *NetEqMainInst = (MainInst_t*) NETEQ_inst_Addr;
     *inst = NETEQ_inst_Addr;
     if (*inst == NULL) return (-1);
+
+    WebRtcSpl_Init();
+
     /* Clear memory */
     WebRtcSpl_MemSetW16((WebRtc_Word16*) NetEqMainInst, 0,
         (sizeof(MainInst_t) / sizeof(WebRtc_Word16)));
@@ -396,8 +399,6 @@
         return (-1);
     }
 
-    WebRtcSpl_Init();
-
 #ifdef NETEQ_VAD
     /* Start out with no PostDecode VAD instance */
     NetEqMainInst->DSPinst.VADInst.VADState = NULL;
diff --git a/modules/audio_coding/neteq/webrtc_neteq_unittest.cc b/modules/audio_coding/neteq/webrtc_neteq_unittest.cc
index fbb9cc2..0d0edfa 100644
--- a/modules/audio_coding/neteq/webrtc_neteq_unittest.cc
+++ b/modules/audio_coding/neteq/webrtc_neteq_unittest.cc
@@ -602,4 +602,32 @@
   EXPECT_GE(delay_after, delay_before - 20 * 16);
 }
 
+TEST_F(NetEqDecodingTest, NoInputDataStereo) {
+  void *ms_info;
+  ms_info = malloc(WebRtcNetEQ_GetMasterSlaveInfoSize());
+  neteq_inst_->setMaster();
+
+  // Slave instance without decoders (because it is easier).
+  WebRtcNetEQDecoder usedCodec[kDecoderReservedEnd - 1];
+  usedCodec[0] = kDecoderPCMu;
+  NETEQTEST_NetEQClass* slave_inst =
+      new NETEQTEST_NetEQClass(usedCodec, 1, 8000, kTCPLargeJitter);
+  ASSERT_TRUE(slave_inst);
+  NETEQTEST_Decoder* dec = new decoder_PCMU(0);
+  ASSERT_TRUE(dec != NULL);
+  dec->loadToNetEQ(*slave_inst);
+  slave_inst->setSlave();
+
+  // Pull out data.
+  const int kNumFrames = 100;
+  for (int i = 0; i < kNumFrames; ++i) {
+    ASSERT_TRUE(kBlockSize8kHz == neteq_inst_->recOut(out_data_, ms_info));
+    ASSERT_TRUE(kBlockSize8kHz == slave_inst->recOut(out_data_, ms_info));
+  }
+
+  delete dec;
+  delete slave_inst;
+  free(ms_info);
+}
+
 }  // namespace
diff --git a/modules/audio_device/android/audio_device_android_jni.cc b/modules/audio_device/android/audio_device_jni_android.cc
similarity index 99%
rename from modules/audio_device/android/audio_device_android_jni.cc
rename to modules/audio_device/android/audio_device_jni_android.cc
index 9f48c40..5934b28 100644
--- a/modules/audio_device/android/audio_device_android_jni.cc
+++ b/modules/audio_device/android/audio_device_jni_android.cc
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 
 #include "audio_device_utility.h"
-#include "audio_device_android_jni.h"
+#include "audio_device_jni_android.h"
 #include "audio_device_config.h"
 
 #include "trace.h"
diff --git a/modules/audio_device/android/audio_device_android_jni.h b/modules/audio_device/android/audio_device_jni_android.h
similarity index 97%
rename from modules/audio_device/android/audio_device_android_jni.h
rename to modules/audio_device/android/audio_device_jni_android.h
index 1e292e3..b8ea745 100644
--- a/modules/audio_device/android/audio_device_android_jni.h
+++ b/modules/audio_device/android/audio_device_jni_android.h
@@ -12,8 +12,8 @@
  *  Android audio device interface (JNI/AudioTrack/AudioRecord usage)
  */
 
-#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ANDROID_JNI_H
-#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ANDROID_JNI_H
+#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_JNI_ANDROID_H
+#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_JNI_ANDROID_H
 
 #include "audio_device_generic.h"
 #include "critical_section_wrapper.h"
@@ -270,4 +270,4 @@
 
 } // namespace webrtc
 
-#endif  // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ANDROID_JNI_H
+#endif  // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_JNI_ANDROID_H
diff --git a/modules/audio_device/android/audio_device_android_opensles.cc b/modules/audio_device/android/audio_device_opensles_android.cc
similarity index 99%
rename from modules/audio_device/android/audio_device_android_opensles.cc
rename to modules/audio_device/android/audio_device_opensles_android.cc
index f383c79..8d8e1f3 100644
--- a/modules/audio_device/android/audio_device_android_opensles.cc
+++ b/modules/audio_device/android/audio_device_opensles_android.cc
@@ -14,7 +14,7 @@
 #include <time.h>
 
 #include "audio_device_utility.h"
-#include "audio_device_android_opensles.h"
+#include "audio_device_opensles_android.h"
 #include "audio_device_config.h"
 
 #include "trace.h"
diff --git a/modules/audio_device/android/audio_device_android_opensles.h b/modules/audio_device/android/audio_device_opensles_android.h
similarity index 97%
rename from modules/audio_device/android/audio_device_android_opensles.h
rename to modules/audio_device/android/audio_device_opensles_android.h
index fc0e0a1..fabdc12 100644
--- a/modules/audio_device/android/audio_device_android_opensles.h
+++ b/modules/audio_device/android/audio_device_opensles_android.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ANDROID_OPENSLES_H
-#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ANDROID_OPENSLES_H
+#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_OPENSLES_ANDROID_H
+#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_OPENSLES_ANDROID_H
 
 #include "audio_device_generic.h"
 #include "critical_section_wrapper.h"
@@ -313,4 +313,4 @@
 
 } // namespace webrtc
 
-#endif  // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ANDROID_OPENSLES_H
+#endif  // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_OPENSLES_ANDROID_H
diff --git a/modules/audio_device/audio_device.gypi b/modules/audio_device/audio_device.gypi
index b8f77ea..640f732 100644
--- a/modules/audio_device/audio_device.gypi
+++ b/modules/audio_device/audio_device.gypi
@@ -122,13 +122,13 @@
               'conditions': [
                 ['enable_android_opensl==1', {
                   'sources': [
-                    'android/audio_device_android_opensles.cc',
-                    'android/audio_device_android_opensles.h',
+                    'android/audio_device_opensles_android.cc',
+                    'android/audio_device_opensles_android.h',
                   ],
                 }, {
                   'sources': [
-                    'android/audio_device_android_jni.cc',
-                    'android/audio_device_android_jni.h',
+                    'android/audio_device_jni_android.cc',
+                    'android/audio_device_jni_android.h',
                   ],
                 }],
               ],
diff --git a/modules/audio_device/audio_device_impl.cc b/modules/audio_device/audio_device_impl.cc
index fef1cbc..c7c87e6 100644
--- a/modules/audio_device/audio_device_impl.cc
+++ b/modules/audio_device/audio_device_impl.cc
@@ -25,11 +25,11 @@
 #elif defined(WEBRTC_ANDROID_OPENSLES)
     #include <stdlib.h>
     #include "audio_device_utility_android.h"
-    #include "audio_device_android_opensles.h"
+    #include "audio_device_opensles_android.h"
 #elif defined(WEBRTC_ANDROID)
     #include <stdlib.h>
     #include "audio_device_utility_android.h"
-    #include "audio_device_android_jni.h"
+    #include "audio_device_jni_android.h"
 #elif defined(WEBRTC_LINUX)
     #include "audio_device_utility_linux.h"
  #if defined(LINUX_ALSA)
@@ -111,6 +111,8 @@
         return NULL;
     }
 
+    WebRtcSpl_Init();
+
     return audioDevice;
 }
 
@@ -608,8 +610,6 @@
     if (!_ptrAudioDevice)
         return -1;
 
-    WebRtcSpl_Init();
-
     _ptrAudioDeviceUtility->Init();
 
     if (_ptrAudioDevice->Init() == -1)
diff --git a/modules/audio_processing/aecm/echo_control_mobile.c b/modules/audio_processing/aecm/echo_control_mobile.c
index b238b2d..d0b90d4 100644
--- a/modules/audio_processing/aecm/echo_control_mobile.c
+++ b/modules/audio_processing/aecm/echo_control_mobile.c
@@ -110,6 +110,8 @@
         return -1;
     }
 
+    WebRtcSpl_Init();
+
     aecm->initFlag = 0;
     aecm->lastError = 0;
 
@@ -171,8 +173,6 @@
     }
     aecm->sampFreq = sampFreq;
 
-    WebRtcSpl_Init();
-
     // Initialize AECM core
     if (WebRtcAecm_InitCore(aecm->aecmCore, aecm->sampFreq) == -1)
     {
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
index d3f180f..e24d1e0 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
@@ -43,8 +43,6 @@
         'remote_rate_control.cc',
         'remote_rate_control.h',
         'rtp_to_ntp.cc',
-        '../../video_engine/stream_synchronization.cc',
-        '../../video_engine/stream_synchronization.h',
       ], # source
     },
   ], # targets
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc
index ebf767c..e98c704 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc
@@ -145,7 +145,13 @@
   if (!remote_rate_.ValidEstimate()) {
     return false;
   }
-  *bitrate_bps = remote_rate_.LatestEstimate();
+  // TODO(holmer): For now we're returning the estimate bandwidth per stream as
+  // it corresponds better to how the ViE API is designed. Will fix this when
+  // the API changes.
+  if (streams_.size() > 0)
+    *bitrate_bps = remote_rate_.LatestEstimate() / streams_.size();
+  else
+    *bitrate_bps = remote_rate_.LatestEstimate();
   return true;
 }
 
diff --git a/system_wrappers/interface/aligned_malloc.h b/system_wrappers/interface/aligned_malloc.h
index 3fda6b6..662acab 100644
--- a/system_wrappers/interface/aligned_malloc.h
+++ b/system_wrappers/interface/aligned_malloc.h
@@ -34,7 +34,19 @@
 // be de-allocated using AlignedFree.
 void* AlignedMalloc(size_t size, size_t alignment);
 // De-allocates memory created using the AlignedMalloc() API.
-void AlignedFree(void* memBlock);
+void AlignedFree(void* mem_block);
+
+// Templated versions to facilitate usage of aligned malloc without casting
+// to and from void*.
+template<typename T>
+T* GetRightAlign(const T* ptr, size_t alignment) {
+  return reinterpret_cast<T*>(GetRightAlign(reinterpret_cast<const void*>(ptr),
+                                            alignment));
+}
+template<typename T>
+T* AlignedMalloc(size_t size, size_t alignment) {
+  return reinterpret_cast<T*>(AlignedMalloc(size, alignment));
+}
 
 // Scoped pointer to AlignedMalloc-memory.
 template<typename T>
diff --git a/system_wrappers/interface/thread_wrapper.h b/system_wrappers/interface/thread_wrapper.h
index 030ac8a..cda4827 100644
--- a/system_wrappers/interface/thread_wrapper.h
+++ b/system_wrappers/interface/thread_wrapper.h
@@ -65,8 +65,12 @@
     // to delete this class until the spawned thread has been reclaimed.
     virtual void SetNotAlive() = 0;
 
-    // Spawns the thread. This will start the triggering of the callback
-    // function.
+    // Tries to spawns a thread and returns true if that was successful.
+    // Additionally, it tries to set thread priority according to the priority
+    // from when CreateThread was called. However, failure to set priority will
+    // not result in a false return value.
+    // TODO(henrike): add a function for polling whether priority was set or
+    //                not.
     virtual bool Start(unsigned int& id) = 0;
 
     // Sets the threads CPU affinity. CPUs are listed 0 - (number of CPUs - 1).
diff --git a/system_wrappers/source/aligned_malloc.cc b/system_wrappers/source/aligned_malloc.cc
index 3dd281f..c8efb42 100644
--- a/system_wrappers/source/aligned_malloc.cc
+++ b/system_wrappers/source/aligned_malloc.cc
@@ -27,14 +27,14 @@
 // TODO(henrike): better to create just one memory block and interpret the
 //                first sizeof(AlignedMemory) bytes as an AlignedMemory struct.
 struct AlignedMemory {
-  void* alignedBuffer;
-  void* memoryPointer;
+  void* aligned_buffer;
+  void* memory_pointer;
 };
 
-uintptr_t GetRightAlign(uintptr_t startPos, size_t alignment) {
+uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
   // The pointer should be aligned with |alignment| bytes. The - 1 guarantees
   // that it is aligned towards the closest higher (right) address.
-  return (startPos + alignment - 1) & ~(alignment - 1);
+  return (start_pos + alignment - 1) & ~(alignment - 1);
 }
 
 // Alignment must be an integer power of two.
@@ -52,8 +52,8 @@
   if (!ValidAlignment(alignment)) {
     return NULL;
   }
-  uintptr_t startPos = reinterpret_cast<uintptr_t>(ptr);
-  return reinterpret_cast<void*>(GetRightAlign(startPos, alignment));
+  uintptr_t start_pos = reinterpret_cast<uintptr_t>(ptr);
+  return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
 }
 
 void* AlignedMalloc(size_t size, size_t alignment) {
@@ -64,8 +64,8 @@
     return NULL;
   }
 
-  AlignedMemory* returnValue = new AlignedMemory();
-  if (returnValue == NULL) {
+  AlignedMemory* return_value = new AlignedMemory();
+  if (return_value == NULL) {
     return NULL;
   }
 
@@ -73,46 +73,46 @@
   // alignment - 1 bytes needs to be allocated.
   // A pointer to AlignedMemory must be stored so that it can be retreived for
   // deletion, ergo the sizeof(uintptr_t).
-  returnValue->memoryPointer = malloc(size + sizeof(uintptr_t) +
-                                      alignment - 1);
-  if (returnValue->memoryPointer == NULL) {
-    delete returnValue;
+  return_value->memory_pointer = malloc(size + sizeof(uintptr_t) +
+                                        alignment - 1);
+  if (return_value->memory_pointer == NULL) {
+    delete return_value;
     return NULL;
   }
 
   // Aligning after the sizeof(header) bytes will leave room for the header
   // in the same memory block.
-  uintptr_t alignStartPos =
-      reinterpret_cast<uintptr_t>(returnValue->memoryPointer);
-  alignStartPos += sizeof(uintptr_t);
-  uintptr_t alignedPos = GetRightAlign(alignStartPos, alignment);
-  returnValue->alignedBuffer = reinterpret_cast<void*>(alignedPos);
+  uintptr_t align_start_pos =
+      reinterpret_cast<uintptr_t>(return_value->memory_pointer);
+  align_start_pos += sizeof(uintptr_t);
+  uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
+  return_value->aligned_buffer = reinterpret_cast<void*>(aligned_pos);
 
   // Store the address to the AlignedMemory struct in the header so that a
   // it's possible to reclaim all memory.
-  uintptr_t headerPos = alignedPos;
-  headerPos -= sizeof(uintptr_t);
-  void* headerPtr = reinterpret_cast<void*>(headerPos);
-  uintptr_t headerValue = reinterpret_cast<uintptr_t>(returnValue);
-  memcpy(headerPtr,&headerValue,sizeof(uintptr_t));
-  return returnValue->alignedBuffer;
+  uintptr_t header_pos = aligned_pos;
+  header_pos -= sizeof(uintptr_t);
+  void* header_ptr = reinterpret_cast<void*>(header_pos);
+  uintptr_t header_value = reinterpret_cast<uintptr_t>(return_value);
+  memcpy(header_ptr, &header_value, sizeof(uintptr_t));
+  return return_value->aligned_buffer;
 }
 
-void AlignedFree(void* memBlock) {
-  if (memBlock == NULL) {
+void AlignedFree(void* mem_block) {
+  if (mem_block == NULL) {
     return;
   }
-  uintptr_t alignedPos = reinterpret_cast<uintptr_t>(memBlock);
-  uintptr_t headerPos = alignedPos - sizeof(uintptr_t);
+  uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
+  uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
 
   // Read out the address of the AlignedMemory struct from the header.
-  uintptr_t* headerPtr = reinterpret_cast<uintptr_t*>(headerPos);
-  AlignedMemory* deleteMemory = reinterpret_cast<AlignedMemory*>(*headerPtr);
+  uintptr_t* header_ptr = reinterpret_cast<uintptr_t*>(header_pos);
+  AlignedMemory* delete_memory = reinterpret_cast<AlignedMemory*>(*header_ptr);
 
-  if (deleteMemory->memoryPointer != NULL) {
-    free(deleteMemory->memoryPointer);
+  if (delete_memory->memory_pointer != NULL) {
+    free(delete_memory->memory_pointer);
   }
-  delete deleteMemory;
+  delete delete_memory;
 }
 
 }  // namespace webrtc
diff --git a/system_wrappers/source/aligned_malloc_unittest.cc b/system_wrappers/source/aligned_malloc_unittest.cc
index 9c6223c..42e13c5 100644
--- a/system_wrappers/source/aligned_malloc_unittest.cc
+++ b/system_wrappers/source/aligned_malloc_unittest.cc
@@ -23,7 +23,7 @@
 // Returns true if |size| and |alignment| are valid combinations.
 bool CorrectUsage(size_t size, size_t alignment) {
   webrtc::Allocator<char>::scoped_ptr_aligned scoped(
-    static_cast<char*> (webrtc::AlignedMalloc(size, alignment)));
+      webrtc::AlignedMalloc<char>(size, alignment));
   if (scoped.get() == NULL) {
     return false;
   }
@@ -36,14 +36,15 @@
   const size_t alignment = 32;
   const size_t left_missalignment = 8;
   webrtc::Allocator<char>::scoped_ptr_aligned scoped(
-    static_cast<char*> (webrtc::AlignedMalloc(size, alignment)));
+      webrtc::AlignedMalloc<char>(size, alignment));
   EXPECT_TRUE(scoped.get() != NULL);
   const uintptr_t aligned_address = reinterpret_cast<uintptr_t> (scoped.get());
   const uintptr_t missaligned_address = aligned_address - left_missalignment;
-  const void* missaligned_ptr =  reinterpret_cast<void*> (missaligned_address);
-  const void* realignedPtr = webrtc::GetRightAlign(
-    missaligned_ptr, alignment);
-  EXPECT_EQ(scoped.get(), realignedPtr);
+  const char* missaligned_ptr = reinterpret_cast<const char*>(
+      missaligned_address);
+  const char* realigned_ptr = webrtc::GetRightAlign(
+      missaligned_ptr, alignment);
+  EXPECT_EQ(scoped.get(), realigned_ptr);
 }
 
 TEST(AlignedMalloc, IncorrectSize) {
diff --git a/system_wrappers/source/system_wrappers.gyp b/system_wrappers/source/system_wrappers.gyp
index dcde1c7..f834709 100644
--- a/system_wrappers/source/system_wrappers.gyp
+++ b/system_wrappers/source/system_wrappers.gyp
@@ -216,6 +216,7 @@
             'data_log_c_helpers_unittest.c',
             'data_log_c_helpers_unittest.h',
             'thread_unittest.cc',
+            'thread_posix_unittest.cc',
             'trace_unittest.cc',
             'unittest_utilities_unittest.cc',
           ],
@@ -225,6 +226,9 @@
             }, {
               'sources!': [ 'data_log_unittest.cc', ],
             }],
+            ['os_posix!=1', {
+              'sources!': [ 'thread_posix_unittest.cc', ],
+            }],
           ],
         },
       ], # targets
diff --git a/system_wrappers/source/thread_posix.cc b/system_wrappers/source/thread_posix.cc
index 14b3338..35c9f81 100644
--- a/system_wrappers/source/thread_posix.cc
+++ b/system_wrappers/source/thread_posix.cc
@@ -44,6 +44,9 @@
 
 #include "thread_posix.h"
 
+#include <algorithm>
+
+#include <assert.h>
 #include <errno.h>
 #include <string.h> // strncpy
 #include <time.h>   // nanosleep
@@ -65,6 +68,32 @@
 #include "system_wrappers/interface/trace.h"
 
 namespace webrtc {
+
+int ConvertToSystemPriority(ThreadPriority priority, int minPrio, int maxPrio)
+{
+    assert(maxPrio - minPrio > 2);
+    const int topPrio = maxPrio - 1;
+    const int lowPrio = minPrio + 1;
+
+    switch (priority)
+    {
+    case kLowPriority:
+        return lowPrio;
+    case kNormalPriority:
+        // The -1 ensures that the kHighPriority is always greater or equal to
+        // kNormalPriority.
+        return (lowPrio + topPrio - 1) / 2;
+    case kHighPriority:
+        return std::max(topPrio - 2, lowPrio);
+    case kHighestPriority:
+        return std::max(topPrio - 1, lowPrio);
+    case kRealtimePriority:
+        return topPrio;
+    }
+    assert(false);
+    return lowPrio;
+}
+
 extern "C"
 {
     static void* StartThread(void* lpParameter)
@@ -177,6 +206,11 @@
     const int policy = SCHED_FIFO;
 #endif
     _event->Reset();
+    // If pthread_create was successful, a thread was created and is running.
+    // Don't return false if it was successful since if there are any other
+    // failures the state will be: thread was started but not configured as
+    // asked for. However, the caller of this API will assume that a false
+    // return value means that the thread never started.
     result |= pthread_create(&_thread, &_attr, &StartThread, this);
     if (result != 0)
     {
@@ -187,9 +221,11 @@
     // race condition if Stop() is called too quickly after start.
     if (kEventSignaled != _event->Wait(WEBRTC_EVENT_10_SEC))
     {
+        WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
+                     "posix thread event never triggered");
         // Timed out. Something went wrong.
         _runFunction = NULL;
-        return false;
+        return true;
     }
 
 #if HAS_THREAD_ID
@@ -201,31 +237,21 @@
     const int maxPrio = sched_get_priority_max(policy);
     if ((minPrio == EINVAL) || (maxPrio == EINVAL))
     {
-        return false;
+        WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
+                     "unable to retreive min or max priority for threads");
+        return true;
     }
-
-    switch (_prio)
+    if (maxPrio - minPrio <= 2)
     {
-    case kLowPriority:
-        param.sched_priority = minPrio + 1;
-        break;
-    case kNormalPriority:
-        param.sched_priority = (minPrio + maxPrio) / 2;
-        break;
-    case kHighPriority:
-        param.sched_priority = maxPrio - 3;
-        break;
-    case kHighestPriority:
-        param.sched_priority = maxPrio - 2;
-        break;
-    case kRealtimePriority:
-        param.sched_priority = maxPrio - 1;
-        break;
+      // There is no room for setting priorities with any granularity.
+      return true;
     }
+    param.sched_priority = ConvertToSystemPriority(_prio, minPrio, maxPrio);
     result = pthread_setschedparam(_thread, policy, &param);
     if (result == EINVAL)
     {
-        return false;
+        WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
+                     "unable to set thread priority");
     }
     return true;
 }
@@ -344,7 +370,7 @@
 #ifdef WEBRTC_LINUX
         prctl(PR_SET_NAME, (unsigned long)_name, 0, 0, 0);
 #endif
-        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
+        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                      "Thread with name:%s started ", _name);
     } else
     {
@@ -382,13 +408,13 @@
         // coupling the thread and the trace class like this.
         if (strcmp(_name, "Trace"))
         {
-            WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
+            WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                          "Thread with name:%s stopped", _name);
         }
     }
     else
     {
-        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
+        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                      "Thread without name stopped");
     }
     {
diff --git a/system_wrappers/source/thread_posix.h b/system_wrappers/source/thread_posix.h
index 45489a8..8fcdf10 100644
--- a/system_wrappers/source/thread_posix.h
+++ b/system_wrappers/source/thread_posix.h
@@ -19,6 +19,8 @@
 class CriticalSectionWrapper;
 class EventWrapper;
 
+int ConvertToSystemPriority(ThreadPriority priority, int minPrio, int maxPrio);
+
 class ThreadPosix : public ThreadWrapper
 {
 public:
diff --git a/system_wrappers/source/thread_posix_unittest.cc b/system_wrappers/source/thread_posix_unittest.cc
new file mode 100644
index 0000000..8d62371
--- /dev/null
+++ b/system_wrappers/source/thread_posix_unittest.cc
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "system_wrappers/source/thread_posix.h"
+
+#include "gtest/gtest.h"
+
+TEST(ThreadTestPosix, PrioritySettings) {
+  // API assumes that maxPrio - minPrio > 2. Test the extreme case.
+  const int kMinPrio = -1;
+  const int kMaxPrio = 2;
+
+  int last_priority = kMinPrio;
+  for (int priority = webrtc::kLowPriority;
+       priority <= webrtc::kRealtimePriority; ++priority) {
+    int system_priority = webrtc::ConvertToSystemPriority(
+        static_cast<webrtc::ThreadPriority>(priority), kMinPrio, kMaxPrio);
+    EXPECT_GT(system_priority, kMinPrio);
+    EXPECT_LT(system_priority, kMaxPrio);
+    EXPECT_GE(system_priority, last_priority);
+    last_priority = system_priority;
+  }
+}
diff --git a/system_wrappers/source/thread_unittest.cc b/system_wrappers/source/thread_unittest.cc
index 361424a..6bbe136 100644
--- a/system_wrappers/source/thread_unittest.cc
+++ b/system_wrappers/source/thread_unittest.cc
@@ -11,6 +11,7 @@
 #include "system_wrappers/interface/thread_wrapper.h"
 
 #include "gtest/gtest.h"
+#include "system_wrappers/interface/scoped_ptr.h"
 #include "system_wrappers/interface/trace.h"
 
 namespace webrtc {
@@ -60,6 +61,13 @@
   TestTraceCallback trace_;
 };
 
+TEST_F(ThreadTest, NullFunctionPointer) {
+  webrtc::scoped_ptr<ThreadWrapper> thread(
+      webrtc::ThreadWrapper::CreateThread());
+  unsigned int id = 42;
+  EXPECT_FALSE(thread->Start(id));
+}
+
 // Function that does nothing, and reports success.
 bool NullRunFunction(void* /* obj */) {
   return true;
diff --git a/system_wrappers/source/thread_win.cc b/system_wrappers/source/thread_win.cc
index 07c586a..f458e0e 100644
--- a/system_wrappers/source/thread_win.cc
+++ b/system_wrappers/source/thread_win.cc
@@ -75,6 +75,9 @@
 
 bool ThreadWindows::Start(unsigned int& threadID)
 {
+    if (!_runFunction) {
+      return false;
+    }
     _doNotCloseHandle = false;
 
     // Set stack size to 1M
diff --git a/video_engine/test/android/jni/Android.mk b/video_engine/test/android/jni/Android.mk
index 15ec8a0..7688d19 100644
--- a/video_engine/test/android/jni/Android.mk
+++ b/video_engine/test/android/jni/Android.mk
@@ -8,6 +8,8 @@
 
 LOCAL_PATH := $(call my-dir)
 
+include $(call all-makefiles-under, $(LOCAL_PATH))
+
 MY_LIBS_PATH := ../../../../../out/Debug/obj.target
 
 include $(CLEAR_VARS)
@@ -311,6 +313,7 @@
     libjpeg_turbo \
     libaudioproc_debug_proto \
     libprotobuf_lite \
-    libvpx
+    libvpx \
+    $(MY_SUPPLEMENTAL_LIBS)
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/video_engine/test/auto_test/primitives/choice_helpers.cc b/video_engine/test/auto_test/primitives/choice_helpers.cc
index 6feea4a..6807d73 100644
--- a/video_engine/test/auto_test/primitives/choice_helpers.cc
+++ b/video_engine/test/auto_test/primitives/choice_helpers.cc
@@ -17,39 +17,16 @@
 
 namespace webrtc {
 
-static const int kNoDefault = 0;
-
 ChoiceBuilder::ChoiceBuilder(const Choices& choices)
-    : choices_(choices), default_choice_(kNoDefault), input_source_(stdin) {
+    : choices_(choices),
+      input_helper_(new IntegerWithinRangeValidator(1, choices.size())) {
 }
 
 int ChoiceBuilder::Choose() {
-  if (!title_.empty()) {
-    printf("\n%s\n", title_.c_str());
-  }
-
-  Choices::const_iterator iterator = choices_.begin();
-  for (int number = 1; iterator != choices_.end(); ++iterator, ++number)
-    printf("  %d. %s\n", number, (*iterator).c_str());
-
-  if (default_choice_ != kNoDefault)
-    printf("  Hit enter for default (%s):\n", default_choice_text_.c_str());
-  printf("# ");
-  char input[8];
-  if (!fgets(input, 8, input_source_))
-    input[0] = '0';  // Make the selection fail
-  int selection;
-  if (input[0] == '\n')
-    selection = default_choice_;
-  else
-    selection = atoi(input);
-
-  if (selection < 1 || selection > static_cast<int>(choices_.size())) {
-    printf("Please select one of the given options.\n");
-    return Choose();
-  }
-
-  return selection;
+  std::string input = input_helper_
+      .WithTitle(MakeTitleWithOptions())
+      .AskForInput();
+  return atoi(input.c_str());
 }
 
 ChoiceBuilder& ChoiceBuilder::WithDefault(const std::string& default_choice) {
@@ -58,13 +35,16 @@
   assert(iterator != choices_.end() && "No such choice.");
 
   // Store the value as the choice number, e.g. its index + 1.
-  default_choice_ = (iterator - choices_.begin()) + 1;
-  default_choice_text_ = default_choice;
+  int choice_index = (iterator - choices_.begin()) + 1;
+  char number[16];
+  sprintf(number, "%d", choice_index);
+
+  input_helper_.WithDefault(number);
   return *this;
 }
 
 ChoiceBuilder& ChoiceBuilder::WithInputSource(FILE* input_source) {
-  input_source_ = input_source;
+  input_helper_.WithInputSource(input_source);
   return *this;
 }
 
@@ -73,6 +53,17 @@
   return *this;
 }
 
+std::string ChoiceBuilder::MakeTitleWithOptions() {
+  std::string title_with_options = title_;
+  Choices::const_iterator iterator = choices_.begin();
+  for (int number = 1; iterator != choices_.end(); ++iterator, ++number) {
+    char buffer[128];
+    sprintf(buffer, "\n  %d. %s", number, (*iterator).c_str());
+    title_with_options += buffer;
+  }
+  return title_with_options;
+}
+
 Choices SplitChoices(const std::string& raw_choices) {
   Choices result;
   size_t current_pos = 0;
diff --git a/video_engine/test/auto_test/primitives/choice_helpers.h b/video_engine/test/auto_test/primitives/choice_helpers.h
index 25c26e1..50ea68d 100644
--- a/video_engine/test/auto_test/primitives/choice_helpers.h
+++ b/video_engine/test/auto_test/primitives/choice_helpers.h
@@ -14,6 +14,8 @@
 #include <string>
 #include <vector>
 
+#include "video_engine/test/auto_test/primitives/input_helpers.h"
+
 namespace webrtc {
 
 typedef std::vector<std::string> Choices;
@@ -52,13 +54,12 @@
   // Prints the choice list and requests input from the input source. Returns
   // the choice number (choices start at 1).
   int Choose();
-
  private:
+  std::string MakeTitleWithOptions();
+
   Choices choices_;
-  int default_choice_;
-  std::string default_choice_text_;
+  InputBuilder input_helper_;
   std::string title_;
-  FILE* input_source_;
 };
 
 // Convenience function that creates a choice builder given a string where
diff --git a/video_engine/test/auto_test/primitives/choice_helpers_unittest.cc b/video_engine/test/auto_test/primitives/choice_helpers_unittest.cc
index 3c4d45c..dd5ac89 100644
--- a/video_engine/test/auto_test/primitives/choice_helpers_unittest.cc
+++ b/video_engine/test/auto_test/primitives/choice_helpers_unittest.cc
@@ -12,21 +12,7 @@
 
 #include "gtest/gtest.h"
 #include "video_engine/test/auto_test/primitives/choice_helpers.h"
-
-namespace {
-
-FILE* FakeStdin(const std::string& input) {
-  FILE* fake_stdin = tmpfile();
-
-  EXPECT_EQ(input.size(),
-      fwrite(input.c_str(), sizeof(char), input.size(), fake_stdin));
-  rewind(fake_stdin);
-
-  return fake_stdin;
-}
-
-}  // namespace
-
+#include "video_engine/test/auto_test/primitives/fake_stdin.h"
 
 namespace webrtc {
 
diff --git a/video_engine/test/auto_test/primitives/fake_stdin.cc b/video_engine/test/auto_test/primitives/fake_stdin.cc
new file mode 100644
index 0000000..4952901
--- /dev/null
+++ b/video_engine/test/auto_test/primitives/fake_stdin.cc
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "video_engine/test/auto_test/primitives/fake_stdin.h"
+
+namespace webrtc {
+
+FILE* FakeStdin(const std::string& input) {
+  FILE* fake_stdin = tmpfile();
+
+  EXPECT_EQ(input.size(),
+      fwrite(input.c_str(), sizeof(char), input.size(), fake_stdin));
+  rewind(fake_stdin);
+
+  return fake_stdin;
+}
+
+}  // namespace webrtc
diff --git a/video_engine/test/auto_test/primitives/fake_stdin.h b/video_engine/test/auto_test/primitives/fake_stdin.h
new file mode 100644
index 0000000..5e0854f
--- /dev/null
+++ b/video_engine/test/auto_test/primitives/fake_stdin.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef FAKE_STDIN_H_
+#define FAKE_STDIN_H_
+
+#include <cstdio>
+#include <string>
+
+#include "gtest/gtest.h"
+
+namespace webrtc {
+
+// Creates a fake stdin-like FILE* for unit test usage.
+FILE* FakeStdin(const std::string& input);
+
+}  // namespace webrtc
+
+#endif  // FAKE_STDIN_H_
diff --git a/video_engine/test/auto_test/primitives/input_helpers.cc b/video_engine/test/auto_test/primitives/input_helpers.cc
new file mode 100644
index 0000000..c11da77
--- /dev/null
+++ b/video_engine/test/auto_test/primitives/input_helpers.cc
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "video_engine/test/auto_test/primitives/input_helpers.h"
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <algorithm>
+
+#include "gflags/gflags.h"
+
+namespace webrtc {
+
+DEFINE_bool(choose_defaults, false,
+    "Make the default choice at every choice when running a custom call.");
+
+class AcceptAllNonEmptyValidator : public InputValidator {
+ public:
+  bool InputOk(const std::string& value) const {
+    return value.length() > 0;
+  }
+};
+
+InputBuilder::InputBuilder(const InputValidator* input_validator)
+    : input_source_(stdin), input_validator_(input_validator),
+      default_value_("") {
+}
+
+InputBuilder::~InputBuilder() {
+  delete input_validator_;
+}
+
+std::string InputBuilder::AskForInput() const {
+  if (FLAGS_choose_defaults && !default_value_.empty())
+    return default_value_;
+  if (!title_.empty())
+    printf("\n%s\n", title_.c_str());
+
+  if (!default_value_.empty())
+    printf("Hit enter for default (%s):\n", default_value_.c_str());
+
+  printf("# ");
+  char raw_input[128];
+  if (!fgets(raw_input, 128, input_source_)) {
+    // If we get here the user probably hit CTRL+D.
+    exit(1);
+  }
+
+  std::string input = raw_input;
+  input = input.substr(0, input.size() - 1);  // Strip last \n.
+
+  if (input.empty() && !default_value_.empty())
+    return default_value_;
+
+  if (!input_validator_->InputOk(input)) {
+    printf("Invalid input. Please try again.\n");
+    return AskForInput();
+  }
+  return input;
+}
+
+InputBuilder& InputBuilder::WithInputSource(FILE* input_source) {
+  input_source_ = input_source;
+  return *this;
+}
+
+InputBuilder& InputBuilder::WithInputValidator(
+    const InputValidator* input_validator) {
+  // If there's a default value, it must be accepted by the input validator.
+  assert(default_value_.empty() || input_validator->InputOk(default_value_));
+  delete input_validator_;
+  input_validator_ = input_validator;
+  return *this;
+}
+
+InputBuilder& InputBuilder::WithDefault(const std::string& default_value) {
+  assert(input_validator_->InputOk(default_value));
+  default_value_ = default_value;
+  return *this;
+}
+
+InputBuilder& InputBuilder::WithTitle(const std::string& title) {
+  title_ = title;
+  return *this;
+}
+
+InputBuilder TypedInput() {
+  return InputBuilder(new AcceptAllNonEmptyValidator());
+}
+
+}  // namespace webrtc
diff --git a/video_engine/test/auto_test/primitives/input_helpers.h b/video_engine/test/auto_test/primitives/input_helpers.h
new file mode 100644
index 0000000..4def929
--- /dev/null
+++ b/video_engine/test/auto_test/primitives/input_helpers.h
@@ -0,0 +1,82 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_VIDEO_ENGINE_TEST_AUTO_TEST_PRIMITIVES_
+#define WEBRTC_VIDEO_ENGINE_TEST_AUTO_TEST_PRIMITIVES_
+
+#include <cstdlib>
+
+#include <string>
+
+namespace webrtc {
+
+class InputValidator {
+ public:
+  virtual ~InputValidator() {}
+
+  virtual bool InputOk(const std::string& value) const = 0;
+};
+
+class InputBuilder {
+ public:
+  // The input builder takes ownership of the validator.
+  explicit InputBuilder(const InputValidator* input_validator);
+  ~InputBuilder();
+
+  // Ask the user for input, reads input from the input source and returns
+  // the answer. This method will keep asking the user until a correct answer
+  // is returned and is thereby guaranteed to return a response that is
+  // acceptable to the input validator.
+  std::string AskForInput() const;
+
+  // Replaces the input source where we ask for input. Default is stdin.
+  InputBuilder& WithInputSource(FILE* input_source);
+
+  // Sets the input validator. The input builder takes ownership. If a default
+  // value has been set, it must be acceptable to this validator.
+  InputBuilder& WithInputValidator(const InputValidator* input_validator);
+  // Sets a default value if the user doesn't want to give input. This value
+  // must be acceptable to the input validator.
+  InputBuilder& WithDefault(const std::string& default_value);
+  // Prints a title before querying the user.
+  InputBuilder& WithTitle(const std::string& title);
+
+ private:
+  FILE* input_source_;
+  const InputValidator* input_validator_;
+  std::string default_value_;
+  std::string title_;
+};
+
+// Ensures input is an integer between low and high (inclusive).
+class IntegerWithinRangeValidator : public InputValidator {
+ public:
+  IntegerWithinRangeValidator(int low, int high)
+      : low_(low), high_(high) {}
+
+  bool InputOk(const std::string& input) const {
+    int value = atoi(input.c_str());
+    // Note: atoi returns 0 on failure.
+    if (value == 0 && input.length() > 0 && input[0] != '0')
+      return false;  // Probably bad input.
+    return value >= low_ && value <= high_;
+  }
+
+ private:
+  int low_;
+  int high_;
+};
+
+// Convenience method for creating an input builder.
+InputBuilder TypedInput();
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_VIDEO_ENGINE_TEST_AUTO_TEST_PRIMITIVES_
diff --git a/video_engine/test/auto_test/primitives/input_helpers_unittest.cc b/video_engine/test/auto_test/primitives/input_helpers_unittest.cc
new file mode 100644
index 0000000..2876a30
--- /dev/null
+++ b/video_engine/test/auto_test/primitives/input_helpers_unittest.cc
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "gtest/gtest.h"
+#include "video_engine/test/auto_test/primitives/fake_stdin.h"
+#include "video_engine/test/auto_test/primitives/input_helpers.h"
+
+namespace webrtc {
+
+class InputHelpersTest: public testing::Test {
+};
+
+TEST_F(InputHelpersTest, AcceptsAnyInputExceptEmptyByDefault) {
+  FILE* fake_stdin = FakeStdin("\n\nWhatever\n");
+  std::string result = TypedInput().WithInputSource(fake_stdin).AskForInput();
+  EXPECT_EQ("Whatever", result);
+  fclose(fake_stdin);
+}
+
+TEST_F(InputHelpersTest, ReturnsDefaultOnEmptyInputIfDefaultSet) {
+  FILE* fake_stdin = FakeStdin("\n\nWhatever\n");
+  std::string result = TypedInput()
+      .WithInputSource(fake_stdin)
+      .WithDefault("MyDefault")
+      .AskForInput();
+  EXPECT_EQ("MyDefault", result);
+  fclose(fake_stdin);
+}
+
+TEST_F(InputHelpersTest, CanSetTitle) {
+  FILE* fake_stdin = FakeStdin("\n\nWhatever\n");
+  std::string result = TypedInput()
+      .WithInputSource(fake_stdin)
+      .WithTitle("Make a choice!")
+      .AskForInput();
+  EXPECT_EQ("Whatever", result);
+  fclose(fake_stdin);
+}
+
+TEST_F(InputHelpersTest, ObeysInputValidator) {
+  class ValidatorWhichOnlyAcceptsFooBar : public InputValidator {
+   public:
+    bool InputOk(const std::string& input) const {
+      return input == "FooBar";
+    }
+  };
+  FILE* fake_stdin = FakeStdin("\nFoo\nBar\nFoo Bar\nFooBar\n");
+  std::string result = TypedInput()
+      .WithInputSource(fake_stdin)
+      .WithInputValidator(new ValidatorWhichOnlyAcceptsFooBar())
+      .AskForInput();
+  EXPECT_EQ("FooBar", result);
+  fclose(fake_stdin);
+}
+};
diff --git a/video_engine/test/auto_test/source/vie_autotest_custom_call.cc b/video_engine/test/auto_test/source/vie_autotest_custom_call.cc
index 16cf0c7..bce0b74 100644
--- a/video_engine/test/auto_test/source/vie_autotest_custom_call.cc
+++ b/video_engine/test/auto_test/source/vie_autotest_custom_call.cc
@@ -8,30 +8,34 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <climits>
 #include <cstdarg>
 #include <cstdio>
 
+#include <algorithm>
+
 #include "video_engine/test/auto_test/interface/vie_autotest.h"
 #include "video_engine/test/auto_test/interface/vie_autotest_defines.h"
 #include "video_engine/test/auto_test/primitives/choice_helpers.h"
+#include "video_engine/test/auto_test/primitives/input_helpers.h"
 
 #define VCM_RED_PAYLOAD_TYPE                            96
 #define VCM_ULPFEC_PAYLOAD_TYPE                         97
 #define DEFAULT_SEND_IP                                 "127.0.0.1"
-#define DEFAULT_VIDEO_PORT                              11111
+#define DEFAULT_VIDEO_PORT                              "11111"
 #define DEFAULT_VIDEO_CODEC                             "VP8"
-#define DEFAULT_VIDEO_CODEC_WIDTH                       640
-#define DEFAULT_VIDEO_CODEC_HEIGHT                      480
-#define DEFAULT_VIDEO_CODEC_BITRATE                     300
-#define DEFAULT_VIDEO_CODEC_MIN_BITRATE                 100
-#define DEFAULT_VIDEO_CODEC_MAX_BITRATE                 1000
-#define DEFAULT_AUDIO_PORT                              11113
+#define DEFAULT_VIDEO_CODEC_WIDTH                       "640"
+#define DEFAULT_VIDEO_CODEC_HEIGHT                      "480"
+#define DEFAULT_VIDEO_CODEC_BITRATE                     "300"
+#define DEFAULT_VIDEO_CODEC_MIN_BITRATE                 "100"
+#define DEFAULT_VIDEO_CODEC_MAX_BITRATE                 "1000"
+#define DEFAULT_AUDIO_PORT                              "11113"
 #define DEFAULT_AUDIO_CODEC                             "ISAC"
 #define DEFAULT_INCOMING_FILE_NAME                      "IncomingFile.avi"
 #define DEFAULT_OUTGOING_FILE_NAME                      "OutgoingFile.avi"
-#define DEFAULT_VIDEO_CODEC_MAX_FRAMERATE               30
+#define DEFAULT_VIDEO_CODEC_MAX_FRAMERATE               "30"
 #define DEFAULT_VIDEO_PROTECTION_METHOD                 "None"
-#define DEFAULT_TEMPORAL_LAYER                          0
+#define DEFAULT_TEMPORAL_LAYER                          "0"
 
 enum StatisticsType {
   kSendStatistic,
@@ -46,6 +50,7 @@
 };
 
 using webrtc::FromChoices;
+using webrtc::TypedInput;
 
 class ViEAutotestFileObserver : public webrtc::ViEFileObserver {
  public:
@@ -92,18 +97,18 @@
 bool GetVideoDevice(webrtc::ViEBase* vie_base,
                     webrtc::ViECapture* vie_capture,
                     char* capture_device_name, char* capture_device_unique_id);
-bool GetIPAddress(char* IP);
+std::string GetIPAddress();
 bool ValidateIP(std::string i_str);
 
 // The following are Print to stdout functions.
-void PrintCallInformation(char* IP,
-                          char* video_capture_device_name,
-                          char* video_capture_unique_id,
+void PrintCallInformation(const char* IP,
+                          const char* video_capture_device_name,
+                          const char* video_capture_unique_id,
                           webrtc::VideoCodec video_codec,
                           int video_tx_port,
                           int video_rx_port,
-                          char* audio_capture_device_name,
-                          char* audio_playbackDeviceName,
+                          const char* audio_capture_device_name,
+                          const char* audio_playbackDeviceName,
                           webrtc::CodecInst audio_codec,
                           int audio_tx_port,
                           int audio_rx_port,
@@ -125,24 +130,16 @@
 void PrintVideoCodec(webrtc::VideoCodec video_codec);
 
 // The following are video functions.
-// TODO(amyfong): change to pointers as input arguments
-// instead of references
-bool SetVideoPorts(int* tx_port, int* rx_port);
-bool SetVideoCodecType(webrtc::ViECodec* vie_codec,
+void GetVideoPorts(int* tx_port, int* rx_port);
+void SetVideoCodecType(webrtc::ViECodec* vie_codec,
                        webrtc::VideoCodec* video_codec);
-bool SetVideoCodecResolution(webrtc::ViECodec* vie_codec,
-                             webrtc::VideoCodec* video_codec);
-bool SetVideoCodecSize(webrtc::ViECodec* vie_codec,
-                       webrtc::VideoCodec* video_codec);
-bool SetVideoCodecBitrate(webrtc::ViECodec* vie_codec,
-                          webrtc::VideoCodec* video_codec);
-bool SetVideoCodecMinBitrate(webrtc::ViECodec* vie_codec,
-                             webrtc::VideoCodec* video_codec);
-bool SetVideoCodecMaxBitrate(webrtc::ViECodec* vie_codec,
-                             webrtc::VideoCodec* video_codec);
-bool SetVideoCodecMaxFramerate(webrtc::ViECodec* vie_codec,
-                               webrtc::VideoCodec* video_codec);
-bool SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec);
+void SetVideoCodecResolution(webrtc::VideoCodec* video_codec);
+void SetVideoCodecSize(webrtc::VideoCodec* video_codec);
+void SetVideoCodecBitrate(webrtc::VideoCodec* video_codec);
+void SetVideoCodecMinBitrate(webrtc::VideoCodec* video_codec);
+void SetVideoCodecMaxBitrate(webrtc::VideoCodec* video_codec);
+void SetVideoCodecMaxFramerate(webrtc::VideoCodec* video_codec);
+void SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec);
 VideoProtectionMethod GetVideoProtection();
 bool SetVideoProtection(webrtc::ViECodec* vie_codec,
                         webrtc::ViERTP_RTCP* vie_rtp_rtcp,
@@ -158,7 +155,7 @@
 bool GetAudioDevices(webrtc::VoEBase* voe_base,
                      webrtc::VoEHardware* voe_hardware,
                      int& recording_device_index, int& playback_device_index);
-bool GetAudioPorts(int* tx_port, int* rx_port);
+void GetAudioPorts(int* tx_port, int* rx_port);
 bool GetAudioCodec(webrtc::VoECodec* voe_codec,
                    webrtc::CodecInst& audio_codec);
 
@@ -244,8 +241,7 @@
                                          __LINE__);
 
   bool start_call = false;
-  const unsigned int kMaxIPLength = 16;
-  char ip_address[kMaxIPLength] = "";
+  std::string ip_address;
   const unsigned int KMaxUniqueIdLength = 256;
   char unique_id[KMaxUniqueIdLength] = "";
   char device_name[KMaxUniqueIdLength] = "";
@@ -267,8 +263,7 @@
 
   while (!start_call) {
     // Get the IP address to use from call.
-    memset(ip_address, 0, kMaxIPLength);
-    GetIPAddress(ip_address);
+    ip_address = GetIPAddress();
 
     // Get the video device to use for call.
     memset(device_name, 0, KMaxUniqueIdLength);
@@ -279,16 +274,16 @@
     // Get and set the video ports for the call.
     video_tx_port = 0;
     video_rx_port = 0;
-    SetVideoPorts(&video_tx_port, &video_rx_port);
+    GetVideoPorts(&video_tx_port, &video_rx_port);
 
     // Get and set the video codec parameters for the call.
     memset(&video_send_codec, 0, sizeof(webrtc::VideoCodec));
     SetVideoCodecType(vie_codec, &video_send_codec);
-    SetVideoCodecSize(vie_codec, &video_send_codec);
-    SetVideoCodecBitrate(vie_codec, &video_send_codec);
-    SetVideoCodecMinBitrate(vie_codec, &video_send_codec);
-    SetVideoCodecMaxBitrate(vie_codec, &video_send_codec);
-    SetVideoCodecMaxFramerate(vie_codec, &video_send_codec);
+    SetVideoCodecSize(&video_send_codec);
+    SetVideoCodecBitrate(&video_send_codec);
+    SetVideoCodecMinBitrate(&video_send_codec);
+    SetVideoCodecMaxBitrate(&video_send_codec);
+    SetVideoCodecMaxFramerate(&video_send_codec);
     SetVideoCodecTemporalLayer(&video_send_codec);
     remb = GetBitrateSignaling();
 
@@ -312,8 +307,8 @@
     GetAudioCodec(voe_codec, audio_codec);
 
     // Now ready to start the call.  Check user wants to continue.
-    PrintCallInformation(ip_address, device_name, unique_id, video_send_codec,
-                         video_tx_port, video_rx_port,
+    PrintCallInformation(ip_address.c_str(), device_name, unique_id,
+                         video_send_codec, video_tx_port, video_rx_port,
                          audio_capture_device_name, audio_playbackDeviceName,
                          audio_codec, audio_tx_port, audio_rx_port,
                          protection_method);
@@ -332,7 +327,7 @@
     // Configure audio channel first.
     audio_channel = voe_base->CreateChannel();
     error = voe_base->SetSendDestination(audio_channel, audio_tx_port,
-                                         ip_address);
+                                         ip_address.c_str());
     number_of_errors += ViETest::TestError(error == 0,
                                            "ERROR: %s at line %d",
                                            __FUNCTION__, __LINE__);
@@ -451,7 +446,7 @@
     number_of_errors += ViETest::TestError(error == 0,
                                            "ERROR: %s at line %d",
                                            __FUNCTION__, __LINE__);
-    error = vie_network->SetSendDestination(video_channel, ip_address,
+    error = vie_network->SetSendDestination(video_channel, ip_address.c_str(),
                                                 video_tx_port);
     number_of_errors += ViETest::TestError(error == 0,
                                            "ERROR: %s at line %d",
@@ -527,7 +522,7 @@
     printf("\n");
     int selection = FromChoices(
         "Stop the call\n"
-        "Modify the call\n").WithDefault("Stop the call").Choose();
+        "Modify the call\n").Choose();
 
     int file_selection = 0;
 
@@ -560,13 +555,13 @@
         case 2:
           // Change video codec.
           SetVideoCodecType(vie_codec, &video_send_codec);
-          SetVideoCodecSize(vie_codec, &video_send_codec);
-          SetVideoCodecBitrate(vie_codec, &video_send_codec);
-          SetVideoCodecMinBitrate(vie_codec, &video_send_codec);
-          SetVideoCodecMaxBitrate(vie_codec, &video_send_codec);
-          SetVideoCodecMaxFramerate(vie_codec, &video_send_codec);
+          SetVideoCodecSize(&video_send_codec);
+          SetVideoCodecBitrate(&video_send_codec);
+          SetVideoCodecMinBitrate(&video_send_codec);
+          SetVideoCodecMaxBitrate(&video_send_codec);
+          SetVideoCodecMaxFramerate(&video_send_codec);
           SetVideoCodecTemporalLayer(&video_send_codec);
-          PrintCallInformation(ip_address, device_name,
+          PrintCallInformation(ip_address.c_str(), device_name,
                                unique_id, video_send_codec,
                                video_tx_port, video_rx_port,
                                audio_capture_device_name,
@@ -583,8 +578,8 @@
           break;
         case 3:
           // Change Video codec size by common resolution.
-          SetVideoCodecResolution(vie_codec, &video_send_codec);
-          PrintCallInformation(ip_address, device_name,
+          SetVideoCodecResolution(&video_send_codec);
+          PrintCallInformation(ip_address.c_str(), device_name,
                                unique_id, video_send_codec,
                                video_tx_port, video_rx_port,
                                audio_capture_device_name,
@@ -601,8 +596,8 @@
           break;
         case 4:
           // Change video codec by size height and width.
-          SetVideoCodecSize(vie_codec, &video_send_codec);
-          PrintCallInformation(ip_address, device_name,
+          SetVideoCodecSize(&video_send_codec);
+          PrintCallInformation(ip_address.c_str(), device_name,
                                unique_id, video_send_codec,
                                video_tx_port, video_rx_port,
                                audio_capture_device_name,
@@ -809,7 +804,7 @@
           break;
         case 12:
           // Print Call information..
-          PrintCallInformation(ip_address, device_name,
+          PrintCallInformation(ip_address.c_str(), device_name,
                                unique_id, video_send_codec,
                                video_tx_port, video_rx_port,
                                audio_capture_device_name,
@@ -1123,148 +1118,55 @@
 
 // General helper functions.
 
-bool GetIPAddress(char* i_ip) {
-  char o_ip[16] = DEFAULT_SEND_IP;
-  std::string str;
-
-  while (1) {
-    std::cout << std::endl;
-    std::cout << "Enter destination IP. Press enter for default ("
-              << o_ip << "): ";
-    std::getline(std::cin, str);
-
-    if (str.compare("") == 0) {
-      // use default value;
-      strcpy(i_ip, o_ip);
-      return true;
+std::string GetIPAddress() {
+  class IpValidator : public webrtc::InputValidator {
+   public:
+    bool InputOk(const std::string& input) const {
+      // Just check quickly that it's on the form x.y.z.w
+      return std::count(input.begin(), input.end(), '.') == 3;
     }
-    if (ValidateIP(str) == false) {
-      std::cout << "Invalid entry. Try again." << std::endl;
-      continue;
-    }
-    // Done, copy std::string to c_string and return.
-    strcpy(i_ip, str.c_str());
-    return true;
-  }
-  assert(false);
-  return false;
-}
-
-bool ValidateIP(std::string i_str) {
-  if (0 == i_str.compare("")) {
-    return false;
-  }
-  return true;
+  };
+  return TypedInput()
+      .WithDefault(DEFAULT_SEND_IP)
+      .WithTitle("Enter destination IP.")
+      .WithInputValidator(new IpValidator())
+      .AskForInput();
 }
 
 // Video settings functions.
 
-bool SetVideoPorts(int* tx_port, int* rx_port) {
-  std::string str;
-  int port = 0;
+void GetVideoPorts(int* tx_port, int* rx_port) {
+  std::string tx_input = TypedInput()
+      .WithTitle("Enter video send port.")
+      .WithDefault(DEFAULT_VIDEO_PORT)
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
+      .AskForInput();
+  *tx_port = atoi(tx_input.c_str());
 
-  // Set to default values.
-  *tx_port = DEFAULT_VIDEO_PORT;
-  *rx_port = DEFAULT_VIDEO_PORT;
-
-  while (1) {
-    std::cout << "Enter video send port. Press enter for default ("
-              << *tx_port << "):  ";
-    std::getline(std::cin, str);
-    port = atoi(str.c_str());
-
-    if (port == 0) {
-      // Default value.
-      break;
-    } else {
-      // User selection.
-      if (port <= 0 || port > 63556) {
-        // Invalid selection.
-        continue;
-      } else {
-        *tx_port = port;
-        break;  // Move on to rx_port.
-      }
-    }
-  }
-
-  while (1) {
-    std::cout << "Enter video receive port. Press enter for default ("
-              << *rx_port << "):  ";
-    std::getline(std::cin, str);
-    port = atoi(str.c_str());
-
-    if (port == 0) {
-      // Default value
-      return true;
-    } else {
-      // User selection.
-      if (port <= 0 || port > 63556) {
-        // Invalid selection.
-        continue;
-      } else {
-        *rx_port = port;
-        return true;
-      }
-    }
-  }
-  assert(false);
-  return false;
+  std::string rx_input = TypedInput()
+      .WithTitle("Enter video receive port.")
+      .WithDefault(DEFAULT_VIDEO_PORT)
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
+      .AskForInput();
+  *rx_port = atoi(rx_input.c_str());
 }
 
 // Audio settings functions.
 
-bool GetAudioPorts(int* tx_port, int* rx_port) {
-  int port = 0;
-  std::string str;
+void GetAudioPorts(int* tx_port, int* rx_port) {
+  std::string tx_input = TypedInput()
+      .WithTitle("Enter audio send port.")
+      .WithDefault(DEFAULT_AUDIO_PORT)
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
+      .AskForInput();
+  *tx_port = atoi(tx_input.c_str());
 
-  // set to default values.
-  *tx_port = DEFAULT_AUDIO_PORT;
-  *rx_port = DEFAULT_AUDIO_PORT;
-
-  while (1) {
-    std::cout << "Enter audio send port. Press enter for default ("
-              << *tx_port << "):  ";
-    std::getline(std::cin, str);
-    port = atoi(str.c_str());
-
-    if (port == 0) {
-      // Default value.
-      break;
-    } else {
-      // User selection.
-      if (port <= 0 || port > 63556) {
-        // Invalid selection.
-        continue;
-      } else {
-        *tx_port = port;
-        break;  // Move on to rx_port.
-      }
-    }
-  }
-
-  while (1) {
-    std::cout << "Enter audio receive port. Press enter for default ("
-              << *rx_port << "):  ";
-    std::getline(std::cin, str);
-    port = atoi(str.c_str());
-
-    if (port == 0) {
-      // Default value.
-      return true;
-    } else {
-      // User selection.
-      if (port <= 0 || port > 63556) {
-        // Invalid selection.
-        continue;
-      } else {
-        *rx_port = port;
-        return true;
-      }
-    }
-  }
-  assert(false);
-  return false;
+  std::string rx_input = TypedInput()
+      .WithTitle("Enter audio receive port.")
+      .WithDefault(DEFAULT_AUDIO_PORT)
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, 65536))
+      .AskForInput();
+  *rx_port = atoi(rx_input.c_str());
 }
 
 bool GetAudioCodec(webrtc::VoECodec* voe_codec,
@@ -1305,12 +1207,12 @@
   return true;
 }
 
-void PrintCallInformation(char* IP, char* video_capture_device_name,
-                          char* video_capture_unique_id,
+void PrintCallInformation(const char* IP, const char* video_capture_device_name,
+                          const char* video_capture_unique_id,
                           webrtc::VideoCodec video_codec,
                           int video_tx_port, int video_rx_port,
-                          char* audio_capture_device_name,
-                          char* audio_playbackDeviceName,
+                          const char* audio_capture_device_name,
+                          const char* audio_playbackDeviceName,
                           webrtc::CodecInst audio_codec,
                           int audio_tx_port, int audio_rx_port,
                           int protection_method) {
@@ -1343,7 +1245,7 @@
             << std::endl;
 }
 
-bool SetVideoCodecType(webrtc::ViECodec* vie_codec,
+void SetVideoCodecType(webrtc::ViECodec* vie_codec,
                        webrtc::VideoCodec* video_codec) {
   int error = 0;
   int number_of_errors = 0;
@@ -1375,14 +1277,12 @@
     video_codec->width = 176;
     video_codec->height = 144;
   }
-  return true;
 }
 
-bool SetVideoCodecResolution(webrtc::ViECodec* vie_codec,
-                             webrtc::VideoCodec* video_codec) {
+void SetVideoCodecResolution(webrtc::VideoCodec* video_codec) {
   if (video_codec->codecType != webrtc::kVideoCodecVP8) {
     printf("Can only change codec size if it's VP8\n");
-    return false;
+    return;
   }
 
   int choice = FromChoices(
@@ -1441,113 +1341,78 @@
       video_codec->height = 768;
       break;
   }
-  return true;
 }
 
-bool SetVideoCodecSize(webrtc::ViECodec* vie_codec,
-                       webrtc::VideoCodec* video_codec) {
+void SetVideoCodecSize(webrtc::VideoCodec* video_codec) {
   if (video_codec->codecType != webrtc::kVideoCodecVP8) {
     printf("Can only change codec size if it's VP8\n");
-    return false;
+    return;
   }
 
-  std::string str;
-  video_codec->width = DEFAULT_VIDEO_CODEC_WIDTH;
-  video_codec->height = DEFAULT_VIDEO_CODEC_HEIGHT;
-  std::cout << "Choose video width. Press enter for default ("
-      << DEFAULT_VIDEO_CODEC_WIDTH << "):  ";
-  std::getline(std::cin, str);
-  int size_selection = atoi(str.c_str());
-  if (size_selection != 0) {
-    video_codec->width = size_selection;
-  }
-  std::cout << "Choose video height. Press enter for default ("
-      << DEFAULT_VIDEO_CODEC_HEIGHT << "):  ";
-  std::getline(std::cin, str);
-  size_selection = atoi(str.c_str());
-  if (size_selection != 0) {
-    video_codec->height = size_selection;
-  }
-  return true;
+  std::string input = TypedInput()
+      .WithDefault(DEFAULT_VIDEO_CODEC_WIDTH)
+      .WithTitle("Choose video width.")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
+      .AskForInput();
+  video_codec->width = atoi(input.c_str());
+
+  input = TypedInput()
+      .WithDefault(DEFAULT_VIDEO_CODEC_HEIGHT)
+      .WithTitle("Choose video height.")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
+      .AskForInput();
+  video_codec->height = atoi(input.c_str());
 }
 
-bool SetVideoCodecBitrate(webrtc::ViECodec* vie_codec,
-                          webrtc::VideoCodec* video_codec) {
-  std::string str;
-  std::cout << std::endl;
-  std::cout << "Choose start rate (in kbps). Press enter for default ("
-            << DEFAULT_VIDEO_CODEC_BITRATE << "):  ";
-  std::getline(std::cin, str);
-  int start_rate = atoi(str.c_str());
-  video_codec->startBitrate = DEFAULT_VIDEO_CODEC_BITRATE;
-  if (start_rate != 0) {
-    video_codec->startBitrate = start_rate;
-  }
-  return true;
+void SetVideoCodecBitrate(webrtc::VideoCodec* video_codec) {
+  std::string input = TypedInput()
+      .WithDefault(DEFAULT_VIDEO_CODEC_BITRATE)
+      .WithTitle("Choose start rate (in kbps).")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
+      .AskForInput();
+
+  video_codec->startBitrate = atoi(input.c_str());
 }
 
-bool SetVideoCodecMaxBitrate(webrtc::ViECodec* vie_codec,
-                             webrtc::VideoCodec* video_codec) {
-  std::string str;
-  std::cout << std::endl;
-  std::cout << "Choose max bitrate (in kbps). Press enter for default ("
-            << DEFAULT_VIDEO_CODEC_MAX_BITRATE << "):  ";
-  std::getline(std::cin, str);
-  int max_rate = atoi(str.c_str());
-  video_codec->maxBitrate = DEFAULT_VIDEO_CODEC_MAX_BITRATE;
-  if (max_rate != 0) {
-    video_codec->maxBitrate = max_rate;
-  }
-  return true;
+void SetVideoCodecMaxBitrate(webrtc::VideoCodec* video_codec) {
+  std::string input = TypedInput()
+      .WithDefault(DEFAULT_VIDEO_CODEC_MAX_BITRATE)
+      .WithTitle("Choose max bitrate (in kbps).")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
+      .AskForInput();
+
+  video_codec->maxBitrate = atoi(input.c_str());
 }
 
-bool SetVideoCodecMinBitrate(webrtc::ViECodec* vie_codec,
-                             webrtc::VideoCodec* video_codec) {
-  std::string str;
-  std::cout << std::endl;
-  std::cout << "Choose min bitrate (in fps). Press enter for default ("
-            << DEFAULT_VIDEO_CODEC_MIN_BITRATE << "):  ";
-  std::getline(std::cin, str);
-  char min_bit_rate = atoi(str.c_str());
-  video_codec->minBitrate = DEFAULT_VIDEO_CODEC_MIN_BITRATE;
-  if (min_bit_rate != 0) {
-    video_codec->minBitrate = min_bit_rate;
-  }
-  return true;
+void SetVideoCodecMinBitrate(webrtc::VideoCodec* video_codec) {
+  std::string input = TypedInput()
+      .WithDefault(DEFAULT_VIDEO_CODEC_MIN_BITRATE)
+      .WithTitle("Choose min bitrate (in kbps).")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
+      .AskForInput();
+
+  video_codec->minBitrate = atoi(input.c_str());
 }
 
-bool SetVideoCodecMaxFramerate(webrtc::ViECodec* vie_codec,
-                               webrtc::VideoCodec* video_codec) {
-  std::string str;
-  std::cout << std::endl;
-  std::cout << "Choose max framerate (in fps). Press enter for default ("
-            << DEFAULT_VIDEO_CODEC_MAX_FRAMERATE << "):  ";
-  std::getline(std::cin, str);
-  char max_frame_rate = atoi(str.c_str());
-  video_codec->maxFramerate = DEFAULT_VIDEO_CODEC_MAX_FRAMERATE;
-  if (max_frame_rate != 0) {
-    video_codec->maxFramerate = max_frame_rate;
-  }
-  return true;
+void SetVideoCodecMaxFramerate(webrtc::VideoCodec* video_codec) {
+  std::string input = TypedInput()
+      .WithDefault(DEFAULT_VIDEO_CODEC_MAX_FRAMERATE)
+      .WithTitle("Choose max framerate (in fps).")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(1, INT_MAX))
+      .AskForInput();
+  video_codec->maxFramerate = atoi(input.c_str());
 }
 
-bool SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec) {
-  if (video_codec->codecType == webrtc::kVideoCodecVP8) {
-    std::string str;
-    std::cout << std::endl;
-    std::cout << "Choose number of temporal layers (1 to 4). "
-              << "Press enter for default ("
-              << DEFAULT_TEMPORAL_LAYER << "):  ";
-    std::getline(std::cin, str);
-    char num_temporal_layers = atoi(str.c_str());
-    video_codec->codecSpecific.VP8.numberOfTemporalLayers =
-        DEFAULT_TEMPORAL_LAYER;
-    if (num_temporal_layers != 0) {
-      video_codec->codecSpecific.VP8.numberOfTemporalLayers =
-          num_temporal_layers;
-    }
-  }
-  return true;
+void SetVideoCodecTemporalLayer(webrtc::VideoCodec* video_codec) {
+  if (video_codec->codecType != webrtc::kVideoCodecVP8)
+    return;
+
+  std::string input = TypedInput()
+      .WithDefault(DEFAULT_TEMPORAL_LAYER)
+      .WithTitle("Choose number of temporal layers (0 to 4).")
+      .WithInputValidator(new webrtc::IntegerWithinRangeValidator(0, 4))
+      .AskForInput();
+  video_codec->codecSpecific.VP8.numberOfTemporalLayers = atoi(input.c_str());
 }
 
 // GetVideoProtection only prints the prompt to get a number
diff --git a/video_engine/test/auto_test/vie_auto_test.gypi b/video_engine/test/auto_test/vie_auto_test.gypi
index bc5a15c..e967d8a 100644
--- a/video_engine/test/auto_test/vie_auto_test.gypi
+++ b/video_engine/test/auto_test/vie_auto_test.gypi
@@ -62,11 +62,16 @@
         'primitives/choice_helpers_unittest.cc',
         'primitives/codec_primitives.cc',
         'primitives/codec_primitives.h',
+        'primitives/fake_stdin.h',
+        'primitives/fake_stdin.cc',
         'primitives/framedrop_primitives.h',
         'primitives/framedrop_primitives.cc',
         'primitives/framedrop_primitives_unittest.cc',
         'primitives/general_primitives.cc',
         'primitives/general_primitives.h',
+        'primitives/input_helpers.cc',
+        'primitives/input_helpers.h',
+        'primitives/input_helpers_unittest.cc',
 
         # Platform independent
         'source/vie_autotest.cc',
diff --git a/voice_engine/voice_engine_impl.cc b/voice_engine/voice_engine_impl.cc
index f90869f..18f841c 100644
--- a/voice_engine/voice_engine_impl.cc
+++ b/voice_engine/voice_engine_impl.cc
@@ -9,7 +9,7 @@
  */
 
 #if defined(WEBRTC_ANDROID) && !defined(WEBRTC_ANDROID_OPENSLES)
-#include "modules/audio_device/android/audio_device_android_jni.h"
+#include "modules/audio_device/android/audio_device_jni_android.h"
 #endif
 
 #include "voice_engine_impl.h"