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, ¶m); 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"