diff --git a/tools/e2e_quality/audio/audio_e2e_harness.cc b/tools/e2e_quality/audio/audio_e2e_harness.cc index 18d6bd924b..4e8f77cf5e 100644 --- a/tools/e2e_quality/audio/audio_e2e_harness.cc +++ b/tools/e2e_quality/audio/audio_e2e_harness.cc @@ -15,20 +15,16 @@ #include "gflags/gflags.h" #include "gtest/gtest.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/voice_engine/include/voe_audio_processing.h" -#include "webrtc/voice_engine/include/voe_base.h" -#include "webrtc/voice_engine/include/voe_codec.h" -#include "webrtc/voice_engine/include/voe_hardware.h" -#include "webrtc/voice_engine/include/voe_network.h" +#include "voice_engine/include/voe_audio_processing.h" +#include "voice_engine/include/voe_base.h" +#include "voice_engine/include/voe_codec.h" +#include "voice_engine/include/voe_hardware.h" DEFINE_string(render, "render", "render device name"); DEFINE_string(codec, "ISAC", "codec name"); DEFINE_int32(rate, 16000, "codec sample rate in Hz"); namespace webrtc { - namespace { void RunHarness() { @@ -42,18 +38,12 @@ void RunHarness() { ASSERT_TRUE(codec != NULL); VoEHardware* hardware = VoEHardware::GetInterface(voe); ASSERT_TRUE(hardware != NULL); - VoENetwork* network = VoENetwork::GetInterface(voe); - ASSERT_TRUE(network != NULL); ASSERT_EQ(0, base->Init()); int channel = base->CreateChannel(); ASSERT_NE(-1, channel); - - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(network, channel)); - - ASSERT_EQ(0, voice_channel_transport->SetSendDestination("127.0.0.1", 1234)); - ASSERT_EQ(0, voice_channel_transport->SetLocalReceiver(1234)); + ASSERT_EQ(0, base->SetSendDestination(channel, 1234, "127.0.0.1")); + ASSERT_EQ(0, base->SetLocalReceiver(channel, 1234)); CodecInst codec_params = {0}; bool codec_found = false; diff --git a/tools/e2e_quality/e2e_quality.gyp b/tools/e2e_quality/e2e_quality.gyp index e108322dc3..250750e734 100644 --- a/tools/e2e_quality/e2e_quality.gyp +++ b/tools/e2e_quality/e2e_quality.gyp @@ -13,7 +13,6 @@ 'target_name': 'audio_e2e_harness', 'type': 'executable', 'dependencies': [ - '<(webrtc_root)/test/udp_transport.gyp:udp_transport', '<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine_core', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/google-gflags/google-gflags.gyp:google-gflags', diff --git a/webrtc.gyp b/webrtc.gyp index 7d5a91094a..0cff614697 100644 --- a/webrtc.gyp +++ b/webrtc.gyp @@ -31,7 +31,6 @@ 'dependencies': [ 'webrtc/test/metrics.gyp:*', 'webrtc/test/test.gyp:*', - 'webrtc/test/udp_transport.gyp:*', 'webrtc/tools/tools.gyp:*', 'tools/e2e_quality/e2e_quality.gyp:*', ], diff --git a/webrtc/engine_configurations.h b/webrtc/engine_configurations.h index f3d2a46853..67effa0690 100644 --- a/webrtc/engine_configurations.h +++ b/webrtc/engine_configurations.h @@ -109,6 +109,7 @@ #define WEBRTC_VIDEO_ENGINE_CODEC_API #define WEBRTC_VIDEO_ENGINE_ENCRYPTION_API #define WEBRTC_VIDEO_ENGINE_IMAGE_PROCESS_API +#define WEBRTC_VIDEO_ENGINE_NETWORK_API #define WEBRTC_VIDEO_ENGINE_RENDER_API #define WEBRTC_VIDEO_ENGINE_RTP_RTCP_API #define WEBRTC_VIDEO_ENGINE_EXTERNAL_CODEC_API diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index 1671c139f6..837d551898 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -27,6 +27,7 @@ 'pacing/pacing.gypi', 'remote_bitrate_estimator/remote_bitrate_estimator.gypi', 'rtp_rtcp/source/rtp_rtcp.gypi', + 'udp_transport/source/udp_transport.gypi', 'utility/source/utility.gypi', 'video_coding/codecs/i420/main/source/i420.gypi', 'video_coding/main/source/video_coding.gypi', diff --git a/webrtc/modules/udp_transport/OWNERS b/webrtc/modules/udp_transport/OWNERS new file mode 100644 index 0000000000..3b2a44459d --- /dev/null +++ b/webrtc/modules/udp_transport/OWNERS @@ -0,0 +1,4 @@ +pwestin@webrtc.org +henrikg@webrtc.org +mallinath@webrtc.org +tomasl@webrtc.org \ No newline at end of file diff --git a/webrtc/test/udp_transport/udp_transport.h b/webrtc/modules/udp_transport/interface/udp_transport.h similarity index 84% rename from webrtc/test/udp_transport/udp_transport.h rename to webrtc/modules/udp_transport/interface/udp_transport.h index 8427c7eed6..2ca4eb8182 100644 --- a/webrtc/test/udp_transport/udp_transport.h +++ b/webrtc/modules/udp_transport/interface/udp_transport.h @@ -8,11 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_TEST_UDP_TRANSPORT_INTERFACE_UDP_TRANSPORT_H_ -#define WEBRTC_TEST_UDP_TRANSPORT_INTERFACE_UDP_TRANSPORT_H_ +#ifndef WEBRTC_MODULES_UDP_TRANSPORT_INTERFACE_UDP_TRANSPORT_H_ +#define WEBRTC_MODULES_UDP_TRANSPORT_INTERFACE_UDP_TRANSPORT_H_ -#include "webrtc/common_types.h" -#include "webrtc/typedefs.h" +#include "common_types.h" +#include "module.h" +#include "typedefs.h" /* * WARNING @@ -21,6 +22,7 @@ * */ + #define SS_MAXSIZE 128 #define SS_ALIGNSIZE (sizeof (WebRtc_UWord64)) #define SS_PAD1SIZE (SS_ALIGNSIZE - sizeof(WebRtc_Word16)) @@ -29,84 +31,94 @@ // BSD requires use of HAVE_STRUCT_SOCKADDR_SA_LEN namespace webrtc { -struct SocketAddressIn { - // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) +struct SocketAddressIn +{ + // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - WebRtc_Word8 sin_length; - WebRtc_Word8 sin_family; + WebRtc_Word8 sin_length; + WebRtc_Word8 sin_family; #else - WebRtc_Word16 sin_family; + WebRtc_Word16 sin_family; #endif - WebRtc_UWord16 sin_port; - WebRtc_UWord32 sin_addr; - WebRtc_Word8 sin_zero[8]; + WebRtc_UWord16 sin_port; + WebRtc_UWord32 sin_addr; + WebRtc_Word8 sin_zero[8]; }; -struct Version6InAddress { - union { - WebRtc_UWord8 _s6_u8[16]; - WebRtc_UWord32 _s6_u32[4]; - WebRtc_UWord64 _s6_u64[2]; - } Version6AddressUnion; +struct Version6InAddress +{ + union + { + WebRtc_UWord8 _s6_u8[16]; + WebRtc_UWord32 _s6_u32[4]; + WebRtc_UWord64 _s6_u64[2]; + } Version6AddressUnion; }; -struct SocketAddressInVersion6 { - // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) +struct SocketAddressInVersion6 +{ + // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - WebRtc_Word8 sin_length; - WebRtc_Word8 sin_family; + WebRtc_Word8 sin_length; + WebRtc_Word8 sin_family; #else - WebRtc_Word16 sin_family; + WebRtc_Word16 sin_family; #endif - // Transport layer port number. - WebRtc_UWord16 sin6_port; - // IPv6 traffic class and flow info or ip4 address. - WebRtc_UWord32 sin6_flowinfo; - // IPv6 address - struct Version6InAddress sin6_addr; - // Set of interfaces for a scope. - WebRtc_UWord32 sin6_scope_id; + // Transport layer port number. + WebRtc_UWord16 sin6_port; + // IPv6 traffic class and flow info or ip4 address. + WebRtc_UWord32 sin6_flowinfo; + // IPv6 address + struct Version6InAddress sin6_addr; + // Set of interfaces for a scope. + WebRtc_UWord32 sin6_scope_id; }; -struct SocketAddressStorage { - // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) +struct SocketAddressStorage +{ + // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - WebRtc_Word8 sin_length; - WebRtc_Word8 sin_family; + WebRtc_Word8 sin_length; + WebRtc_Word8 sin_family; #else - WebRtc_Word16 sin_family; + WebRtc_Word16 sin_family; #endif - WebRtc_Word8 __ss_pad1[SS_PAD1SIZE]; - WebRtc_UWord64 __ss_align; - WebRtc_Word8 __ss_pad2[SS_PAD2SIZE]; + WebRtc_Word8 __ss_pad1[SS_PAD1SIZE]; + WebRtc_UWord64 __ss_align; + WebRtc_Word8 __ss_pad2[SS_PAD2SIZE]; }; -struct SocketAddress { - union { - struct SocketAddressIn _sockaddr_in; - struct SocketAddressInVersion6 _sockaddr_in6; - struct SocketAddressStorage _sockaddr_storage; - }; +struct SocketAddress +{ + union + { + struct SocketAddressIn _sockaddr_in; + struct SocketAddressInVersion6 _sockaddr_in6; + struct SocketAddressStorage _sockaddr_storage; + }; }; // Callback class that receives packets from UdpTransport. -class UdpTransportData { - public: - virtual ~UdpTransportData() {}; +class UdpTransportData +{ +public: + virtual ~UdpTransportData() {}; - virtual void IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, - const WebRtc_Word32 rtpPacketLength, - const char* fromIP, - const WebRtc_UWord16 fromPort) = 0; + virtual void IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) = 0; - virtual void IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, - const WebRtc_Word32 rtcpPacketLength, - const char* fromIP, - const WebRtc_UWord16 fromPort) = 0; + virtual void IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) = 0; }; -class UdpTransport : public Transport { - public: + +class UdpTransport : public Module, public Transport +{ +public: enum { kIpAddressVersion6Length = 64, @@ -377,7 +389,6 @@ class UdpTransport : public Transport { // is interptreted as IPv6. static bool IsIpAddressValid(const char* ipaddr, const bool ipV6); }; - } // namespace webrtc -#endif // WEBRTC_TEST_UDP_TRANSPORT_INTERFACE_UDP_TRANSPORT_H_ +#endif // WEBRTC_MODULES_UDP_TRANSPORT_INTERFACE_UDP_TRANSPORT_H_ diff --git a/webrtc/test/udp_transport/Android.mk b/webrtc/modules/udp_transport/source/Android.mk similarity index 100% rename from webrtc/test/udp_transport/Android.mk rename to webrtc/modules/udp_transport/source/Android.mk diff --git a/webrtc/test/udp_transport/traffic_control_win.cc b/webrtc/modules/udp_transport/source/traffic_control_windows.cc similarity index 99% rename from webrtc/test/udp_transport/traffic_control_win.cc rename to webrtc/modules/udp_transport/source/traffic_control_windows.cc index fcafe7c75c..09038c06fb 100644 --- a/webrtc/test/udp_transport/traffic_control_win.cc +++ b/webrtc/modules/udp_transport/source/traffic_control_windows.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "traffic_control_win.h" +#include "traffic_control_windows.h" #include diff --git a/webrtc/test/udp_transport/traffic_control_win.h b/webrtc/modules/udp_transport/source/traffic_control_windows.h similarity index 100% rename from webrtc/test/udp_transport/traffic_control_win.h rename to webrtc/modules/udp_transport/source/traffic_control_windows.h diff --git a/webrtc/test/udp_transport/udp_socket2_manager_win.cc b/webrtc/modules/udp_transport/source/udp_socket2_manager_windows.cc similarity index 99% rename from webrtc/test/udp_transport/udp_socket2_manager_win.cc rename to webrtc/modules/udp_transport/source/udp_socket2_manager_windows.cc index 94dddc1eea..32863d3068 100644 --- a/webrtc/test/udp_transport/udp_socket2_manager_win.cc +++ b/webrtc/modules/udp_transport/source/udp_socket2_manager_windows.cc @@ -8,13 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "udp_socket2_manager_win.h" +#include "udp_socket2_manager_windows.h" #include #include #include "aligned_malloc.h" -#include "udp_socket2_win.h" +#include "udp_socket2_windows.h" namespace webrtc { WebRtc_UWord32 UdpSocket2ManagerWindows::_numOfActiveManagers = 0; diff --git a/webrtc/test/udp_transport/udp_socket2_manager_win.h b/webrtc/modules/udp_transport/source/udp_socket2_manager_windows.h similarity index 99% rename from webrtc/test/udp_transport/udp_socket2_manager_win.h rename to webrtc/modules/udp_transport/source/udp_socket2_manager_windows.h index 8cf5ebcd4b..782cb41cfe 100644 --- a/webrtc/test/udp_transport/udp_socket2_manager_win.h +++ b/webrtc/modules/udp_transport/source/udp_socket2_manager_windows.h @@ -22,7 +22,7 @@ #include "event_wrapper.h" #include "list_wrapper.h" #include "thread_wrapper.h" -#include "udp_socket2_win.h" +#include "udp_socket2_windows.h" #include "udp_socket_manager_wrapper.h" #define MAX_IO_BUFF_SIZE 1600 diff --git a/webrtc/test/udp_transport/udp_socket2_win.cc b/webrtc/modules/udp_transport/source/udp_socket2_windows.cc similarity index 99% rename from webrtc/test/udp_transport/udp_socket2_win.cc rename to webrtc/modules/udp_transport/source/udp_socket2_windows.cc index 0cb0c61909..2362cdd011 100644 --- a/webrtc/test/udp_transport/udp_socket2_win.cc +++ b/webrtc/modules/udp_transport/source/udp_socket2_windows.cc @@ -8,14 +8,14 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "udp_socket2_win.h" +#include "udp_socket2_windows.h" #include #include #include -#include "traffic_control_win.h" -#include "udp_socket2_manager_win.h" +#include "traffic_control_windows.h" +#include "udp_socket2_manager_windows.h" #pragma warning(disable : 4311) diff --git a/webrtc/test/udp_transport/udp_socket2_win.h b/webrtc/modules/udp_transport/source/udp_socket2_windows.h similarity index 99% rename from webrtc/test/udp_transport/udp_socket2_win.h rename to webrtc/modules/udp_transport/source/udp_socket2_windows.h index e63f277614..8cc46eefa7 100644 --- a/webrtc/test/udp_transport/udp_socket2_win.h +++ b/webrtc/modules/udp_transport/source/udp_socket2_windows.h @@ -27,7 +27,7 @@ #include "rw_lock_wrapper.h" #include "trace.h" #include "udp_socket_wrapper.h" -#include "udp_socket2_manager_win.h" +#include "udp_socket2_manager_windows.h" namespace webrtc { class UdpSocket2ManagerWindows; diff --git a/webrtc/test/udp_transport/udp_socket_manager_posix.cc b/webrtc/modules/udp_transport/source/udp_socket_manager_posix.cc similarity index 100% rename from webrtc/test/udp_transport/udp_socket_manager_posix.cc rename to webrtc/modules/udp_transport/source/udp_socket_manager_posix.cc diff --git a/webrtc/test/udp_transport/udp_socket_manager_posix.h b/webrtc/modules/udp_transport/source/udp_socket_manager_posix.h similarity index 100% rename from webrtc/test/udp_transport/udp_socket_manager_posix.h rename to webrtc/modules/udp_transport/source/udp_socket_manager_posix.h diff --git a/webrtc/test/udp_transport/udp_socket_manager_unittest.cc b/webrtc/modules/udp_transport/source/udp_socket_manager_unittest.cc similarity index 100% rename from webrtc/test/udp_transport/udp_socket_manager_unittest.cc rename to webrtc/modules/udp_transport/source/udp_socket_manager_unittest.cc diff --git a/webrtc/test/udp_transport/udp_socket_manager_wrapper.cc b/webrtc/modules/udp_transport/source/udp_socket_manager_wrapper.cc similarity index 97% rename from webrtc/test/udp_transport/udp_socket_manager_wrapper.cc rename to webrtc/modules/udp_transport/source/udp_socket_manager_wrapper.cc index a1fae5a5f2..37388be662 100644 --- a/webrtc/test/udp_transport/udp_socket_manager_wrapper.cc +++ b/webrtc/modules/udp_transport/source/udp_socket_manager_wrapper.cc @@ -14,7 +14,7 @@ #ifdef _WIN32 #include "fix_interlocked_exchange_pointer_win.h" -#include "udp_socket2_manager_win.h" +#include "udp_socket2_manager_windows.h" #else #include "udp_socket_manager_posix.h" #endif diff --git a/webrtc/test/udp_transport/udp_socket_manager_wrapper.h b/webrtc/modules/udp_transport/source/udp_socket_manager_wrapper.h similarity index 100% rename from webrtc/test/udp_transport/udp_socket_manager_wrapper.h rename to webrtc/modules/udp_transport/source/udp_socket_manager_wrapper.h diff --git a/webrtc/test/udp_transport/udp_socket_posix.cc b/webrtc/modules/udp_transport/source/udp_socket_posix.cc similarity index 100% rename from webrtc/test/udp_transport/udp_socket_posix.cc rename to webrtc/modules/udp_transport/source/udp_socket_posix.cc diff --git a/webrtc/test/udp_transport/udp_socket_posix.h b/webrtc/modules/udp_transport/source/udp_socket_posix.h similarity index 100% rename from webrtc/test/udp_transport/udp_socket_posix.h rename to webrtc/modules/udp_transport/source/udp_socket_posix.h diff --git a/webrtc/test/udp_transport/udp_socket_wrapper.cc b/webrtc/modules/udp_transport/source/udp_socket_wrapper.cc similarity index 98% rename from webrtc/test/udp_transport/udp_socket_wrapper.cc rename to webrtc/modules/udp_transport/source/udp_socket_wrapper.cc index 89489874f9..6445e76a52 100644 --- a/webrtc/test/udp_transport/udp_socket_wrapper.cc +++ b/webrtc/modules/udp_transport/source/udp_socket_wrapper.cc @@ -18,7 +18,7 @@ #include "udp_socket_manager_wrapper.h" #if defined(_WIN32) - #include "udp_socket2_win.h" + #include "udp_socket2_windows.h" #else #include "udp_socket_posix.h" #endif diff --git a/webrtc/test/udp_transport/udp_socket_wrapper.h b/webrtc/modules/udp_transport/source/udp_socket_wrapper.h similarity index 100% rename from webrtc/test/udp_transport/udp_socket_wrapper.h rename to webrtc/modules/udp_transport/source/udp_socket_wrapper.h diff --git a/webrtc/test/udp_transport/udp_socket_wrapper_unittest.cc b/webrtc/modules/udp_transport/source/udp_socket_wrapper_unittest.cc similarity index 94% rename from webrtc/test/udp_transport/udp_socket_wrapper_unittest.cc rename to webrtc/modules/udp_transport/source/udp_socket_wrapper_unittest.cc index 0d6c37daea..2489604d52 100644 --- a/webrtc/test/udp_transport/udp_socket_wrapper_unittest.cc +++ b/webrtc/modules/udp_transport/source/udp_socket_wrapper_unittest.cc @@ -22,8 +22,8 @@ #include "gtest/gtest.h" #include "gmock/gmock.h" -#include "webrtc/test/udp_transport/udp_socket_wrapper.h" -#include "webrtc/test/udp_transport/udp_socket_manager_wrapper.h" +#include "modules/udp_transport/source/udp_socket_wrapper.h" +#include "modules/udp_transport/source/udp_socket_manager_wrapper.h" using ::testing::_; using ::testing::Return; diff --git a/webrtc/modules/udp_transport/source/udp_transport.gypi b/webrtc/modules/udp_transport/source/udp_transport.gypi new file mode 100644 index 0000000000..a73a58735c --- /dev/null +++ b/webrtc/modules/udp_transport/source/udp_transport.gypi @@ -0,0 +1,114 @@ +# Copyright (c) 2011 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. + +{ + 'targets': [ + { + 'target_name': 'udp_transport', + 'type': 'static_library', + 'dependencies': [ + '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + ], + 'include_dirs': [ + '../interface', + '../../interface', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../interface', + '../../interface', + ], + }, + 'sources': [ + # PLATFORM INDEPENDENT SOURCE FILES + '../interface/udp_transport.h', + 'udp_transport_impl.cc', + 'udp_socket_wrapper.cc', + 'udp_socket_manager_wrapper.cc', + 'udp_transport_impl.h', + 'udp_socket_wrapper.h', + 'udp_socket_manager_wrapper.h', + # PLATFORM SPECIFIC SOURCE FILES - Will be filtered below + # Posix (Linux/Mac) + 'udp_socket_posix.cc', + 'udp_socket_posix.h', + 'udp_socket_manager_posix.cc', + 'udp_socket_manager_posix.h', + # Windows + 'udp_socket2_manager_windows.cc', + 'udp_socket2_manager_windows.h', + 'udp_socket2_windows.cc', + 'udp_socket2_windows.h', + 'traffic_control_windows.cc', + 'traffic_control_windows.h', + ], # source + 'conditions': [ + # DEFINE PLATFORM SPECIFIC SOURCE FILES + ['os_posix==0', { + 'sources!': [ + 'udp_socket_posix.cc', + 'udp_socket_posix.h', + 'udp_socket_manager_posix.cc', + 'udp_socket_manager_posix.h', + ], + }], + ['OS!="win"', { + 'sources!': [ + 'udp_socket2_manager_windows.cc', + 'udp_socket2_manager_windows.h', + 'udp_socket2_windows.cc', + 'udp_socket2_windows.h', + 'traffic_control_windows.cc', + 'traffic_control_windows.h', + ], + }], + ['OS=="linux"', { + 'cflags': [ + '-fno-strict-aliasing', + ], + }], + ['OS=="mac"', { + 'xcode_settings': { + 'OTHER_CPLUSPLUSFLAGS': [ '-fno-strict-aliasing' ], + }, + }], + ] # conditions + }, + ], # targets + 'conditions': [ + ['include_tests==1', { + 'targets': [ + { + 'target_name': 'udp_transport_unittests', + 'type': 'executable', + 'dependencies': [ + 'udp_transport', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/testing/gmock.gyp:gmock', + '<(webrtc_root)/test/test.gyp:test_support_main', + ], + 'sources': [ + 'udp_transport_unittest.cc', + 'udp_socket_manager_unittest.cc', + 'udp_socket_wrapper_unittest.cc', + ], + # Disable warnings to enable Win64 build, issue 1323. + 'msvs_disabled_warnings': [ + 4267, # size_t to int truncation. + ], + }, # udp_transport_unittests + ], # targets + }], # include_tests + ], # conditions +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/webrtc/test/udp_transport/udp_transport_impl.cc b/webrtc/modules/udp_transport/source/udp_transport_impl.cc similarity index 99% rename from webrtc/test/udp_transport/udp_transport_impl.cc rename to webrtc/modules/udp_transport/source/udp_transport_impl.cc index 875ce934b0..b7ded87463 100644 --- a/webrtc/test/udp_transport/udp_transport_impl.cc +++ b/webrtc/modules/udp_transport/source/udp_transport_impl.cc @@ -179,6 +179,44 @@ UdpTransportImpl::~UdpTransportImpl() __FUNCTION__); } +WebRtc_Word32 UdpTransportImpl::ChangeUniqueId(const WebRtc_Word32 id) +{ + + CriticalSectionScoped cs(_crit); + _id = id; + if(_mgr) + { + _mgr->ChangeUniqueId(id); + } + if(_ptrRtpSocket) + { + _ptrRtpSocket->ChangeUniqueId(id); + } + if(_ptrRtcpSocket) + { + _ptrRtcpSocket->ChangeUniqueId(id); + } + if(_ptrSendRtpSocket) + { + _ptrSendRtpSocket->ChangeUniqueId(id); + } + if(_ptrSendRtcpSocket) + { + _ptrSendRtcpSocket->ChangeUniqueId(id); + } + return 0; +} + +WebRtc_Word32 UdpTransportImpl::TimeUntilNextProcess() +{ + return 100; +} + +WebRtc_Word32 UdpTransportImpl::Process() +{ + return 0; +} + UdpTransport::ErrorCode UdpTransportImpl::LastError() const { return _lastError; @@ -1360,7 +1398,7 @@ UdpTransportImpl::ErrorCode UdpTransportImpl::BindLocalRTPSocket() { SocketAddress stLclName; #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - stLclName.sin_lenght = 0; + stLclName.sin_length = 0; stLclName.sin_family = PF_INET6; #else stLclName._sockaddr_storage.sin_family = PF_INET6; @@ -2523,7 +2561,7 @@ WebRtc_Word32 UdpTransport::LocalHostAddressIPV6(char n_localIP[16]) req.r.ifa_family = AF_INET6; // Fill up all the attributes for the rtnetlink header. - // The lenght is very important. 16 signifies the ipv6 address. + // The length is very important. 16 signifies the ipv6 address. rta = (struct rtattr*)(((char*)&req) + NLMSG_ALIGN(req.n.nlmsg_len)); rta->rta_len = RTA_LENGTH(16); diff --git a/webrtc/test/udp_transport/udp_transport_impl.h b/webrtc/modules/udp_transport/source/udp_transport_impl.h similarity index 98% rename from webrtc/test/udp_transport/udp_transport_impl.h rename to webrtc/modules/udp_transport/source/udp_transport_impl.h index e2fa7956aa..9f4fd9fb06 100644 --- a/webrtc/test/udp_transport/udp_transport_impl.h +++ b/webrtc/modules/udp_transport/source/udp_transport_impl.h @@ -42,6 +42,11 @@ public: UdpSocketManager* socket_manager); virtual ~UdpTransportImpl(); + // Module functions + virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id); + virtual WebRtc_Word32 TimeUntilNextProcess(); + virtual WebRtc_Word32 Process(); + // UdpTransport functions virtual WebRtc_Word32 InitializeSendSockets( const char* ipAddr, diff --git a/webrtc/test/udp_transport/udp_transport_unittest.cc b/webrtc/modules/udp_transport/source/udp_transport_unittest.cc similarity index 96% rename from webrtc/test/udp_transport/udp_transport_unittest.cc rename to webrtc/modules/udp_transport/source/udp_transport_unittest.cc index 243cbda4d3..3125e2e5fb 100644 --- a/webrtc/test/udp_transport/udp_transport_unittest.cc +++ b/webrtc/modules/udp_transport/source/udp_transport_unittest.cc @@ -10,14 +10,14 @@ #include +#include "udp_transport.h" #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "webrtc/test/udp_transport/udp_transport.h" // We include the implementation header file to get at the dependency-injecting // constructor. -#include "webrtc/test/udp_transport/udp_transport_impl.h" +#include "udp_transport_impl.h" // We must mock the socket manager, for which we need its definition. -#include "webrtc/test/udp_transport/udp_socket_manager_wrapper.h" +#include "udp_socket_manager_wrapper.h" using ::testing::_; using ::testing::Return; diff --git a/webrtc/modules/udp_transport/test/SocketManagerTest.cc b/webrtc/modules/udp_transport/test/SocketManagerTest.cc new file mode 100644 index 0000000000..03119bec56 --- /dev/null +++ b/webrtc/modules/udp_transport/test/SocketManagerTest.cc @@ -0,0 +1,449 @@ +/* + * 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 +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#define Sleep(x) usleep(x*1000) +#endif + +#include "udp_transport.h" +#include "common_types.h" +#include "trace.h" + +//#define QOS_TEST +//#define QOS_TEST_WITH_OVERRIDE // require admin on Win7 +//#define TOS_TEST // require admin on Win7 +//#define TOS_TEST_USING_SETSOCKOPT +//#define PCP_TEST + +class UdpTransportDataA: public UdpTransportData +{ +public: + UdpTransportDataA() : + _counterRTP(0), + _counterRTCP(0) + { + }; + virtual void IncomingRTPPacket(const WebRtc_Word8* incommingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) + { + _counterRTP++; + }; + + virtual void IncomingRTCPPacket(const WebRtc_Word8* incommingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) + { + _counterRTCP++; + }; + WebRtc_UWord32 _counterRTP; + WebRtc_UWord32 _counterRTCP; +}; + +class UdpTransportDataB: public UdpTransportData +{ +public: + UdpTransportDataB() : + _counterRTP(0), + _counterRTCP(0) + { + }; + virtual void IncomingRTPPacket(const WebRtc_Word8* incommingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) + { + _counterRTP++; + }; + + virtual void IncomingRTCPPacket(const WebRtc_Word8* incommingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) + { + _counterRTCP++; + }; + WebRtc_UWord32 _counterRTP; + WebRtc_UWord32 _counterRTCP; +}; + +#ifdef _WIN32 +int _tmain(int argc, _TCHAR* argv[]) +#else +int main(int argc, char* argv[]) +#endif +{ + Trace::CreateTrace(); + Trace::SetTraceFile("testTrace.txt"); + Trace::SetEncryptedTraceFile("testTraceDebug.txt"); + Trace::SetLevelFilter(webrtc::kTraceAll); + + printf("Start UdpTransport test\n"); + + WebRtc_UWord8 numberOfSocketThreads = 5; + UdpTransport* client1 = UdpTransport::Create(1,numberOfSocketThreads,NULL); + numberOfSocketThreads = 0; + UdpTransport* client2 = UdpTransport::Create(2,numberOfSocketThreads,NULL); + assert(5 == numberOfSocketThreads); + + UdpTransportDataA* client1Callback = new UdpTransportDataA(); + UdpTransportDataB* client2Callback = new UdpTransportDataB(); + + WebRtc_UWord32 localIP = 0; + char localIPAddr[64]; + assert( 0 == client1->LocalHostAddress(localIP)); // network host order aka big-endian + + sprintf(localIPAddr,"%lu.%lu.%lu.%lu",(localIP>>24)& 0x0ff,(localIP>>16)& 0x0ff ,(localIP>>8)& 0x0ff, localIP & 0x0ff); + printf("\tLocal IP:%s\n", localIPAddr); + + char localIPV6[16]; + char localIPAddrV6[128]; + if( 0 == client1->LocalHostAddressIPV6(localIPV6)) + { + sprintf(localIPAddrV6,"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", localIPV6[0],localIPV6[1],localIPV6[2],localIPV6[3],localIPV6[4],localIPV6[5],localIPV6[6],localIPV6[7], localIPV6[8],localIPV6[9],localIPV6[10],localIPV6[11],localIPV6[12],localIPV6[13],localIPV6[14],localIPV6[15]); + printf("\tLocal IPV6:%s\n", localIPAddrV6); + } + + char test[9] = "testtest"; + assert( 0 == client1->InitializeReceiveSockets(client1Callback,1234, localIPAddr)); + +#if defined QOS_TEST_WITH_OVERRIDE || defined QOS_TEST || defined TOS_TEST || defined TOS_TEST_USING_SETSOCKOPT + assert( -1 == client1->SetQoS(true, 3, 1000)); // should fail + assert( 0 == client1->InitializeSendSockets("192.168.200.1", 1236,1237)); +#else + assert( 0 == client1->InitializeSendSockets(localIPAddr, 1236,1237)); +#endif + assert( 0 == client1->StartReceiving(20)); + + assert( 0 == client2->InitializeReceiveSockets(client2Callback,1236)); + assert( 0 == client2->InitializeSendSockets(localIPAddr, 1234,1235)); + assert( 0 == client2->StartReceiving(20)); + + Sleep(10); + +#ifdef TOS_TEST + // note: you need to have QOS installed on your interface for this test + // test by doing a ethereal sniff and filter out packets with ip.dst == 192.168.200.1 + assert( 0 == client1->SetToS(2)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetToS(3)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetToS(0)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + + printf("Tested TOS \n"); + Sleep(5000); + return 0; +#endif + +#ifdef TOS_TEST_USING_SETSOCKOPT + // note: you need to have QOS installed on your interface for this test + // test by doing a ethereal sniff and filter out packets with ip.dst == 192.168.200.1 + assert( 0 == client1->SetToS(2, true)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetToS(3, true)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetToS(0, true)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + + printf("Tested TOS using setsockopt \n"); + Sleep(5000); + return 0; +#endif + +#ifdef QOS_TEST + // note: you need to have QOS installed on your interface for this test + // test by doing a ethereal sniff and filter out packets with ip.dst == 192.168.200.1 + assert( 0 == client1->SetQoS(true, 2, 1000)); // SERVICETYPE_CONTROLLEDLOAD 2 + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetQoS(true, 3, 1000)); // SERVICETYPE_GUARANTEED 3 + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetQoS(false, 0)); // + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + + printf("Tested QOS \n"); + Sleep(5000); + return 0; +#endif + +#ifdef QOS_TEST_WITH_OVERRIDE + // note: you need to have QOS installed on your interface for this test + // test by doing a ethereal sniff and filter out packets with ip.dst == 192.168.200.1 + assert( 0 == client1->SetQoS(true, 2, 1000, 1)); // SERVICETYPE_CONTROLLEDLOAD 2 + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetQoS(true, 2, 1000, 2)); // SERVICETYPE_GUARANTEED 3 + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + Sleep(10); + assert( 0 == client1->SetQoS(false, 0)); // + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + printf("Tested QOS with override \n"); + Sleep(5000); + return 0; +#endif + +#ifdef PCP_TEST + // Note: We currently don't know how to test that the bits are actually set in the frame, + // this test simply tests the API and that we can send a packet after setting PCP. + assert( -1 == client1->SetPCP(-1)); // should fail + assert( -1 == client1->SetPCP(8)); // should fail + printf("Setting PCP to 7 returned %d \n", client1->SetPCP(7)); + printf("(Failing is normal, requires the CAP_NET_ADMIN capability to succeed.) \n"); + Sleep(10); + for (int pcp = 6; pcp >= 0; --pcp) + { + assert( 0 == client1->SetPCP(pcp)); + Sleep(10); + assert( 9 == client1->SendPacket(-1, test, 9)); + } + printf("Tested PCP \n"); + Sleep(5000); + return 0; +#endif + + Sleep(10); + + assert( 9 == client1->SendPacket(-1, test, 9)); + + // test start rec after a socket has revceived data + // result: packets received before first startReceive is saved by the OS +/* + for(int i = 0; i < 100; i++) + { + assert( 9 == client1->SendPacket(-1, test, 9)); + } + Sleep(10); + assert( 0 == client2->StartReceiving(20)); + +// assert( 0 == client2->StopReceiving()); + + Sleep(10); + for(int i = 0; i < 100; i++) + { + assert( 9 == client1->SendPacket(-1, test, 9)); + } + + assert( 0 == client2->StartReceiving(20)); + + for(int i = 0; i < 100; i++) + { + assert( 9 == client1->SendPacket(-1, test, 9)); + } +*/ + Sleep(10); + + assert( 0 == client1Callback->_counterRTP); + assert( 1 == client2Callback->_counterRTP); + assert( 0 == client1Callback->_counterRTCP); + assert( 0 == client2Callback->_counterRTCP); + + printf("Sent 1 packet on one socket \n"); + + char ipAddr[64]; + char tempIpAddr[64]; + char ipMulticastAddr[64]; + WebRtc_UWord16 rtpPort = 0; + WebRtc_UWord16 rtcpPort = 0; + bool reusableSocket = true; + assert( 0 == client2->RemoteSocketInformation(ipAddr, rtpPort, rtcpPort)); + assert( rtpPort == 1234); + assert( strncmp(ipAddr, localIPAddr, 16) == 0); + + assert( 0 == client2->ReceiveSocketInformation(ipAddr, rtpPort, rtcpPort, ipMulticastAddr, reusableSocket)); + assert( rtpPort == 1236); + assert( rtcpPort == 1237); + assert( strncmp(ipAddr, "0.0.0.0", 16) == 0); + assert( ipMulticastAddr[0] == 0); + assert( reusableSocket == false); + + assert( 0 == client2->SendSocketInformation(ipAddr, rtpPort, rtcpPort)); + assert( rtpPort == 1234); + assert( rtcpPort == 1235); + assert( strncmp(ipAddr,localIPAddr, 16) == 0); + + const int numberOfPackets = 1000; + int n = 0; + while(n < numberOfPackets) + { + assert( 9 == client1->SendPacket(-1, test, 9)); + assert( 9 == client2->SendPacket(-1, test, 9)); + assert( 9 == client1->SendRTCPPacket(-1, test, 9)); + assert( 9 == client2->SendRTCPPacket(-1, test, 9)); + n++; + } + int loops = 0; + for(; loops < 100 && + !(client1Callback->_counterRTP == numberOfPackets && + client1Callback->_counterRTCP == numberOfPackets && + client2Callback->_counterRTP == numberOfPackets+1 && + client2Callback->_counterRTCP == numberOfPackets); + loops++) + { + Sleep(10); + } + printf("\tSent %d packets on 4 sockets in:%d ms\n", numberOfPackets, loops*10); + + assert( numberOfPackets == client1Callback->_counterRTP); + assert( numberOfPackets+1 == client2Callback->_counterRTP); + assert( numberOfPackets == client1Callback->_counterRTCP); + assert( numberOfPackets == client2Callback->_counterRTCP); + + assert( 0 == client1->StopReceiving()); + assert( 0 == client2->StopReceiving()); + + printf("Tear down client 2\n"); + + // configure that fail + assert( -1 == client2->InitializeReceiveSockets(client2Callback,1234, localIPAddr)); // port in use + assert( !client2->ReceiveSocketsInitialized()); + assert( 0 == client2->InitializeReceiveSockets(client2Callback,1236)); + assert( 0 == client2->StartReceiving(20)); + + printf("Client 2 re-configured\n"); + + assert( client1->SendSocketsInitialized()); + assert( client1->ReceiveSocketsInitialized()); + assert( client2->SendSocketsInitialized()); + assert( client2->ReceiveSocketsInitialized()); + + assert( 9 == client1->SendPacket(-1, test, 9)); + + // this should not be received since we dont receive in client 1 + assert( 9 == client2->SendPacket(-1, test, 9)); + + Sleep(10); + + assert( numberOfPackets == client1Callback->_counterRTP); + assert( numberOfPackets+2 == client2Callback->_counterRTP); + assert( numberOfPackets == client1Callback->_counterRTCP); + assert( numberOfPackets == client2Callback->_counterRTCP); + printf("\tSent 1 packet on one socket \n"); + + printf("Start filter test\n"); + + assert( 0 == client1->StartReceiving(20)); + + assert( 0 == client1->SetFilterPorts(1234, 1235)); // should filter out what we send + assert( 0 == client1->SetFilterIP(localIPAddr)); + + assert( 0 == client1->FilterIP(tempIpAddr)); + assert( strncmp(tempIpAddr, localIPAddr, 16) == 0); + + assert( 9 == client2->SendPacket(-1, test, 9)); + assert( 9 == client2->SendRTCPPacket(-1, test, 9)); + + Sleep(10); + + assert( numberOfPackets == client1Callback->_counterRTP); + assert( numberOfPackets+2 == client2Callback->_counterRTP); + assert( numberOfPackets == client1Callback->_counterRTCP); + assert( numberOfPackets == client2Callback->_counterRTCP); + + assert( 0 == client1->SetFilterPorts(1236, 1237)); // should pass through + + assert( 9 == client2->SendPacket(-1, test, 9)); + assert( 9 == client2->SendRTCPPacket(-1, test, 9)); + printf("\tSent 1 packet on two sockets \n"); + + Sleep(10); + + assert( numberOfPackets+1 == client1Callback->_counterRTP); + assert( numberOfPackets+2 == client2Callback->_counterRTP); + assert( numberOfPackets+1 == client1Callback->_counterRTCP); + assert( numberOfPackets == client2Callback->_counterRTCP); + + assert( 0 == client1->SetFilterIP("127.0.0.2")); + + assert( 9 == client2->SendPacket(-1, test, 9)); + assert( 9 == client2->SendRTCPPacket(-1, test, 9)); + printf("\tSent 1 packet on two sockets \n"); + + Sleep(10); + + assert( numberOfPackets+1 == client1Callback->_counterRTP); + assert( numberOfPackets+2 == client2Callback->_counterRTP); + assert( numberOfPackets+1 == client1Callback->_counterRTCP); + assert( numberOfPackets == client2Callback->_counterRTCP); + + assert( 0 == client1->SetFilterIP(NULL)); + assert( 0 == client1->SetFilterPorts(0, 0)); + + printf("Tested filter \n"); + + assert( 0 == client2->InitializeSourcePorts(1238, 1239)); + assert( 9 == client2->SendPacket(-1, test, 9)); + assert( 9 == client2->SendRTCPPacket(-1, test, 9)); + printf("\tSent 1 packet on two sockets \n"); + + Sleep(10); + + assert( numberOfPackets+2 == client1Callback->_counterRTP); + assert( numberOfPackets+2 == client2Callback->_counterRTP); + assert( numberOfPackets+2 == client1Callback->_counterRTCP); + assert( numberOfPackets == client2Callback->_counterRTCP); + + assert( 0 == client1->RemoteSocketInformation(ipAddr, rtpPort, rtcpPort)); + assert( rtpPort == 1238); + assert( rtcpPort == 1239); + assert( strncmp(ipAddr, localIPAddr, 16) == 0); + + printf("Tested source port \n"); + + assert( 0 == client2->InitializeSourcePorts(1240 )); + assert( 9 == client2->SendPacket(-1, test, 9)); + assert( 9 == client2->SendRTCPPacket(-1, test, 9)); + printf("\tSent 1 packet on two sockets \n"); + + Sleep(10); + + assert( 0 == client1->RemoteSocketInformation(ipAddr, rtpPort, rtcpPort)); + assert( rtpPort == 1240); + assert( rtcpPort == 1241); + + printf("Tested SetSendPorts source port \n"); + + UdpTransport::Destroy(client1); + UdpTransport::Destroy(client2); + + printf("\n\nUdpTransport test done\n"); + + delete client1Callback; + delete client2Callback; + + Sleep(5000); + Trace::ReturnTrace(); +}; diff --git a/webrtc/test/udp_transport.gyp b/webrtc/test/udp_transport.gyp deleted file mode 100644 index 37c9e73487..0000000000 --- a/webrtc/test/udp_transport.gyp +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2011 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. - -{ - 'includes': [ - '../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'udp_transport', - 'type': 'static_library', - 'dependencies': [ - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - 'udp_transport/include', - ], - }, - 'sources': [ - # PLATFORM INDEPENDENT SOURCE FILES - 'udp_transport/channel_transport.cc', - 'udp_transport/include/channel_transport.h', - 'udp_transport/udp_transport.h', - 'udp_transport/udp_transport_impl.cc', - 'udp_transport/udp_socket_wrapper.cc', - 'udp_transport/udp_socket_manager_wrapper.cc', - 'udp_transport/udp_transport_impl.h', - 'udp_transport/udp_socket_wrapper.h', - 'udp_transport/udp_socket_manager_wrapper.h', - # PLATFORM SPECIFIC SOURCE FILES - Will be filtered below - # Posix (Linux/Mac) - 'udp_transport/udp_socket_posix.cc', - 'udp_transport/udp_socket_posix.h', - 'udp_transport/udp_socket_manager_posix.cc', - 'udp_transport/udp_socket_manager_posix.h', - # win - 'udp_transport/udp_socket2_manager_win.cc', - 'udp_transport/udp_socket2_manager_win.h', - 'udp_transport/udp_socket2_win.cc', - 'udp_transport/udp_socket2_win.h', - 'udp_transport/traffic_control_win.cc', - 'udp_transport/traffic_control_win.h', - ], # source - }, - { - 'target_name': 'udp_transport_unittests', - 'type': 'executable', - 'dependencies': [ - 'udp_transport', - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(DEPTH)/testing/gmock.gyp:gmock', - '<(webrtc_root)/test/test.gyp:test_support_main', - ], - 'sources': [ - 'udp_transport/udp_transport_unittest.cc', - 'udp_transport/udp_socket_manager_unittest.cc', - 'udp_transport/udp_socket_wrapper_unittest.cc', - ], - # Disable warnings to enable Win64 build, issue 1323. - 'msvs_disabled_warnings': [ - 4267, # size_t to int truncation. - ], - }, # udp_transport_unittests - ], # targets -} diff --git a/webrtc/test/udp_transport/channel_transport.cc b/webrtc/test/udp_transport/channel_transport.cc deleted file mode 100644 index 8be8938314..0000000000 --- a/webrtc/test/udp_transport/channel_transport.cc +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2013 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 "webrtc/test/udp_transport/include/channel_transport.h" - -#include "webrtc/test/udp_transport/udp_transport.h" -#include "webrtc/video_engine/include/vie_network.h" -#include "webrtc/voice_engine/include/voe_network.h" - -namespace webrtc { - -VoiceChannelTransport::VoiceChannelTransport(VoENetwork* voe_network, - int channel) - : channel_(channel), - voe_network_(voe_network) { - WebRtc_UWord8 socket_threads = 1; - socket_transport_ = UdpTransport::Create(channel, socket_threads); - voe_network_->RegisterExternalTransport(channel, *socket_transport_); -} - -VoiceChannelTransport::~VoiceChannelTransport() { - voe_network_->DeRegisterExternalTransport(channel_); - UdpTransport::Destroy(socket_transport_); -} - -void VoiceChannelTransport::IncomingRTPPacket( - const WebRtc_Word8* incoming_rtp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/) { - voe_network_->ReceivedRTPPacket(channel_, incoming_rtp_packet, packet_length); -} - -void VoiceChannelTransport::IncomingRTCPPacket( - const WebRtc_Word8* incoming_rtcp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/) { - voe_network_->ReceivedRTCPPacket(channel_, incoming_rtcp_packet, - packet_length); -} - -int VoiceChannelTransport::SetLocalReceiver(WebRtc_UWord16 rtp_port) { - return socket_transport_->InitializeReceiveSockets(this, rtp_port); -} - -int VoiceChannelTransport::SetSendDestination(const char* ip_address, - WebRtc_UWord16 rtp_port) { - return socket_transport_->InitializeSendSockets(ip_address, rtp_port); -} - - -VideoChannelTransport::VideoChannelTransport(ViENetwork* vie_network, - int channel) - : channel_(channel), - vie_network_(vie_network) { - WebRtc_UWord8 socket_threads = 1; - socket_transport_ = UdpTransport::Create(channel, socket_threads); - vie_network_->RegisterSendTransport(channel, *socket_transport_); -} - -VideoChannelTransport::~VideoChannelTransport() { - vie_network_->DeregisterSendTransport(channel_); - UdpTransport::Destroy(socket_transport_); -} - -void VideoChannelTransport::IncomingRTPPacket( - const WebRtc_Word8* incoming_rtp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/) { - vie_network_->ReceivedRTPPacket(channel_, incoming_rtp_packet, packet_length); -} - -void VideoChannelTransport::IncomingRTCPPacket( - const WebRtc_Word8* incoming_rtcp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/) { - vie_network_->ReceivedRTCPPacket(channel_, incoming_rtcp_packet, - packet_length); -} - -int VideoChannelTransport::SetLocalReceiver(WebRtc_UWord16 rtp_port) { - return socket_transport_->InitializeReceiveSockets(this, rtp_port); -} - -int VideoChannelTransport::SetSendDestination(const char* ip_address, - WebRtc_UWord16 rtp_port) { - return socket_transport_->InitializeSendSockets(ip_address, rtp_port); -} - -} // namespace webrtc diff --git a/webrtc/test/udp_transport/include/channel_transport.h b/webrtc/test/udp_transport/include/channel_transport.h deleted file mode 100644 index e3291efdb9..0000000000 --- a/webrtc/test/udp_transport/include/channel_transport.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2013 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_TEST_UDP_TRANSPORT_INTERFACE_CHANNEL_TRANSPORT_H_ -#define WEBRTC_TEST_UDP_TRANSPORT_INTERFACE_CHANNEL_TRANSPORT_H_ - -#include "webrtc/test/udp_transport/udp_transport.h" - -namespace webrtc { - -class ViENetwork; -class VoENetwork; - -// Helper class for VoiceEngine tests. -class VoiceChannelTransport : public UdpTransportData { - public: - VoiceChannelTransport(VoENetwork* voe_network, int channel); - - virtual ~VoiceChannelTransport(); - - // Start implementation of UdpTransportData. - void IncomingRTPPacket(const WebRtc_Word8* incoming_rtp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/); - - void IncomingRTCPPacket(const WebRtc_Word8* incoming_rtcp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/); - // End implementation of UdpTransportData. - - // Specifies the ports to receive RTP packets on. - int SetLocalReceiver(WebRtc_UWord16 rtp_port); - - // Specifies the destination port and IP address for a specified channel. - int SetSendDestination(const char* ip_address, WebRtc_UWord16 rtp_port); - - private: - int channel_; - VoENetwork* voe_network_; - UdpTransport* socket_transport_; -}; - -// Helper class for VideoEngine tests. -class VideoChannelTransport : public UdpTransportData { - public: - VideoChannelTransport(ViENetwork* vie_network, int channel); - - virtual ~VideoChannelTransport(); - - // Start implementation of UdpTransportData. - void IncomingRTPPacket(const WebRtc_Word8* incoming_rtp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/); - - void IncomingRTCPPacket(const WebRtc_Word8* incoming_rtcp_packet, - const WebRtc_Word32 packet_length, - const char* /*from_ip*/, - const WebRtc_UWord16 /*from_port*/); - // End implementation of UdpTransportData. - - // Specifies the ports to receive RTP packets on. - int SetLocalReceiver(WebRtc_UWord16 rtp_port); - - // Specifies the destination port and IP address for a specified channel. - int SetSendDestination(const char* ip_address, WebRtc_UWord16 rtp_port); - - private: - int channel_; - ViENetwork* vie_network_; - UdpTransport* socket_transport_; -}; - -} // namespace webrtc - -#endif // WEBRTC_TEST_UDP_TRANSPORT_INTERFACE_CHANNEL_TRANSPORT_H_ - diff --git a/webrtc/video_engine/include/vie_network.h b/webrtc/video_engine/include/vie_network.h index d3515dbba5..9752008d93 100644 --- a/webrtc/video_engine/include/vie_network.h +++ b/webrtc/video_engine/include/vie_network.h @@ -65,6 +65,34 @@ class WEBRTC_DLLEXPORT ViENetwork { // for all sub-API:s before the VideoEngine object can be safely deleted. virtual int Release() = 0; + // Specifies the ports to receive RTP packets on. It is also possible to set + // port for RTCP and local IP address. + virtual int SetLocalReceiver(const int video_channel, + const unsigned short rtp_port, + const unsigned short rtcp_port = 0, + const char* ip_address = NULL) = 0; + + // Gets the local receiver ports and address for a specified channel. + virtual int GetLocalReceiver(const int video_channel, + unsigned short& rtp_port, + unsigned short& rtcp_port, char* ip_address) = 0; + + // Specifies the destination port and IP address for a specified channel. + virtual int SetSendDestination(const int video_channel, + const char* ip_address, + const unsigned short rtp_port, + const unsigned short rtcp_port = 0, + const unsigned short source_rtp_port = 0, + const unsigned short source_rtcp_port = 0) = 0; + + // Get the destination port and address for a specified channel. + virtual int GetSendDestination(const int video_channel, + char* ip_address, + unsigned short& rtp_port, + unsigned short& rtcp_port, + unsigned short& source_rtp_port, + unsigned short& source_rtcp_port) = 0; + // This function registers a user implementation of Transport to use for // sending RTP and RTCP packets on this channel. virtual int RegisterSendTransport(const int video_channel, @@ -86,6 +114,63 @@ class WEBRTC_DLLEXPORT ViENetwork { const void* data, const int length) = 0; + // Gets the source ports and IP address of the incoming stream for a + // specified channel. + virtual int GetSourceInfo(const int video_channel, + unsigned short& rtp_port, + unsigned short& rtcp_port, + char* ip_address, + unsigned int ip_address_length) = 0; + + // Gets the local IP address, in string format. + virtual int GetLocalIP(char ip_address[64], bool ipv6 = false) = 0; + + // Enables IPv6, instead of IPv4, for a specified channel. + virtual int EnableIPv6(int video_channel) = 0; + + // The function returns true if IPv6 is enabled, false otherwise. + virtual bool IsIPv6Enabled(int video_channel) = 0; + + // Enables a port and IP address filtering for incoming packets on a + // specific channel. + virtual int SetSourceFilter(const int video_channel, + const unsigned short rtp_port, + const unsigned short rtcp_port = 0, + const char* ip_address = NULL) = 0; + + // Gets current port and IP address filter for a specified channel. + virtual int GetSourceFilter(const int video_channel, + unsigned short& rtp_port, + unsigned short& rtcp_port, + char* ip_address) = 0; + + // This function sets the six‐bit Differentiated Services Code Point (DSCP) + // in the IP header of the outgoing stream for a specific channel. + // Windows and Linux only. + virtual int SetSendToS(const int video_channel, + const int DSCP, + const bool use_set_sockOpt = false) = 0; + + // Retrieves the six‐bit Differentiated Services Code Point (DSCP) in the IP + // header of the outgoing stream for a specific channel. + virtual int GetSendToS(const int video_channel, + int& DSCP, + bool& use_set_sockOpt) = 0; + + // This function sets the Generic Quality of Service (GQoS) service level. + // The Windows operating system then maps to a Differentiated Services Code + // Point (DSCP) and to an 802.1p setting. Windows only. + virtual int SetSendGQoS(const int video_channel, const bool enable, + const int service_type, + const int overrideDSCP = 0) = 0; + + // This function retrieves the currently set GQoS service level for a + // specific channel. + virtual int GetSendGQoS(const int video_channel, + bool& enabled, + int& service_type, + int& overrideDSCP) = 0; + // This function sets the Maximum Transition Unit (MTU) for a channel. The // RTP packet will be packetized based on this MTU to optimize performance // over the network. @@ -112,6 +197,14 @@ class WEBRTC_DLLEXPORT ViENetwork { const bool enable, const unsigned int sample_time_seconds = KDefaultSampleTimeSeconds) = 0; + // This function handles sending a raw UDP data packet over an existing RTP + // or RTCP socket. + virtual int SendUDPPacket(const int video_channel, + const void* data, + const unsigned int length, + int& transmitted_bytes, + bool use_rtcp_socket = false) = 0; + protected: ViENetwork() {} virtual ~ViENetwork() {} diff --git a/webrtc/video_engine/test/android/jni/vie_android_java_api.cc b/webrtc/video_engine/test/android/jni/vie_android_java_api.cc index d1b6f2bd86..8c8aa0b6bb 100644 --- a/webrtc/video_engine/test/android/jni/vie_android_java_api.cc +++ b/webrtc/video_engine/test/android/jni/vie_android_java_api.cc @@ -34,9 +34,6 @@ #include "common_types.h" #include "android_media_codec_decoder.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" - #define WEBRTC_LOG_TAG "*WEBRTCN*" #define VALIDATE_BASE_POINTER \ if (!voeData.base) \ @@ -110,8 +107,6 @@ typedef struct VoEHardware* hardware; VoERTP_RTCP* rtp; JavaVM* jvm; - scoped_ptr transport; - // TODO } VoiceEngineData; class AndroidVideoRenderCallback; @@ -127,7 +122,6 @@ typedef struct ViECapture* capture; ViEExternalCodec* externalCodec; VideoCallbackAndroid* callback; - scoped_ptr transport; } VideoEngineData; @@ -595,7 +589,7 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_CreateCh if (voiceChannel >= 0) { vieData.base->ConnectAudioChannel(channel, voiceChannel); } - vieData.transport.reset(new VideoChannelTransport(vieData.netw, channel)); + return channel; } else { @@ -616,10 +610,13 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_SetLocal { __android_log_write(ANDROID_LOG_DEBUG, WEBRTC_LOG_TAG, "SetLocalReceiver"); - if (vieData.transport.get()) { - return vieData.transport->SetLocalReceiver(port); + if (vieData.vie) { + int ret = vieData.netw->SetLocalReceiver(channel, port); + return ret; + } + else { + return -1; } - return -1; } /* @@ -649,10 +646,7 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_SetSendD "SetSendDestination: channel=%d, port=%d, ip=%s\n", channel, port, ip); - if (vieData.transport.get()) { - return vieData.transport->SetSendDestination(ip, port); - } - return -1; + return vieData.netw->SetSendDestination(channel, ip, port); } @@ -1270,7 +1264,7 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Cre } jint channel = voeData.base->CreateChannel(); - voeData.transport.reset(new VoiceChannelTransport(voeData.netw, channel)); + return channel; } @@ -1301,10 +1295,7 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Set { __android_log_write(ANDROID_LOG_DEBUG, WEBRTC_LOG_TAG, "SetLocalReceiver"); VALIDATE_BASE_POINTER; - if (voeData.transport.get()) { - return voeData.transport->SetLocalReceiver(port); - } - return -1; + return voeData.base->SetLocalReceiver(channel, port); } /* @@ -1328,13 +1319,9 @@ JNIEXPORT jint JNICALL Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_VoE_1Set "Could not get UTF string"); return -1; } - if (voeData.transport.get()) { - jint retVal = voeData.transport->SetSendDestination(ipaddrNative, port); - env->ReleaseStringUTFChars(ipaddr, ipaddrNative); - return retVal; - } + jint retVal = voeData.base->SetSendDestination(channel, port, ipaddrNative); env->ReleaseStringUTFChars(ipaddr, ipaddrNative); - return -1; + return retVal; } /* diff --git a/webrtc/video_engine/test/auto_test/automated/vie_api_integration_test.cc b/webrtc/video_engine/test/auto_test/automated/vie_api_integration_test.cc index 96b401b003..7b49103b9f 100644 --- a/webrtc/video_engine/test/auto_test/automated/vie_api_integration_test.cc +++ b/webrtc/video_engine/test/auto_test/automated/vie_api_integration_test.cc @@ -48,6 +48,10 @@ TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), tests_->ViEImageProcessAPITest(); } +TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsNetworkTestWithoutErrors) { + tests_->ViENetworkAPITest(); +} + TEST_F(DISABLED_ON_MAC(ViEApiIntegrationTest), RunsRenderTestWithoutErrors) { tests_->ViERenderAPITest(); } diff --git a/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc b/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc index d224bdebb9..c091475cac 100644 --- a/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc +++ b/webrtc/video_engine/test/auto_test/automated/vie_extended_integration_test.cc @@ -50,6 +50,11 @@ TEST_F(DISABLED_ON_MAC(ViEExtendedIntegrationTest), tests_->ViEImageProcessExtendedTest(); } +TEST_F(DISABLED_ON_MAC(ViEExtendedIntegrationTest), + RunsNetworkTestWithoutErrors) { + tests_->ViENetworkExtendedTest(); +} + TEST_F(DISABLED_ON_MAC(ViEExtendedIntegrationTest), RunsRenderTestWithoutErrors) { tests_->ViERenderExtendedTest(); diff --git a/webrtc/video_engine/test/auto_test/automated/vie_standard_integration_test.cc b/webrtc/video_engine/test/auto_test/automated/vie_standard_integration_test.cc index 30364e0231..4f90aace81 100644 --- a/webrtc/video_engine/test/auto_test/automated/vie_standard_integration_test.cc +++ b/webrtc/video_engine/test/auto_test/automated/vie_standard_integration_test.cc @@ -54,6 +54,10 @@ TEST_F(ViEStandardIntegrationTest, RunsImageProcessTestWithoutErrors) { tests_->ViEImageProcessStandardTest(); } +TEST_F(ViEStandardIntegrationTest, RunsNetworkTestWithoutErrors) { + tests_->ViENetworkStandardTest(); +} + TEST_F(ViEStandardIntegrationTest, RunsRenderTestWithoutErrors) { tests_->ViERenderStandardTest(); } diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest.cc index 200e256ce2..363eccb875 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest.cc @@ -67,6 +67,7 @@ void ViEAutoTest::ViEStandardTest() ViEEncryptionStandardTest(); ViEFileStandardTest(); ViEImageProcessStandardTest(); + ViENetworkStandardTest(); ViERenderStandardTest(); ViERtpRtcpStandardTest(); } @@ -79,6 +80,7 @@ void ViEAutoTest::ViEExtendedTest() ViEEncryptionExtendedTest(); ViEFileExtendedTest(); ViEImageProcessExtendedTest(); + ViENetworkExtendedTest(); ViERenderExtendedTest(); ViERtpRtcpExtendedTest(); } @@ -91,6 +93,7 @@ void ViEAutoTest::ViEAPITest() ViEEncryptionAPITest(); ViEFileAPITest(); ViEImageProcessAPITest(); + ViENetworkAPITest(); ViERenderAPITest(); ViERtpRtcpAPITest(); } diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc index 80d8d90f68..d1622dba5e 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_android.cc @@ -162,14 +162,21 @@ int ViEAutoTestAndroid::RunAutotest(int testSelection, int subTestSelection, vieAutoTest.ViEImageProcessExtendedTest(); break; - case 8: // Render + case 8: // network + vieAutoTest.ViENetworkExtendedTest(); + break; + + case 9: // Render vieAutoTest.ViERenderExtendedTest(); break; - case 9: // RTP/RTCP + case 10: // RTP/RTCP vieAutoTest.ViERtpRtcpExtendedTest(); break; + case 11: + break; + default: break; } diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc index 05572eabd8..e9d24f3c7d 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc @@ -9,12 +9,11 @@ */ #include "webrtc/modules/video_capture/include/video_capture_factory.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" -#include "webrtc/video_engine/test/auto_test/primitives/base_primitives.h" -#include "webrtc/video_engine/test/auto_test/primitives/general_primitives.h" -#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h" +#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/base_primitives.h" +#include "video_engine/test/auto_test/primitives/general_primitives.h" +#include "video_engine/test/libvietest/include/tb_interfaces.h" void ViEAutoTest::ViEBaseStandardTest() { // *************************************************************** @@ -151,30 +150,20 @@ void ViEAutoTest::ViEBaseAPITest() { // Create a receive only channel and a send channel. Verify we can't send on // the receive only channel. EXPECT_EQ(0, vie_base->CreateReceiveChannel(video_channel2, - video_channel)); + video_channel)); EXPECT_EQ(0, vie_base->CreateChannel(video_channel3, video_channel)); const char* ip_address = "127.0.0.1\0"; const int send_port = 1234; - EXPECT_EQ(0, vie_rtp->SetLocalSSRC(video_channel, 1)); + EXPECT_EQ(0, vie_network->SetSendDestination(video_channel, ip_address, + send_port)); EXPECT_EQ(0, vie_rtp->SetLocalSSRC(video_channel, 2)); + EXPECT_EQ(0, vie_network->SetSendDestination(video_channel2, ip_address, + send_port + 2)); EXPECT_EQ(0, vie_rtp->SetLocalSSRC(video_channel, 3)); - - webrtc::VideoChannelTransport* video_channel_transport_1 = - new webrtc::VideoChannelTransport(vie_network, video_channel); - - ASSERT_EQ(0, video_channel_transport_1->SetSendDestination(ip_address, - send_port)); - - webrtc::VideoChannelTransport* video_channel_transport_2 = - new webrtc::VideoChannelTransport(vie_network, video_channel2); - - webrtc::VideoChannelTransport* video_channel_transport_3 = - new webrtc::VideoChannelTransport(vie_network, video_channel3); - - ASSERT_EQ(0, video_channel_transport_3->SetSendDestination(ip_address, - send_port + 4)); + EXPECT_EQ(0, vie_network->SetSendDestination(video_channel3, ip_address, + send_port + 4)); EXPECT_EQ(0, vie_base->StartSend(video_channel)); EXPECT_EQ(-1, vie_base->StartSend(video_channel2)); @@ -231,9 +220,6 @@ void ViEAutoTest::ViEBaseAPITest() { EXPECT_FALSE(webrtc::VideoEngine::Delete(video_engine)) << "Should fail since there are interfaces left."; - delete video_channel_transport_1; - delete video_channel_transport_2; - delete video_channel_transport_3; EXPECT_EQ(0, vie_base->Release()); EXPECT_TRUE(webrtc::VideoEngine::Delete(video_engine)); } diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc index 74ce9d09f0..87169a63a6 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_codec.cc @@ -8,24 +8,21 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" -#include "webrtc/video_engine/test/libvietest/include/tb_capture_device.h" -#include "webrtc/video_engine/test/libvietest/include/tb_I420_codec.h" -#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h" -#include "webrtc/video_engine/test/libvietest/include/tb_video_channel.h" -#include "webrtc/video_engine/include/vie_base.h" -#include "webrtc/video_engine/include/vie_capture.h" -#include "webrtc/video_engine/include/vie_codec.h" -#include "webrtc/video_engine/include/vie_external_codec.h" -#include "webrtc/video_engine/include/vie_network.h" -#include "webrtc/video_engine/include/vie_render.h" -#include "webrtc/video_engine/include/vie_rtp_rtcp.h" -#include "webrtc/voice_engine/include/voe_base.h" +#include "common_types.h" // NOLINT +#include "engine_configurations.h" // NOLINT +#include "video_engine/test/auto_test/interface/vie_autotest_defines.h" +#include "video_engine/test/auto_test/interface/vie_autotest.h" +#include "video_engine/test/libvietest/include/tb_capture_device.h" +#include "video_engine/test/libvietest/include/tb_I420_codec.h" +#include "video_engine/test/libvietest/include/tb_interfaces.h" +#include "video_engine/test/libvietest/include/tb_video_channel.h" +#include "video_engine/include/vie_base.h" +#include "video_engine/include/vie_capture.h" +#include "video_engine/include/vie_codec.h" +#include "video_engine/include/vie_network.h" +#include "video_engine/include/vie_render.h" +#include "video_engine/include/vie_rtp_rtcp.h" +#include "voice_engine/include/voe_base.h" class TestCodecObserver : public webrtc::ViEEncoderObserver, @@ -167,16 +164,13 @@ void ViEAutoTest::ViECodecStandardTest() { break; } } + const char* ip_address = "127.0.0.1"; const uint16_t rtp_port = 6000; - - webrtc::scoped_ptr video_channel_transport( - new webrtc::VideoChannelTransport(network, video_channel)); - - ASSERT_EQ(0, video_channel_transport->SetSendDestination(ip_address, - rtp_port)); - ASSERT_EQ(0, video_channel_transport->SetLocalReceiver(rtp_port)); - + EXPECT_EQ(0, network->SetLocalReceiver(video_channel, rtp_port)); + EXPECT_EQ(0, base->StartReceive(video_channel)); + EXPECT_EQ(0, network->SetSendDestination( + video_channel, ip_address, rtp_port)); EXPECT_EQ(0, base->StartSend(video_channel)); // Make sure all codecs runs @@ -306,14 +300,10 @@ void ViEAutoTest::ViECodecExtendedTest() { const char* ip_address = "127.0.0.1"; const uint16_t rtp_port = 6000; - - webrtc::scoped_ptr video_channel_transport( - new webrtc::VideoChannelTransport(network, video_channel)); - - ASSERT_EQ(0, video_channel_transport->SetSendDestination(ip_address, - rtp_port)); - ASSERT_EQ(0, video_channel_transport->SetLocalReceiver(rtp_port)); - + EXPECT_EQ(0, network->SetLocalReceiver(video_channel, rtp_port)); + EXPECT_EQ(0, base->StartReceive(video_channel)); + EXPECT_EQ(0, network->SetSendDestination( + video_channel, ip_address, rtp_port)); EXPECT_EQ(0, base->StartSend(video_channel)); // Codec specific tests @@ -339,7 +329,6 @@ void ViEAutoTest::ViECodecExtendedTest() { // the received streams. TbInterfaces video_engine("ViECodecExtendedTest2"); TbCaptureDevice tb_capture(video_engine); - webrtc::ViENetwork* network = video_engine.network; // Create channel 1. int video_channel_1 = -1; @@ -352,25 +341,17 @@ void ViEAutoTest::ViECodecExtendedTest() { EXPECT_NE(video_channel_1, video_channel_2) << "Channel 2 should be unique."; - const char* ip_address = "127.0.0.1"; uint16_t rtp_port_1 = 12000; uint16_t rtp_port_2 = 13000; - - webrtc::scoped_ptr video_channel_transport_1( - new webrtc::VideoChannelTransport(network, video_channel_1)); - - ASSERT_EQ(0, video_channel_transport_1->SetSendDestination(ip_address, - rtp_port_1)); - ASSERT_EQ(0, video_channel_transport_1->SetLocalReceiver(rtp_port_1)); - - webrtc::scoped_ptr video_channel_transport_2( - new webrtc::VideoChannelTransport(network, video_channel_2)); - - ASSERT_EQ(0, video_channel_transport_2->SetSendDestination(ip_address, - rtp_port_2)); - ASSERT_EQ(0, video_channel_transport_2->SetLocalReceiver(rtp_port_2)); - + EXPECT_EQ(0, video_engine.network->SetLocalReceiver( + video_channel_1, rtp_port_1)); + EXPECT_EQ(0, video_engine.network->SetSendDestination( + video_channel_1, "127.0.0.1", rtp_port_1)); EXPECT_EQ(0, video_engine.rtp_rtcp->SetLocalSSRC(video_channel_1, 1)); + EXPECT_EQ(0, video_engine.network->SetLocalReceiver( + video_channel_2, rtp_port_2)); + EXPECT_EQ(0, video_engine.network->SetSendDestination( + video_channel_2, "127.0.0.1", rtp_port_2)); EXPECT_EQ(0, video_engine.rtp_rtcp->SetLocalSSRC(video_channel_2, 2)); tb_capture.ConnectTo(video_channel_1); tb_capture.ConnectTo(video_channel_2); @@ -502,6 +483,9 @@ void ViEAutoTest::ViECodecAPITest() { EXPECT_TRUE(webrtc::VideoEngine::Delete(video_engine)); } +#ifdef WEBRTC_VIDEO_ENGINE_EXTERNAL_CODEC_API +#include "video_engine/include/vie_external_codec.h" +#endif void ViEAutoTest::ViECodecExternalCodecTest() { ViETest::Log(" "); ViETest::Log("========================================"); diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc index 8c03d0763a..b862b64393 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_custom_call.cc @@ -15,15 +15,12 @@ #include #include "gflags/gflags.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" -#include "webrtc/video_engine/test/auto_test/primitives/choice_helpers.h" -#include "webrtc/video_engine/test/auto_test/primitives/general_primitives.h" -#include "webrtc/video_engine/test/auto_test/primitives/input_helpers.h" -#include "webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h" -#include "webrtc/voice_engine/include/voe_network.h" +#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/general_primitives.h" +#include "video_engine/test/auto_test/primitives/input_helpers.h" +#include "video_engine/test/libvietest/include/vie_to_file_renderer.h" #define VCM_RED_PAYLOAD_TYPE 96 #define VCM_ULPFEC_PAYLOAD_TYPE 97 @@ -205,12 +202,6 @@ int ViEAutoTest::ViECustomCall() { "ERROR: %s at line %d", __FUNCTION__, __LINE__); - webrtc::VoENetwork* voe_network= - webrtc::VoENetwork::GetInterface(voe); - number_of_errors += ViETest::TestError(voe_network != NULL, - "ERROR: %s at line %d", __FUNCTION__, - __LINE__); - webrtc::VoEAudioProcessing* voe_apm = webrtc::VoEAudioProcessing::GetInterface(voe); number_of_errors += ViETest::TestError(voe_apm != NULL, @@ -279,8 +270,6 @@ int ViEAutoTest::ViECustomCall() { int buffer_delay_ms = 0; bool is_image_scale_enabled = false; bool remb = true; - webrtc::scoped_ptr video_channel_transport; - webrtc::scoped_ptr voice_channel_transport; while (!start_call) { // Get the IP address to use from call. @@ -351,17 +340,13 @@ int ViEAutoTest::ViECustomCall() { if (start_call == true) { // Configure audio channel first. audio_channel = voe_base->CreateChannel(); - - voice_channel_transport.reset( - new webrtc::VoiceChannelTransport(voe_network, audio_channel)); - - error = voice_channel_transport->SetSendDestination(ip_address.c_str(), - audio_tx_port); + error = voe_base->SetSendDestination(audio_channel, audio_tx_port, + ip_address.c_str()); number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__); - error = voice_channel_transport->SetLocalReceiver(audio_rx_port); + error = voe_base->SetLocalReceiver(audio_channel, audio_rx_port); number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__); @@ -487,17 +472,13 @@ int ViEAutoTest::ViECustomCall() { file_renderer.PrepareForRendering(output_path, filename); RenderToFile(vie_renderer, video_channel, &file_renderer); } - - video_channel_transport.reset( - new webrtc::VideoChannelTransport(vie_network, video_channel)); - - error = video_channel_transport->SetSendDestination(ip_address.c_str(), - video_tx_port); + 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", __FUNCTION__, __LINE__); - error = video_channel_transport->SetLocalReceiver(video_rx_port); + error = vie_network->SetLocalReceiver(video_channel, video_rx_port); number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d", __FUNCTION__, __LINE__); @@ -931,9 +912,6 @@ int ViEAutoTest::ViECustomCall() { // Now tear down the ViE engine. error = vie_base->DisconnectAudioChannel(video_channel); - voice_channel_transport.reset(NULL); - video_channel_transport.reset(NULL); - // If Encoder/Decoder Observer is running, delete them. if (codec_encoder_observer) { error = vie_codec->DeregisterEncoderObserver(video_channel); diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_file.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_file.cc index ce2d327b8b..80831710c4 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_file.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_file.cc @@ -18,9 +18,6 @@ #include "voe_codec.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" - class ViEAutotestFileObserver: public webrtc::ViEFileObserver { public: @@ -106,18 +103,14 @@ void ViEAutoTest::ViEFileStandardTest() break; } } + + const char* ipAddress = "127.0.0.1"; const unsigned short rtpPort = 6000; - - webrtc::scoped_ptr - video_channel_transport( - new webrtc::VideoChannelTransport(ptrViENetwork, videoChannel)); - - EXPECT_EQ(0, video_channel_transport->SetSendDestination(ipAddress, - rtpPort)); - EXPECT_EQ(0, video_channel_transport->SetLocalReceiver(rtpPort)); - + EXPECT_EQ(0, ptrViENetwork->SetLocalReceiver(videoChannel, rtpPort)); EXPECT_EQ(0, ptrViEBase->StartReceive(videoChannel)); + EXPECT_EQ(0, ptrViENetwork->SetSendDestination( + videoChannel, ipAddress, rtpPort)); EXPECT_EQ(0, ptrViEBase->StartSend(videoChannel)); webrtc::ViEFile* ptrViEFile = webrtc::ViEFile::GetInterface(ptrViE); EXPECT_TRUE(ptrViEFile != NULL); diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc index 879941887b..1f8fcdd081 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc @@ -32,8 +32,6 @@ #include "vie_network.h" #include "vie_render.h" #include "vie_rtp_rtcp.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" #define VCM_RED_PAYLOAD_TYPE 96 #define VCM_ULPFEC_PAYLOAD_TYPE 97 @@ -474,9 +472,6 @@ int VideoEngineSampleCode(void* window1, void* window2) // Setting External transport TbExternalTransport extTransport(*(ptrViENetwork), videoChannel, NULL); - webrtc::VideoChannelTransport* video_channel_transport = - new webrtc::VideoChannelTransport(ptrViENetwork, videoChannel); - int testMode = 0; std::cout << std::endl; std::cout << "Enter 1 for testing packet loss and delay with " @@ -529,17 +524,17 @@ int VideoEngineSampleCode(void* window1, void* window2) std::cout << std::endl; std::cout << "Using rtp port: " << rtpPort << std::endl; std::cout << std::endl; - - error = video_channel_transport->SetLocalReceiver(rtpPort); + error = ptrViENetwork->SetLocalReceiver(videoChannel, rtpPort); if (error == -1) { - printf("ERROR in SetLocalReceiver\n"); + printf("ERROR in ViENetwork::SetLocalReceiver\n"); return -1; } - error = video_channel_transport->SetSendDestination(ipAddress, rtpPort); + error = ptrViENetwork->SetSendDestination(videoChannel, + ipAddress, rtpPort); if (error == -1) { - printf("ERROR in SetSendDestination\n"); + printf("ERROR in ViENetwork::SetSendDestination\n"); return -1; } } @@ -642,7 +637,7 @@ int VideoEngineSampleCode(void* window1, void* window2) printf("ERROR in ViEBase::DeleteChannel\n"); return -1; } - delete video_channel_transport; + int remainingInterfaces = 0; remainingInterfaces = ptrViECodec->Release(); remainingInterfaces += ptrViECapture->Release(); diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_network.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_network.cc new file mode 100644 index 0000000000..550bd4f9a8 --- /dev/null +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_network.cc @@ -0,0 +1,573 @@ +/* + * 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. + */ + +// +// vie_autotest_network.cc +// + +#include "vie_autotest_defines.h" +#include "vie_autotest.h" +#include "engine_configurations.h" + +#include "tb_capture_device.h" +#include "tb_external_transport.h" +#include "tb_interfaces.h" +#include "tb_video_channel.h" + +#if defined(_WIN32) +#include +#endif + +class ViEAutoTestNetworkObserver: public webrtc::ViENetworkObserver +{ +public: + ViEAutoTestNetworkObserver() + { + } + virtual ~ViEAutoTestNetworkObserver() + { + } + virtual void OnPeriodicDeadOrAlive(const int videoChannel, const bool alive) + { + } + virtual void PacketTimeout(const int videoChannel, + const webrtc::ViEPacketTimeout timeout) + { + } +}; + +void ViEAutoTest::ViENetworkStandardTest() +{ + TbInterfaces ViE("ViENetworkStandardTest"); // Create VIE + TbCaptureDevice tbCapture(ViE); + { + // Create a video channel + TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8); + tbCapture.ConnectTo(tbChannel.videoChannel); + + RenderCaptureDeviceAndOutputStream(&ViE, &tbChannel, &tbCapture); + + // *************************************************************** + // Engine ready. Begin testing class + // *************************************************************** + + // + // Transport + // + TbExternalTransport testTransport(*ViE.network, tbChannel.videoChannel, + NULL); + EXPECT_EQ(0, ViE.network->RegisterSendTransport( + tbChannel.videoChannel, testTransport)); + EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.rtp_rtcp->SetKeyFrameRequestMethod( + tbChannel.videoChannel, webrtc::kViEKeyFrameRequestPliRtcp)); + + ViETest::Log("Call started using external transport, video should " + "see video in both windows\n"); + AutoTestSleep(kAutoTestSleepTimeMs); + + EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.network->DeregisterSendTransport( + tbChannel.videoChannel)); + + char myIpAddress[64]; + memset(myIpAddress, 0, 64); + unsigned short rtpPort = 1234; + memcpy(myIpAddress, "127.0.0.1", sizeof("127.0.0.1")); + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, rtpPort, rtpPort + 1, myIpAddress)); + EXPECT_EQ(0, ViE.network->SetSendDestination( + tbChannel.videoChannel, myIpAddress, rtpPort, + rtpPort + 1, rtpPort)); + EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + + ViETest::Log("Changed to WebRTC SocketTransport, you should still see " + "video in both windows\n"); + AutoTestSleep(kAutoTestSleepTimeMs); + + EXPECT_EQ(0, ViE.network->SetSourceFilter( + tbChannel.videoChannel, rtpPort + 10, rtpPort + 11, myIpAddress)); + ViETest::Log("Added UDP port filter for incorrect ports, you should " + "not see video in Window2"); + AutoTestSleep(2000); + EXPECT_EQ(0, ViE.network->SetSourceFilter( + tbChannel.videoChannel, rtpPort, rtpPort + 1, "123.1.1.0")); + ViETest::Log("Added IP filter for incorrect IP address, you should not " + "see video in Window2"); + AutoTestSleep(2000); + EXPECT_EQ(0, ViE.network->SetSourceFilter( + tbChannel.videoChannel, rtpPort, rtpPort + 1, myIpAddress)); + ViETest::Log("Added IP filter for this computer, you should see video " + "in Window2 again\n"); + AutoTestSleep(kAutoTestSleepTimeMs); + + tbCapture.Disconnect(tbChannel.videoChannel); + } +} + +void ViEAutoTest::ViENetworkExtendedTest() +{ + //*************************************************************** + // Begin create/initialize WebRTC Video Engine for testing + //*************************************************************** + + TbInterfaces ViE("ViENetworkExtendedTest"); // Create VIE + TbCaptureDevice tbCapture(ViE); + EXPECT_EQ(0, ViE.render->AddRenderer( + tbCapture.captureId, _window1, 0, 0.0, 0.0, 1.0, 1.0)); + EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId)); + + { + // + // ToS + // + // Create a video channel + TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8); + tbCapture.ConnectTo(tbChannel.videoChannel); + const char* remoteIp = "192.168.200.1"; + int DSCP = 0; + bool useSetSockOpt = false; + + webrtc::VideoCodec videoCodec; + EXPECT_EQ(0, ViE.codec->GetSendCodec( + tbChannel.videoChannel, videoCodec)); + videoCodec.maxFramerate = 5; + EXPECT_EQ(0, ViE.codec->SetSendCodec( + tbChannel.videoChannel, videoCodec)); + + //*************************************************************** + // Engine ready. Begin testing class + //*************************************************************** + + char myIpAddress[64]; + memset(myIpAddress, 0, 64); + unsigned short rtpPort = 9000; + EXPECT_EQ(0, ViE.network->GetLocalIP(myIpAddress, false)); + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, rtpPort, rtpPort + 1, myIpAddress)); + EXPECT_EQ(0, ViE.network->SetSendDestination( + tbChannel.videoChannel, remoteIp, rtpPort, rtpPort + 1, rtpPort)); + + // ToS + int tos_result = ViE.network->SetSendToS(tbChannel.videoChannel, 2); + EXPECT_EQ(0, tos_result); + if (tos_result != 0) + { + ViETest::Log("ViESetSendToS error!."); + ViETest::Log("You must be admin to run these tests."); + ViETest::Log("On Win7 and late Vista, you need to right click the " + "exe and choose"); + ViETest::Log("\"Run as administrator\"\n"); + getchar(); + } + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); // No ToS set + + EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + + ViETest::Log("Use Wireshark to capture the outgoing video stream and " + "verify ToS settings\n"); + ViETest::Log(" DSCP set to 0x%x\n", DSCP); + AutoTestSleep(1000); + + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 63)); + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); // No ToS set + ViETest::Log(" DSCP set to 0x%x\n", DSCP); + AutoTestSleep(1000); + + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 0)); + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 2, true)); + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); // No ToS set + ViETest::Log(" DSCP set to 0x%x\n", DSCP); + AutoTestSleep(1000); + + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 63, true)); + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); // No ToS set + ViETest::Log(" DSCP set to 0x%x\n", DSCP); + AutoTestSleep(1000); + + tbCapture.Disconnect(tbChannel.videoChannel); + } + + //*************************************************************** + // Testing finished. Tear down Video Engine + //*************************************************************** +} + +void ViEAutoTest::ViENetworkAPITest() +{ + //*************************************************************** + // Begin create/initialize WebRTC Video Engine for testing + //*************************************************************** + + TbInterfaces ViE("ViENetworkAPITest"); // Create VIE + { + // Create a video channel + TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecI420); + + //*************************************************************** + // Engine ready. Begin testing class + //*************************************************************** + + // + // External transport + // + TbExternalTransport testTransport(*ViE.network, tbChannel.videoChannel, + NULL); + EXPECT_EQ(0, ViE.network->RegisterSendTransport( + tbChannel.videoChannel, testTransport)); + EXPECT_NE(0, ViE.network->RegisterSendTransport( + tbChannel.videoChannel, testTransport)); + + // Create a empty RTP packet. + unsigned char packet[3000]; + memset(packet, 0, sizeof(packet)); + packet[0] = 0x80; // V=2, P=0, X=0, CC=0 + packet[1] = 0x7C; // M=0, PT = 124 (I420) + + // Create a empty RTCP app packet. + unsigned char rtcpacket[3000]; + memset(rtcpacket,0, sizeof(rtcpacket)); + rtcpacket[0] = 0x80; // V=2, P=0, X=0, CC=0 + rtcpacket[1] = 0xCC; // M=0, PT = 204 (RTCP app) + rtcpacket[2] = 0x0; + rtcpacket[3] = 0x03; // 3 Octets long. + + EXPECT_NE(0, ViE.network->ReceivedRTPPacket( + tbChannel.videoChannel, packet, 1500)); + EXPECT_NE(0, ViE.network->ReceivedRTCPPacket( + tbChannel.videoChannel, rtcpacket, 1500)); + EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.network->ReceivedRTPPacket( + tbChannel.videoChannel, packet, 1500)); + EXPECT_EQ(0, ViE.network->ReceivedRTCPPacket( + tbChannel.videoChannel, rtcpacket, 1500)); + EXPECT_NE(0, ViE.network->ReceivedRTPPacket( + tbChannel.videoChannel, packet, 11)); + EXPECT_NE(0, ViE.network->ReceivedRTPPacket( + tbChannel.videoChannel, packet, 11)); + EXPECT_EQ(0, ViE.network->ReceivedRTPPacket( + tbChannel.videoChannel, packet, 3000)); + EXPECT_EQ(0, ViE.network->ReceivedRTPPacket( + tbChannel.videoChannel, packet, 3000)); + EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + EXPECT_NE(0, ViE.network->DeregisterSendTransport( + tbChannel.videoChannel)); // Sending + EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.network->DeregisterSendTransport( + tbChannel.videoChannel)); + EXPECT_NE(0, ViE.network->DeregisterSendTransport( + tbChannel.videoChannel)); // Already deregistered + + // + // Local receiver + // + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, 1234, 1235, "127.0.0.1")); + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, 1234, 1235, "127.0.0.1")); + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, 1236, 1237, "127.0.0.1")); + + unsigned short rtpPort = 0; + unsigned short rtcpPort = 0; + char ipAddress[64]; + memset(ipAddress, 0, 64); + EXPECT_EQ(0, ViE.network->GetLocalReceiver( + tbChannel.videoChannel, rtpPort, rtcpPort, ipAddress)); + EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel)); + EXPECT_NE(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, 1234, 1235, "127.0.0.1")); + EXPECT_EQ(0, ViE.network->GetLocalReceiver( + tbChannel.videoChannel, rtpPort, rtcpPort, ipAddress)); + EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel)); + + // + // Send destination + // + EXPECT_EQ(0, ViE.network->SetSendDestination( + tbChannel.videoChannel, "127.0.0.1", 1234, 1235, 1234, 1235)); + EXPECT_EQ(0, ViE.network->SetSendDestination( + tbChannel.videoChannel, "127.0.0.1", 1236, 1237, 1234, 1235)); + + unsigned short sourceRtpPort = 0; + unsigned short sourceRtcpPort = 0; + EXPECT_EQ(0, ViE.network->GetSendDestination( + tbChannel.videoChannel, ipAddress, rtpPort, rtcpPort, + sourceRtpPort, sourceRtcpPort)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + + // Not allowed while sending + EXPECT_NE(0, ViE.network->SetSendDestination( + tbChannel.videoChannel, "127.0.0.1", 1234, 1235, 1234, 1235)); + EXPECT_EQ(kViENetworkAlreadySending, ViE.base->LastError()); + + EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.network->SetSendDestination( + tbChannel.videoChannel, "127.0.0.1", 1234, 1235, 1234, 1235)); + EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel)); + EXPECT_EQ(0, ViE.network->GetSendDestination( + tbChannel.videoChannel, ipAddress, rtpPort, rtcpPort, + sourceRtpPort, sourceRtcpPort)); + EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel)); + + // + // Address information + // + + // GetSourceInfo: Tested in functional test + EXPECT_EQ(0, ViE.network->GetLocalIP(ipAddress, false)); + + // TODO(unknown): IPv6 + + // + // Filter + // + EXPECT_NE(0, ViE.network->GetSourceFilter( + tbChannel.videoChannel, rtpPort, rtcpPort, ipAddress)); + EXPECT_EQ(0, ViE.network->SetSourceFilter( + tbChannel.videoChannel, 1234, 1235, "10.10.10.10")); + EXPECT_EQ(0, ViE.network->SetSourceFilter( + tbChannel.videoChannel, 1236, 1237, "127.0.0.1")); + EXPECT_EQ(0, ViE.network->GetSourceFilter( + tbChannel.videoChannel, rtpPort, rtcpPort, ipAddress)); + EXPECT_EQ(0, ViE.network->SetSourceFilter( + tbChannel.videoChannel, 0, 0, NULL)); + EXPECT_NE(0, ViE.network->GetSourceFilter( + tbChannel.videoChannel, rtpPort, rtcpPort, ipAddress)); + } + { + TbVideoChannel tbChannel(ViE); // Create a video channel + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, 1234)); + + int DSCP = 0; + bool useSetSockOpt = false; + // SetSockOpt should work without a locally bind socket + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); // No ToS set + EXPECT_EQ(0, DSCP); + + // Invalid input + EXPECT_NE(0, ViE.network->SetSendToS(tbChannel.videoChannel, -1, true)); + + // Invalid input + EXPECT_NE(0, ViE.network->SetSendToS(tbChannel.videoChannel, 64, true)); + + // Valid + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 20, true)); + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); + + EXPECT_EQ(20, DSCP); + EXPECT_TRUE(useSetSockOpt); + + // Disable + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 0, true)); + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); + EXPECT_EQ(0, DSCP); + + char myIpAddress[64]; + memset(myIpAddress, 0, 64); + // Get local ip to be able to set ToS withtou setSockOpt + EXPECT_EQ(0, ViE.network->GetLocalIP(myIpAddress, false)); + EXPECT_EQ(0, ViE.network->SetLocalReceiver( + tbChannel.videoChannel, 1234, 1235, myIpAddress)); + + // Invalid input + EXPECT_NE(0, ViE.network->SetSendToS( + tbChannel.videoChannel, -1, false)); + EXPECT_NE(0, ViE.network->SetSendToS( + tbChannel.videoChannel, 64, false)); // Invalid input + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); // No ToS set + EXPECT_EQ(0, DSCP); + int tos_result = ViE.network->SetSendToS( + tbChannel.videoChannel, 20, false); // Valid + EXPECT_EQ(0, tos_result); + if (tos_result != 0) + { + ViETest::Log("ViESetSendToS error!."); + ViETest::Log("You must be admin to run these tests."); + ViETest::Log("On Win7 and late Vista, you need to right click the " + "exe and choose"); + ViETest::Log("\"Run as administrator\"\n"); + getchar(); + } + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); + EXPECT_EQ(20, DSCP); +#ifdef _WIN32 + EXPECT_FALSE(useSetSockOpt); +#else // useSetSockOpt is true on Linux and Mac + EXPECT_TRUE(useSetSockOpt); +#endif + EXPECT_EQ(0, ViE.network->SetSendToS(tbChannel.videoChannel, 0, false)); + EXPECT_EQ(0, ViE.network->GetSendToS( + tbChannel.videoChannel, DSCP, useSetSockOpt)); + EXPECT_EQ(0, DSCP); + } + { + // From qos.h. (*) -> supported by ViE + // + // #define SERVICETYPE_NOTRAFFIC 0x00000000 + // #define SERVICETYPE_BESTEFFORT 0x00000001 (*) + // #define SERVICETYPE_CONTROLLEDLOAD 0x00000002 (*) + // #define SERVICETYPE_GUARANTEED 0x00000003 (*) + // #define SERVICETYPE_NETWORK_UNAVAILABLE 0x00000004 + // #define SERVICETYPE_GENERAL_INFORMATION 0x00000005 + // #define SERVICETYPE_NOCHANGE 0x00000006 + // #define SERVICETYPE_NONCONFORMING 0x00000009 + // #define SERVICETYPE_NETWORK_CONTROL 0x0000000A + // #define SERVICETYPE_QUALITATIVE 0x0000000D (*) + // + // #define SERVICE_BESTEFFORT 0x80010000 + // #define SERVICE_CONTROLLEDLOAD 0x80020000 + // #define SERVICE_GUARANTEED 0x80040000 + // #define SERVICE_QUALITATIVE 0x80200000 + + TbVideoChannel tbChannel(ViE); // Create a video channel + + +#if defined(_WIN32) + // These tests are disabled since they currently fail on Windows. + // Exact reason is unkown. + // See https://code.google.com/p/webrtc/issues/detail?id=1266. + // TODO(mflodman): remove these APIs? + + //// No socket + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_BESTEFFORT)); + + //EXPECT_EQ(0, ViE.network->SetLocalReceiver( + // tbChannel.videoChannel, 1234)); + + //// Sender not initialized + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_BESTEFFORT)); + //EXPECT_EQ(0, ViE.network->SetSendDestination( + // tbChannel.videoChannel, "127.0.0.1", 12345)); + + //// Try to set all non-supported service types + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_NOTRAFFIC)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_NETWORK_UNAVAILABLE)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_GENERAL_INFORMATION)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_NOCHANGE)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_NONCONFORMING)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_NOTRAFFIC)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_NETWORK_CONTROL)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICE_BESTEFFORT)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICE_CONTROLLEDLOAD)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICE_GUARANTEED)); + //EXPECT_NE(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICE_QUALITATIVE)); + + //// Loop through valid service settings + //bool enabled = false; + //int serviceType = 0; + //int overrideDSCP = 0; + + //EXPECT_EQ(0, ViE.network->GetSendGQoS( + // tbChannel.videoChannel, enabled, serviceType, overrideDSCP)); + //EXPECT_FALSE(enabled); + //EXPECT_EQ(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_BESTEFFORT)); + //EXPECT_EQ(0, ViE.network->GetSendGQoS( + // tbChannel.videoChannel, enabled, serviceType, overrideDSCP)); + //EXPECT_TRUE(enabled); + //EXPECT_EQ(SERVICETYPE_BESTEFFORT, serviceType); + //EXPECT_FALSE(overrideDSCP); + + //EXPECT_EQ(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_CONTROLLEDLOAD)); + //EXPECT_EQ(0, ViE.network->GetSendGQoS( + // tbChannel.videoChannel, enabled, serviceType, overrideDSCP)); + //EXPECT_TRUE(enabled); + //EXPECT_EQ(SERVICETYPE_CONTROLLEDLOAD, serviceType); + //EXPECT_FALSE(overrideDSCP); + + //EXPECT_EQ(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_GUARANTEED)); + //EXPECT_EQ(0, ViE.network->GetSendGQoS( + // tbChannel.videoChannel, enabled, serviceType, overrideDSCP)); + //EXPECT_TRUE(enabled); + //EXPECT_EQ(SERVICETYPE_GUARANTEED, serviceType); + //EXPECT_FALSE(overrideDSCP); + + //EXPECT_EQ(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, true, SERVICETYPE_QUALITATIVE)); + //EXPECT_EQ(0, ViE.network->GetSendGQoS( + // tbChannel.videoChannel, enabled, serviceType, overrideDSCP)); + //EXPECT_TRUE(enabled); + //EXPECT_EQ(SERVICETYPE_QUALITATIVE, serviceType); + //EXPECT_FALSE(overrideDSCP); + + //EXPECT_EQ(0, ViE.network->SetSendGQoS( + // tbChannel.videoChannel, false, SERVICETYPE_QUALITATIVE)); + //EXPECT_EQ(0, ViE.network->GetSendGQoS( + // tbChannel.videoChannel, enabled, serviceType, overrideDSCP)); + //EXPECT_FALSE(enabled); +#endif + } + { + // + // MTU and packet burst + // + // Create a video channel + TbVideoChannel tbChannel(ViE); + // Invalid input + EXPECT_NE(0, ViE.network->SetMTU(tbChannel.videoChannel, 1600)); + // Valid input + EXPECT_EQ(0, ViE.network->SetMTU(tbChannel.videoChannel, 800)); + + // + // Observer and timeout + // + ViEAutoTestNetworkObserver vieTestObserver; + EXPECT_EQ(0, ViE.network->RegisterObserver( + tbChannel.videoChannel, vieTestObserver)); + EXPECT_NE(0, ViE.network->RegisterObserver( + tbChannel.videoChannel, vieTestObserver)); + EXPECT_EQ(0, ViE.network->SetPeriodicDeadOrAliveStatus( + tbChannel.videoChannel, true)); // No observer + EXPECT_EQ(0, ViE.network->DeregisterObserver(tbChannel.videoChannel)); + + EXPECT_NE(0, ViE.network->DeregisterObserver(tbChannel.videoChannel)); + EXPECT_NE(0, ViE.network->SetPeriodicDeadOrAliveStatus( + tbChannel.videoChannel, true)); // No observer + + // Packet timout notification + EXPECT_EQ(0, ViE.network->SetPacketTimeoutNotification( + tbChannel.videoChannel, true, 10)); + } + + //*************************************************************** + // Testing finished. Tear down Video Engine + //*************************************************************** +} diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc index eb378c8954..15b2a83f27 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_record.cc @@ -17,22 +17,20 @@ #include #include -#include "webrtc/common_types.h" -#include "webrtc/system_wrappers/interface/tick_util.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/video_engine/test/libvietest/include/tb_external_transport.h" -#include "webrtc/voice_engine/include/voe_base.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h" -#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" -#include "webrtc/video_engine/include/vie_base.h" -#include "webrtc/video_engine/include/vie_capture.h" -#include "webrtc/video_engine/include/vie_codec.h" -#include "webrtc/video_engine/include/vie_file.h" -#include "webrtc/video_engine/include/vie_network.h" -#include "webrtc/video_engine/include/vie_render.h" -#include "webrtc/video_engine/include/vie_rtp_rtcp.h" -#include "webrtc/voice_engine/include/voe_network.h" -#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" +#include "common_types.h" +#include "video_engine/test/libvietest/include/tb_external_transport.h" +#include "voice_engine/include/voe_base.h" +#include "video_engine/test/auto_test/interface/vie_autotest_defines.h" +#include "video_engine/test/auto_test/interface/vie_autotest.h" +#include "video_engine/include/vie_base.h" +#include "video_engine/include/vie_capture.h" +#include "video_engine/include/vie_codec.h" +#include "video_engine/include/vie_file.h" +#include "video_engine/include/vie_network.h" +#include "video_engine/include/vie_render.h" +#include "video_engine/include/vie_rtp_rtcp.h" +#include "voice_engine/include/voe_rtp_rtcp.h" +#include "system_wrappers/interface/tick_util.h" #define VCM_RED_PAYLOAD_TYPE 96 #define VCM_ULPFEC_PAYLOAD_TYPE 97 @@ -141,8 +139,6 @@ int VideoEngineSampleRecordCode(void* window1, void* window2) { webrtc::VoECodec* voe_codec = webrtc::VoECodec::GetInterface(voe); webrtc::VoEAudioProcessing* voe_apm = webrtc::VoEAudioProcessing::GetInterface(voe); - webrtc::VoENetwork* voe_network = - webrtc::VoENetwork::GetInterface(voe); // Get the audio device for the call. memset(audio_capture_device_name, 0, KMaxUniqueIdLength); @@ -151,23 +147,20 @@ int VideoEngineSampleRecordCode(void* window1, void* window2) { audio_capture_device_index, audio_playbackDeviceName, audio_playback_device_index); + // Get the audio codec for the call. memset(static_cast(&audio_codec), 0, sizeof(audio_codec)); GetAudioCodecRecord(voe_codec, audio_codec); audio_channel = voe_base->CreateChannel(); - - webrtc::scoped_ptr voice_channel_transport( - new webrtc::VoiceChannelTransport(voe_network, audio_channel)); - - voice_channel_transport->SetSendDestination(ipAddress, audio_tx_port); - voice_channel_transport->SetLocalReceiver(audio_rx_port); - - voe_hardware->SetRecordingDevice(audio_capture_device_index); - voe_hardware->SetPlayoutDevice(audio_playback_device_index); - voe_codec->SetSendCodec(audio_channel, audio_codec); - voe_apm->SetAgcStatus(true, webrtc::kAgcDefault); - voe_apm->SetNsStatus(true, webrtc::kNsHighSuppression); + error = voe_base->SetSendDestination(audio_channel, audio_tx_port, + ipAddress); + error = voe_base->SetLocalReceiver(audio_channel, audio_rx_port); + error = voe_hardware->SetRecordingDevice(audio_capture_device_index); + error = voe_hardware->SetPlayoutDevice(audio_playback_device_index); + error = voe_codec->SetSendCodec(audio_channel, audio_codec); + error = voe_apm->SetAgcStatus(true, webrtc::kAgcDefault); + error = voe_apm->SetNsStatus(true, webrtc::kNsHighSuppression); // // List available capture devices, allocate and connect. @@ -359,17 +352,18 @@ int VideoEngineSampleRecordCode(void* window1, void* window2) { printf("ERROR in ViENetwork::GetInterface\n"); return -1; } - webrtc::VideoChannelTransport* video_channel_transport = - new webrtc::VideoChannelTransport(ptrViENetwork, videoChannel); - error = video_channel_transport->SetSendDestination(ipAddress, rtpPort); + // Setting External transport + TbExternalTransport extTransport(*(ptrViENetwork), videoChannel, NULL); + error = ptrViENetwork->SetLocalReceiver(videoChannel, rtpPort); if (error == -1) { - printf("ERROR in SetSendDestination\n"); + printf("ERROR in ViENetwork::SetLocalReceiver\n"); return -1; } - error = video_channel_transport->SetLocalReceiver(rtpPort); + error = ptrViENetwork->SetSendDestination(videoChannel, + ipAddress, rtpPort); if (error == -1) { - printf("ERROR in SetLocalReceiver\n"); + printf("ERROR in ViENetwork::SetSendDestination\n"); return -1; } @@ -526,7 +520,6 @@ int VideoEngineSampleRecordCode(void* window1, void* window2) { printf("ERROR in ViEBase::DeleteChannel\n"); return -1; } - delete video_channel_transport; int remainingInterfaces = 0; remainingInterfaces = ptrViECodec->Release(); @@ -539,6 +532,7 @@ int VideoEngineSampleRecordCode(void* window1, void* window2) { printf("ERROR: Could not release all interfaces\n"); return -1; } + bool deleted = webrtc::VideoEngine::Delete(ptrViE); if (deleted == false) { printf("ERROR in VideoEngine::Delete\n"); @@ -570,7 +564,7 @@ int ViEAutoTest::ViERecordCall() { } bool GetAudioCodecRecord(webrtc::VoECodec* voe_codec, - webrtc::CodecInst& audio_codec) { + webrtc::CodecInst& audio_codec) { int error = 0; int number_of_errors = 0; memset(&audio_codec, 0, sizeof(webrtc::CodecInst)); diff --git a/webrtc/video_engine/test/auto_test/vie_auto_test.gypi b/webrtc/video_engine/test/auto_test/vie_auto_test.gypi index 99f8dda6b9..984cc7581c 100644 --- a/webrtc/video_engine/test/auto_test/vie_auto_test.gypi +++ b/webrtc/video_engine/test/auto_test/vie_auto_test.gypi @@ -20,7 +20,6 @@ '<(DEPTH)/third_party/google-gflags/google-gflags.gyp:google-gflags', '<(webrtc_root)/test/metrics.gyp:metrics', '<(webrtc_root)/test/test.gyp:test_support', - '<(webrtc_root)/test/udp_transport.gyp:udp_transport', '<(webrtc_root)/test/libtest/libtest.gyp:libtest', 'video_engine_core', 'libvietest', @@ -82,6 +81,7 @@ 'source/vie_autotest_image_process.cc', 'source/vie_autotest_loopback.cc', 'source/vie_autotest_main.cc', + 'source/vie_autotest_network.cc', 'source/vie_autotest_render.cc', 'source/vie_autotest_record.cc', 'source/vie_autotest_rtp_rtcp.cc', diff --git a/webrtc/video_engine/test/libvietest/include/tb_video_channel.h b/webrtc/video_engine/test/libvietest/include/tb_video_channel.h index c3a458a55e..5c7e6f8b82 100644 --- a/webrtc/video_engine/test/libvietest/include/tb_video_channel.h +++ b/webrtc/video_engine/test/libvietest/include/tb_video_channel.h @@ -11,39 +11,32 @@ #ifndef WEBRTC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_INTERFACE_TB_VIDEO_CHANNEL_H_ #define WEBRTC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_INTERFACE_TB_VIDEO_CHANNEL_H_ -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h" +#include "video_engine/test/libvietest/include/tb_interfaces.h" -namespace webrtc { -class VideoChannelTransport; -} // namespace webrtc +class TbVideoChannel +{ +public: + TbVideoChannel(TbInterfaces& Engine, + webrtc::VideoCodecType sendCodec = webrtc::kVideoCodecVP8, + int width = 352, int height = 288, int frameRate = 30, + int startBitrate = 300); -class TbVideoChannel { - public: - TbVideoChannel(TbInterfaces& Engine, - webrtc::VideoCodecType sendCodec = webrtc::kVideoCodecVP8, - int width = 352, int height = 288, int frameRate = 30, - int startBitrate = 300); + ~TbVideoChannel(void); - ~TbVideoChannel(void); + void SetFrameSettings(int width, int height, int frameRate); - void SetFrameSettings(int width, int height, int frameRate); + void StartSend(const unsigned short rtpPort = 11000, + const char* ipAddress = "127.0.0.1"); - void StartSend(const unsigned short rtpPort = 11000, - const char* ipAddress = "127.0.0.1"); + void StopSend(); - void StopSend(); + void StartReceive(const unsigned short rtpPort = 11000); - void StartReceive(const unsigned short rtpPort = 11000); + void StopReceive(); - void StopReceive(); - - int videoChannel; - - private: - TbInterfaces& ViE; - webrtc::scoped_ptr channel_transport_; + int videoChannel; +private: + TbInterfaces& ViE; }; - #endif // WEBRTC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_INTERFACE_TB_VIDEO_CHANNEL_H_ diff --git a/webrtc/video_engine/test/libvietest/testbed/tb_video_channel.cc b/webrtc/video_engine/test/libvietest/testbed/tb_video_channel.cc index fe3a4385e9..3359f18edf 100644 --- a/webrtc/video_engine/test/libvietest/testbed/tb_video_channel.cc +++ b/webrtc/video_engine/test/libvietest/testbed/tb_video_channel.cc @@ -11,73 +11,82 @@ #include "video_engine/test/libvietest/include/tb_video_channel.h" #include "gtest/gtest.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" TbVideoChannel::TbVideoChannel(TbInterfaces& Engine, webrtc::VideoCodecType sendCodec, int width, - int height, int frameRate, int startBitrate) - : videoChannel(-1), - ViE(Engine) { - EXPECT_EQ(0, ViE.base->CreateChannel(videoChannel)); - channel_transport_.reset(new webrtc::VideoChannelTransport( - ViE.network, videoChannel)); + int height, int frameRate, int startBitrate) : + videoChannel(-1), ViE(Engine) +{ + EXPECT_EQ(0, ViE.base->CreateChannel(videoChannel)); - webrtc::VideoCodec videoCodec; - memset(&videoCodec, 0, sizeof(webrtc::VideoCodec)); - bool sendCodecSet = false; - for (int idx = 0; idx < ViE.codec->NumberOfCodecs(); idx++) { - EXPECT_EQ(0, ViE.codec->GetCodec(idx, videoCodec)); + webrtc::VideoCodec videoCodec; + memset(&videoCodec, 0, sizeof(webrtc::VideoCodec)); + bool sendCodecSet = false; + for (int idx = 0; idx < ViE.codec->NumberOfCodecs(); idx++) + { + EXPECT_EQ(0, ViE.codec->GetCodec(idx, videoCodec)); + videoCodec.width = width; + videoCodec.height = height; + videoCodec.maxFramerate = frameRate; + + if (videoCodec.codecType == sendCodec && sendCodecSet == false) + { + if(videoCodec.codecType != webrtc::kVideoCodecI420 ) + { + videoCodec.startBitrate = startBitrate; + videoCodec.maxBitrate = startBitrate * 3; + } + EXPECT_EQ(0, ViE.codec->SetSendCodec(videoChannel, videoCodec)); + sendCodecSet = true; + } + if (videoCodec.codecType == webrtc::kVideoCodecVP8) + { + videoCodec.width = 352; + videoCodec.height = 288; + } + EXPECT_EQ(0, ViE.codec->SetReceiveCodec(videoChannel, videoCodec)); + } + EXPECT_TRUE(sendCodecSet); +} + +TbVideoChannel::~TbVideoChannel(void) +{ + EXPECT_EQ(0, ViE.base->DeleteChannel(videoChannel)); +} + +void TbVideoChannel::StartSend(const unsigned short rtpPort /*= 11000*/, + const char* ipAddress /*= "127.0.0.1"*/) +{ + EXPECT_EQ(0, ViE.network->SetSendDestination(videoChannel, ipAddress, + rtpPort)); + + EXPECT_EQ(0, ViE.base->StartSend(videoChannel)); +} + +void TbVideoChannel::SetFrameSettings(int width, int height, int frameRate) +{ + webrtc::VideoCodec videoCodec; + EXPECT_EQ(0, ViE.codec->GetSendCodec(videoChannel, videoCodec)); videoCodec.width = width; videoCodec.height = height; videoCodec.maxFramerate = frameRate; - if (videoCodec.codecType == sendCodec && sendCodecSet == false) { - if (videoCodec.codecType != webrtc::kVideoCodecI420) { - videoCodec.startBitrate = startBitrate; - videoCodec.maxBitrate = startBitrate * 3; - } - EXPECT_EQ(0, ViE.codec->SetSendCodec(videoChannel, videoCodec)); - sendCodecSet = true; - } - if (videoCodec.codecType == webrtc::kVideoCodecVP8) { - videoCodec.width = 352; - videoCodec.height = 288; - } + EXPECT_EQ(0, ViE.codec->SetSendCodec(videoChannel, videoCodec)); EXPECT_EQ(0, ViE.codec->SetReceiveCodec(videoChannel, videoCodec)); - } - EXPECT_TRUE(sendCodecSet); } -TbVideoChannel::~TbVideoChannel() { - EXPECT_EQ(0, ViE.base->DeleteChannel(videoChannel)); +void TbVideoChannel::StopSend() +{ + EXPECT_EQ(0, ViE.base->StopSend(videoChannel)); } -void TbVideoChannel::StartSend(const unsigned short rtp_port, - const char* ip_address) { - EXPECT_EQ(0, channel_transport_->SetSendDestination(ip_address, rtp_port)); - EXPECT_EQ(0, ViE.base->StartSend(videoChannel)); +void TbVideoChannel::StartReceive(const unsigned short rtpPort /*= 11000*/) +{ + EXPECT_EQ(0, ViE.network->SetLocalReceiver(videoChannel, rtpPort)); + EXPECT_EQ(0, ViE.base->StartReceive(videoChannel)); } -void TbVideoChannel::SetFrameSettings(int width, int height, int frameRate) { - webrtc::VideoCodec videoCodec; - EXPECT_EQ(0, ViE.codec->GetSendCodec(videoChannel, videoCodec)); - videoCodec.width = width; - videoCodec.height = height; - videoCodec.maxFramerate = frameRate; - - EXPECT_EQ(0, ViE.codec->SetSendCodec(videoChannel, videoCodec)); - EXPECT_EQ(0, ViE.codec->SetReceiveCodec(videoChannel, videoCodec)); -} - -void TbVideoChannel::StopSend() { - EXPECT_EQ(0, ViE.base->StopSend(videoChannel)); -} - -void TbVideoChannel::StartReceive(unsigned short rtp_port) { - EXPECT_EQ(0, channel_transport_->SetLocalReceiver(rtp_port)); - EXPECT_EQ(0, ViE.base->StartReceive(videoChannel)); -} - -void TbVideoChannel::StopReceive() { - EXPECT_EQ(0, ViE.base->StopReceive(videoChannel)); +void TbVideoChannel::StopReceive() +{ + EXPECT_EQ(0, ViE.base->StopReceive(videoChannel)); } diff --git a/webrtc/video_engine/video_engine_core.gypi b/webrtc/video_engine/video_engine_core.gypi index d8e2986907..8f28ef6afa 100644 --- a/webrtc/video_engine/video_engine_core.gypi +++ b/webrtc/video_engine/video_engine_core.gypi @@ -26,6 +26,7 @@ # ModulesShared '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', + '<(webrtc_root)/modules/modules.gyp:udp_transport', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', # ModulesVideo diff --git a/webrtc/video_engine/vie_base_impl.cc b/webrtc/video_engine/vie_base_impl.cc index e35a21661b..6348bc4974 100644 --- a/webrtc/video_engine/vie_base_impl.cc +++ b/webrtc/video_engine/vie_base_impl.cc @@ -325,6 +325,14 @@ int ViEBaseImpl::StartReceive(const int video_channel) { shared_data_.SetLastError(kViEBaseInvalidChannelId); return -1; } + if (vie_channel->Receiving()) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_.instance_id(), video_channel), + "%s: Channel %d already receive.", __FUNCTION__, + video_channel); + shared_data_.SetLastError(kViEBaseAlreadyReceiving); + return -1; + } if (vie_channel->StartReceive() != 0) { shared_data_.SetLastError(kViEBaseUnknownError); return -1; diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index cb1aada92b..a93530ad9c 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -16,6 +16,7 @@ #include "common_video/libyuv/include/webrtc_libyuv.h" #include "modules/pacing/include/paced_sender.h" #include "modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "modules/udp_transport/interface/udp_transport.h" #include "modules/utility/interface/process_thread.h" #include "modules/video_coding/main/interface/video_coding.h" #include "modules/video_processing/main/interface/video_processing.h" @@ -71,6 +72,10 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id, rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()), default_rtp_rtcp_(default_rtp_rtcp), rtp_rtcp_(NULL), +#ifndef WEBRTC_EXTERNAL_TRANSPORT + socket_transport_(*UdpTransport::Create( + ViEModuleId(engine_id, channel_id), num_socket_threads_)), +#endif vcm_(*VideoCodingModule::Create(ViEModuleId(engine_id, channel_id))), vie_receiver_(channel_id, &vcm_, remote_bitrate_estimator), vie_sender_(channel_id), @@ -207,6 +212,9 @@ ViEChannel::~ViEChannel() { channel_id_, engine_id_); // Make sure we don't get more callbacks from the RTP module. +#ifndef WEBRTC_EXTERNAL_TRANSPORT + socket_transport_.StopReceiving(); +#endif module_process_thread_.DeRegisterModule(rtp_rtcp_.get()); module_process_thread_.DeRegisterModule(&vcm_); module_process_thread_.DeRegisterModule(&vie_sync_); @@ -225,6 +233,10 @@ ViEChannel::~ViEChannel() { if (decode_thread_) { StopDecodeThread(); } + // Release modules. +#ifndef WEBRTC_EXTERNAL_TRANSPORT + UdpTransport::Destroy(&socket_transport_); +#endif VideoCodingModule::Destroy(&vcm_); } @@ -1276,16 +1288,265 @@ WebRtc_Word32 ViEChannel::StopRTPDump(RTPDirections direction) { } } +WebRtc_Word32 ViEChannel::SetLocalReceiver(const WebRtc_UWord16 rtp_port, + const WebRtc_UWord16 rtcp_port, + const char* ip_address) { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + + callback_cs_->Enter(); + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: external transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.Receiving()) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: already receiving", __FUNCTION__); + return -1; + } + + const char* multicast_ip_address = NULL; + if (socket_transport_.InitializeReceiveSockets(&vie_receiver_, rtp_port, + ip_address, + multicast_ip_address, + rtcp_port) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not initialize receive sockets. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::GetLocalReceiver(WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + char* ip_address) const { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + + callback_cs_->Enter(); + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: external transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.ReceiveSocketsInitialized() == false) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: receive sockets not initialized", __FUNCTION__); + return -1; + } + + char multicast_ip_address[UdpTransport::kIpAddressVersion6Length]; + if (socket_transport_.ReceiveSocketInformation(ip_address, *rtp_port, + *rtcp_port, + multicast_ip_address) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not get receive socket information. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::SetSendDestination( + const char* ip_address, + const WebRtc_UWord16 rtp_port, + const WebRtc_UWord16 rtcp_port, + const WebRtc_UWord16 source_rtp_port, + const WebRtc_UWord16 source_rtcp_port) { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + + callback_cs_->Enter(); + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: external transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + const bool is_ipv6 = socket_transport_.IpV6Enabled(); + if (UdpTransport::IsIpAddressValid(ip_address, is_ipv6) == false) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Not a valid IP address: %s", __FUNCTION__, ip_address); + return -1; + } + if (socket_transport_.InitializeSendSockets(ip_address, rtp_port, + rtcp_port)!= 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not initialize send socket. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + + if (source_rtp_port != 0) { + WebRtc_UWord16 receive_rtp_port = 0; + WebRtc_UWord16 receive_rtcp_port = 0; + if (socket_transport_.ReceiveSocketInformation(NULL, receive_rtp_port, + receive_rtcp_port, + NULL) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not get receive port information. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + // Initialize an extra socket only if send port differs from receive + // port. + if (source_rtp_port != receive_rtp_port) { + if (socket_transport_.InitializeSourcePorts(source_rtp_port, + source_rtcp_port) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not set source ports. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + } + } + vie_sender_.RegisterSendTransport(&socket_transport_); + + // Workaround to avoid SSRC colision detection in loppback tests. + if (!is_ipv6) { + WebRtc_UWord32 local_host_address = 0; + const WebRtc_UWord32 current_ip_address = + UdpTransport::InetAddrIPV4(ip_address); + + if ((UdpTransport::LocalHostAddress(local_host_address) == 0 && + local_host_address == current_ip_address) || + strncmp("127.0.0.1", ip_address, 9) == 0) { + rtp_rtcp_->SetSSRC(0xFFFFFFFF); + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "Running in loopback. Forcing fixed SSRC"); + } + } else { + char local_host_address[16]; + char current_ip_address[16]; + + WebRtc_Word32 conv_result = + UdpTransport::LocalHostAddressIPV6(local_host_address); + conv_result += socket_transport_.InetPresentationToNumeric( + 23, ip_address, current_ip_address); + if (conv_result == 0) { + bool local_host = true; + for (WebRtc_Word32 i = 0; i < 16; i++) { + if (local_host_address[i] != current_ip_address[i]) { + local_host = false; + break; + } + } + if (!local_host) { + local_host = true; + for (WebRtc_Word32 i = 0; i < 15; i++) { + if (current_ip_address[i] != 0) { + local_host = false; + break; + } + } + if (local_host == true && current_ip_address[15] != 1) { + local_host = false; + } + } + if (local_host) { + rtp_rtcp_->SetSSRC(0xFFFFFFFF); + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, + ViEId(engine_id_, channel_id_), + "Running in loopback. Forcing fixed SSRC"); + } + } + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, + ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::GetSendDestination( + char* ip_address, + WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + WebRtc_UWord16* source_rtp_port, + WebRtc_UWord16* source_rtcp_port) const { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + + callback_cs_->Enter(); + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: external transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.SendSocketsInitialized() == false) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: send sockets not initialized", __FUNCTION__); + return -1; + } + if (socket_transport_.SendSocketInformation(ip_address, *rtp_port, + *rtcp_port) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not get send socket information. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + *source_rtp_port = 0; + *source_rtcp_port = 0; + if (socket_transport_.SourcePortsInitialized()) { + socket_transport_.SourcePorts(*source_rtp_port, *source_rtcp_port); + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + WebRtc_Word32 ViEChannel::StartSend() { CriticalSectionScoped cs(callback_cs_.get()); WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", __FUNCTION__); - if (!external_transport_) { - WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), - "%s: send sockets not initialized", __FUNCTION__); - return -1; - } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!external_transport_) { + if (socket_transport_.SendSocketsInitialized() == false) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: send sockets not initialized", __FUNCTION__); + return -1; + } + } +#endif rtp_rtcp_->SetSendingMediaStatus(true); if (rtp_rtcp_->Sending()) { @@ -1354,10 +1615,35 @@ WebRtc_Word32 ViEChannel::StartReceive() { WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", __FUNCTION__); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!external_transport_) { + if (socket_transport_.Receiving()) { + // Warning, don't return error. + WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: already receiving", __FUNCTION__); + return 0; + } + if (socket_transport_.ReceiveSocketsInitialized() == false) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: receive sockets not initialized", __FUNCTION__); + return -1; + } + if (socket_transport_.StartReceiving(kViENumReceiveSocketBuffers) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not get receive socket information. Socket error:%d", + __FUNCTION__, socket_error); + return -1; + } + } +#endif if (StartDecodeThread() != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), "%s: could not start decoder thread", __FUNCTION__); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + socket_transport_.StopReceiving(); +#endif vie_receiver_.StopReceive(); return -1; } @@ -1373,12 +1659,100 @@ WebRtc_Word32 ViEChannel::StopReceive() { vie_receiver_.StopReceive(); StopDecodeThread(); vcm_.ResetDecoder(); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + return 0; + } + } + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.Receiving() == false) { + // Warning, don't return error + WEBRTC_TRACE(kTraceWarning, kTraceVideo, + ViEId(engine_id_, channel_id_), "%s: not receiving", + __FUNCTION__); + return 0; + } + if (socket_transport_.StopReceiving() != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Socket error: %d", __FUNCTION__, socket_error); + return -1; + } +#endif + return 0; } +bool ViEChannel::Receiving() { +#ifndef WEBRTC_EXTERNAL_TRANSPORT + return socket_transport_.Receiving(); +#else + return false; +#endif +} + +WebRtc_Word32 ViEChannel::GetSourceInfo(WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + char* ip_address, + WebRtc_UWord32 ip_address_length) { + { + CriticalSectionScoped cs(callback_cs_.get()); + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: external transport registered", __FUNCTION__); + return -1; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.IpV6Enabled() && + ip_address_length < UdpTransport::kIpAddressVersion6Length) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: IP address length is too small for IPv6", __FUNCTION__); + return -1; + } else if (ip_address_length < UdpTransport::kIpAddressVersion4Length) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: IP address length is too small for IPv4", __FUNCTION__); + return -1; + } + + if (socket_transport_.RemoteSocketInformation(ip_address, *rtp_port, + *rtcp_port) != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Error getting source ports. Socket error: %d", + __FUNCTION__, socket_error); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + WebRtc_Word32 ViEChannel::RegisterSendTransport(Transport* transport) { WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", __FUNCTION__); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.SendSocketsInitialized() || + socket_transport_.ReceiveSocketsInitialized()) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: socket transport already initialized", __FUNCTION__); + return -1; + } +#endif + if (rtp_rtcp_->Sending()) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Sending", __FUNCTION__); + return -1; + } + CriticalSectionScoped cs(callback_cs_.get()); if (external_transport_) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), @@ -1416,14 +1790,258 @@ WebRtc_Word32 ViEChannel::DeregisterSendTransport() { WebRtc_Word32 ViEChannel::ReceivedRTPPacket( const void* rtp_packet, const WebRtc_Word32 rtp_packet_length) { + { + CriticalSectionScoped cs(callback_cs_.get()); + if (!external_transport_) { + return -1; + } + } return vie_receiver_.ReceivedRTPPacket(rtp_packet, rtp_packet_length); } WebRtc_Word32 ViEChannel::ReceivedRTCPPacket( - const void* rtcp_packet, const WebRtc_Word32 rtcp_packet_length) { + const void* rtcp_packet, const WebRtc_Word32 rtcp_packet_length) { + { + CriticalSectionScoped cs(callback_cs_.get()); + if (!external_transport_) { + return -1; + } + } return vie_receiver_.ReceivedRTCPPacket(rtcp_packet, rtcp_packet_length); } +WebRtc_Word32 ViEChannel::EnableIPv6() { + callback_cs_->Enter(); + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s", __FUNCTION__); + + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.IpV6Enabled()) { + WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: IPv6 already enabled", __FUNCTION__); + return -1; + } + + if (socket_transport_.EnableIpV6() != 0) { + WebRtc_Word32 socket_error = socket_transport_.LastError(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: could not enable IPv6. Socket error: %d", __FUNCTION__, + socket_error); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +bool ViEChannel::IsIPv6Enabled() { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return false; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + return socket_transport_.IpV6Enabled(); +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return false; +#endif +} + +WebRtc_Word32 ViEChannel::SetSourceFilter(const WebRtc_UWord16 rtp_port, + const WebRtc_UWord16 rtcp_port, + const char* ip_address) { + callback_cs_->Enter(); + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.SetFilterIP(ip_address) != 0) { + // Logging done in module. + return -1; + } + if (socket_transport_.SetFilterPorts(rtp_port, rtcp_port) != 0) { + // Logging done. + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::GetSourceFilter(WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + char* ip_address) const { + callback_cs_->Enter(); + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + + if (external_transport_) { + callback_cs_->Leave(); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + callback_cs_->Leave(); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.FilterIP(ip_address) != 0) { + // Logging done in module. + return -1; + } + if (socket_transport_.FilterPorts(*rtp_port, *rtcp_port) != 0) { + // Logging done in module. + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::SetToS(const WebRtc_Word32 DSCP, + const bool use_set_sockOpt) { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.SetToS(DSCP, use_set_sockOpt) != 0) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Socket error: %d", __FUNCTION__, + socket_transport_.LastError()); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::GetToS(WebRtc_Word32* DSCP, + bool* use_set_sockOpt) const { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.ToS(*DSCP, *use_set_sockOpt) != 0) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Socket error: %d", __FUNCTION__, + socket_transport_.LastError()); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::SetSendGQoS(const bool enable, + const WebRtc_Word32 service_type, + const WebRtc_UWord32 max_bitrate, + const WebRtc_Word32 overrideDSCP) { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.SetQoS(enable, service_type, max_bitrate, overrideDSCP, + false) != 0) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Socket error: %d", __FUNCTION__, + socket_transport_.LastError()); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + +WebRtc_Word32 ViEChannel::GetSendGQoS(bool* enabled, + WebRtc_Word32* service_type, + WebRtc_Word32* overrideDSCP) const { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.QoS(*enabled, *service_type, *overrideDSCP) != 0) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: Socket error: %d", __FUNCTION__, + socket_transport_.LastError()); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + WebRtc_Word32 ViEChannel::SetMTU(WebRtc_UWord16 mtu) { WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", __FUNCTION__); @@ -1534,6 +2152,35 @@ WebRtc_Word32 ViEChannel::SetPeriodicDeadOrAliveStatus( return 0; } +WebRtc_Word32 ViEChannel::SendUDPPacket(const WebRtc_Word8* data, + const WebRtc_UWord32 length, + WebRtc_Word32& transmitted_bytes, + bool use_rtcp_socket) { + WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + { + CriticalSectionScoped cs(callback_cs_.get()); + if (external_transport_) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: External transport registered", __FUNCTION__); + return -1; + } + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + transmitted_bytes = socket_transport_.SendRaw(data, length, use_rtcp_socket); + if (transmitted_bytes == -1) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_), "%s", + __FUNCTION__); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(engine_id_, channel_id_), + "%s: not available for external transport", __FUNCTION__); + return -1; +#endif +} + WebRtc_Word32 ViEChannel::EnableColorEnhancement(bool enable) { WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s(enable: %d)", __FUNCTION__, enable); @@ -1747,7 +2394,7 @@ WebRtc_Word32 ViEChannel::DeRegisterExternalEncryption() { return -1; } - external_encryption_ = NULL; + external_transport_ = NULL; vie_receiver_.DeregisterExternalDecryption(); vie_sender_.DeregisterExternalEncryption(); WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), @@ -1868,7 +2515,11 @@ void ViEChannel::OnPacketTimeout(const WebRtc_Word32 id) { CriticalSectionScoped cs(callback_cs_.get()); if (networkObserver_) { +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (socket_transport_.Receiving() || external_transport_) { +#else if (external_transport_) { +#endif networkObserver_->PacketTimeout(channel_id_, NoPacket); rtp_packet_timeout_ = true; } diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index 631fb3780d..fe333aa7f8 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -15,6 +15,7 @@ #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "modules/udp_transport/interface/udp_transport.h" #include "modules/video_coding/main/interface/video_coding_defines.h" #include "system_wrappers/interface/scoped_ptr.h" #include "system_wrappers/interface/tick_util.h" @@ -218,6 +219,27 @@ class ViEChannel const WebRtc_UWord32 CSRC, const bool added); + WebRtc_Word32 SetLocalReceiver(const WebRtc_UWord16 rtp_port, + const WebRtc_UWord16 rtcp_port, + const char* ip_address); + WebRtc_Word32 GetLocalReceiver(WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + char* ip_address) const; + WebRtc_Word32 SetSendDestination(const char* ip_address, + const WebRtc_UWord16 rtp_port, + const WebRtc_UWord16 rtcp_port, + const WebRtc_UWord16 source_rtp_port, + const WebRtc_UWord16 source_rtcp_port); + WebRtc_Word32 GetSendDestination(char* ip_address, + WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + WebRtc_UWord16* source_rtp_port, + WebRtc_UWord16* source_rtcp_port) const; + WebRtc_Word32 GetSourceInfo(WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + char* ip_address, + WebRtc_UWord32 ip_address_length); + WebRtc_Word32 SetRemoteSSRCType(const StreamType usage, const uint32_t SSRC) const; @@ -226,6 +248,7 @@ class ViEChannel bool Sending(); WebRtc_Word32 StartReceive(); WebRtc_Word32 StopReceive(); + bool Receiving(); WebRtc_Word32 RegisterSendTransport(Transport* transport); WebRtc_Word32 DeregisterSendTransport(); @@ -238,6 +261,25 @@ class ViEChannel WebRtc_Word32 ReceivedRTCPPacket(const void* rtcp_packet, const WebRtc_Word32 rtcp_packet_length); + WebRtc_Word32 EnableIPv6(); + bool IsIPv6Enabled(); + WebRtc_Word32 SetSourceFilter(const WebRtc_UWord16 rtp_port, + const WebRtc_UWord16 rtcp_port, + const char* ip_address); + WebRtc_Word32 GetSourceFilter(WebRtc_UWord16* rtp_port, + WebRtc_UWord16* rtcp_port, + char* ip_address) const; + + WebRtc_Word32 SetToS(const WebRtc_Word32 DSCP, const bool use_set_sockOpt); + WebRtc_Word32 GetToS(WebRtc_Word32* DSCP, bool* use_set_sockOpt) const; + WebRtc_Word32 SetSendGQoS(const bool enable, + const WebRtc_Word32 service_type, + const WebRtc_UWord32 max_bitrate, + const WebRtc_Word32 overrideDSCP); + WebRtc_Word32 GetSendGQoS(bool* enabled, + WebRtc_Word32* service_type, + WebRtc_Word32* overrideDSCP) const; + // Sets the maximum transfer unit size for the network link, i.e. including // IP, UDP and RTP headers. WebRtc_Word32 SetMTU(WebRtc_UWord16 mtu); @@ -256,6 +298,11 @@ class ViEChannel WebRtc_Word32 SetPeriodicDeadOrAliveStatus( const bool enable, const WebRtc_UWord32 sample_time_seconds); + WebRtc_Word32 SendUDPPacket(const WebRtc_Word8* data, + const WebRtc_UWord32 length, + WebRtc_Word32& transmitted_bytes, + bool use_rtcp_socket); + WebRtc_Word32 EnableColorEnhancement(bool enable); // Gets the modules used by the channel. @@ -337,6 +384,9 @@ class ViEChannel scoped_ptr rtp_rtcp_; std::list simulcast_rtp_rtcp_; std::list removed_rtp_rtcp_; +#ifndef WEBRTC_EXTERNAL_TRANSPORT + UdpTransport& socket_transport_; +#endif VideoCodingModule& vcm_; ViEReceiver vie_receiver_; ViESender vie_sender_; diff --git a/webrtc/video_engine/vie_impl.cc b/webrtc/video_engine/vie_impl.cc index 6b1eb43380..b8066d74ab 100644 --- a/webrtc/video_engine/vie_impl.cc +++ b/webrtc/video_engine/vie_impl.cc @@ -127,12 +127,14 @@ bool VideoEngine::Delete(VideoEngine*& video_engine) { return false; } #endif +#ifdef WEBRTC_VIDEO_ENGINE_NETWORK_API ViENetworkImpl* vie_network = vie_impl; if (vie_network->GetCount() > 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, g_vie_active_instance_counter, "ViENetwork ref count: %d", vie_network->GetCount()); return false; } +#endif #ifdef WEBRTC_VIDEO_ENGINE_RENDER_API ViERenderImpl* vie_render = vie_impl; if (vie_render->GetCount() > 0) { diff --git a/webrtc/video_engine/vie_impl.h b/webrtc/video_engine/vie_impl.h index b230fba72f..ca5d903138 100644 --- a/webrtc/video_engine/vie_impl.h +++ b/webrtc/video_engine/vie_impl.h @@ -31,7 +31,9 @@ #ifdef WEBRTC_VIDEO_ENGINE_IMAGE_PROCESS_API #include "video_engine/vie_image_process_impl.h" #endif +#ifdef WEBRTC_VIDEO_ENGINE_NETWORK_API #include "video_engine/vie_network_impl.h" +#endif #ifdef WEBRTC_VIDEO_ENGINE_RENDER_API #include "video_engine/vie_render_impl.h" #endif @@ -61,7 +63,9 @@ class VideoEngineImpl #ifdef WEBRTC_VIDEO_ENGINE_IMAGE_PROCESS_API , public ViEImageProcessImpl #endif +#ifdef WEBRTC_VIDEO_ENGINE_NETWORK_API , public ViENetworkImpl +#endif #ifdef WEBRTC_VIDEO_ENGINE_RENDER_API , public ViERenderImpl #endif @@ -90,7 +94,9 @@ class VideoEngineImpl #ifdef WEBRTC_VIDEO_ENGINE_IMAGE_PROCESS_API , ViEImageProcessImpl(ViEBaseImpl::shared_data()) #endif +#ifdef WEBRTC_VIDEO_ENGINE_NETWORK_API , ViENetworkImpl(ViEBaseImpl::shared_data()) +#endif #ifdef WEBRTC_VIDEO_ENGINE_RENDER_API , ViERenderImpl(ViEBaseImpl::shared_data()) #endif diff --git a/webrtc/video_engine/vie_network_impl.cc b/webrtc/video_engine/vie_network_impl.cc index 96c8be57ee..378d08f316 100644 --- a/webrtc/video_engine/vie_network_impl.cc +++ b/webrtc/video_engine/vie_network_impl.cc @@ -10,6 +10,11 @@ #include "video_engine/vie_network_impl.h" +#include +#if (defined(WIN32_) || defined(WIN64_)) +#include +#endif + #include "engine_configurations.h" // NOLINT #include "system_wrappers/interface/trace.h" #include "video_engine/include/vie_errors.h" @@ -23,6 +28,7 @@ namespace webrtc { ViENetwork* ViENetwork::GetInterface(VideoEngine* video_engine) { +#ifdef WEBRTC_VIDEO_ENGINE_NETWORK_API if (!video_engine) { return NULL; } @@ -31,6 +37,9 @@ ViENetwork* ViENetwork::GetInterface(VideoEngine* video_engine) { // Increase ref count. (*vie_networkImpl)++; return vie_networkImpl; +#else + return NULL; +#endif } int ViENetworkImpl::Release() { @@ -62,6 +71,140 @@ ViENetworkImpl::~ViENetworkImpl() { "ViENetworkImpl::~ViENetworkImpl() Dtor"); } +int ViENetworkImpl::SetLocalReceiver(const int video_channel, + const uint16_t rtp_port, + const uint16_t rtcp_port, + const char* ip_address) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d, rtp_port: %u, rtcp_port: %u, ip_address: %s)", + __FUNCTION__, video_channel, rtp_port, rtcp_port, ip_address); + if (!shared_data_->Initialized()) { + shared_data_->SetLastError(kViENotInitialized); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s - ViE instance %d not initialized", __FUNCTION__, + shared_data_->instance_id()); + return -1; + } + + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + // The channel doesn't exists. + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + + if (vie_channel->Receiving()) { + shared_data_->SetLastError(kViENetworkAlreadyReceiving); + return -1; + } + if (vie_channel->SetLocalReceiver(rtp_port, rtcp_port, ip_address) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::GetLocalReceiver(const int video_channel, + uint16_t& rtp_port, + uint16_t& rtcp_port, + char* ip_address) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->GetLocalReceiver(&rtp_port, &rtcp_port, ip_address) != 0) { + shared_data_->SetLastError(kViENetworkLocalReceiverNotSet); + return -1; + } + return 0; +} + +int ViENetworkImpl::SetSendDestination(const int video_channel, + const char* ip_address, + const uint16_t rtp_port, + const uint16_t rtcp_port, + const uint16_t source_rtp_port, + const uint16_t source_rtcp_port) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d, ip_address: %s, rtp_port: %u, rtcp_port: %u, " + "sourceRtpPort: %u, source_rtcp_port: %u)", + __FUNCTION__, video_channel, ip_address, rtp_port, rtcp_port, + source_rtp_port, source_rtcp_port); + if (!shared_data_->Initialized()) { + shared_data_->SetLastError(kViENotInitialized); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s - ViE instance %d not initialized", __FUNCTION__, + shared_data_->instance_id()); + return -1; + } + + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s Channel doesn't exist", __FUNCTION__); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->Sending()) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s Channel already sending.", __FUNCTION__); + shared_data_->SetLastError(kViENetworkAlreadySending); + return -1; + } + if (vie_channel->SetSendDestination(ip_address, rtp_port, rtcp_port, + source_rtp_port, + source_rtcp_port) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::GetSendDestination(const int video_channel, + char* ip_address, + uint16_t& rtp_port, + uint16_t& rtcp_port, + uint16_t& source_rtp_port, + uint16_t& source_rtcp_port) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->GetSendDestination(ip_address, &rtp_port, &rtcp_port, + &source_rtp_port, + &source_rtcp_port) != 0) { + shared_data_->SetLastError(kViENetworkDestinationNotSet); + return -1; + } + return 0; +} + int ViENetworkImpl::RegisterSendTransport(const int video_channel, Transport& transport) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, @@ -175,6 +318,340 @@ int ViENetworkImpl::ReceivedRTCPPacket(const int video_channel, return vie_channel->ReceivedRTCPPacket(data, length); } +int ViENetworkImpl::GetSourceInfo(const int video_channel, + uint16_t& rtp_port, + uint16_t& rtcp_port, char* ip_address, + unsigned int ip_address_length) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->GetSourceInfo(&rtp_port, &rtcp_port, ip_address, + ip_address_length) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::GetLocalIP(char ip_address[64], bool ipv6) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s( ip_address, ipV6: %d)", __FUNCTION__, ipv6); + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!shared_data_->Initialized()) { + shared_data_->SetLastError(kViENotInitialized); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s - ViE instance %d not initialized", __FUNCTION__, + shared_data_->instance_id()); + return -1; + } + + if (!ip_address) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s: No argument", __FUNCTION__); + shared_data_->SetLastError(kViENetworkInvalidArgument); + return -1; + } + + WebRtc_UWord8 num_socket_threads = 1; + UdpTransport* socket_transport = UdpTransport::Create( + ViEModuleId(shared_data_->instance_id(), -1), num_socket_threads); + + if (!socket_transport) { + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s: Could not create socket module", __FUNCTION__); + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + + char local_ip_address[64]; + if (ipv6) { + char local_ip[16]; + if (socket_transport->LocalHostAddressIPV6(local_ip) != 0) { + UdpTransport::Destroy(socket_transport); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s: Could not get local IP", __FUNCTION__); + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + // Convert 128-bit address to character string (a:b:c:d:e:f:g:h). + // TODO(mflodman) Change sprintf. + sprintf(local_ip_address, // NOLINT + "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:" + "%.2x%.2x", + local_ip[0], local_ip[1], local_ip[2], local_ip[3], local_ip[4], + local_ip[5], local_ip[6], local_ip[7], local_ip[8], local_ip[9], + local_ip[10], local_ip[11], local_ip[12], local_ip[13], + local_ip[14], local_ip[15]); + } else { + WebRtc_UWord32 local_ip = 0; + if (socket_transport->LocalHostAddress(local_ip) != 0) { + UdpTransport::Destroy(socket_transport); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s: Could not get local IP", __FUNCTION__); + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + // Convert 32-bit address to character string (x.y.z.w). + // TODO(mflodman) Change sprintf. + sprintf(local_ip_address, "%d.%d.%d.%d", // NOLINT + static_cast((local_ip >> 24) & 0x0ff), + static_cast((local_ip >> 16) & 0x0ff), + static_cast((local_ip >> 8) & 0x0ff), + static_cast(local_ip & 0x0ff)); + } + strncpy(ip_address, local_ip_address, sizeof(local_ip_address)); + UdpTransport::Destroy(socket_transport); + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s: local ip = %s", __FUNCTION__, local_ip_address); + return 0; +#else + WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s: not available for external transport", __FUNCTION__); + + return -1; +#endif +} + +int ViENetworkImpl::EnableIPv6(int video_channel) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->EnableIPv6() != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +bool ViENetworkImpl::IsIPv6Enabled(int video_channel) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return false; + } + return vie_channel->IsIPv6Enabled(); +} + +int ViENetworkImpl::SetSourceFilter(const int video_channel, + const uint16_t rtp_port, + const uint16_t rtcp_port, + const char* ip_address) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d, rtp_port: %u, rtcp_port: %u, ip_address: %s)", + __FUNCTION__, video_channel, rtp_port, rtcp_port, ip_address); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->SetSourceFilter(rtp_port, rtcp_port, ip_address) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::GetSourceFilter(const int video_channel, + uint16_t& rtp_port, + uint16_t& rtcp_port, + char* ip_address) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->GetSourceFilter(&rtp_port, &rtcp_port, ip_address) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::SetSendToS(const int video_channel, const int DSCP, + const bool use_set_sockOpt = false) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d, DSCP: %d, use_set_sockOpt: %d)", __FUNCTION__, + video_channel, DSCP, use_set_sockOpt); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + +#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) + WEBRTC_TRACE(kTraceInfo, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + " force use_set_sockopt=true since there is no alternative" + " implementation"); + if (vie_channel->SetToS(DSCP, true) != 0) { +#else + if (vie_channel->SetToS(DSCP, use_set_sockOpt) != 0) { +#endif + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::GetSendToS(const int video_channel, + int& DSCP, // NOLINT + bool& use_set_sockOpt) { // NOLINT + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->GetToS(&DSCP, &use_set_sockOpt) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + +int ViENetworkImpl::SetSendGQoS(const int video_channel, const bool enable, + const int service_type, + const int overrideDSCP) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d, enable: %d, service_type: %d, " + "overrideDSCP: %d)", __FUNCTION__, video_channel, enable, + service_type, overrideDSCP); + if (!shared_data_->Initialized()) { + shared_data_->SetLastError(kViENotInitialized); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s - ViE instance %d not initialized", __FUNCTION__, + shared_data_->instance_id()); + return -1; + } + +#if (defined(WIN32_) || defined(WIN64_)) + // Sanity check. We might crash if testing and relying on an OS socket error. + if (enable && + (service_type != SERVICETYPE_BESTEFFORT) && + (service_type != SERVICETYPE_CONTROLLEDLOAD) && + (service_type != SERVICETYPE_GUARANTEED) && + (service_type != SERVICETYPE_QUALITATIVE)) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s: service type %d not supported", __FUNCTION__, + video_channel, service_type); + shared_data_->SetLastError(kViENetworkServiceTypeNotSupported); + return -1; + } + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + ViEEncoder* vie_encoder = cs.Encoder(video_channel); + if (!vie_encoder) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + VideoCodec video_codec; + if (vie_encoder->GetEncoder(video_codec) != 0) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s: Could not get max bitrate for the channel", + __FUNCTION__); + shared_data_->SetLastError(kViENetworkSendCodecNotSet); + return -1; + } + if (vie_channel->SetSendGQoS(enable, service_type, video_codec.maxBitrate, + overrideDSCP) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +#else + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s: Not supported", __FUNCTION__); + shared_data_->SetLastError(kViENetworkNotSupported); + return -1; +#endif +} + +int ViENetworkImpl::GetSendGQoS(const int video_channel, + bool& enabled, // NOLINT + int& service_type, // NOLINT + int& overrideDSCP) { // NOLINT + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->GetSendGQoS(&enabled, &service_type, &overrideDSCP) != 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + int ViENetworkImpl::SetMTU(int video_channel, unsigned int mtu) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), @@ -289,4 +766,38 @@ int ViENetworkImpl::SetPeriodicDeadOrAliveStatus( return 0; } +int ViENetworkImpl::SendUDPPacket(const int video_channel, const void* data, + const unsigned int length, + int& transmitted_bytes, + bool use_rtcp_socket = false) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d, data: -, length: %d, transmitter_bytes: -, " + "useRtcpSocket: %d)", __FUNCTION__, video_channel, length, + use_rtcp_socket); + if (!shared_data_->Initialized()) { + shared_data_->SetLastError(kViENotInitialized); + WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()), + "%s - ViE instance %d not initialized", __FUNCTION__, + shared_data_->instance_id()); + return -1; + } + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "Channel doesn't exist"); + shared_data_->SetLastError(kViENetworkInvalidChannelId); + return -1; + } + if (vie_channel->SendUDPPacket((const WebRtc_Word8*) data, length, + (WebRtc_Word32&) transmitted_bytes, + use_rtcp_socket) < 0) { + shared_data_->SetLastError(kViENetworkUnknownError); + return -1; + } + return 0; +} + } // namespace webrtc diff --git a/webrtc/video_engine/vie_network_impl.h b/webrtc/video_engine/vie_network_impl.h index 6e992eb0d7..56832df089 100644 --- a/webrtc/video_engine/vie_network_impl.h +++ b/webrtc/video_engine/vie_network_impl.h @@ -25,6 +25,26 @@ class ViENetworkImpl public: // Implements ViENetwork. virtual int Release(); + virtual int SetLocalReceiver(const int video_channel, + const uint16_t rtp_port, + const uint16_t rtcp_port, + const char* ip_address); + virtual int GetLocalReceiver(const int video_channel, + uint16_t& rtp_port, + uint16_t& rtcp_port, + char* ip_address); + virtual int SetSendDestination(const int video_channel, + const char* ip_address, + const uint16_t rtp_port, + const uint16_t rtcp_port, + const uint16_t source_rtp_port, + const uint16_t source_rtcp_port); + virtual int GetSendDestination(const int video_channel, + char* ip_address, + uint16_t& rtp_port, + uint16_t& rtcp_port, + uint16_t& source_rtp_port, + uint16_t& source_rtcp_port); virtual int RegisterSendTransport(const int video_channel, Transport& transport); virtual int DeregisterSendTransport(const int video_channel); @@ -34,6 +54,36 @@ class ViENetworkImpl virtual int ReceivedRTCPPacket(const int video_channel, const void* data, const int length); + virtual int GetSourceInfo(const int video_channel, + uint16_t& rtp_port, + uint16_t& rtcp_port, + char* ip_address, + unsigned int ip_address_length); + virtual int GetLocalIP(char ip_address[64], bool ipv6); + virtual int EnableIPv6(int video_channel); + virtual bool IsIPv6Enabled(int video_channel); + virtual int SetSourceFilter(const int video_channel, + const uint16_t rtp_port, + const uint16_t rtcp_port, + const char* ip_address); + virtual int GetSourceFilter(const int video_channel, + uint16_t& rtp_port, + uint16_t& rtcp_port, + char* ip_address); + virtual int SetSendToS(const int video_channel, + const int DSCP, + const bool use_set_sockOpt); + virtual int GetSendToS(const int video_channel, + int& DSCP, + bool& use_set_sockOpt); + virtual int SetSendGQoS(const int video_channel, + const bool enable, + const int service_type, + const int overrideDSCP); + virtual int GetSendGQoS(const int video_channel, + bool& enabled, + int& service_type, + int& overrideDSCP); virtual int SetMTU(int video_channel, unsigned int mtu); virtual int SetPacketTimeoutNotification(const int video_channel, bool enable, @@ -45,6 +95,11 @@ class ViENetworkImpl const int video_channel, const bool enable, const unsigned int sample_time_seconds); + virtual int SendUDPPacket(const int video_channel, + const void* data, + const unsigned int length, + int& transmitted_bytes, + bool use_rtcp_socket); protected: explicit ViENetworkImpl(ViESharedData* shared_data); diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc index 57c9d163ea..43aa566164 100644 --- a/webrtc/video_engine/vie_receiver.cc +++ b/webrtc/video_engine/vie_receiver.cc @@ -87,6 +87,20 @@ void ViEReceiver::RegisterSimulcastRtpRtcpModules( } } +void ViEReceiver::IncomingRTPPacket(const WebRtc_Word8* rtp_packet, + const WebRtc_Word32 rtp_packet_length, + const char* from_ip, + const WebRtc_UWord16 from_port) { + InsertRTPPacket(rtp_packet, rtp_packet_length); +} + +void ViEReceiver::IncomingRTCPPacket(const WebRtc_Word8* rtcp_packet, + const WebRtc_Word32 rtcp_packet_length, + const char* from_ip, + const WebRtc_UWord16 from_port) { + InsertRTCPPacket(rtcp_packet, rtcp_packet_length); +} + int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet, int rtp_packet_length) { if (!receiving_) { diff --git a/webrtc/video_engine/vie_receiver.h b/webrtc/video_engine/vie_receiver.h index dda2f290bf..4f43fc9d67 100644 --- a/webrtc/video_engine/vie_receiver.h +++ b/webrtc/video_engine/vie_receiver.h @@ -15,6 +15,7 @@ #include "engine_configurations.h" // NOLINT #include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "modules/udp_transport/interface/udp_transport.h" #include "system_wrappers/interface/scoped_ptr.h" #include "typedefs.h" // NOLINT #include "video_engine/vie_defines.h" @@ -28,7 +29,7 @@ class RtpDump; class RtpRtcp; class VideoCodingModule; -class ViEReceiver : public RtpData { +class ViEReceiver : public UdpTransportData, public RtpData { public: ViEReceiver(const int32_t channel_id, VideoCodingModule* module_vcm, RemoteBitrateEstimator* remote_bitrate_estimator); @@ -47,6 +48,16 @@ class ViEReceiver : public RtpData { int StartRTPDump(const char file_nameUTF8[1024]); int StopRTPDump(); + // Implements UdpTransportData. + virtual void IncomingRTPPacket(const WebRtc_Word8* rtp_packet, + const WebRtc_Word32 rtp_packet_length, + const char* from_ip, + const WebRtc_UWord16 from_port); + virtual void IncomingRTCPPacket(const WebRtc_Word8* rtcp_packet, + const WebRtc_Word32 rtcp_packet_length, + const char* from_ip, + const WebRtc_UWord16 from_port); + // Receives packets from external transport. int ReceivedRTPPacket(const void* rtp_packet, int rtp_packet_length); int ReceivedRTCPPacket(const void* rtcp_packet, int rtcp_packet_length); diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc index 7691bf0902..1eabee8401 100644 --- a/webrtc/voice_engine/channel.cc +++ b/webrtc/voice_engine/channel.cc @@ -331,6 +331,163 @@ Channel::SendRTCPPacket(int channel, const void *data, int len) return len; } +void +Channel::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) +{ + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::IncomingRTPPacket(rtpPacketLength=%d," + " fromIP=%s, fromPort=%u)", + rtpPacketLength, fromIP, fromPort); + + // Store playout timestamp for the received RTP packet + // to be used for upcoming delay estimations + WebRtc_UWord32 playoutTimestamp(0); + if (GetPlayoutTimeStamp(playoutTimestamp) == 0) + { + _playoutTimeStampRTP = playoutTimestamp; + } + + WebRtc_UWord8* rtpBufferPtr = (WebRtc_UWord8*)incomingRtpPacket; + WebRtc_Word32 rtpBufferLength = rtpPacketLength; + + // SRTP or External decryption + if (_decrypting) + { + CriticalSectionScoped cs(&_callbackCritSect); + + if (_encryptionPtr) + { + if (!_decryptionRTPBufferPtr) + { + // Allocate memory for decryption buffer one time only + _decryptionRTPBufferPtr = + new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes]; + } + + // Perform decryption (SRTP or external) + WebRtc_Word32 decryptedBufferLength = 0; + _encryptionPtr->decrypt(_channelId, + rtpBufferPtr, + _decryptionRTPBufferPtr, + rtpBufferLength, + (int*)&decryptedBufferLength); + if (decryptedBufferLength <= 0) + { + _engineStatisticsPtr->SetLastError( + VE_DECRYPTION_FAILED, kTraceError, + "Channel::IncomingRTPPacket() decryption failed"); + return; + } + + // Replace default data buffer with decrypted buffer + rtpBufferPtr = _decryptionRTPBufferPtr; + rtpBufferLength = decryptedBufferLength; + } + } + + // Dump the RTP packet to a file (if RTP dump is enabled). + if (_rtpDumpIn.DumpPacket(rtpBufferPtr, + (WebRtc_UWord16)rtpBufferLength) == -1) + { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, + VoEId(_instanceId,_channelId), + "Channel::SendPacket() RTP dump to input file failed"); + } + + // Deliver RTP packet to RTP/RTCP module for parsing + // The packet will be pushed back to the channel thru the + // OnReceivedPayloadData callback so we don't push it to the ACM here + if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtpBufferPtr, + (WebRtc_UWord16)rtpBufferLength) == -1) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, + "Channel::IncomingRTPPacket() RTP packet is invalid"); + return; + } +} + +void +Channel::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) +{ + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::IncomingRTCPPacket(rtcpPacketLength=%d, fromIP=%s," + " fromPort=%u)", + rtcpPacketLength, fromIP, fromPort); + + // Temporary buffer pointer and size for decryption + WebRtc_UWord8* rtcpBufferPtr = (WebRtc_UWord8*)incomingRtcpPacket; + WebRtc_Word32 rtcpBufferLength = rtcpPacketLength; + + // Store playout timestamp for the received RTCP packet + // which will be read by the GetRemoteRTCPData API + WebRtc_UWord32 playoutTimestamp(0); + if (GetPlayoutTimeStamp(playoutTimestamp) == 0) + { + _playoutTimeStampRTCP = playoutTimestamp; + } + + // SRTP or External decryption + if (_decrypting) + { + CriticalSectionScoped cs(&_callbackCritSect); + + if (_encryptionPtr) + { + if (!_decryptionRTCPBufferPtr) + { + // Allocate memory for decryption buffer one time only + _decryptionRTCPBufferPtr = + new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes]; + } + + // Perform decryption (SRTP or external). + WebRtc_Word32 decryptedBufferLength = 0; + _encryptionPtr->decrypt_rtcp(_channelId, + rtcpBufferPtr, + _decryptionRTCPBufferPtr, + rtcpBufferLength, + (int*)&decryptedBufferLength); + if (decryptedBufferLength <= 0) + { + _engineStatisticsPtr->SetLastError( + VE_DECRYPTION_FAILED, kTraceError, + "Channel::IncomingRTCPPacket() decryption failed"); + return; + } + + // Replace default data buffer with decrypted buffer + rtcpBufferPtr = _decryptionRTCPBufferPtr; + rtcpBufferLength = decryptedBufferLength; + } + } + + // Dump the RTCP packet to a file (if RTP dump is enabled). + if (_rtpDumpIn.DumpPacket(rtcpBufferPtr, + (WebRtc_UWord16)rtcpBufferLength) == -1) + { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, + VoEId(_instanceId,_channelId), + "Channel::SendPacket() RTCP dump to input file failed"); + } + + // Deliver RTCP packet to RTP/RTCP module for parsing + if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtcpBufferPtr, + (WebRtc_UWord16)rtcpBufferLength) == -1) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, + "Channel::IncomingRTPPacket() RTCP packet is invalid"); + return; + } +} + void Channel::OnPlayTelephoneEvent(const WebRtc_Word32 id, const WebRtc_UWord8 event, @@ -871,6 +1028,11 @@ Channel::Channel(const WebRtc_Word32 channelId, _channelId(channelId), _audioCodingModule(*AudioCodingModule::Create( VoEModuleId(instanceId, channelId))), +#ifndef WEBRTC_EXTERNAL_TRANSPORT + _numSocketThreads(KNumSocketThreads), + _socketTransportModule(*UdpTransport::Create( + VoEModuleId(instanceId, channelId), _numSocketThreads)), +#endif #ifdef WEBRTC_SRTP _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId, channelId))), @@ -999,6 +1161,18 @@ Channel::~Channel() DeRegisterExternalMediaProcessing(kRecordingPerChannel); } StopSend(); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + StopReceiving(); + // De-register packet callback to ensure we're not in a callback when + // deleting channel state, avoids race condition and deadlock. + if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0) + != 0) + { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, + VoEId(_instanceId, _channelId), + "~Channel() failed to de-register receive callback"); + } +#endif StopPlayout(); { @@ -1045,6 +1219,15 @@ Channel::~Channel() " (Audio coding module)"); } // De-register modules in process thread +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule) + == -1) + { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, + VoEId(_instanceId,_channelId), + "~Channel() failed to deregister socket module"); + } +#endif if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, @@ -1053,6 +1236,10 @@ Channel::~Channel() } // Destroy modules +#ifndef WEBRTC_EXTERNAL_TRANSPORT + UdpTransport::Destroy( + &_socketTransportModule); +#endif AudioCodingModule::Destroy(&_audioCodingModule); #ifdef WEBRTC_SRTP SrtpModule::DestroySrtpModule(&_srtpModule); @@ -1097,7 +1284,12 @@ Channel::Init() const bool processThreadFail = ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) || +#ifndef WEBRTC_EXTERNAL_TRANSPORT + (_moduleProcessThreadPtr->RegisterModule( + &_socketTransportModule) != 0)); +#else false); +#endif if (processThreadFail) { _engineStatisticsPtr->SetLastError( @@ -1231,6 +1423,17 @@ Channel::Init() } #endif } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + // Ensure that the WebRtcSocketTransport implementation is used as + // Transport on the sending side + { + // A lock is needed here since users can call + // RegisterExternalTransport() at the same time. + CriticalSectionScoped cs(&_callbackCritSect); + _transportPtr = &_socketTransportModule; + } +#endif + // Initialize the far end AP module // Using 8 kHz as initial Fs, the same as in transmission. Might be // changed at the first receiving audio. @@ -1459,6 +1662,25 @@ Channel::StartReceiving() // If external transport is used, we will only initialize/set the variables // after this section, since we are not using the WebRtc transport but // still need to keep track of e.g. if we are receiving. +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_externalTransport) + { + if (!_socketTransportModule.ReceiveSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKETS_NOT_INITED, kTraceError, + "StartReceive() must set local receiver first"); + return -1; + } + if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "StartReceiving() failed to start receiving"); + return -1; + } + } +#endif _receiving = true; _numberOfDiscardedPackets = 0; return 0; @@ -1473,6 +1695,20 @@ Channel::StopReceiving() { return 0; } + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_externalTransport && + _socketTransportModule.ReceiveSocketsInitialized()) + { + if (_socketTransportModule.StopReceiving() != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "StopReceiving() failed to stop receiving."); + return -1; + } + } +#endif // Recover DTMF detection status. WebRtc_Word32 ret = _rtpRtcpModule->SetTelephoneEventForwardToDecoder(true); if (ret != 0) { @@ -1485,6 +1721,310 @@ Channel::StopReceiving() return 0; } +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::SetLocalReceiver(const WebRtc_UWord16 rtpPort, + const WebRtc_UWord16 rtcpPort, + const char ipAddr[64], + const char multicastIpAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetLocalReceiver()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetLocalReceiver() conflict with external transport"); + return -1; + } + + if (_sending) + { + _engineStatisticsPtr->SetLastError( + VE_ALREADY_SENDING, kTraceError, + "SetLocalReceiver() already sending"); + return -1; + } + if (_receiving) + { + _engineStatisticsPtr->SetLastError( + VE_ALREADY_LISTENING, kTraceError, + "SetLocalReceiver() already receiving"); + return -1; + } + + if (_socketTransportModule.InitializeReceiveSockets(this, + rtpPort, + ipAddr, + multicastIpAddr, + rtcpPort) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kIpAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetLocalReceiver() invalid IP address"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetLocalReceiver() invalid socket"); + break; + case UdpTransport::kPortInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_PORT_NMBR, kTraceError, + "SetLocalReceiver() invalid port"); + break; + case UdpTransport::kFailedToBindPort: + _engineStatisticsPtr->SetLastError( + VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError, + "SetLocalReceiver() binding failed"); + break; + default: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetLocalReceiver() undefined socket error"); + break; + } + return -1; + } + return 0; +} +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetLocalReceiver()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetLocalReceiver() conflict with external transport"); + return -1; + } + + char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0}; + WebRtc_UWord16 rtpPort(0); + WebRtc_UWord16 rtcpPort(0); + char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0}; + + // Acquire socket information from the socket module + if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp, + rtpPort, + rtcpPort, + multicastIpAddr) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_CANNOT_GET_SOCKET_INFO, kTraceError, + "GetLocalReceiver() unable to retrieve socket information"); + return -1; + } + + // Deliver valid results to the user + port = static_cast (rtpPort); + RTCPport = static_cast (rtcpPort); + if (ipAddr != NULL) + { + strcpy(ipAddr, ipAddrTmp); + } + return 0; +} +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::SetSendDestination(const WebRtc_UWord16 rtpPort, + const char ipAddr[64], + const int sourcePort, + const WebRtc_UWord16 rtcpPort) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSendDestination()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSendDestination() conflict with external transport"); + return -1; + } + + // Initialize ports and IP address for the remote (destination) side. + // By default, the sockets used for receiving are used for transmission as + // well, hence the source ports for outgoing packets are the same as the + // receiving ports specified in SetLocalReceiver. + // If an extra send socket has been created, it will be utilized until a + // new source port is specified or until the channel has been deleted and + // recreated. If no socket exists, sockets will be created when the first + // RTP and RTCP packets shall be transmitted (see e.g. + // UdpTransportImpl::SendPacket()). + // + // NOTE: this function does not require that sockets exists; all it does is + // to build send structures to be used with the sockets when they exist. + // It is therefore possible to call this method before SetLocalReceiver. + // However, sockets must exist if a multi-cast address is given as input. + + // Build send structures and enable QoS (if enabled and supported) + if (_socketTransportModule.InitializeSendSockets( + ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kIpAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetSendDestination() invalid IP address 1"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() invalid socket 1"); + break; + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError( + VE_GQOS_ERROR, kTraceError, + "SetSendDestination() failed to set QoS"); + break; + case UdpTransport::kMulticastAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_MULTICAST_ADDRESS, kTraceError, + "SetSendDestination() invalid multicast address"); + break; + default: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() undefined socket error 1"); + break; + } + return -1; + } + + // Check if the user has specified a non-default source port different from + // the local receive port. + // If so, an extra local socket will be created unless the source port is + // not unique. + if (sourcePort != kVoEDefault) + { + WebRtc_UWord16 receiverRtpPort(0); + WebRtc_UWord16 rtcpNA(0); + if (_socketTransportModule.ReceiveSocketInformation(NULL, + receiverRtpPort, + rtcpNA, + NULL) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_CANNOT_GET_SOCKET_INFO, kTraceError, + "SetSendDestination() failed to retrieve socket information"); + return -1; + } + + WebRtc_UWord16 sourcePortUW16 = + static_cast (sourcePort); + + // An extra socket will only be created if the specified source port + // differs from the local receive port. + if (sourcePortUW16 != receiverRtpPort) + { + // Initialize extra local socket to get a different source port + // than the local + // receiver port. Always use default source for RTCP. + // Note that, this calls UdpTransport::CloseSendSockets(). + if (_socketTransportModule.InitializeSourcePorts( + sourcePortUW16, + sourcePortUW16+1) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kIpAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetSendDestination() invalid IP address 2"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() invalid socket 2"); + break; + default: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() undefined socket error 2"); + break; + } + return -1; + } + WEBRTC_TRACE(kTraceInfo, kTraceVoice, + VoEId(_instanceId,_channelId), + "SetSendDestination() extra local socket is created" + " to facilitate unique source port"); + } + else + { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, + VoEId(_instanceId,_channelId), + "SetSendDestination() sourcePort equals the local" + " receive port => no extra socket is created"); + } + } + + return 0; +} +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::GetSendDestination(int& port, + char ipAddr[64], + int& sourcePort, + int& RTCPport) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSendDestination()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSendDestination() conflict with external transport"); + return -1; + } + + char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0}; + WebRtc_UWord16 rtpPort(0); + WebRtc_UWord16 rtcpPort(0); + WebRtc_UWord16 rtpSourcePort(0); + WebRtc_UWord16 rtcpSourcePort(0); + + // Acquire sending socket information from the socket module + _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort); + _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort); + + // Deliver valid results to the user + port = static_cast (rtpPort); + RTCPport = static_cast (rtcpPort); + sourcePort = static_cast (rtpSourcePort); + if (ipAddr != NULL) + { + strcpy(ipAddr, ipAddrTmp); + } + + return 0; +} +#endif + + WebRtc_Word32 Channel::SetNetEQPlayoutMode(NetEqModes mode) { @@ -2088,6 +2628,24 @@ WebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport) CriticalSectionScoped cs(&_callbackCritSect); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + // Sanity checks for default (non external transport) to avoid conflict with + // WebRtc sockets. + if (_socketTransportModule.SendSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT, + kTraceError, + "RegisterExternalTransport() send sockets already initialized"); + return -1; + } + if (_socketTransportModule.ReceiveSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT, + kTraceError, + "RegisterExternalTransport() receive sockets already initialized"); + return -1; + } +#endif if (_externalTransport) { _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, @@ -2117,81 +2675,396 @@ Channel::DeRegisterExternalTransport() return 0; } _externalTransport = false; +#ifdef WEBRTC_EXTERNAL_TRANSPORT _transportPtr = NULL; WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "DeRegisterExternalTransport() all transport is disabled"); +#else + _transportPtr = &_socketTransportModule; + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "DeRegisterExternalTransport() internal Transport is enabled"); +#endif return 0; } WebRtc_Word32 Channel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length) { - WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::ReceivedRTPPacket()"); - - // Store playout timestamp for the received RTP packet - // to be used for upcoming delay estimations - WebRtc_UWord32 playoutTimestamp(0); - if (GetPlayoutTimeStamp(playoutTimestamp) == 0) - { - _playoutTimeStampRTP = playoutTimestamp; - } - // Dump the RTP packet to a file (if RTP dump is enabled). - if (_rtpDumpIn.DumpPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId,_channelId), - "Channel::SendPacket() RTP dump to input file failed"); - } - - // Deliver RTP packet to RTP/RTCP module for parsing - // The packet will be pushed back to the channel thru the - // OnReceivedPayloadData callback so we don't push it to the ACM here - if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - _engineStatisticsPtr->SetLastError( - VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, - "Channel::IncomingRTPPacket() RTP packet is invalid"); - } - return 0; + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::ReceivedRTPPacket()"); + const char dummyIP[] = "127.0.0.1"; + IncomingRTPPacket(data, length, dummyIP, 0); + return 0; } WebRtc_Word32 Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length) { - WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::ReceivedRTCPPacket()"); - - // Store playout timestamp for the received RTCP packet - // which will be read by the GetRemoteRTCPData API - WebRtc_UWord32 playoutTimestamp(0); - if (GetPlayoutTimeStamp(playoutTimestamp) == 0) - { - _playoutTimeStampRTCP = playoutTimestamp; - } - - // Dump the RTCP packet to a file (if RTP dump is enabled). - if (_rtpDumpIn.DumpPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId,_channelId), - "Channel::SendPacket() RTCP dump to input file failed"); - } - - // Deliver RTCP packet to RTP/RTCP module for parsing - if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - _engineStatisticsPtr->SetLastError( - VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, - "Channel::IncomingRTPPacket() RTCP packet is invalid"); - } - return 0; + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::ReceivedRTCPPacket()"); + const char dummyIP[] = "127.0.0.1"; + IncomingRTCPPacket(data, length, dummyIP, 0); + return 0; } +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSourceInfo()"); + + WebRtc_UWord16 rtpPortModule; + WebRtc_UWord16 rtcpPortModule; + char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0}; + + if (_socketTransportModule.RemoteSocketInformation(ipaddr, + rtpPortModule, + rtcpPortModule) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetSourceInfo() failed to retrieve remote socket information"); + return -1; + } + strcpy(ipAddr, ipaddr); + rtpPort = rtpPortModule; + rtcpPort = rtcpPortModule; + + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s", + rtpPort, rtcpPort, ipAddr); + return 0; +} + +WebRtc_Word32 +Channel::EnableIPv6() +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::EnableIPv6()"); + if (_socketTransportModule.ReceiveSocketsInitialized() || + _socketTransportModule.SendSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_OPERATION, kTraceError, + "EnableIPv6() socket layer is already initialized"); + return -1; + } + if (_socketTransportModule.EnableIpV6() != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "EnableIPv6() failed to enable IPv6"); + const UdpTransport::ErrorCode lastError = + _socketTransportModule.LastError(); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport::LastError() => %d", lastError); + return -1; + } + return 0; +} + +bool +Channel::IPv6IsEnabled() const +{ + bool isEnabled = _socketTransportModule.IpV6Enabled(); + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "IPv6IsEnabled() => %d", isEnabled); + return isEnabled; +} + +WebRtc_Word32 +Channel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSourceFilter()"); + if (_socketTransportModule.SetFilterPorts( + static_cast(rtpPort), + static_cast(rtcpPort)) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "SetSourceFilter() failed to set filter ports"); + const UdpTransport::ErrorCode lastError = + _socketTransportModule.LastError(); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport::LastError() => %d", + lastError); + return -1; + } + const char* filterIpAddress = ipAddr; + if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetSourceFilter() failed to set filter IP address"); + const UdpTransport::ErrorCode lastError = + _socketTransportModule.LastError(); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport::LastError() => %d", lastError); + return -1; + } + return 0; +} + +WebRtc_Word32 +Channel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSourceFilter()"); + WebRtc_UWord16 rtpFilterPort(0); + WebRtc_UWord16 rtcpFilterPort(0); + if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, + "GetSourceFilter() failed to retrieve filter ports"); + } + char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0}; + if (_socketTransportModule.FilterIP(ipAddrTmp) != 0) + { + // no filter has been configured (not seen as an error) + memset(ipAddrTmp, + 0, UdpTransport::kIpAddressVersion6Length); + } + rtpPort = static_cast (rtpFilterPort); + rtcpPort = static_cast (rtcpFilterPort); + strcpy(ipAddr, ipAddrTmp); + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s", + rtpPort, rtcpPort, ipAddr); + return 0; +} + +WebRtc_Word32 +Channel::SetSendTOS(int DSCP, int priority, bool useSetSockopt) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)", + DSCP, (int)useSetSockopt); + + // Set TOS value and possibly try to force usage of setsockopt() + if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kTosError: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() TOS error"); + break; + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError( + VE_TOS_GQOS_CONFLICT, kTraceError, + "SetSendTOS() GQOS error"); + break; + case UdpTransport::kTosInvalid: + // can't switch SetSockOpt method without disabling TOS first, or + // SetSockopt() call failed + _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError, + "SetSendTOS() invalid TOS"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError, + "SetSendTOS() invalid Socket"); + break; + default: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() TOS error"); + break; + } + WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport => lastError = %d", + lastSockError); + return -1; + } + + // Set priority (PCP) value, -1 means don't change + if (-1 != priority) + { + if (_socketTransportModule.SetPCP(priority) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kPcpError: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() PCP error"); + break; + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError( + VE_TOS_GQOS_CONFLICT, kTraceError, + "SetSendTOS() GQOS conflict"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendTOS() invalid Socket"); + break; + default: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() PCP error"); + break; + } + WEBRTC_TRACE(kTraceError, kTraceVoice, + VoEId(_instanceId,_channelId), + "UdpTransport => lastError = %d", + lastSockError); + return -1; + } + } + + return 0; +} + +WebRtc_Word32 +Channel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)"); + WebRtc_Word32 dscp(0), prio(0); + bool setSockopt(false); + if (_socketTransportModule.ToS(dscp, setSockopt) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetSendTOS() failed to get TOS info"); + return -1; + } + if (_socketTransportModule.PCP(prio) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetSendTOS() failed to get PCP info"); + return -1; + } + DSCP = static_cast (dscp); + priority = static_cast (prio); + useSetSockopt = setSockopt; + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), + "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d", + DSCP, priority, (int)useSetSockopt); + return 0; +} + +#if defined(_WIN32) +WebRtc_Word32 +Channel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSendGQoS(enable=%d, serviceType=%d, " + "overrideDSCP=%d)", + (int)enable, serviceType, overrideDSCP); + if(!_socketTransportModule.ReceiveSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKETS_NOT_INITED, kTraceError, + "SetSendGQoS() GQoS state must be set after sockets are created"); + return -1; + } + if(!_socketTransportModule.SendSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_DESTINATION_NOT_INITED, kTraceError, + "SetSendGQoS() GQoS state must be set after sending side is " + "initialized"); + return -1; + } + if (enable && + (serviceType != SERVICETYPE_BESTEFFORT) && + (serviceType != SERVICETYPE_CONTROLLEDLOAD) && + (serviceType != SERVICETYPE_GUARANTEED) && + (serviceType != SERVICETYPE_QUALITATIVE)) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_ARGUMENT, kTraceError, + "SetSendGQoS() Invalid service type"); + return -1; + } + if (enable && ((overrideDSCP < 0) || (overrideDSCP > 63))) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_ARGUMENT, kTraceError, + "SetSendGQoS() Invalid overrideDSCP value"); + return -1; + } + + // Avoid GQoS/ToS conflict when user wants to override the default DSCP + // mapping + bool QoS(false); + WebRtc_Word32 sType(0); + WebRtc_Word32 ovrDSCP(0); + if (_socketTransportModule.QoS(QoS, sType, ovrDSCP)) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "SetSendGQoS() failed to get QOS info"); + return -1; + } + if (QoS && ovrDSCP == 0 && overrideDSCP != 0) + { + _engineStatisticsPtr->SetLastError( + VE_TOS_GQOS_CONFLICT, kTraceError, + "SetSendGQoS() QOS is already enabled and overrideDSCP differs," + " not allowed"); + return -1; + } + const WebRtc_Word32 maxBitrate(0); + if (_socketTransportModule.SetQoS(enable, + static_cast(serviceType), + maxBitrate, + static_cast(overrideDSCP), + true)) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError, + "SetSendGQoS() QOS error"); + break; + default: + _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError, + "SetSendGQoS() Socket error"); + break; + } + WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport() => lastError = %d", + lastSockError); + return -1; + } + return 0; +} +#endif + +#if defined(_WIN32) +WebRtc_Word32 +Channel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSendGQoS(enable=?, serviceType=?, " + "overrideDSCP=?)"); + + bool QoS(false); + WebRtc_Word32 serviceTypeModule(0); + WebRtc_Word32 overrideDSCPModule(0); + _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule); + + enabled = QoS; + serviceType = static_cast (serviceTypeModule); + overrideDSCP = static_cast (overrideDSCPModule); + + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d", + (int)enabled, serviceType, overrideDSCP); + return 0; +} +#endif +#endif + WebRtc_Word32 Channel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds) { @@ -2327,6 +3200,65 @@ Channel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds) return 0; } +WebRtc_Word32 +Channel::SendUDPPacket(const void* data, + unsigned int length, + int& transmittedBytes, + bool useRtcpSocket) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SendUDPPacket()"); + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SendUDPPacket() external transport is enabled"); + return -1; + } + if (useRtcpSocket && !_rtpRtcpModule->RTCP()) + { + _engineStatisticsPtr->SetLastError( + VE_RTCP_ERROR, kTraceError, + "SendUDPPacket() RTCP is disabled"); + return -1; + } + if (!_sending) + { + _engineStatisticsPtr->SetLastError( + VE_NOT_SENDING, kTraceError, + "SendUDPPacket() not sending"); + return -1; + } + + char* dataC = new char[length]; + if (NULL == dataC) + { + _engineStatisticsPtr->SetLastError( + VE_NO_MEMORY, kTraceError, + "SendUDPPacket() memory allocation failed"); + return -1; + } + memcpy(dataC, data, length); + + transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket); + + delete [] dataC; + dataC = NULL; + + if (transmittedBytes <= 0) + { + _engineStatisticsPtr->SetLastError( + VE_SEND_ERROR, kTraceError, + "SendUDPPacket() transmission failed"); + transmittedBytes = 0; + return -1; + } + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "SendUDPPacket() => transmittedBytes=%d", transmittedBytes); + return 0; +} + + int Channel::StartPlayingFileLocally(const char* fileName, const bool loop, const FileFormats format, diff --git a/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h index cdb0790eaf..f1c5809be3 100644 --- a/webrtc/voice_engine/channel.h +++ b/webrtc/voice_engine/channel.h @@ -27,6 +27,9 @@ #include "webrtc/voice_engine/shared_data.h" #include "webrtc/voice_engine/voice_engine_defines.h" +#ifndef WEBRTC_EXTERNAL_TRANSPORT +#include "webrtc/modules/udp_transport/interface/udp_transport.h" +#endif #ifdef WEBRTC_SRTP #include "SrtpModule.h" #endif @@ -62,6 +65,9 @@ class Channel: public RtpData, public RtpFeedback, public RtcpFeedback, +#ifndef WEBRTC_EXTERNAL_TRANSPORT + public UdpTransportData, // receiving packet from sockets +#endif public FileCallback, // receiving notification from file player & recorder public Transport, public RtpAudioFeedback, @@ -175,6 +181,9 @@ public: int sampleTimeSeconds); WebRtc_Word32 GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds); + WebRtc_Word32 SendUDPPacket(const void* data, unsigned int length, + int& transmittedBytes, bool useRtcpSocket); + // VoEFile int StartPlayingFileLocally(const char* fileName, const bool loop, const FileFormats format, @@ -403,6 +412,18 @@ public: const WebRtc_UWord16 lengthMs, const WebRtc_UWord8 volume); +public: + // From UdpTransportData in the Socket Transport module + void IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort); + + void IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort); + public: // From Transport (called by the RTP/RTCP module) int SendPacket(int /*channel*/, const void *data, int len); @@ -476,6 +497,16 @@ public: { return _outputAudioLevel.Level(); } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + bool SendSocketsInitialized() const + { + return _socketTransportModule.SendSocketsInitialized(); + } + bool ReceiveSocketsInitialized() const + { + return _socketTransportModule.ReceiveSocketsInitialized(); + } +#endif WebRtc_UWord32 Demultiplex(const AudioFrame& audioFrame); WebRtc_UWord32 PrepareEncodeAndSend(int mixingFrequency); WebRtc_UWord32 EncodeAndSend(); @@ -504,6 +535,10 @@ private: private: scoped_ptr _rtpRtcpModule; AudioCodingModule& _audioCodingModule; +#ifndef WEBRTC_EXTERNAL_TRANSPORT + WebRtc_UWord8 _numSocketThreads; + UdpTransport& _socketTransportModule; +#endif #ifdef WEBRTC_SRTP SrtpModule& _srtpModule; #endif diff --git a/webrtc/voice_engine/include/voe_base.h b/webrtc/voice_engine/include/voe_base.h index 70cbab191e..84cd4fc4fa 100644 --- a/webrtc/voice_engine/include/voe_base.h +++ b/webrtc/voice_engine/include/voe_base.h @@ -14,6 +14,7 @@ // - Initialization and termination. // - Trace information on text files or via callbacks. // - Multi-channel support (mixing, sending to multiple destinations etc.). +// - Call setup (port and address) for receiving and sending sides. // // To support other codecs than G.711, the VoECodec sub-API must be utilized. // @@ -139,6 +140,28 @@ public: // Deletes an existing channel and releases the utilized resources. virtual int DeleteChannel(int channel) = 0; + // Sets the local receiver port and address for a specified + // |channel| number. + virtual int SetLocalReceiver(int channel, int port, + int RTCPport = kVoEDefault, + const char ipAddr[64] = NULL, + const char multiCastAddr[64] = NULL) = 0; + + // Gets the local receiver port and address for a specified + // |channel| number. + virtual int GetLocalReceiver(int channel, int& port, int& RTCPport, + char ipAddr[64]) = 0; + + // Sets the destination port and address for a specified |channel| number. + virtual int SetSendDestination(int channel, int port, + const char ipAddr[64], + int sourcePort = kVoEDefault, + int RTCPport = kVoEDefault) = 0; + + // Gets the destination port and address for a specified |channel| number. + virtual int GetSendDestination(int channel, int& port, char ipAddr[64], + int& sourcePort, int& RTCPport) = 0; + // Prepares and initiates the VoiceEngine for reception of // incoming RTP/RTCP packets on the specified |channel|. virtual int StartReceive(int channel) = 0; diff --git a/webrtc/voice_engine/include/voe_network.h b/webrtc/voice_engine/include/voe_network.h index 9a2ff732e1..10acf1c516 100644 --- a/webrtc/voice_engine/include/voe_network.h +++ b/webrtc/voice_engine/include/voe_network.h @@ -11,6 +11,9 @@ // This sub-API supports the following functionalities: // // - External protocol support. +// - Extended port and address APIs. +// - Port and address filters. +// - Windows GQoS functions. // - Packet timeout notification. // - Dead-or-Alive connection observations. // - Transmission of raw RTP/RTCP packets into existing channels. @@ -90,6 +93,49 @@ public: virtual int ReceivedRTCPPacket( int channel, const void* data, unsigned int length) = 0; + // Gets the source ports and IP address of incoming packets on a + // specific |channel|. + virtual int GetSourceInfo( + int channel, int& rtpPort, int& rtcpPort, char ipAddr[64]) = 0; + + // Gets the local (host) IP address. + virtual int GetLocalIP(char ipAddr[64], bool ipv6 = false) = 0; + + // Enables IPv6 for a specified |channel|. + virtual int EnableIPv6(int channel) = 0; + + // Gets the current IPv6 staus for a specified |channel|. + virtual bool IPv6IsEnabled(int channel) = 0; + + // Enables a port and IP address filter for incoming packets on a + // specific |channel|. + virtual int SetSourceFilter(int channel, + int rtpPort, int rtcpPort = 0, const char ipAddr[64] = 0) = 0; + + // Gets the current port and IP-address filter for a specified |channel|. + virtual int GetSourceFilter( + int channel, int& rtpPort, int& rtcpPort, char ipAddr[64]) = 0; + + // Sets the six-bit Differentiated Services Code Point (DSCP) in the + // IP header of the outgoing stream for a specific |channel|. + virtual int SetSendTOS(int channel, + int DSCP, int priority = -1, bool useSetSockopt = false) = 0; + + // Gets the six-bit DSCP in the IP header of the outgoing stream for + // a specific channel. + virtual int GetSendTOS( + int channel, int& DSCP, int& priority, bool& useSetSockopt) = 0; + + // Sets the Generic Quality of Service (GQoS) service level. + // The Windows operating system then maps to a Differentiated Services + // Code Point (DSCP) and to an 802.1p setting. [Windows only] + virtual int SetSendGQoS( + int channel, bool enable, int serviceType, int overrideDSCP = 0) = 0; + + // Gets the Generic Quality of Service (GQoS) service level. + virtual int GetSendGQoS( + int channel, bool& enabled, int& serviceType, int& overrideDSCP) = 0; + // Enables or disables warnings that report if packets have not been // received in |timeoutSeconds| seconds for a specific |channel|. virtual int SetPacketTimeoutNotification( @@ -115,6 +161,12 @@ public: virtual int GetPeriodicDeadOrAliveStatus( int channel, bool& enabled, int& sampleTimeSeconds) = 0; + // Handles sending a raw UDP data packet over an existing RTP or RTCP + // socket. + virtual int SendUDPPacket( + int channel, const void* data, unsigned int length, + int& transmittedBytes, bool useRtcpSocket = false) = 0; + protected: VoENetwork() {} virtual ~VoENetwork() {} diff --git a/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h b/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h index c5f05007c7..bbdd64d0d8 100644 --- a/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h +++ b/webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h @@ -13,30 +13,9 @@ #include "before_initialization_fixture.h" #include "scoped_ptr.h" -#include "webrtc/common_types.h" class TestErrorObserver; -class LoopBackTransport : public webrtc::Transport { - public: - LoopBackTransport(webrtc::VoENetwork* voe_network) - : voe_network_(voe_network) { - } - - virtual int SendPacket(int channel, const void *data, int len) { - voe_network_->ReceivedRTPPacket(channel, data, len); - return len; - } - - virtual int SendRTCPPacket(int channel, const void *data, int len) { - voe_network_->ReceivedRTCPPacket(channel, data, len); - return len; - } - - private: - webrtc::VoENetwork* voe_network_; -}; - // This fixture initializes the voice engine in addition to the work // done by the before-initialization fixture. It also registers an error // observer which will fail tests on error callbacks. This fixture is diff --git a/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc b/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc index 353888a6df..d1e6039e38 100644 --- a/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc +++ b/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc @@ -12,6 +12,8 @@ #include +static const char* kLoopbackIp = "127.0.0.1"; + AfterStreamingFixture::AfterStreamingFixture() : channel_(voe_base_->CreateChannel()) { EXPECT_GE(channel_, 0); @@ -28,9 +30,7 @@ AfterStreamingFixture::~AfterStreamingFixture() { voe_file_->StopPlayingFileAsMicrophone(channel_); PausePlaying(); - EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(channel_)); voe_base_->DeleteChannel(channel_); - delete transport_; } void AfterStreamingFixture::SwitchToManualMicrophone() { @@ -59,8 +59,8 @@ void AfterStreamingFixture::ResumePlaying() { } void AfterStreamingFixture::SetUpLocalPlayback() { - transport_ = new LoopBackTransport(voe_network_); - EXPECT_EQ(0, voe_network_->RegisterExternalTransport(channel_, *transport_)); + EXPECT_EQ(0, voe_base_->SetSendDestination(channel_, 8000, kLoopbackIp)); + EXPECT_EQ(0, voe_base_->SetLocalReceiver(0, 8000)); webrtc::CodecInst codec; codec.channels = 1; diff --git a/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h b/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h index 26e37a7b2b..6b0a61f304 100644 --- a/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h +++ b/webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h @@ -42,8 +42,6 @@ class AfterStreamingFixture : public AfterInitializationFixture { private: void SetUpLocalPlayback(); - - LoopBackTransport* transport_; }; diff --git a/webrtc/voice_engine/test/auto_test/standard/mixing_test.cc b/webrtc/voice_engine/test/auto_test/standard/mixing_test.cc index 1d2aea3848..6a90c07e68 100644 --- a/webrtc/voice_engine/test/auto_test/standard/mixing_test.cc +++ b/webrtc/voice_engine/test/auto_test/standard/mixing_test.cc @@ -32,13 +32,7 @@ class MixingTest : public AfterInitializationFixture { : input_filename_(test::OutputPath() + "mixing_test_input.pcm"), output_filename_(test::OutputPath() + "mixing_test_output.pcm") { } - void SetUp() { - transport_ = new LoopBackTransport(voe_network_); - } - void TearDown() { - delete transport_; - } - + // Creates and mixes |num_remote_streams| which play a file "as microphone" // with |num_local_streams| which play a file "locally", using a constant // amplitude of |input_value|. The local streams manifest as "anonymous" @@ -171,7 +165,8 @@ class MixingTest : public AfterInitializationFixture { // Start up a single remote stream. void StartRemoteStream(int stream, const CodecInst& codec_inst, int port) { EXPECT_EQ(0, voe_codec_->SetRecPayloadType(stream, codec_inst)); - EXPECT_EQ(0, voe_network_->RegisterExternalTransport(stream, *transport_)); + EXPECT_EQ(0, voe_base_->SetLocalReceiver(stream, port)); + EXPECT_EQ(0, voe_base_->SetSendDestination(stream, port, "127.0.0.1")); EXPECT_EQ(0, voe_base_->StartReceive(stream)); EXPECT_EQ(0, voe_base_->StartPlayout(stream)); EXPECT_EQ(0, voe_codec_->SetSendCodec(stream, codec_inst)); @@ -185,14 +180,12 @@ class MixingTest : public AfterInitializationFixture { EXPECT_EQ(0, voe_base_->StopSend(streams[i])); EXPECT_EQ(0, voe_base_->StopPlayout(streams[i])); EXPECT_EQ(0, voe_base_->StopReceive(streams[i])); - EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(streams[i])); EXPECT_EQ(0, voe_base_->DeleteChannel(streams[i])); } } const std::string input_filename_; const std::string output_filename_; - LoopBackTransport* transport_; }; // These tests assume a maximum of three mixed participants. We typically allow diff --git a/webrtc/voice_engine/test/auto_test/standard/network_before_streaming_test.cc b/webrtc/voice_engine/test/auto_test/standard/network_before_streaming_test.cc new file mode 100644 index 0000000000..7a41e806b8 --- /dev/null +++ b/webrtc/voice_engine/test/auto_test/standard/network_before_streaming_test.cc @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 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 "after_initialization_fixture.h" + +class NetworkBeforeStreamingTest : public AfterInitializationFixture { + protected: + void SetUp() { + channel_ = voe_base_->CreateChannel(); + } + + void TearDown() { + voe_base_->DeleteChannel(channel_); + } + + int channel_; +}; + +TEST_F(NetworkBeforeStreamingTest, + GetSourceInfoReturnsEmptyValuesForUnconfiguredChannel) { + char src_ip[32] = "0.0.0.0"; + int src_rtp_port = 1234; + int src_rtcp_port = 1235; + + EXPECT_EQ(0, voe_network_->GetSourceInfo( + channel_, src_rtp_port, src_rtcp_port, src_ip)); + EXPECT_EQ(0, src_rtp_port); + EXPECT_EQ(0, src_rtcp_port); + EXPECT_STRCASEEQ("", src_ip); +} + +TEST_F(NetworkBeforeStreamingTest, + GetSourceFilterReturnsEmptyValuesForUnconfiguredChannel) { + int filter_port = -1; + int filter_port_rtcp = -1; + char filter_ip[32] = "0.0.0.0"; + + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_port, filter_port_rtcp, filter_ip)); + + EXPECT_EQ(0, filter_port); + EXPECT_EQ(0, filter_port_rtcp); + EXPECT_STRCASEEQ("", filter_ip); +} + +TEST_F(NetworkBeforeStreamingTest, SetSourceFilterSucceeds) { + EXPECT_EQ(0, voe_network_->SetSourceFilter(channel_, 0)); +} diff --git a/webrtc/voice_engine/test/auto_test/standard/network_test.cc b/webrtc/voice_engine/test/auto_test/standard/network_test.cc index f4713dc100..8bf2d11c9e 100644 --- a/webrtc/voice_engine/test/auto_test/standard/network_test.cc +++ b/webrtc/voice_engine/test/auto_test/standard/network_test.cc @@ -23,6 +23,79 @@ class NetworkTest : public AfterStreamingFixture { using ::testing::Between; +TEST_F(NetworkTest, GetSourceInfoReturnsPortsAndIpAfterReceivingPackets) { + // Give some time to send speech packets. + Sleep(200); + + int rtp_port = 0; + int rtcp_port = 0; + char source_ip[32] = "127.0.0.1"; + + EXPECT_EQ(0, voe_network_->GetSourceInfo(channel_, rtp_port, rtcp_port, + source_ip)); + + EXPECT_EQ(kDefaultRtpPort, rtp_port); + EXPECT_EQ(kDefaultRtcpPort, rtcp_port); +} + +TEST_F(NetworkTest, NoFilterIsEnabledByDefault) { + int filter_rtp_port = -1; + int filter_rtcp_port = -1; + char filter_ip[64] = { 0 }; + + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_rtp_port, filter_rtcp_port, filter_ip)); + + EXPECT_EQ(0, filter_rtp_port); + EXPECT_EQ(0, filter_rtcp_port); + EXPECT_STREQ("", filter_ip); +} + +TEST_F(NetworkTest, ManualCanFilterRtpPort) { + TEST_LOG("No filter, should hear audio.\n"); + Sleep(1000); + + int port_to_block = kDefaultRtpPort + 10; + EXPECT_EQ(0, voe_network_->SetSourceFilter(channel_, port_to_block)); + + // Changes should take effect immediately. + int filter_rtp_port = -1; + int filter_rtcp_port = -1; + char filter_ip[64] = { 0 }; + + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_rtp_port, filter_rtcp_port, filter_ip)); + + EXPECT_EQ(port_to_block, filter_rtp_port); + + TEST_LOG("Now filtering port %d, should not hear audio.\n", port_to_block); + Sleep(1000); + + TEST_LOG("Removing filter, should hear audio.\n"); + EXPECT_EQ(0, voe_network_->SetSourceFilter(channel_, 0)); + Sleep(1000); +} + +TEST_F(NetworkTest, ManualCanFilterIp) { + TEST_LOG("You should hear audio.\n"); + Sleep(1000); + + int rtcp_port_to_block = kDefaultRtcpPort + 10; + TEST_LOG("Filtering IP 10.10.10.10, should not hear audio.\n"); + EXPECT_EQ(0, voe_network_->SetSourceFilter( + channel_, 0, rtcp_port_to_block, "10.10.10.10")); + + int filter_rtp_port = -1; + int filter_rtcp_port = -1; + char filter_ip[64] = { 0 }; + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_rtp_port, filter_rtcp_port, filter_ip)); + + EXPECT_EQ(0, filter_rtp_port); + EXPECT_EQ(rtcp_port_to_block, filter_rtcp_port); + EXPECT_STREQ("10.10.10.10", filter_ip); +} + TEST_F(NetworkTest, CallsObserverOnTimeoutAndRestartWhenPacketTimeoutNotificationIsEnabled) { // First, get rid of the default, asserting observer and install our observer. diff --git a/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc b/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc index 7815288dc6..3549cb3664 100644 --- a/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc +++ b/webrtc/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc @@ -101,10 +101,10 @@ class RtpRtcpTest : public AfterStreamingFixture { second_channel_ = voe_base_->CreateChannel(); EXPECT_GE(second_channel_, 0); - transport_ = new LoopBackTransport(voe_network_); - EXPECT_EQ(0, voe_network_->RegisterExternalTransport(second_channel_, - *transport_)); - + EXPECT_EQ(0, voe_base_->SetSendDestination( + second_channel_, 8002, "127.0.0.1")); + EXPECT_EQ(0, voe_base_->SetLocalReceiver( + second_channel_, 8002)); EXPECT_EQ(0, voe_base_->StartReceive(second_channel_)); EXPECT_EQ(0, voe_base_->StartPlayout(second_channel_)); EXPECT_EQ(0, voe_rtp_rtcp_->SetLocalSSRC(second_channel_, 5678)); @@ -115,13 +115,10 @@ class RtpRtcpTest : public AfterStreamingFixture { } void TearDown() { - EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(second_channel_)); voe_base_->DeleteChannel(second_channel_); - delete transport_; } int second_channel_; - LoopBackTransport* transport_; }; void RtcpAppHandler::OnApplicationDataReceived( diff --git a/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc b/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc index 2737ee82f1..14e4a00ec1 100644 --- a/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc +++ b/webrtc/voice_engine/test/auto_test/voe_cpu_test.cc @@ -8,8 +8,6 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "voe_cpu_test.h" - #include #include #include @@ -18,8 +16,7 @@ #include #endif -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" +#include "voe_cpu_test.h" using namespace webrtc; @@ -48,7 +45,6 @@ int VoECpuTest::DoTest() { VoEFile* file = _mgr.FilePtr(); VoECodec* codec = _mgr.CodecPtr(); VoEAudioProcessing* apm = _mgr.APMPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); int channel(-1); CodecInst isac; @@ -63,12 +59,8 @@ int VoECpuTest::DoTest() { CHECK(base->Init()); channel = base->CreateChannel(); - scoped_ptr voice_socket_transport( - new VoiceChannelTransport(voe_network, channel)); - - CHECK(voice_socket_transport->SetSendDestination("127.0.0.1", 5566)); - CHECK(voice_socket_transport->SetLocalReceiver(5566)); - + CHECK(base->SetLocalReceiver(channel, 5566)); + CHECK(base->SetSendDestination(channel, 5566, "127.0.0.1")); CHECK(codec->SetRecPayloadType(channel, isac)); CHECK(codec->SetSendCodec(channel, isac)); @@ -94,6 +86,7 @@ int VoECpuTest::DoTest() { base->DeleteChannel(channel); CHECK(base->Terminate()); + return 0; } diff --git a/webrtc/voice_engine/test/auto_test/voe_extended_test.cc b/webrtc/voice_engine/test/auto_test/voe_extended_test.cc index ce26992390..d4c49c449e 100644 --- a/webrtc/voice_engine/test/auto_test/voe_extended_test.cc +++ b/webrtc/voice_engine/test/auto_test/voe_extended_test.cc @@ -8,17 +8,22 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/voice_engine/test/auto_test/voe_extended_test.h" - #include #include #include +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/event_wrapper.h" +#include "webrtc/system_wrappers/interface/ref_count.h" +#include "webrtc/system_wrappers/interface/sleep.h" +#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/voice_engine/voice_engine_defines.h" +#include "webrtc/voice_engine/test/auto_test/voe_extended_test.h" #if defined(_WIN32) #include +#include #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) #include #endif @@ -153,6 +158,21 @@ int ExtendedTestTransport::SendRTCPPacket(int channel, const void *data, int len return len; } +XTransport::XTransport(VoENetwork* netw, VoEFile* file) : + _netw(netw), _file(file) { +} + +int XTransport::SendPacket(int channel, const void *data, int len) { + // loopback + // _netw->ReceivedRTPPacket(channel, data, len); + + return 0; +} + +int XTransport::SendRTCPPacket(int, const void *, int) { + return 0; +} + // ---------------------------------------------------------------------------- // VoERTPObserver // ---------------------------------------------------------------------------- @@ -235,14 +255,8 @@ void VoEExtendedTest::StartMedia(int channel, int rtpPort, bool listen, _playing[channel] = false; _sending[channel] = false; - VoENetwork* voe_network = _mgr.NetworkPtr(); - - voice_channel_transports_[channel].reset( - new VoiceChannelTransport(voe_network, channel)); - - voice_channel_transports_[channel]->SetSendDestination("127.0.0.1", rtpPort); - voice_channel_transports_[channel]->SetLocalReceiver(rtpPort); - + voe_base_->SetLocalReceiver(channel, rtpPort); + voe_base_->SetSendDestination(channel, rtpPort, "127.0.0.1"); if (listen) { _listening[channel] = true; voe_base_->StartReceive(channel); @@ -272,7 +286,6 @@ void VoEExtendedTest::StopMedia(int channel) { _sending[channel] = false; voe_base_->StopSend(channel); } - voice_channel_transports_[channel].reset(NULL); } void VoEExtendedTest::Play(int channel, unsigned int timeMillisec, bool addFileAsMicrophone, @@ -320,7 +333,7 @@ int VoEExtendedTest::TestBase() { // instance variable since it is required in order to appease the // gods of darkness. VoEBase* voe_base_ = _mgr.BasePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); + VoENetwork* netw = _mgr.NetworkPtr(); #ifdef _TEST_RTP_RTCP_ VoERTP_RTCP* rtp = _mgr.RTP_RTCPPtr(); #endif @@ -541,6 +554,305 @@ int VoEExtendedTest::TestBase() { ANL(); ANL(); + // ------------------------------------------------------------------------ + // >> SetLocalReceiver + // + // State: VE not initialized, no existing channels + TEST_MUSTPASS(voe_base_->Init()); + + int ch; + + TEST(SetLocalReceiver); + ANL(); + + // no channel created yet => should fail + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(0, 100)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + ch = voe_base_->CreateChannel(); + +#ifdef WEBRTC_IOS + printf("\nNOTE: Local IP must be set in source code (line %d) \n", + __LINE__ + 1); + char* localIp = "127.0.0.1"; +#else + char localIp[64] = { 0 }; + TEST_MUSTPASS(netw->GetLocalIP(localIp)); + MARK(); + // NOTE: This API is supported on Win, Mac and Linux and may fail or not + // return local IP for other platforms. +#endif + + // trivial invalid function calls + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch+1, 12345)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, -1)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); + + // check conflict with ongoing receiving + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + TEST_ERROR(VE_ALREADY_LISTENING); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + // check conflict with ongoing transmission + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + TEST_ERROR(VE_ALREADY_SENDING); + TEST_MUSTPASS(voe_base_->StopSend(ch)); + + // valid function calls + // Need to sleep between, otherwise it may fail for unknown reason + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, NULL, + "230.1.2.3")); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp, + "230.1.2.3")); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 5555, NULL)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + + // STATE: no media but sockets exists and are binded to 12345 and 12346 + // respectively + + // Add some dynamic tests as well: + + // ensure that last setting is used (cancels old settings) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 44444)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 54321)); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 54321, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + Play(ch, 1000, true, true); + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of SetLocalReceiver + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetLocalReceiver + // + // State: VE initialized, no existing channels + TEST(GetLocalReceiver); + ANL(); + + int port; + char ipaddr[64]; + int RTCPport; + + ch = voe_base_->CreateChannel(); + + // verify non-configured (blank) local receiver + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 0); + TEST_MUSTPASS(RTCPport != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // check some trivial set/get combinations + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)) + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 12345); + TEST_MUSTPASS(RTCPport != 12346); + TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); // now binded to "any" IP + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 55555)) + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 12345); + TEST_MUSTPASS(RTCPport != 55555); + TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp)) + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 12345); + TEST_MUSTPASS(RTCPport != 12346); + TEST_MUSTPASS(strcmp(ipaddr, localIp) != 0); + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetLocalReceiver + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSendDestination + // + // State: VE initialized, no existing channels + TEST(SetSendDestination); + ANL(); + + // call without existing channel + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + ch = voe_base_->CreateChannel(); + + // trivial fail tests + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 65536, "127.0.0.1")); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid RTP port + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid source port + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", kVoEDefault, + 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid RTCP port + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.300")); + MARK(); + TEST_ERROR(VE_INVALID_IP_ADDRESS); // invalid IP address + + // sockets must be created first to support multi-cast (not required + // otherwise) + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 55555, "230.0.0.1")); + MARK(); + TEST_ERROR(VE_SOCKET_ERROR); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); // create sockets + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "230.0.0.1")); + MARK(); // should work now + + voe_base_->DeleteChannel(0); + ch = voe_base_->CreateChannel(); + + // STATE: one channel created, no sockets exist + + // valid function calls + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1")); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444)); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", kVoEDefault, + 55555)); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444, + 55555)); + MARK(); + + voe_base_->DeleteChannel(0); + ch = voe_base_->CreateChannel(); + + // create receive sockets first and then an extra pair of send sockets + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 44444)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1", 11111)); + MARK(); // binds to 11111 + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of SetSendDestination + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetSendDestination + // + // State: VE initialized, no existing channels + TEST(GetSendDestination); + ANL(); + + int sourcePort; + + ch = voe_base_->CreateChannel(); + + // verify non-configured (blank) local receiver + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 0); + TEST_MUSTPASS(sourcePort != 0); + TEST_MUSTPASS(RTCPport != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // check some trivial set/get combinations + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 44444); + TEST_MUSTPASS(sourcePort != 0); // should be 0 since no local receiver has + // NOT been defined yet + TEST_MUSTPASS(RTCPport != 44445); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 44444); + TEST_MUSTPASS(sourcePort != 55555); // should be equal to local port + TEST_MUSTPASS(RTCPport != 44445); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + voe_base_->DeleteChannel(0); + ch = voe_base_->CreateChannel(); + + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1")); + // NULL as IP-address input should work as well + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, NULL, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 44444); + TEST_MUSTPASS(sourcePort != 0); + TEST_MUSTPASS(RTCPport != 44445); + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetLocalReceiver + // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ // >> StartReceive // >> StopReceive @@ -559,14 +871,14 @@ int VoEExtendedTest::TestBase() { MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); - int ch = voe_base_->CreateChannel(); + ch = voe_base_->CreateChannel(); - // must register external transport first. + // sockets must be created first TEST_MUSTPASS(!voe_base_->StartReceive(0)); MARK(); - - ExtendedTestTransport* ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + TEST_ERROR(VE_SOCKETS_NOT_INITED); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); MARK(); // should work this time // enable again (should work) @@ -580,6 +892,7 @@ int VoEExtendedTest::TestBase() { MARK(); // Verify in loopback + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartSend(ch)); Play(ch, 1000, true, true); TEST_MUSTPASS(voe_base_->StopSend(ch)); @@ -587,15 +900,16 @@ int VoEExtendedTest::TestBase() { MARK(); voe_base_->DeleteChannel(0); - delete ptrTransport; ch = voe_base_->CreateChannel(); // Ensure that it is OK to add delay between SetLocalReceiver and StarListen TEST_LOG("\nspeak after 2 seconds and ensure that no delay is added:\n"); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); Sleep(2000, true); // adding emulated delay here TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartSend(ch)); Play(ch, 2000, true, true); TEST_MUSTPASS(voe_base_->StopSend(ch)); @@ -608,23 +922,23 @@ int VoEExtendedTest::TestBase() { for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 11111+2*i)); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); MARK(); } for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { - voe_base_->DeleteChannel(i); + TEST_MUSTPASS(voe_base_->StopReceive(i)); MARK(); + voe_base_->DeleteChannel(i); } for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { ch = voe_base_->CreateChannel(); - ExtendedTestTransport* ptrTransport = - new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 11111+2*i)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); MARK(); TEST_MUSTPASS(voe_base_->StopReceive(ch)); MARK(); voe_base_->DeleteChannel(ch); - delete ptrTransport; } ANL(); @@ -719,24 +1033,25 @@ int VoEExtendedTest::TestBase() { MARK(); TEST_ERROR(VE_DESTINATION_NOT_INITED); - // initialize destination and try again (should work even without existing // sockets) - ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartSend(ch)); MARK(); SleepMs(100); + // STATE: sockets should now have been created automatically at the first + // transmitted packet should be binded to 33333 and "0.0.0.0" TEST_MUSTPASS(voe_base_->StopSend(ch)); MARK(); voe_base_->DeleteChannel(ch); - delete ptrTransport; ch = voe_base_->CreateChannel(); - ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + // try loopback with unique send sockets (closed when channel is deleted or + // new source is set) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33333)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444)); TEST_MUSTPASS(voe_base_->StartSend(ch)); MARK(); TEST_MUSTPASS(voe_base_->StartReceive(ch)); @@ -746,7 +1061,31 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopReceive(ch)); voe_base_->DeleteChannel(ch); + ANL(); + // Multi-channel tests + for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { + ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33333 + 2*i)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333 + 2*i, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + MARK(); + } + for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { + TEST_MUSTPASS(voe_base_->StopSend(i)); + MARK(); + voe_base_->DeleteChannel(i); + } + for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { + ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 45633 + 2*i)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 45633 + 2*i, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + MARK(); + TEST_MUSTPASS(voe_base_->StopSend(ch)); + MARK(); + voe_base_->DeleteChannel(ch); + } ANL(); AOK(); ANL(); @@ -824,11 +1163,9 @@ int VoEExtendedTest::TestBase() { ch = voe_base_->CreateChannel(); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, ch)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); @@ -869,9 +1206,9 @@ int VoEExtendedTest::TestBase() { #ifdef _TEST_RTP_RTCP_ TEST_MUSTPASS(rtp->SetRTCP_CNAME(ch, "Johnny")); #endif - voice_channel_transport.reset(new VoiceChannelTransport(voe_network, ch)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 12349)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", kVoEDefault, + 12349)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -889,11 +1226,18 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(rtp->GetRemoteRTCP_CNAME(ch, tmpStr)); TEST_MUSTPASS(_stricmp("Johnny", tmpStr)); #endif + int rtpPort(0), rtcpPort(0); + char ipAddr[64] = { 0 }; + TEST_MUSTPASS(netw->GetSourceInfo(ch, rtpPort, rtcpPort, ipAddr)); + TEST_MUSTPASS(12349 != rtcpPort); TEST_MUSTPASS(voe_base_->StopSend(ch)); TEST_MUSTPASS(voe_base_->StopPlayout(ch)); TEST_MUSTPASS(voe_base_->StopReceive(ch)); // Call StartSend before StartReceive + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); @@ -907,6 +1251,9 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopReceive(ch)); // Try again using same ports + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); @@ -917,17 +1264,38 @@ int VoEExtendedTest::TestBase() { SleepMs(7000); // Make sure we get RTCP packet PAUSE + // Verify correct RTCP source port + TEST_MUSTPASS(netw->GetSourceInfo(ch, rtpPort, rtcpPort, ipAddr)); + TEST_MUSTPASS(12345+1 != rtcpPort); TEST_MUSTPASS(voe_base_->StopSend(ch)); TEST_MUSTPASS(voe_base_->StopPlayout(ch)); TEST_MUSTPASS(voe_base_->StopReceive(ch)); voe_base_->DeleteChannel(ch); - ch = voe_base_->CreateChannel(); - voice_channel_transport.reset(new VoiceChannelTransport(voe_network, ch)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + // Try with extra send socket + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 22222)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 22222, "127.0.0.1", 11111)); + + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + TEST_MUSTPASS(voe_base_->StartPlayout(ch)); + + TEST_LOG("\nfull duplex is now activated (4)\n"); + + PAUSE + + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopPlayout(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + // repeat default case starting with a fresh channel + + voe_base_->DeleteChannel(ch); + ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -942,6 +1310,7 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopReceive(ch)); // restart call again + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -954,15 +1323,35 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopPlayout(ch)); TEST_MUSTPASS(voe_base_->StopReceive(ch)); + // force sending from new socket + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", 12350, + 12359)); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartPlayout(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + TEST_LOG("\nfull duplex is now activated (7)\n"); + + PAUSE + + // Test getting send settings + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, rtpPort, ipAddr, sourcePort, + rtcpPort)); + TEST_MUSTPASS(12345 != rtpPort); + TEST_MUSTPASS(_stricmp("127.0.0.1", ipAddr)); + TEST_MUSTPASS(12350 != sourcePort); + TEST_MUSTPASS(12359 != rtcpPort); + + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopPlayout(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + // new channel and new port ch = voe_base_->CreateChannel(); - scoped_ptr voice_channel_transport_2( - new VoiceChannelTransport(voe_network, ch)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 33221)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33221, "127.0.0.1")); - voice_channel_transport_2->SetSendDestination("127.0.0.1", 33221); - voice_channel_transport_2->SetLocalReceiver(33221); - TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -971,6 +1360,36 @@ int VoEExtendedTest::TestBase() { PAUSE + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopPlayout(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + voe_base_->DeleteChannel(ch); + ch = voe_base_->CreateChannel(); + +#ifndef WEBRTC_IOS + // bind to local IP and try again + strcpy(localIp, "127.0.0.1"); +#else + localIp = "127.0.0.1"; +#endif + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33221, 12349, localIp)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33221, localIp)); + + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartPlayout(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + + TEST_LOG("\nfull duplex is now activated (9)\n"); + + PAUSE + + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, rtpPort, rtcpPort, ipAddr)); + TEST_MUSTPASS(33221 != rtpPort); + TEST_MUSTPASS(_stricmp(localIp, ipAddr)); + TEST_MUSTPASS(12349 != rtcpPort); + ANL(); AOK(); ANL(); @@ -1058,6 +1477,7 @@ int VoEExtendedTest::TestBase() { voe_base_->DeleteChannel(0); TEST_MUSTPASS(voe_base_->Terminate()); + return 0; } @@ -1071,7 +1491,7 @@ int VoEExtendedTest::TestCallReport() { VoECallReport* report = _mgr.CallReportPtr(); VoEFile* file = _mgr.FilePtr(); VoEAudioProcessing* apm = _mgr.APMPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); + VoENetwork* netw = _mgr.NetworkPtr(); PrepareTest("CallReport"); @@ -1096,10 +1516,8 @@ int VoEExtendedTest::TestCallReport() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -1163,14 +1581,14 @@ int VoEExtendedTest::TestCallReport() { // All results should be -1 since dead-or-alive is not active TEST_MUSTPASS(report->GetDeadOrAliveSummary(0, nDead, nAlive) != -1); MARK(); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 1)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1)); SleepMs(2000); // All results should be >= 0 since dead-or-alive is active TEST_MUSTPASS(report->GetDeadOrAliveSummary(0, nDead, nAlive)); MARK(); TEST_MUSTPASS(nDead == -1); TEST_MUSTPASS(nAlive == -1) - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); AOK(); ANL(); @@ -1223,7 +1641,6 @@ int VoEExtendedTest::TestCodec() { VoEBase* voe_base_ = _mgr.BasePtr(); VoECodec* codec = _mgr.CodecPtr(); VoEFile* file = _mgr.FilePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -1240,8 +1657,14 @@ int VoEExtendedTest::TestCodec() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - ExtendedTestTransport* ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + ExtendedTestTransport* ptrTransport(NULL); + ptrTransport = new ExtendedTestTransport(netw); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); +#else + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); +#endif TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -1717,6 +2140,10 @@ int VoEExtendedTest::TestCodec() { TEST_MUSTPASS(voe_base_->StopReceive(0)); // start loopback streaming (PCMU is default) +#ifndef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(voe_base_->SetSendDestination(0,8000,"127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0,8000)); +#endif TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -1989,12 +2416,16 @@ int VoEExtendedTest::TestCodec() { TEST(SetRecPayloadType - removing receive codecs); ANL(); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); +#endif TEST_MUSTPASS(voe_base_->StartSend(0)); if (file) { TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0, - _mgr.AudioFilename(), - true, - true)); + _mgr.AudioFilename(), + true, + true)); } // Scan all supported and valid codecs and remove from receiving db, then @@ -2509,7 +2940,12 @@ int VoEExtendedTest::TestCodec() { // set iSAC as sending codec // set iSAC-wb as sending codec - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); +#else + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8001, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8001)); +#endif TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartReceive(0)); @@ -2555,8 +2991,10 @@ int VoEExtendedTest::TestCodec() { TEST_LOG("Skipping extended iSAC API tests - " "WEBRTC_CODEC_ISAC not defined\n"); #endif // #if defined(WEBRTC_CODEC_ISAC) - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); delete ptrTransport; +#endif TEST_MUSTPASS(voe_base_->DeleteChannel(0)); TEST_MUSTPASS(voe_base_->Terminate()); @@ -2575,7 +3013,6 @@ int VoEExtendedTest::TestDtmf() { VoEDtmf* dtmf = _mgr.DtmfPtr(); VoECodec* codec = _mgr.CodecPtr(); VoEVolumeControl* volume = _mgr.VolumeControlPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); std::string output_path = webrtc::test::OutputPath(); TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -2591,10 +3028,8 @@ int VoEExtendedTest::TestDtmf() { //#endif TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -2904,7 +3339,6 @@ int VoEExtendedTest::TestEncryption() { VoEBase* voe_base_ = _mgr.BasePtr(); VoEFile* file = _mgr.FilePtr(); VoEEncryption* encrypt = _mgr.EncryptionPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -2920,10 +3354,8 @@ int VoEExtendedTest::TestEncryption() { #endif TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -3418,7 +3850,6 @@ int VoEExtendedTest::TestExternalMedia() { VoEBase* voe_base_ = _mgr.BasePtr(); VoEExternalMedia* xmedia = _mgr.ExternalMediaPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); // check if this interface is supported if (!xmedia) { @@ -3436,10 +3867,8 @@ int VoEExtendedTest::TestExternalMedia() { #endif TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -3544,7 +3973,6 @@ int VoEExtendedTest::TestFile() { VoEBase* voe_base_ = _mgr.BasePtr(); VoEFile* file = _mgr.FilePtr(); VoECodec* codec = _mgr.CodecPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -3561,10 +3989,8 @@ int VoEExtendedTest::TestFile() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -3963,10 +4389,9 @@ int VoEExtendedTest::TestFile() { TEST_MUSTPASS(ch == -1); TEST_MUSTPASS(voe_base_->StopPlayout(ch)); } - scoped_ptr voice_channel_transport_1( - new VoiceChannelTransport(voe_network, 1)); - voice_channel_transport_1->SetSendDestination("127.0.0.1", 12356); - voice_channel_transport_1->SetLocalReceiver(12356); + + TEST_MUSTPASS(voe_base_->SetSendDestination(1, 12356, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(1, 12356)); TEST_MUSTPASS(voe_base_->StartReceive(1)); TEST_MUSTPASS(voe_base_->StopPlayout(1)); TEST_MUSTPASS(voe_base_->StartSend(1)); @@ -4553,8 +4978,20 @@ int VoEExtendedTest::TestNetEqStats() { int VoEExtendedTest::TestNetwork() { PrepareTest("Network"); +#ifdef WEBRTC_ANDROID + int sleepTime = 200; + int sleepTime2 = 250; +#elif defined(WEBRTC_IOS) // WEBRTC_IOS needs more delay for getSourceInfo() + int sleepTime = 150; + int sleepTime2 = 200; +#else + int sleepTime = 100; + int sleepTime2 = 200; +#endif + VoEBase* voe_base_ = _mgr.BasePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); + VoEFile* file = _mgr.FilePtr(); + VoENetwork* netw = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile((output_path + @@ -4571,6 +5008,259 @@ int VoEExtendedTest::TestNetwork() { TEST_MUSTPASS(voe_base_->Init()); + // ------------------------------------------------------------------------ + // >> GetLocalIP + // + // State: VE initialized, no existing channels + TEST(GetLocalIP); + ANL(); + +#ifdef WEBRTC_IOS + // Should fail + TEST_MUSTPASS(!netw->GetLocalIP(NULL, 0)); MARK(); + TEST_ERROR(VE_FUNC_NOT_SUPPORTED); + + ANL(); + printf("NOTE: Local IP must be set in source code (line %d) \n", + __LINE__ + 1); + const char* localIP = "192.168.1.4"; + +#else + // Must be big enough so that we can print an IPv6 address. + char localIP[256] = {0}; + + // invalid parameter + TEST_MUSTPASS(!netw->GetLocalIP(NULL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // default function calls (IPv4) + TEST_MUSTPASS(netw->GetLocalIP(localIP)); + MARK(); + TEST_LOG("[local IPv4: %s]\n", localIP); + TEST_MUSTPASS(netw->GetLocalIP(localIP)); + MARK(); + +#if !defined(WEBRTC_MAC) && !defined(WEBRTC_ANDROID) + // default function calls (IPv6) + TEST_MUSTPASS(netw->GetLocalIP(localIP, true)); + MARK(); + TEST_LOG("[local IPv6: %s]\n", localIP); + TEST_MUSTPASS(netw->GetLocalIP(localIP, true)); + MARK(); +#endif + + // one last call to ensure that local + TEST_MUSTPASS(netw->GetLocalIP(localIP)); + MARK(); +#endif + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetLocalIP + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetSourceInfo + // + // - VE initialized + // - no existing channels + TEST(GetSourceInfo); + ANL(); + + int rtpPort(0); + int rtcpPort(0); + char ipaddr[64] = { 0 }; + ExtendedTestTransport* ptrTransport(NULL); + + // call without valid channel + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // NULL as input string + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, NULL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // call when external transport is enabled + ptrTransport = new ExtendedTestTransport(netw); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + delete ptrTransport; + + // call when external transport is disabled (no packet received yet) + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + // send and receive packets with default settings for a while + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime2); // does not guarantee RTCP + + // verify remote parameters (exclude RTCP) + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // ensure that valid results are maintained after StopListen + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // verify that results are maintained after new call to SetLocalReceiver + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // STATE: not listening, not sending + // send and receive packets with other settings for a while + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 9005)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // STATE: listening, sending + + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9005); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // restart sending to and from local IP + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 9005, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9005); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); // should not be "127.0.0.1" + + // use non-default source port in outgoing packets + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 9005)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, "127.0.0.1", 9010)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9010); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // STATE: listening and sending using an extra local socket + + // stop/start sending + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify that the unique source port is maintained for the extra socket + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9010); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // set new source port for outgoing packets (9010 -> 9020) + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, "127.0.0.1", 9020)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); +#ifdef WEBRTC_IOS + SleepMs(500); // Need extra pause for some reason +#endif + + // verify that the unique source port is set for the new extra socket + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9020); + // STATE: listening and sending using an extra local socket + + // remove extra send socket and restart call again + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); // delete channel => destroys the + // extra socket + TEST_MUSTPASS(voe_base_->CreateChannel()); // new channel uses one socket only + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); // use new port as well + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify that remote info is correct + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // STATE: listening and sending using shared socket + + // use non-default source port in outgoing packets to create extra send + // socket + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 7000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 7000, "127.0.0.1", 7010)); + // RTP src is 7010 => RTCP src = 7011 + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 7010); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // check RTCP port as well (should be 7010 + 1 = 7011) + Sleep(8000, true); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 7010); + TEST_MUSTPASS(rtcpPort != 7011); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetSourceInfo + // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ // >> SetExternalTransport // @@ -4581,54 +5271,127 @@ int VoEExtendedTest::TestNetwork() { TEST(SetExternalTransport); ANL(); - ExtendedTestTransport* ptrTransport = new ExtendedTestTransport(voe_network); + ptrTransport = new ExtendedTestTransport(netw); // call without valid channel - TEST_MUSTPASS(!voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(!netw->DeRegisterExternalTransport(0)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); // different valid call combinations - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); - TEST_MUSTPASS(!voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); // must deregister first - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); // STATE: external transport is disabled + + // initialize sending and ensure that external transport can't be enabled + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 1234, "127.0.0.2")); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); + MARK(); + TEST_ERROR(VE_SEND_SOCKETS_CONFLICT); + + // restart channel to ensure that "initialized sender" state is cleared + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // initialize receiving and ensure that external transport can't be enabled + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 5678)); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); + MARK(); + TEST_ERROR(VE_RECEIVE_SOCKETS_CONFLICT); + + // restart channel to ensure that "initialized receiver" state is cleared TEST_MUSTPASS(voe_base_->DeleteChannel(0)); TEST_MUSTPASS(voe_base_->CreateChannel()); // enable external transport and verify that "emulated loopback" works - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); TEST_MUSTPASS(voe_base_->StartSend(0)); // should only start recording - TEST_MUSTPASS(!voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); // should fail - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); Play(0, 2000, true, true); // play file as mic and verify loopback audio - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); + // STATE: external transport is disabled +#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) + int testError = VE_FUNC_NOT_SUPPORTED; +#else + int testError = VE_EXTERNAL_TRANSPORT_ENABLED; +#endif + + // check all APIs that should fail when external transport is enabled + int DSCP, priority, serviceType, overrideDSCP, nBytes(0); + bool useSetSockopt, enabled; + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); + MARK(); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(0, 12345)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!voe_base_->GetLocalReceiver(0, rtpPort, rtcpPort, ipaddr)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!voe_base_->GetSendDestination(0, rtpPort, ipaddr, rtpPort, + rtcpPort)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->EnableIPv6(0)) + TEST_ERROR(testError); + TEST_MUSTPASS(netw->IPv6IsEnabled(0) != false) + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345, 12346)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + // modified i VoE 3.4 (can be called also for external transport) TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StopReceive(0)); +#if (!defined(_WIN32) && !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC)) || \ + defined(WEBRTC_EXTERNAL_TRANSPORT) + testError = VE_FUNC_NOT_SUPPORTED; +#else + testError = VE_EXTERNAL_TRANSPORT_ENABLED; +#endif + TEST_MUSTPASS(!netw->SetSendTOS(0, 0)); + TEST_ERROR(testError); + TEST_MUSTPASS(!netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_ERROR(testError); +#if !defined(_WIN32) || defined(WEBRTC_EXTERNAL_TRANSPORT) + testError = VE_FUNC_NOT_SUPPORTED; +#else + testError = VE_EXTERNAL_TRANSPORT_ENABLED; +#endif + TEST_MUSTPASS(!netw->SetSendGQoS(0, false, 0)); + TEST_ERROR(testError); + TEST_MUSTPASS(!netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_ERROR(testError); + char dummy[1] = { 'a' }; + TEST_MUSTPASS(!netw->SendUDPPacket(0, dummy, 1, nBytes)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + // always disable external transport before deleting the Transport object; // will lead to crash for RTCP transmission otherwise - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); delete ptrTransport; @@ -4642,6 +5405,350 @@ int VoEExtendedTest::TestNetwork() { // >> end of SetExternalTransport // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ + // >> EnableIPv6 + // + // - VE initialized + // - no existing channels + // - no media + // - NOTE: set _ENABLE_IPV6_TESTS_ to include these tests + // - http://www.microsoft.com/resources/documentation/windows/xp/all/ + // proddocs/en-us/sag_ip_v6_pro_rt_enable.mspx?mfr=true + // >> ipv6 install + // >> ipv6 [-v] if [IfIndex] + // >> ping6 ::1 + // >> ping6 fe80::1 + +#ifdef _ENABLE_IPV6_TESTS_ + + TEST(EnableIPv6); ANL(); + + // call without valid channel + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // call with enabled external transport + ptrTransport = new ExtendedTestTransport(netw); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); + delete ptrTransport; + + // Test "locking" to IPv4 + TEST_MUSTPASS(netw->IPv6IsEnabled(0)); MARK(); // After this call we cannot + // enable IPv6 + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); // Should fail + + // Check that IPv6 address is invalid + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 8000, "::1")); MARK(); // fail + + // New channel + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // valid default call + TEST_MUSTPASS(netw->EnableIPv6(0)); MARK(); + TEST_MUSTPASS(netw->GetLocalIP(localIP)); MARK(); // should still read IPv4 + TEST_LOG("[local IPv4: %s]", localIP); + + // ensure that Ipv6 is enabled + TEST_MUSTPASS(netw->IPv6IsEnabled(0) != true); + + // check that IPv4 address is invalid + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_ERROR(VE_INVALID_IP_ADDRESS); + + // verify usage of IPv6 loopback address + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + // IPv6 loopback address is 0:0:0:0:0:0:0:1 + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "::1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); // Should fail + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); + ANL(); + + // Restart channel + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); + + TEST_MUSTPASS(netw->EnableIPv6(0)); MARK(); + // ensure that Ipv6 is enabled + TEST_MUSTPASS(netw->IPv6IsEnabled(0) != true); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + // IPv6 loopback address is 0:0:0:0:0:0:0:1 + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "::1")); + TEST_MUSTPASS(voe_base_->StartPlayout(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + file->StartPlayingFileAsMicrophone(0, _mgr.AudioFilename(), true, + true); + SleepMs(500); // ensure that we receieve some packets + + // SetSourceFilter and GetSourceFilter + TEST(SetSourceFilter and GetSourceFilter for IPv6); ANL(); + char sourceIp[64] = + { 0}; + char filterIp[64] = + { 0}; + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, sourceIp)); + TEST_LOG("Source port: %d \n", rtpPort); + TEST_LOG("Source RTCP port: %d \n", rtcpPort); + TEST_LOG("Source IP: %s \n", sourceIp); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_LOG("Filter port RTP: %d \n", rtpPort); + TEST_LOG("Filter port RTCP: %d \n", rtcpPort); + TEST_LOG("Filter IP: %s \n", filterIp); + TEST_MUSTPASS(0 != rtpPort); + TEST_MUSTPASS(0 != rtcpPort); + TEST_MUSTPASS(filterIp[0] != '\0'); + TEST_LOG("Set filter IP to %s => should hear audio\n", sourceIp); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, sourceIp)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(0 != rtpPort); + TEST_MUSTPASS(0 != rtcpPort); + TEST_MUSTPASS(_stricmp(filterIp, sourceIp)); + SleepMs(1500); + TEST_LOG("Set filter IP to ::10:10:10 => should *not* hear audio\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::10:10:10")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(_stricmp(filterIp, "::10:10:10")); + SleepMs(1500); + TEST_LOG("Disable IP filter => should hear audio again\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::0")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(_stricmp(filterIp, "::")); + SleepMs(1500); + TEST_LOG("Set filter IP to ::10:10:10 => should *not* hear audio\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::10:10:10")); + SleepMs(1500); + TEST_LOG("Disable IP filter => should hear audio again\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(filterIp[0] != '\0'); + SleepMs(1500); + TEST_LOG("Set filter IP to ::10:10:10 => should *not* hear audio\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::10:10:10")); + SleepMs(1500); + TEST_LOG("Disable IP filter => should hear audio again\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(_stricmp(filterIp, "::")); + SleepMs(1500); + + file->StopPlayingFileAsMicrophone(0); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + +#endif // #ifdef _ENABLE_IPV6_TESTS_ + // >> end of EnableIPv6 + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSourceFilter + // + // - VE initialized + // - no existing channels + // - no media + TEST(SetSourceFilter); + ANL(); + + // call without valid channel + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // invalid parameters + TEST_MUSTPASS(!netw->SetSourceFilter(0, 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345, 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345, 12346, "300.300.300.300")); + MARK(); + TEST_ERROR(VE_INVALID_IP_ADDRESS); + + // STATE: RTP filter port is 12345, RTCP filter port is 12346 + + // disable all filters and ensure that media is received + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + MARK(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 2000); + TEST_MUSTPASS(rtcpPort != 2001); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); + + // clear states and restart loopback session + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); // clear source info state + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // set RTP filter to port 2002 and verify that source 2000 is blocked + TEST_MUSTPASS(netw->SetSourceFilter(0, 2002, 0, NULL));; + MARK(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // ensure that received packets originates from 2002 and that they now pass + // the filter + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + // RTP source is 2002 + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2002, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2002, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 2002); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); + + // clear states and restart loopback session + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); // clear source info state + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // set IP filter to local IP and verify that default loopback stream is + // blocked + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, localIP));; + MARK(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // ensure that received packets originates from the local IP and that they + // now pass the filter + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + // should pass the filter + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 2000); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); + + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + + // STATE: no active media, IP filter is active + + // disable all filters + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL));; + MARK(); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of SetSourceFilter + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetSourceFilter + // + // - VE initialized + // - no existing channels + // - no media + TEST(GetSourceFilter); + ANL(); + + // call without valid channel + TEST_MUSTPASS(!netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // invalid input parameters + TEST_MUSTPASS(!netw->GetSourceFilter(0, rtpPort, rtcpPort, NULL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // valid call without any filter set + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // STATE: no active media and no enabled filters + + // set different filters and verify that they "bite" + TEST_MUSTPASS(netw->SetSourceFilter(0, 54321, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 54321); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 15425, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtcpPort != 15425); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "192.168.199.19")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "192.168.199.19") != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "0.0.0.0")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetSourceFilter + // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ // >> RegisterDeadOrAliveObserver // >> DeRegisterDeadOrAliveObserver @@ -4655,24 +5762,24 @@ int VoEExtendedTest::TestNetwork() { ANL(); // call without valid channel - TEST_MUSTPASS(!voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(!netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); - TEST_MUSTPASS(voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); - TEST_MUSTPASS(!voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(!netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); // already registered TEST_ERROR(VE_INVALID_OPERATION); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); // OK to do it again - TEST_MUSTPASS(voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); TEST_MUSTPASS(voe_base_->DeleteChannel(0)); @@ -4691,43 +5798,39 @@ int VoEExtendedTest::TestNetwork() { // - no media // call without valid channel - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(0, false)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); // Invalid paramters - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 0)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(0, true, 0)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 151)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(0, true, 151)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(1, true, 10)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(1, true, 10)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); int sampleTime(0); - bool enabled; // Valid parameters - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 1)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1)); MARK(); - TEST_MUSTPASS( - voe_network ->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); + TEST_MUSTPASS(netw->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(sampleTime != 1); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 150)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 150)); MARK(); - TEST_MUSTPASS( - voe_network ->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); + TEST_MUSTPASS(netw->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(sampleTime != 150); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); MARK(); - TEST_MUSTPASS( - voe_network ->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); + TEST_MUSTPASS(netw->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); TEST_MUSTPASS(enabled != false); TEST_MUSTPASS(sampleTime != 150); // ensure last set time isnt modified @@ -4736,25 +5839,25 @@ int VoEExtendedTest::TestNetwork() { // STATE: full duplex media is active // test the dead-or-alive mechanism - TEST_MUSTPASS(voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); TEST_LOG("\nVerify that Alive callbacks are received (dT=2sec): "); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 2)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 2)); SleepMs(6000); TEST_LOG("\nChange dT to 1 second: "); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 1)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1)); SleepMs(6000); TEST_LOG("\nDisable dead-or-alive callbacks: "); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); SleepMs(6000); TEST_LOG("\nStop sending and enable callbacks again.\n"); TEST_LOG("Verify that Dead callbacks are received (dT=2sec): "); fflush(NULL); TEST_MUSTPASS(voe_base_->StopSend(0)); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 2)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 2)); SleepMs(6000); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_LOG("\nRestart sending.\n"); @@ -4763,8 +5866,8 @@ int VoEExtendedTest::TestNetwork() { SleepMs(6000); TEST_LOG("\nDisable dead-or-alive callbacks."); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); StopMedia(0); @@ -4795,47 +5898,47 @@ int VoEExtendedTest::TestNetwork() { ANL(); // call without existing valid channel - TEST_MUSTPASS(!voe_network ->SetPacketTimeoutNotification(0, false)); + TEST_MUSTPASS(!netw->SetPacketTimeoutNotification(0, false)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); // invalid function calls - TEST_MUSTPASS(!voe_network ->SetPacketTimeoutNotification(0, true, 0)); + TEST_MUSTPASS(!netw->SetPacketTimeoutNotification(0, true, 0)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); - TEST_MUSTPASS(!voe_network ->SetPacketTimeoutNotification(0, true, 151)); + TEST_MUSTPASS(!netw->SetPacketTimeoutNotification(0, true, 151)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); // valid function calls (no active media) - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, true, 2)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, true, 2)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(timeOut != 2); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, false)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, false)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != false); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, true, 10)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, true, 10)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(timeOut != 10); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, true, 2)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, true, 2)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(timeOut != 2); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, false)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, false)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != false); @@ -4844,18 +5947,521 @@ int VoEExtendedTest::TestNetwork() { AOK(); ANL(); ANL(); - return 0; -} + // >> end of SetPacketTimeoutNotification // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ + // >> SendUDPPacket + // + // - VE initialized + // - no existing channels + // - no media + + + // >> end of SendUDPPacket + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSendTOS + // + // - VE initialized + // - no existing channels + // - no media + TEST(SetSendTOS); + ANL(); +#if defined(_WIN32) || defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) + + // call without existing valid channel + + TEST_MUSTPASS(!netw->SetSendTOS(0, 0)); MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // trivial invalid function calls + TEST_MUSTPASS(!netw->SetSendTOS(0, -1)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 64)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, -2)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, 8)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 1)); MARK(); + TEST_ERROR(VE_SOCKET_ERROR); // must create sockets first + +#ifdef _WIN32 + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 3000)); + + // enable ToS using SetSockopt (should work without local binding) + TEST_MUSTPASS(netw->SetSendTOS(0, 1, -1, true)); MARK(); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 1); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != true); + + // try to disable SetSockopt while ToS is enabled (should fail) + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, -1, false)); MARK(); + TEST_ERROR(VE_TOS_INVALID); // must disable ToS before enabling SetSockopt + + // disable ToS to be able to stop using SetSockopt + TEST_MUSTPASS(netw->SetSendTOS(0, 0, -1, true)); MARK(); // disable ToS + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 0); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != true); + + // to use the "non-SetSockopt" method, local binding is required, + // trying without it should fail + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, -1, false)); MARK(); + TEST_ERROR(VE_TOS_ERROR); // must bind to local IP first + + // bind to local IP and try again (should work this time) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345, kVoEDefault, localIP)); + TEST_LOG("\nThis test needs to be run as administrator\n"); + TEST_MUSTPASS(netw->SetSendTOS(0, 1, -1, false)); MARK(); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 1); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != false); + + // STATE: binded to local IP, local port is 12345 and DSCP is 1 (not using + // SetSockopt) + + // verify loopback audio with the current settings + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + +#ifdef _SEND_TO_REMOTE_IP_ + // Send to remote destination and verify the DSCP using Wireshark. + // Use filter ip.src == "RemoteIP". + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP at the " + "remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each DSCP below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + TEST_LOG(" DSCP is set to 0x%02x\n", 1); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 2)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x\n", DSCP); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 63)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x\n", DSCP); + SleepMs(100); + + // stop and resume sending + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x\n", DSCP); + SleepMs(100); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 0)); +#endif // _SEND_TO_REMOTE_IP_ + // Windows priority tests (priority cannot be set using setsockopt on Win) + TEST_LOG("Testing priority\n"); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(!netw->SetSendTOS(0, 0, 3, true)); // Should fail + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(netw->SetSendTOS(0, 0, 3, false)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 1, 3, false)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); +#endif // _WIN32 + // STATE: no media, disabled ToS, no defined receiver + + // Repeat tests above but using setsockopt() this time. + // Binding to local IP should not be required. + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345, kVoEDefault)); + TEST_MUSTPASS(netw->SetSendTOS(0, 10, -1, true)); MARK(); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 10); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != true); + + // STATE: *not* binded to local IP, local port is 12345 and DSCP is 10 + // (using SetSockopt) + + // verify loopback audio with the current settings + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + +#ifdef _SEND_TO_REMOTE_IP_ + // Send to remote destination and verify the DSCP using Wireshark. + // Use filter ip.src == "RemoteIP". + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP at the" + " remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each DSCP below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 20, -1, true)); // use setsockopt() + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 61, -1, true)); // use setsockopt() + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + + // stop and resume sending + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 0, -1, true)); +#endif // _SEND_TO_REMOTE_IP_ +#if defined(WEBRTC_LINUX) + // Linux priority tests (using setsockopt) + TEST_LOG("Testing priority\n"); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 0, 3, true)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 1, 3, true)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... +#endif // #if defined(WEBRTC_LINUX) +#if !defined(_WIN32) && !defined(WEBRTC_LINUX) + // Fail tests for other than Wind and Linux + TEST_MUSTPASS(!netw->SetSendTOS(0, 0, 3, false)); // Should fail + TEST_ERROR(VE_INVALID_ARGUMENT); +#endif // #if !defined(_WIN32) && !defined(WEBRTC_LINUX) + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); AOK(); ANL(); ANL(); + + // END #if defined(_WIN32) || defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) +#else + TEST_LOG("Skipping ToS tests - _WIN32, LINUX, MAC is not defined or " + "WEBRTC_ANDROID is defined"); +#endif + + // >> end of SetSendTOS + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSendGQoS (Windows only) + // + // - VE initialized + // - no existing channels + // - no media + // + // From qos.h: + // + // #define SERVICETYPE_NOTRAFFIC 0x00000000 + // #define SERVICETYPE_BESTEFFORT 0x00000001 (*) + // #define SERVICETYPE_CONTROLLEDLOAD 0x00000002 (*) + // #define SERVICETYPE_GUARANTEED 0x00000003 (*) + // #define SERVICETYPE_NETWORK_UNAVAILABLE 0x00000004 + // #define SERVICETYPE_GENERAL_INFORMATION 0x00000005 + // #define SERVICETYPE_NOCHANGE 0x00000006 + // #define SERVICETYPE_NONCONFORMING 0x00000009 + // #define SERVICETYPE_NETWORK_CONTROL 0x0000000A + // #define SERVICETYPE_QUALITATIVE 0x0000000D (*) + // + // #define SERVICE_BESTEFFORT 0x80010000 + // #define SERVICE_CONTROLLEDLOAD 0x80020000 + // #define SERVICE_GUARANTEED 0x80040000 + // #define SERVICE_QUALITATIVE 0x80200000 + // + // (*) supported in WEBRTC VoE + TEST(SetSendGQoS); + ANL(); +#ifdef _WIN32 + + // call without existing valid channel + TEST_MUSTPASS(!netw->SetSendGQoS(0, false, 0)); MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // supported service type but no sockets + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_ERROR(VE_SOCKETS_NOT_INITED); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + + // supported service type but sender is not initialized + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_ERROR(VE_DESTINATION_NOT_INITED); + + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + + // invalid service types + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NOTRAFFIC)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NETWORK_UNAVAILABLE)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_GENERAL_INFORMATION)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NOCHANGE)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NONCONFORMING)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NETWORK_CONTROL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_BESTEFFORT)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_CONTROLLEDLOAD)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_GUARANTEED)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_QUALITATIVE)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // Is ToS enabled here? + + // Settings which don't require binding to local IP + + // set SERVICETYPE_BESTEFFORT + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_BESTEFFORT); + TEST_MUSTPASS(overrideDSCP != false); + + // set SERVICETYPE_CONTROLLEDLOAD + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_CONTROLLEDLOAD)); + MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_CONTROLLEDLOAD); + TEST_MUSTPASS(overrideDSCP != false); + + // set SERVICETYPE_GUARANTEED + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_GUARANTEED)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_GUARANTEED); + TEST_MUSTPASS(overrideDSCP != false); + + // set SERVICETYPE_QUALITATIVE + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_QUALITATIVE)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_QUALITATIVE); + TEST_MUSTPASS(overrideDSCP != false); + + // disable GQoS + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != false); + TEST_MUSTPASS(serviceType != SERVICETYPE_QUALITATIVE); + TEST_MUSTPASS(overrideDSCP != false); + + // STATE: diabled QGoS, sockets exists, sending side is initialized, no media + + // Loopback tests using the four different GQoS settings + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + ANL(); + TEST_LOG("[SERVICETYPE_BESTEFFORT]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_CONTROLLEDLOAD)); MARK(); + ANL(); + TEST_LOG("[SERVICETYPE_CONTROLLEDLOAD]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_GUARANTEED)); MARK(); + ANL(); + TEST_LOG("[SERVICETYPE_GUARANTEED]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_QUALITATIVE)); MARK(); + ANL(); + TEST_LOG("[SERVICETYPE_QUALITATIVE]"); + Play(0, 2000, true, true); // file should be played out here... + +#ifdef _SEND_TO_REMOTE_IP_ + // Send to remote destination and verify the DSCP mapping using Wireshark. + // Use filter ip.src == "RemoteIP". + + // Modify the send destination on the fly + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP mapping at" + " the remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each GQoS setting below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT (0x%02x), should " + "be mapped to DSCP = 0x00\n", serviceType); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_CONTROLLEDLOAD)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_CONTROLLEDLOAD (0x%02x), " + "should be mapped to DSCP = 0x18\n", serviceType); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_LOG(" QoS is disabled, should give DSCP = 0x%02x\n", 0); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_GUARANTEED)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_GUARANTEED (0x%02x), should " + "be mapped to DSCP = 0x28\n", serviceType); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_QUALITATIVE)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_QUALITATIVE (0x%02x), should" + " be mapped to DSCP = 0x00\n", serviceType); + SleepMs(100); +#endif // _SEND_TO_REMOTE_IP_ + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + + // STATE: sockets exists, sending side is initialized, no media + + // Repeat test above but this time using overrideDSCP. + + // Some initial loopack tests. + // NOTE - override DSCP requres binding to local IP. + + // should not work since QoS is enabled + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 3)); + MARK(); + TEST_ERROR(VE_TOS_GQOS_CONFLICT); + + // disble QoS and try to override again (should fail again since local + // binding is not done yet) + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 3)); + MARK(); + TEST_ERROR(VE_GQOS_ERROR); + + // make proper settings and try again (should work this time) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 3)); + MARK(); + + // Now, let's try some loopback tests using override DSCP + + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + ANL(); + TEST_LOG("[overrideDSCP=3]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 17)); + MARK(); + ANL(); + TEST_LOG("[overrideDSCP=17]"); + Play(0, 2000, true, true); // file should be played out here... + + // And finally, send to remote side as well to verify that the new mapping + // works as it should. + +#ifdef _SEND_TO_REMOTE_IP_ + // Modify the send destination on the fly + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP mapping at" + " the remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each GQoS setting below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 18)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 62)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 32)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 1)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_LOG(" QoS is disabled, should give DSCP = 0x%02x\n", 0); + SleepMs(100); +#endif // _SEND_TO_REMOTE_IP_ + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); AOK(); ANL(); ANL(); + +#else + TEST_LOG("Skipping GQoS tests - _WIN32 is not defined"); +#endif // #ifdef _WIN32 + // >> end of SetSendGQoS + // ------------------------------------------------------------------------ + + if (file) { + file->StopPlayingFileAsMicrophone(0); + } + voe_base_->StopSend(0); + voe_base_->StopPlayout(0); + voe_base_->StopReceive(0); + voe_base_->DeleteChannel(0); + voe_base_->Terminate(); + + ANL(); + AOK(); + return 0; +} + // ---------------------------------------------------------------------------- // VoEExtendedTest::TestRTP_RTCP // ---------------------------------------------------------------------------- // Used to validate packets during the RTP audio level indication test. class RTPAudioTransport: public Transport { - public: +public: + RTPAudioTransport() : mute_(false) { } @@ -4906,6 +6512,7 @@ class RTPAudioTransport: public Transport { assert(vad == 0 || vad == 1); assert(level >= 0 && level <= 127); } + return 0; } @@ -4914,7 +6521,7 @@ class RTPAudioTransport: public Transport { return 0; } - private: +private: bool mute_; }; @@ -4951,13 +6558,8 @@ int VoEExtendedTest::TestRTP_RTCP() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -5060,12 +6662,8 @@ int VoEExtendedTest::TestRTP_RTCP() { TEST_MUSTPASS(voe_base_->DeleteChannel(1)); TEST_MUSTPASS(voe_base_->CreateChannel()); - - voice_channel_transport.reset(new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -5074,7 +6672,7 @@ int VoEExtendedTest::TestRTP_RTCP() { ANL(); // ------------------------------------------------------------------------ - // >> SetLocalSSRC + // >> InsertExtraRTPPacket int i(0); @@ -5091,6 +6689,58 @@ int VoEExtendedTest::TestRTP_RTCP() { TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0, _mgr.AudioFilename(), true, true)); + // ------------------------------------------------------------------------ + // >> InsertExtraRTPPacket + TEST(InsertExtraRTPPacket); + ANL(); + + const char payloadData[8] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; + + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(-1, 0, false, + payloadData, 8)); + MARK(); // invalid channel + TEST_ERROR(VE_CHANNEL_NOT_VALID); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, -1, false, + payloadData, 8)); + MARK(); // invalid payload type + TEST_ERROR(VE_INVALID_PLTYPE); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 128, false, + payloadData, 8)); + MARK(); // invalid payload type + TEST_ERROR(VE_INVALID_PLTYPE); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 99, false, + NULL, 8)); + MARK(); // invalid pointer + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 99, false, + payloadData, 1500-28+1)); + MARK(); // invalid size + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 99, false, + payloadData, 8)); + MARK(); // not sending + TEST_ERROR(VE_NOT_SENDING); + TEST_MUSTPASS(voe_base_->StartSend(0)); + TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0, _mgr.AudioFilename(), + true, true)); + + SleepMs(1000); + for (int p = 0; p < 128; p++) { + TEST_MUSTPASS(rtp_rtcp->InsertExtraRTPPacket(0, p, false, + payloadData, 8)); + MARK(); + TEST_MUSTPASS(rtp_rtcp->InsertExtraRTPPacket(0, p, true, + payloadData, 8)); + MARK(); + } + + // Ensure we have sent all extra packets before we move forward to avoid + //incorrect error code + SleepMs(1000); + + ANL(); + // ------------------------------------------------------------------------ // >> RTP dump APIs TEST(Start/StopRtpDump); @@ -5229,12 +6879,8 @@ int VoEExtendedTest::TestRTP_RTCP() { SleepMs(100); TEST_MUSTPASS(voe_base_->CreateChannel()); - - voice_channel_transport.reset(new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -5480,12 +7126,8 @@ int VoEExtendedTest::TestRTP_RTCP() { // We have to re-register the audio codec payload type as stopReceive will // clean the database TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst)); - - voice_channel_transport.reset(new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 8000); - voice_channel_transport->SetLocalReceiver(8000); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -5521,7 +7163,6 @@ int VoEExtendedTest::TestVideoSync() VoEBase* voe_base_ = _mgr.BasePtr(); VoEVideoSync* vsync = _mgr.VideoSyncPtr(); - VoENetwork* network = _mgr.NetworkPtr(); // check if this interface is supported if (!vsync) @@ -5545,13 +7186,8 @@ int VoEExtendedTest::TestVideoSync() TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -5629,7 +7265,6 @@ int VoEExtendedTest::TestVolumeControl() VoEBase* voe_base_ = _mgr.BasePtr(); VoEVolumeControl* volume = _mgr.VolumeControlPtr(); - VoENetwork* network = _mgr.NetworkPtr(); #ifdef _TEST_FILE_ VoEFile* file = _mgr.FilePtr(); #endif @@ -5661,10 +7296,8 @@ int VoEExtendedTest::TestVolumeControl() TEST_MUSTPASS(hardware->SetPlayoutDevice(0)); #endif #endif - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); diff --git a/webrtc/voice_engine/test/auto_test/voe_extended_test.h b/webrtc/voice_engine/test/auto_test/voe_extended_test.h index af549f81b4..c685d885dc 100644 --- a/webrtc/voice_engine/test/auto_test/voe_extended_test.h +++ b/webrtc/voice_engine/test/auto_test/voe_extended_test.h @@ -12,14 +12,7 @@ #define WEBRTC_VOICE_ENGINE_VOE_EXTENDED_TEST_H #include "voe_standard_test.h" -#include "webrtc/modules/audio_device/include/audio_device.h" -#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/ref_count.h" -#include "webrtc/system_wrappers/interface/sleep.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" +#include "modules/audio_device/include/audio_device.h" namespace voetest { @@ -432,22 +425,20 @@ class VoEExtendedTest : public VoiceEngineObserver, int TestRTP_RTCP(); int TestVideoSync(); int TestVolumeControl(); - + public: int ErrorCode() const { return _errCode; } void ClearErrorCode() { _errCode = 0; } - protected: // from VoiceEngineObserver void CallbackOnError(const int errCode, const int channel); void CallbackOnTrace(const TraceLevel level, const char* message, const int length); - + protected: // from VoEConnectionObserver void OnPeriodicDeadOrAlive(const int channel, const bool alive); - private: void Play(int channel, unsigned int timeMillisec, bool addFileAsMicrophone = false, bool addTimeMarker = false); @@ -457,12 +448,12 @@ class VoEExtendedTest : public VoiceEngineObserver, int RunMixingTest(int num_remote_channels, int num_local_channels, int16_t input_value, int16_t max_output_value, int16_t min_output_value); - + private: VoETestManager& _mgr; + private: int _errCode; bool _alive; bool _listening[32]; - scoped_ptr voice_channel_transports_[32]; bool _playing[32]; bool _sending[32]; }; diff --git a/webrtc/voice_engine/test/auto_test/voe_stress_test.cc b/webrtc/voice_engine/test/auto_test/voe_stress_test.cc index 519bf83896..c92191317d 100644 --- a/webrtc/voice_engine/test/auto_test/voe_stress_test.cc +++ b/webrtc/voice_engine/test/auto_test/voe_stress_test.cc @@ -23,12 +23,10 @@ #endif #include "webrtc/voice_engine/test/auto_test/voe_stress_test.h" +#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" #include "webrtc/voice_engine/voice_engine_defines.h" // defines build macros using namespace webrtc; @@ -124,7 +122,6 @@ int VoEStressTest::StartStopTest() { // Get sub-API pointers VoEBase* base = _mgr.BasePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); // Set trace // VALIDATE_STRESS(base->SetTraceFileName( @@ -150,12 +147,9 @@ int VoEStressTest::StartStopTest() { printf("Test will take approximately %d minutes. \n", numberOfLoops * loopSleep / 1000 / 60 + 1); - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - for (i = 0; i < numberOfLoops; ++i) { - voice_channel_transport->SetSendDestination("127.0.0.1", 4800); - voice_channel_transport->SetLocalReceiver(4800); + VALIDATE_STRESS(base->SetLocalReceiver(0, 4800)); + VALIDATE_STRESS(base->SetSendDestination(0, 4800, "127.0.0.1")); VALIDATE_STRESS(base->StartReceive(0)); VALIDATE_STRESS(base->StartPlayout(0)); VALIDATE_STRESS(base->StartSend(0)); @@ -168,9 +162,8 @@ int VoEStressTest::StartStopTest() { } ANL(); - VALIDATE_STRESS(voice_channel_transport->SetSendDestination("127.0.0.1", - 4800)); - VALIDATE_STRESS(voice_channel_transport->SetLocalReceiver(4800)); + VALIDATE_STRESS(base->SetLocalReceiver(0, 4800)); + VALIDATE_STRESS(base->SetSendDestination(0, 4800, "127.0.0.1")); VALIDATE_STRESS(base->StartReceive(0)); VALIDATE_STRESS(base->StartPlayout(0)); VALIDATE_STRESS(base->StartSend(0)); diff --git a/webrtc/voice_engine/test/auto_test/voe_unit_test.cc b/webrtc/voice_engine/test/auto_test/voe_unit_test.cc index 8c4a7fbf98..b152aabfba 100644 --- a/webrtc/voice_engine/test/auto_test/voe_unit_test.cc +++ b/webrtc/voice_engine/test/auto_test/voe_unit_test.cc @@ -248,17 +248,13 @@ int VoEUnitTest::StartMedia(int channel, int rtpPort, bool listen, bool playout, bool send, bool fileAsMic, bool localFile) { VoEBase* base = _mgr.BasePtr(); VoEFile* file = _mgr.FilePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); _listening[channel] = false; _playing[channel] = false; _sending[channel] = false; - voice_channel_transports_[channel].reset( - new VoiceChannelTransport(voe_network, channel)); - - CHECK(voice_channel_transports_[channel]->SetLocalReceiver(rtpPort)); - CHECK(voice_channel_transports_[channel]->SetSendDestination("127.0.0.1", - rtpPort)); + + CHECK(base->SetLocalReceiver(channel, rtpPort)); + CHECK(base->SetSendDestination(channel, rtpPort, "127.0.0.1")); if (listen) { _listening[channel] = true; CHECK(base->StartReceive(channel)); diff --git a/webrtc/voice_engine/test/auto_test/voe_unit_test.h b/webrtc/voice_engine/test/auto_test/voe_unit_test.h index 8db8d67619..346713a177 100644 --- a/webrtc/voice_engine/test/auto_test/voe_unit_test.h +++ b/webrtc/voice_engine/test/auto_test/voe_unit_test.h @@ -11,9 +11,7 @@ #ifndef WEBRTC_VOICE_ENGINE_VOE_UNIT_TEST_H #define WEBRTC_VOICE_ENGINE_VOE_UNIT_TEST_H -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" +#include "voice_engine/test/auto_test/voe_standard_test.h" namespace voetest { @@ -59,7 +57,6 @@ class VoEUnitTest : public Encryption { bool _listening[32]; bool _playing[32]; bool _sending[32]; - scoped_ptr voice_channel_transports_[32]; private: bool _extOnOff; diff --git a/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc b/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc index d4bfc4b21b..2035e4eeaf 100644 --- a/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc +++ b/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc @@ -18,6 +18,8 @@ #include #include "gtest/gtest.h" +#include "test/testsupport/fileutils.h" + #include "voe_errors.h" #include "voe_base.h" #include "voe_codec.h" @@ -33,15 +35,14 @@ #include "voe_network.h" #include "voe_neteq_stats.h" #include "engine_configurations.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/test/testsupport/fileutils.h" // Enable this this flag to run this test with hard coded // IP/Port/codec and start test automatically with key input // it could be useful in repeat tests. //#define DEBUG +// #define EXTERNAL_TRANSPORT + using namespace webrtc; #define VALIDATE \ @@ -69,6 +70,29 @@ VoENetEqStats* neteqst = NULL; void RunTest(std::string out_path); +#ifdef EXTERNAL_TRANSPORT + +class my_transportation : public Transport +{ + int SendPacket(int channel,const void *data,int len); + int SendRTCPPacket(int channel, const void *data, int len); +}; + +int my_transportation::SendPacket(int channel,const void *data,int len) +{ + netw->ReceivedRTPPacket(channel, data, len); + return 0; +} + +int my_transportation::SendRTCPPacket(int channel, const void *data, int len) +{ + netw->ReceivedRTCPPacket(channel, data, len); + return 0; +} + +my_transportation my_transport; +#endif + class MyObserver : public VoiceEngineObserver { public: virtual void CallbackOnError(const int channel, const int err_code); @@ -246,24 +270,44 @@ void RunTest(std::string out_path) { cnt++; int j = 0; +#ifdef EXTERNAL_TRANSPORT + my_transportation ch0transport; + printf("Enabling external transport \n"); + netw->RegisterExternalTransport(0, ch0transport); +#else char ip[64]; #ifdef DEBUG strcpy(ip, "127.0.0.1"); #else + char localip[64]; + netw->GetLocalIP(localip); + printf("local IP:%s\n", localip); + printf("1. 127.0.0.1 \n"); printf("2. Specify IP \n"); ASSERT_EQ(1, scanf("%i", &i)); - if (1 == i) { + if (1 == i) strcpy(ip, "127.0.0.1"); - } else { + else { printf("Specify remote IP: "); ASSERT_EQ(1, scanf("%s", ip)); } #endif - int rPort = 8500; -#ifndef DEBUG + int colons(0); + while (ip[j] != '\0' && j < 64 && !(colons = (ip[j++] == ':'))) + ; + if (colons) { + printf("Enabling IPv6\n"); + res = netw->EnableIPv6(0); + VALIDATE; + } + + int rPort; +#ifdef DEBUG + rPort=8500; +#else printf("Specify remote port (1=1234): "); ASSERT_EQ(1, scanf("%i", &rPort)); if (1 == rPort) @@ -271,24 +315,23 @@ void RunTest(std::string out_path) { printf("Set Send port \n"); #endif - scoped_ptr voice_channel_transport( - new VoiceChannelTransport(netw, chan)); - printf("Set Send IP \n"); - res = voice_channel_transport->SetSendDestination(ip, rPort); + res = base1->SetSendDestination(chan, rPort, ip); VALIDATE; - int lPort = 8500; -#ifndef DEBUG + int lPort; +#ifdef DEBUG + lPort=8500; +#else printf("Specify local port (1=1234): "); ASSERT_EQ(1, scanf("%i", &lPort)); if (1 == lPort) lPort = 1234; printf("Set Rec Port \n"); #endif - - res = voice_channel_transport->SetLocalReceiver(lPort); + res = base1->SetLocalReceiver(chan, lPort); VALIDATE; +#endif printf("\n"); for (i = 0; i < codec->NumOfCodecs(); i++) { @@ -324,19 +367,12 @@ void RunTest(std::string out_path) { #endif int channel_index = 0; std::vector channels(kMaxNumChannels); - std::vector > voice_channel_transports; - for (i = 0; i < kMaxNumChannels; ++i) { channels[i] = base1->CreateChannel(); int port = rPort + (i + 1) * 2; - - voice_channel_transports[i].reset( - new VoiceChannelTransport(netw, channels[i])); - - printf("Set Send IP \n"); - res = voice_channel_transports[i]->SetSendDestination(ip, port); + res = base1->SetSendDestination(channels[i], port, ip); VALIDATE; - res = voice_channel_transports[i]->SetLocalReceiver(port); + res = base1->SetLocalReceiver(channels[i], port); VALIDATE; res = codec->SetSendCodec(channels[i], cinst); VALIDATE; diff --git a/webrtc/voice_engine/test/voice_engine_tests.gypi b/webrtc/voice_engine/test/voice_engine_tests.gypi index af6cb93289..d02ef08fc8 100644 --- a/webrtc/voice_engine/test/voice_engine_tests.gypi +++ b/webrtc/voice_engine/test/voice_engine_tests.gypi @@ -20,7 +20,6 @@ '<(DEPTH)/testing/gmock.gyp:gmock', '<(DEPTH)/third_party/google-gflags/google-gflags.gyp:google-gflags', '<(webrtc_root)/test/libtest/libtest.gyp:libtest', - '<(webrtc_root)/test/udp_transport.gyp:udp_transport', ], 'include_dirs': [ 'auto_test', @@ -60,6 +59,7 @@ 'auto_test/standard/mixing_test.cc', 'auto_test/standard/neteq_stats_test.cc', 'auto_test/standard/neteq_test.cc', + 'auto_test/standard/network_before_streaming_test.cc', 'auto_test/standard/network_test.cc', 'auto_test/standard/rtp_rtcp_before_streaming_test.cc', 'auto_test/standard/rtp_rtcp_test.cc', @@ -102,7 +102,6 @@ '<(DEPTH)/testing/gtest.gyp:gtest', 'voice_engine_core', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', - '<(webrtc_root)/test/udp_transport.gyp:udp_transport', ], 'sources': [ 'cmd_test/voe_cmd_test.cc', diff --git a/webrtc/voice_engine/voe_base_impl.cc b/webrtc/voice_engine/voe_base_impl.cc index 7446c2249a..864b6da369 100644 --- a/webrtc/voice_engine/voe_base_impl.cc +++ b/webrtc/voice_engine/voe_base_impl.cc @@ -683,9 +683,265 @@ int VoEBaseImpl::DeleteChannel(int channel) { return -1; } + return 0; } +int VoEBaseImpl::SetLocalReceiver(int channel, int port, int RTCPport, + const char ipAddr[64], + const char multiCastAddr[64]) +{ + // Inititialize local receive sockets (RTP and RTCP). + // + // The sockets are always first closed and then created again by this + // function call. The created sockets are by default also used for + // transmission (unless source port is set in SetSendDestination). + // + // Note that, sockets can also be created automatically if a user calls + // SetSendDestination and StartSend without having called SetLocalReceiver + // first. The sockets are then created at the first packet transmission. + + CriticalSectionScoped cs(_shared->crit_sec()); + if (ipAddr == NULL && multiCastAddr == NULL) + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d)", + channel, port, RTCPport); + } + else if (ipAddr != NULL && multiCastAddr == NULL) + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d, ipAddr=%s)", + channel, port, RTCPport, ipAddr); + } + else if (ipAddr == NULL && multiCastAddr != NULL) + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d, " + "multiCastAddr=%s)", channel, port, RTCPport, multiCastAddr); + } + else + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d, " + "ipAddr=%s, multiCastAddr=%s)", channel, port, RTCPport, ipAddr, + multiCastAddr); + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if ((port < 0) || (port > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetLocalReceiver() invalid RTP port"); + return -1; + } + if (((RTCPport != kVoEDefault) && (RTCPport < 0)) || ((RTCPport + != kVoEDefault) && (RTCPport > 65535))) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetLocalReceiver() invalid RTCP port"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetLocalReceiver() failed to locate channel"); + return -1; + } + + // Cast RTCP port. In the RTP module 0 corresponds to RTP port + 1 in + // the module, which is the default. + WebRtc_UWord16 rtcpPortUW16(0); + if (RTCPport != kVoEDefault) + { + rtcpPortUW16 = static_cast (RTCPport); + } + + return channelPtr->SetLocalReceiver(port, rtcpPortUW16, ipAddr, + multiCastAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, + kTraceWarning, "SetLocalReceiver() VoE is built for external " + "transport"); + return -1; +#endif +} + +int VoEBaseImpl::GetLocalReceiver(int channel, int& port, int& RTCPport, + char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetLocalReceiver(channel=%d, ipAddr[]=?)", channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetLocalReceiver() failed to locate channel"); + return -1; + } + WebRtc_Word32 ret = channelPtr->GetLocalReceiver(port, RTCPport, ipAddr); + if (ipAddr != NULL) + { + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetLocalReceiver() => port=%d, RTCPport=%d, ipAddr=%s", + port, RTCPport, ipAddr); + } + else + { + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetLocalReceiver() => port=%d, RTCPport=%d", port, RTCPport); + } + return ret; +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetLocalReceiver() VoE is built for external transport"); + return -1; +#endif +} + +int VoEBaseImpl::SetSendDestination(int channel, int port, const char* ipaddr, + int sourcePort, int RTCPport) +{ + WEBRTC_TRACE( + kTraceApiCall, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetSendDestination(channel=%d, port=%d, ipaddr=%s," + "sourcePort=%d, RTCPport=%d)", + channel, port, ipaddr, sourcePort, RTCPport); + CriticalSectionScoped cs(_shared->crit_sec()); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSendDestination() failed to locate channel"); + return -1; + } + if ((port < 0) || (port > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSendDestination() invalid RTP port"); + return -1; + } + if (((RTCPport != kVoEDefault) && (RTCPport < 0)) || ((RTCPport + != kVoEDefault) && (RTCPport > 65535))) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSendDestination() invalid RTCP port"); + return -1; + } + if (((sourcePort != kVoEDefault) && (sourcePort < 0)) || ((sourcePort + != kVoEDefault) && (sourcePort > 65535))) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSendDestination() invalid source port"); + return -1; + } + + // Cast RTCP port. In the RTP module 0 corresponds to RTP port + 1 in the + // module, which is the default. + WebRtc_UWord16 rtcpPortUW16(0); + if (RTCPport != kVoEDefault) + { + rtcpPortUW16 = static_cast (RTCPport); + WEBRTC_TRACE( + kTraceInfo, + kTraceVoice, + VoEId(_shared->instance_id(), channel), + "SetSendDestination() non default RTCP port %u will be " + "utilized", + rtcpPortUW16); + } + + return channelPtr->SetSendDestination(port, ipaddr, sourcePort, + rtcpPortUW16); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSendDestination() VoE is built for external transport"); + return -1; +#endif +} + +int VoEBaseImpl::GetSendDestination(int channel, int& port, char ipAddr[64], + int& sourcePort, int& RTCPport) +{ + WEBRTC_TRACE( + kTraceApiCall, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetSendDestination(channel=%d, ipAddr[]=?, sourcePort=?," + "RTCPport=?)", + channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSendDestination() failed to locate channel"); + return -1; + } + WebRtc_Word32 ret = channelPtr->GetSendDestination(port, ipAddr, + sourcePort, RTCPport); + if (ipAddr != NULL) + { + WEBRTC_TRACE( + kTraceStateInfo, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetSendDestination() => port=%d, RTCPport=%d, ipAddr=%s, " + "sourcePort=%d, RTCPport=%d", + port, RTCPport, ipAddr, sourcePort, RTCPport); + } + else + { + WEBRTC_TRACE( + kTraceStateInfo, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetSendDestination() => port=%d, RTCPport=%d, " + "sourcePort=%d, RTCPport=%d", + port, RTCPport, sourcePort, RTCPport); + } + return ret; +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSendDestination() VoE is built for external transport"); + return -1; +#endif +} + int VoEBaseImpl::StartReceive(int channel) { WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), @@ -808,6 +1064,15 @@ int VoEBaseImpl::StartSend(int channel) { return 0; } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!channelPtr->ExternalTransport() + && !channelPtr->SendSocketsInitialized()) + { + _shared->SetLastError(VE_DESTINATION_NOT_INITED, kTraceError, + "StartSend() must set send destination first"); + return -1; + } +#endif if (StartSend() != 0) { _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, @@ -880,6 +1145,16 @@ int VoEBaseImpl::GetVersion(char version[1024]) accLen += len; assert(accLen < kVoiceEngineVersionMaxMessageSize); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + len = AddExternalTransportBuild(versionPtr); + if (len == -1) + { + return -1; + } + versionPtr += len; + accLen += len; + assert(accLen < kVoiceEngineVersionMaxMessageSize); +#endif #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT len = AddExternalRecAndPlayoutBuild(versionPtr); if (len == -1) @@ -932,6 +1207,13 @@ WebRtc_Word32 VoEBaseImpl::AddVoEVersion(char* str) const return sprintf(str, "VoiceEngine 4.1.0\n"); } +#ifdef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 VoEBaseImpl::AddExternalTransportBuild(char* str) const +{ + return sprintf(str, "External transport build\n"); +} +#endif + #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT WebRtc_Word32 VoEBaseImpl::AddExternalRecAndPlayoutBuild(char* str) const { diff --git a/webrtc/voice_engine/voe_base_impl.h b/webrtc/voice_engine/voe_base_impl.h index 92f1539d5a..17c6ed3d21 100644 --- a/webrtc/voice_engine/voe_base_impl.h +++ b/webrtc/voice_engine/voe_base_impl.h @@ -44,6 +44,25 @@ public: virtual int DeleteChannel(int channel); + virtual int SetLocalReceiver(int channel, int port, + int RTCPport = kVoEDefault, + const char ipAddr[64] = NULL, + const char multiCastAddr[64] = NULL); + + virtual int GetLocalReceiver(int channel, int& port, int& RTCPport, + char ipAddr[64]); + + virtual int SetSendDestination(int channel, int port, + const char ipAddr[64], + int sourcePort = kVoEDefault, + int RTCPport = kVoEDefault); + + virtual int GetSendDestination(int channel, + int& port, + char ipAddr[64], + int& sourcePort, + int& RTCPport); + virtual int StartReceive(int channel); virtual int StartPlayout(int channel); @@ -106,6 +125,9 @@ private: WebRtc_Word32 AddBuildInfo(char* str) const; WebRtc_Word32 AddVoEVersion(char* str) const; +#ifdef WEBRTC_EXTERNAL_TRANSPORT + WebRtc_Word32 AddExternalTransportBuild(char* str) const; +#endif #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT WebRtc_Word32 AddExternalRecAndPlayoutBuild(char* str) const; #endif @@ -117,6 +139,7 @@ private: WebRtc_UWord32 _oldMicLevel; AudioFrame _audioFrame; voe::SharedData* _shared; + }; } // namespace webrtc diff --git a/webrtc/voice_engine/voe_network_impl.cc b/webrtc/voice_engine/voe_network_impl.cc index 6c4cfc2bee..c5639008ac 100644 --- a/webrtc/voice_engine/voe_network_impl.cc +++ b/webrtc/voice_engine/voe_network_impl.cc @@ -170,6 +170,504 @@ int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data, return channelPtr->ReceivedRTCPPacket((const WebRtc_Word8*) data, length); } +int VoENetworkImpl::GetSourceInfo(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSourceInfo(channel=%d, rtpPort=?, rtcpPort=?, ipAddr[]=?)", + channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == ipAddr) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetSourceInfo() invalid IP-address buffer"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSourceInfo() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSourceInfo() external transport is enabled"); + return -1; + } + return channelPtr->GetSourceInfo(rtpPort, rtcpPort, ipAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSourceInfo() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetLocalIP(char ipAddr[64], bool ipv6) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetLocalIP(ipAddr[]=?, ipv6=%d)", ipv6); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == ipAddr) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetLocalIP() invalid IP-address buffer"); + return -1; + } + + // Create a temporary socket module to ensure that this method can be + // called also when no channels are created. + WebRtc_UWord8 numSockThreads(1); + UdpTransport* socketPtr = + UdpTransport::Create( + -1, + numSockThreads); + if (NULL == socketPtr) + { + _shared->SetLastError(VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetLocalIP() failed to create socket module"); + return -1; + } + + // Use a buffer big enough for IPv6 addresses and initialize it with zeros. + char localIPAddr[256] = {0}; + + if (ipv6) + { + char localIP[16]; + if (socketPtr->LocalHostAddressIPV6(localIP) != 0) + { + _shared->SetLastError(VE_INVALID_IP_ADDRESS, kTraceError, + "GetLocalIP() failed to retrieve local IP - 1"); + UdpTransport::Destroy(socketPtr); + return -1; + } + // Convert 128-bit address to character string (a:b:c:d:e:f:g:h) + sprintf(localIPAddr, + "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x" + "%.2x:%.2x%.2x", + localIP[0], localIP[1], localIP[2], localIP[3], localIP[4], + localIP[5], localIP[6], localIP[7], localIP[8], localIP[9], + localIP[10], localIP[11], localIP[12], localIP[13], + localIP[14], localIP[15]); + } + else + { + WebRtc_UWord32 localIP(0); + // Read local IP (as 32-bit address) from the socket module + if (socketPtr->LocalHostAddress(localIP) != 0) + { + _shared->SetLastError(VE_INVALID_IP_ADDRESS, kTraceError, + "GetLocalIP() failed to retrieve local IP - 2"); + UdpTransport::Destroy(socketPtr); + return -1; + } + // Convert 32-bit address to character string (x.y.z.w) + sprintf(localIPAddr, "%d.%d.%d.%d", (int) ((localIP >> 24) & 0x0ff), + (int) ((localIP >> 16) & 0x0ff), + (int) ((localIP >> 8) & 0x0ff), + (int) (localIP & 0x0ff)); + } + + strcpy(ipAddr, localIPAddr); + + UdpTransport::Destroy(socketPtr); + + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetLocalIP() => ipAddr=%s", ipAddr); + return 0; +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetLocalIP() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::EnableIPv6(int channel) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "EnableIPv6(channel=%d)", channel); + ANDROID_NOT_SUPPORTED(_shared->statistics()); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "EnableIPv6() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "EnableIPv6() external transport is enabled"); + return -1; + } + return channelPtr->EnableIPv6(); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "EnableIPv6() VoE is built for external transport"); + return -1; +#endif +} + +bool VoENetworkImpl::IPv6IsEnabled(int channel) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "IPv6IsEnabled(channel=%d)", channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return false; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "IPv6IsEnabled() failed to locate channel"); + return false; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "IPv6IsEnabled() external transport is enabled"); + return false; + } + return channelPtr->IPv6IsEnabled(); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "IPv6IsEnabled() VoE is built for external transport"); + return false; +#endif +} + +int VoENetworkImpl::SetSourceFilter(int channel, + int rtpPort, + int rtcpPort, + const char ipAddr[64]) +{ + (ipAddr == NULL) ? WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetSourceFilter(channel=%d, rtpPort=%d," + " rtcpPort=%d)", + channel, rtpPort, rtcpPort) + : WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetSourceFilter(channel=%d, rtpPort=%d," + " rtcpPort=%d, ipAddr=%s)", + channel, rtpPort, rtcpPort, ipAddr); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if ((rtpPort < 0) || (rtpPort > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSourceFilter() invalid RTP port"); + return -1; + } + if ((rtcpPort < 0) || (rtcpPort > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSourceFilter() invalid RTCP port"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSourceFilter() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSourceFilter() external transport is enabled"); + return -1; + } + return channelPtr->SetSourceFilter(rtpPort, rtcpPort, ipAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSourceFilter() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetSourceFilter(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSourceFilter(channel=%d, rtpPort=?, rtcpPort=?, " + "ipAddr[]=?)", + channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == ipAddr) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetSourceFilter() invalid IP-address buffer"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSourceFilter() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSourceFilter() external transport is enabled"); + return -1; + } + return channelPtr->GetSourceFilter(rtpPort, rtcpPort, ipAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSourceFilter() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::SetSendTOS(int channel, + int DSCP, + int priority, + bool useSetSockopt) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SetSendTOS(channel=%d, DSCP=%d, useSetSockopt=%d)", + channel, DSCP, useSetSockopt); + +#if !defined(_WIN32) && !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "SetSendTOS() is not supported on this platform"); + return -1; +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if ((DSCP < 0) || (DSCP > 63)) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() Invalid DSCP value"); + return -1; + } +#if defined(_WIN32) || defined(WEBRTC_LINUX) + if ((priority < -1) || (priority > 7)) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() Invalid priority value"); + return -1; + } +#else + if (-1 != priority) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() priority not supported"); + return -1; + } +#endif +#if defined(_WIN32) + if ((priority >= 0) && useSetSockopt) + { + // On Windows, priority and useSetSockopt cannot be combined + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() priority and useSetSockopt conflict"); + return -1; + } +#endif + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSendTOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSendTOS() external transport is enabled"); + return -1; + } +#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) + useSetSockopt = true; + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1), + " force useSetSockopt=true since there is no alternative" + " implementation"); +#endif + + return channelPtr->SetSendTOS(DSCP, priority, useSetSockopt); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSendTOS() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetSendTOS(int channel, + int& DSCP, + int& priority, + bool& useSetSockopt) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSendTOS(channel=%d)", channel); + +#if !defined(_WIN32) && !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "GetSendTOS() is not supported on this platform"); + return -1; +#endif +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSendTOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSendTOS() external transport is enabled"); + return -1; + } + return channelPtr->GetSendTOS(DSCP, priority, useSetSockopt); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSendTOS() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::SetSendGQoS(int channel, + bool enable, + int serviceType, + int overrideDSCP) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SetSendGQOS(channel=%d, enable=%d, serviceType=%d," + " overrideDSCP=%d)", + channel, (int) enable, serviceType, overrideDSCP); + ANDROID_NOT_SUPPORTED(_shared->statistics()); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#if !defined(_WIN32) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "SetSendGQOS() is not supported on this platform"); + return -1; +#elif !defined(WEBRTC_EXTERNAL_TRANSPORT) + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSendGQOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSendGQOS() external transport is enabled"); + return -1; + } + return channelPtr->SetSendGQoS(enable, serviceType, overrideDSCP); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSendGQOS() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetSendGQoS(int channel, + bool& enabled, + int& serviceType, + int& overrideDSCP) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSendGQOS(channel=%d)", channel); + ANDROID_NOT_SUPPORTED(_shared->statistics()); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#if !defined(_WIN32) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "GetSendGQOS() is not supported on this platform"); + return -1; +#elif !defined(WEBRTC_EXTERNAL_TRANSPORT) + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSendGQOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSendGQOS() external transport is enabled"); + return -1; + } + return channelPtr->GetSendGQoS(enabled, serviceType, overrideDSCP); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSendGQOS() VoE is built for external transport"); + return -1; +#endif +} + int VoENetworkImpl::SetPacketTimeoutNotification(int channel, bool enable, int timeoutSeconds) @@ -323,6 +821,52 @@ int VoENetworkImpl::GetPeriodicDeadOrAliveStatus(int channel, sampleTimeSeconds); } +int VoENetworkImpl::SendUDPPacket(int channel, + const void* data, + unsigned int length, + int& transmittedBytes, + bool useRtcpSocket) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SendUDPPacket(channel=%d, data=0x%x, length=%u, useRTCP=%d)", + channel, data, length, useRtcpSocket); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == data) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SendUDPPacket() invalid data buffer"); + return -1; + } + if (0 == length) + { + _shared->SetLastError(VE_INVALID_PACKET, kTraceError, + "SendUDPPacket() invalid packet size"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SendUDPPacket() failed to locate channel"); + return -1; + } + return channelPtr->SendUDPPacket(data, + length, + transmittedBytes, + useRtcpSocket); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SendUDPPacket() VoE is built for external transport"); + return -1; +#endif +} + #endif // WEBRTC_VOICE_ENGINE_NETWORK_API } // namespace webrtc diff --git a/webrtc/voice_engine/voe_network_impl.h b/webrtc/voice_engine/voe_network_impl.h index 4dbe4f3231..b159c81b5a 100644 --- a/webrtc/voice_engine/voe_network_impl.h +++ b/webrtc/voice_engine/voe_network_impl.h @@ -34,6 +34,47 @@ public: const void* data, unsigned int length); + virtual int GetSourceInfo(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]); + + virtual int GetLocalIP(char ipAddr[64], bool ipv6 = false); + + virtual int EnableIPv6(int channel); + + virtual bool IPv6IsEnabled(int channel); + + virtual int SetSourceFilter(int channel, + int rtpPort, + int rtcpPort, + const char ipAddr[64] = 0); + + virtual int GetSourceFilter(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]); + + virtual int SetSendTOS(int channel, + int DSCP, + int priority = -1, + bool useSetSockopt = false); + + virtual int GetSendTOS(int channel, + int& DSCP, + int& priority, + bool& useSetSockopt); + + virtual int SetSendGQoS(int channel, + bool enable, + int serviceType, + int overrideDSCP); + + virtual int GetSendGQoS(int channel, + bool& enabled, + int& serviceType, + int& overrideDSCP); + virtual int SetPacketTimeoutNotification(int channel, bool enable, int timeoutSeconds = 2); @@ -55,6 +96,12 @@ public: bool& enabled, int& sampleTimeSeconds); + virtual int SendUDPPacket(int channel, + const void* data, + unsigned int length, + int& transmittedBytes, + bool useRtcpSocket = false); + protected: VoENetworkImpl(voe::SharedData* shared); virtual ~VoENetworkImpl(); diff --git a/webrtc/voice_engine/voice_engine_core.gypi b/webrtc/voice_engine/voice_engine_core.gypi index 21bfca41e0..1c28c0d4a1 100644 --- a/webrtc/voice_engine/voice_engine_core.gypi +++ b/webrtc/voice_engine/voice_engine_core.gypi @@ -20,6 +20,7 @@ '<(webrtc_root)/modules/modules.gyp:audio_processing', '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', + '<(webrtc_root)/modules/modules.gyp:udp_transport', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', ], @@ -133,6 +134,7 @@ '<(webrtc_root)/modules/modules.gyp:audio_conference_mixer', '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', + '<(webrtc_root)/modules/modules.gyp:udp_transport', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', ],