Merge branch 'master' into feature/chainable-rtcp-handlers
# Conflicts: # src/h264packetizationhandler.cpp
2
.gitignore
vendored
@ -5,7 +5,7 @@ node_modules/
|
|||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
tests
|
/tests
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
project(libdatachannel
|
project(libdatachannel
|
||||||
VERSION 0.11.0
|
VERSION 0.11.1
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
set(PROJECT_DESCRIPTION "WebRTC Data Channels Library")
|
set(PROJECT_DESCRIPTION "WebRTC Data Channels Library")
|
||||||
|
|
||||||
@ -135,6 +135,24 @@ set(TESTS_SOURCES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(TESTS_UWP_RESOURCES
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/Logo.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/package.appxManifest
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/SmallLogo.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/SmallLogo44x44.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/SplashScreen.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/StoreLogo.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/tests/Windows_TemporaryKey.pfx)
|
||||||
|
|
||||||
|
set(BENCHMARK_UWP_RESOURCES
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/Logo.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/package.appxManifest
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/SmallLogo.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/SmallLogo44x44.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/SplashScreen.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/StoreLogo.png
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test/uwp/benchmark/Windows_TemporaryKey.pfx)
|
||||||
|
|
||||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
@ -292,24 +310,30 @@ endif()
|
|||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
if(NOT NO_TESTS)
|
if(NOT NO_TESTS)
|
||||||
add_executable(datachannel-tests ${TESTS_SOURCES})
|
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
|
||||||
|
# Add resource files needed for UWP apps.
|
||||||
|
add_executable(datachannel-tests ${TESTS_SOURCES} ${TESTS_UWP_RESOURCES})
|
||||||
|
else()
|
||||||
|
add_executable(datachannel-tests ${TESTS_SOURCES})
|
||||||
|
endif()
|
||||||
set_target_properties(datachannel-tests PROPERTIES
|
set_target_properties(datachannel-tests PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
CXX_STANDARD 17)
|
CXX_STANDARD 17)
|
||||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") # Prevent a bug in manifest generation for UWP
|
set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
|
||||||
set_target_properties(datachannel-tests PROPERTIES OUTPUT_NAME tests)
|
|
||||||
endif()
|
|
||||||
target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(datachannel-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
target_link_libraries(datachannel-tests datachannel)
|
target_link_libraries(datachannel-tests datachannel)
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
add_executable(datachannel-benchmark test/benchmark.cpp)
|
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
|
||||||
|
# Add resource files needed for UWP apps.
|
||||||
|
add_executable(datachannel-benchmark test/benchmark.cpp ${BENCHMARK_UWP_RESOURCES})
|
||||||
|
else()
|
||||||
|
add_executable(datachannel-benchmark test/benchmark.cpp)
|
||||||
|
endif()
|
||||||
set_target_properties(datachannel-benchmark PROPERTIES
|
set_target_properties(datachannel-benchmark PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
CXX_STANDARD 17)
|
CXX_STANDARD 17)
|
||||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") # Prevent a bug in manifest generation for UWP
|
set_target_properties(datachannel-benchmark PROPERTIES OUTPUT_NAME benchmark)
|
||||||
set_target_properties(datachannel-benchmark PROPERTIES OUTPUT_NAME benchmark)
|
|
||||||
endif()
|
|
||||||
target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
|
target_compile_definitions(datachannel-benchmark PRIVATE BENCHMARK_MAIN=1)
|
||||||
target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(datachannel-benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
target_link_libraries(datachannel-benchmark datachannel)
|
target_link_libraries(datachannel-benchmark datachannel)
|
||||||
|
@ -54,12 +54,10 @@ function createPeerConnection() {
|
|||||||
|
|
||||||
// connect audio / video
|
// connect audio / video
|
||||||
pc.addEventListener('track', function (evt) {
|
pc.addEventListener('track', function (evt) {
|
||||||
if (evt.track.kind == 'video') {
|
document.getElementById('media').style.display = 'block';
|
||||||
document.getElementById('media').style.display = 'block';
|
const videoTag = document.getElementById('video');
|
||||||
document.getElementById('video').srcObject = evt.streams[0];
|
videoTag.srcObject = evt.streams[0];
|
||||||
} else {
|
videoTag.play();
|
||||||
document.getElementById('audio').srcObject = evt.streams[0];
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let time_start = null;
|
let time_start = null;
|
||||||
|
@ -52,7 +52,6 @@
|
|||||||
|
|
||||||
<div id="media" style="display: none">
|
<div id="media" style="display: none">
|
||||||
<h2>Media</h2>
|
<h2>Media</h2>
|
||||||
<audio id="audio" autoplay></audio>
|
|
||||||
<video id="video" autoplay playsinline></video>
|
<video id="video" autoplay playsinline></video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ int main(int argc, char **argv) try {
|
|||||||
shared_ptr<ClientTrackData> addVideo(const shared_ptr<PeerConnection> pc, const uint8_t payloadType, const uint32_t ssrc, const string cname, const string msid, const function<void (void)> onOpen) {
|
shared_ptr<ClientTrackData> addVideo(const shared_ptr<PeerConnection> pc, const uint8_t payloadType, const uint32_t ssrc, const string cname, const string msid, const function<void (void)> onOpen) {
|
||||||
auto video = Description::Video(cname);
|
auto video = Description::Video(cname);
|
||||||
video.addH264Codec(payloadType);
|
video.addH264Codec(payloadType);
|
||||||
video.addSSRC(ssrc, cname, msid);
|
video.addSSRC(ssrc, cname, msid, cname);
|
||||||
auto track = pc->addTrack(video);
|
auto track = pc->addTrack(video);
|
||||||
// create RTP configuration
|
// create RTP configuration
|
||||||
auto rtpConfig = shared_ptr<RtpPacketizationConfig>(new RtpPacketizationConfig(ssrc, cname, payloadType, H264RtpPacketizer::defaultClockRate));
|
auto rtpConfig = shared_ptr<RtpPacketizationConfig>(new RtpPacketizationConfig(ssrc, cname, payloadType, H264RtpPacketizer::defaultClockRate));
|
||||||
@ -238,7 +238,7 @@ shared_ptr<ClientTrackData> addVideo(const shared_ptr<PeerConnection> pc, const
|
|||||||
shared_ptr<ClientTrackData> addAudio(const shared_ptr<PeerConnection> pc, const uint8_t payloadType, const uint32_t ssrc, const string cname, const string msid, const function<void (void)> onOpen) {
|
shared_ptr<ClientTrackData> addAudio(const shared_ptr<PeerConnection> pc, const uint8_t payloadType, const uint32_t ssrc, const string cname, const string msid, const function<void (void)> onOpen) {
|
||||||
auto audio = Description::Audio(cname);
|
auto audio = Description::Audio(cname);
|
||||||
audio.addOpusCodec(payloadType);
|
audio.addOpusCodec(payloadType);
|
||||||
audio.addSSRC(ssrc, cname, msid);
|
audio.addSSRC(ssrc, cname, msid, cname);
|
||||||
auto track = pc->addTrack(audio);
|
auto track = pc->addTrack(audio);
|
||||||
// create RTP configuration
|
// create RTP configuration
|
||||||
auto rtpConfig = shared_ptr<RtpPacketizationConfig>(new RtpPacketizationConfig(ssrc, cname, payloadType, OpusRtpPacketizer::defaultClockRate));
|
auto rtpConfig = shared_ptr<RtpPacketizationConfig>(new RtpPacketizationConfig(ssrc, cname, payloadType, OpusRtpPacketizer::defaultClockRate));
|
||||||
|
@ -44,7 +44,7 @@ struct RTC_CPP_EXPORT IceServer {
|
|||||||
RelayType relayType_ = RelayType::TurnUdp);
|
RelayType relayType_ = RelayType::TurnUdp);
|
||||||
|
|
||||||
string hostname;
|
string hostname;
|
||||||
string service;
|
uint16_t port;
|
||||||
Type type;
|
Type type;
|
||||||
string username;
|
string username;
|
||||||
string password;
|
string password;
|
||||||
@ -54,11 +54,11 @@ struct RTC_CPP_EXPORT IceServer {
|
|||||||
struct RTC_CPP_EXPORT ProxyServer {
|
struct RTC_CPP_EXPORT ProxyServer {
|
||||||
enum class Type { None = 0, Socks5, Http, Last = Http };
|
enum class Type { None = 0, Socks5, Http, Last = Http };
|
||||||
|
|
||||||
ProxyServer(Type type_, string ip_, uint16_t port_, string username_ = "",
|
ProxyServer(Type type_, string hostname_, uint16_t port_, string username_ = "",
|
||||||
string password_ = "");
|
string password_ = "");
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
string ip;
|
string hostname;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
string username;
|
string username;
|
||||||
string password;
|
string password;
|
||||||
|
@ -141,9 +141,9 @@ public:
|
|||||||
void removeFormat(const string &fmt);
|
void removeFormat(const string &fmt);
|
||||||
|
|
||||||
void addSSRC(uint32_t ssrc, std::optional<string> name,
|
void addSSRC(uint32_t ssrc, std::optional<string> name,
|
||||||
std::optional<string> msid = nullopt);
|
std::optional<string> msid = nullopt, std::optional<string> trackID = nullopt);
|
||||||
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<string> name,
|
void replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<string> name,
|
||||||
std::optional<string> msid = nullopt);
|
std::optional<string> msid = nullopt, std::optional<string> trackID = nullopt);
|
||||||
bool hasSSRC(uint32_t ssrc);
|
bool hasSSRC(uint32_t ssrc);
|
||||||
std::vector<uint32_t> getSSRCs();
|
std::vector<uint32_t> getSSRCs();
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef H264RtpPacketizer_hpp
|
#ifndef H264_RTP_PACKETIZER_H
|
||||||
#define H264RtpPacketizer_hpp
|
#define H264_RTP_PACKETIZER_H
|
||||||
|
|
||||||
#if RTC_ENABLE_MEDIA
|
#if RTC_ENABLE_MEDIA
|
||||||
|
|
||||||
@ -64,4 +64,4 @@ private:
|
|||||||
|
|
||||||
#endif /* RTC_ENABLE_MEDIA */
|
#endif /* RTC_ENABLE_MEDIA */
|
||||||
|
|
||||||
#endif /* H264RtpPacketizer_hpp */
|
#endif /* H264_RTP_PACKETIZER_H */
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NalUnit_hpp
|
#ifndef NAL_UNIT_H
|
||||||
#define NalUnit_hpp
|
#define NAL_UNIT_H
|
||||||
|
|
||||||
#if RTC_ENABLE_MEDIA
|
#if RTC_ENABLE_MEDIA
|
||||||
|
|
||||||
@ -152,4 +152,4 @@ public:
|
|||||||
|
|
||||||
#endif /* RTC_ENABLE_MEDIA */
|
#endif /* RTC_ENABLE_MEDIA */
|
||||||
|
|
||||||
#endif /* NalUnit_hpp */
|
#endif /* NAL_UNIT_H */
|
||||||
|
@ -216,8 +216,9 @@ RTC_EXPORT int rtcGetTrackDescription(int tr, char *buffer, int size);
|
|||||||
/// @param _direction Direction
|
/// @param _direction Direction
|
||||||
/// @param _name Name (optional)
|
/// @param _name Name (optional)
|
||||||
/// @param _msid MSID (optional)
|
/// @param _msid MSID (optional)
|
||||||
|
/// @param _trackID Track ID used in MSID (optional)
|
||||||
/// @returns Track id
|
/// @returns Track id
|
||||||
RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid, rtcDirection direction, const char *_name, const char *_msid);
|
RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid, rtcDirection direction, const char *_name, const char *_msid, const char *_trackID);
|
||||||
|
|
||||||
/// Set H264PacketizationHandler for track
|
/// Set H264PacketizationHandler for track
|
||||||
/// @param tr Track id
|
/// @param tr Track id
|
||||||
|
@ -167,9 +167,12 @@ bool Candidate::resolve(ResolveMode mode) {
|
|||||||
if (getnameinfo(p->ai_addr, socklen_t(p->ai_addrlen), nodebuffer,
|
if (getnameinfo(p->ai_addr, socklen_t(p->ai_addrlen), nodebuffer,
|
||||||
MAX_NUMERICNODE_LEN, servbuffer, MAX_NUMERICSERV_LEN,
|
MAX_NUMERICNODE_LEN, servbuffer, MAX_NUMERICSERV_LEN,
|
||||||
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
||||||
|
try {
|
||||||
|
mPort = uint16_t(std::stoul(servbuffer));
|
||||||
|
} catch (...) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
mAddress = nodebuffer;
|
mAddress = nodebuffer;
|
||||||
mPort = uint16_t(std::stoul(servbuffer));
|
|
||||||
mFamily = p->ai_family == AF_INET6 ? Family::Ipv6 : Family::Ipv4;
|
mFamily = p->ai_family == AF_INET6 ? Family::Ipv6 : Family::Ipv4;
|
||||||
PLOG_VERBOSE << "Resolved candidate: " << mAddress << ' ' << mPort;
|
PLOG_VERBOSE << "Resolved candidate: " << mAddress << ' ' << mPort;
|
||||||
break;
|
break;
|
||||||
|
13
src/capi.cpp
@ -453,7 +453,7 @@ int rtcDeleteDataChannel(int dc) {
|
|||||||
|
|
||||||
#if RTC_ENABLE_MEDIA
|
#if RTC_ENABLE_MEDIA
|
||||||
|
|
||||||
void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid) {
|
void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid, const char *_trackID) {
|
||||||
|
|
||||||
optional<string> name = nullopt;
|
optional<string> name = nullopt;
|
||||||
if (_name) {
|
if (_name) {
|
||||||
@ -465,11 +465,16 @@ void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name,
|
|||||||
msid = string(_msid);
|
msid = string(_msid);
|
||||||
}
|
}
|
||||||
|
|
||||||
description->addSSRC(ssrc, name, msid);
|
optional<string> trackID = nullopt;
|
||||||
|
if (_trackID) {
|
||||||
|
trackID = string(_trackID);
|
||||||
|
}
|
||||||
|
|
||||||
|
description->addSSRC(ssrc, name, msid, trackID);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid,
|
int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid,
|
||||||
rtcDirection _direction, const char *_name, const char *_msid) {
|
rtcDirection _direction, const char *_name, const char *_msid, const char *_trackID) {
|
||||||
return WRAP({
|
return WRAP({
|
||||||
auto peerConnection = getPeerConnection(pc);
|
auto peerConnection = getPeerConnection(pc);
|
||||||
|
|
||||||
@ -534,7 +539,7 @@ int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const
|
|||||||
throw std::invalid_argument("Unexpected codec");
|
throw std::invalid_argument("Unexpected codec");
|
||||||
} else {
|
} else {
|
||||||
auto description = optDescription.value();
|
auto description = optDescription.value();
|
||||||
setSSRC(&description, ssrc, _name, _msid);
|
setSSRC(&description, ssrc, _name, _msid, _trackID);
|
||||||
|
|
||||||
int tr = emplaceTrack(peerConnection->addTrack(std::move(description)));
|
int tr = emplaceTrack(peerConnection->addTrack(std::move(description)));
|
||||||
if (auto ptr = getUserPointer(pc)) {
|
if (auto ptr = getUserPointer(pc)) {
|
||||||
|
@ -60,32 +60,51 @@ IceServer::IceServer(const string &url) {
|
|||||||
|
|
||||||
username = opt[6].value_or("");
|
username = opt[6].value_or("");
|
||||||
password = opt[8].value_or("");
|
password = opt[8].value_or("");
|
||||||
hostname = opt[10].value();
|
|
||||||
service = opt[12].value_or(relayType == RelayType::TurnTls ? "5349" : "3478");
|
|
||||||
|
|
||||||
|
hostname = opt[10].value();
|
||||||
while (!hostname.empty() && hostname.front() == '[')
|
while (!hostname.empty() && hostname.front() == '[')
|
||||||
hostname.erase(hostname.begin());
|
hostname.erase(hostname.begin());
|
||||||
while (!hostname.empty() && hostname.back() == ']')
|
while (!hostname.empty() && hostname.back() == ']')
|
||||||
hostname.pop_back();
|
hostname.pop_back();
|
||||||
|
|
||||||
|
string service = opt[12].value_or(relayType == RelayType::TurnTls ? "5349" : "3478");
|
||||||
|
try {
|
||||||
|
port = uint16_t(std::stoul(service));
|
||||||
|
} catch (...) {
|
||||||
|
throw std::invalid_argument("Invalid ICE server port in URL: " + service);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IceServer::IceServer(string hostname_, uint16_t port_)
|
IceServer::IceServer(string hostname_, uint16_t port_)
|
||||||
: IceServer(std::move(hostname_), std::to_string(port_)) {}
|
: hostname(std::move(hostname_)), port(port_), type(Type::Stun) {}
|
||||||
|
|
||||||
IceServer::IceServer(string hostname_, string service_)
|
IceServer::IceServer(string hostname_, string service_)
|
||||||
: hostname(std::move(hostname_)), service(std::move(service_)), type(Type::Stun) {}
|
: hostname(std::move(hostname_)), type(Type::Stun) {
|
||||||
|
try {
|
||||||
|
port = uint16_t(std::stoul(service_));
|
||||||
|
} catch (...) {
|
||||||
|
throw std::invalid_argument("Invalid ICE server port: " + service_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IceServer::IceServer(string hostname_, uint16_t port_, string username_, string password_,
|
IceServer::IceServer(string hostname_, uint16_t port_, string username_, string password_,
|
||||||
RelayType relayType_)
|
RelayType relayType_)
|
||||||
: IceServer(hostname_, std::to_string(port_), std::move(username_), std::move(password_),
|
: hostname(std::move(hostname_)), port(port_), type(Type::Turn), username(std::move(username_)),
|
||||||
relayType_) {}
|
password(std::move(password_)), relayType(relayType_) {}
|
||||||
|
|
||||||
IceServer::IceServer(string hostname_, string service_, string username_, string password_,
|
IceServer::IceServer(string hostname_, string service_, string username_, string password_,
|
||||||
RelayType relayType_)
|
RelayType relayType_)
|
||||||
: hostname(std::move(hostname_)), service(std::move(service_)), type(Type::Turn),
|
: hostname(std::move(hostname_)), type(Type::Turn), username(std::move(username_)),
|
||||||
username(std::move(username_)), password(std::move(password_)), relayType(relayType_) {}
|
password(std::move(password_)), relayType(relayType_) {
|
||||||
|
try {
|
||||||
|
port = uint16_t(std::stoul(service_));
|
||||||
|
} catch (...) {
|
||||||
|
throw std::invalid_argument("Invalid ICE server port: " + service_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProxyServer::ProxyServer(Type type_, string ip_, uint16_t port_, string username_, string password_)
|
ProxyServer::ProxyServer(Type type_, string hostname_, uint16_t port_, string username_,
|
||||||
: type(type_), ip(ip_), port(port_), username(username_), password(password_) {}
|
string password_)
|
||||||
|
: type(type_), hostname(hostname_), port(port_), username(username_), password(password_) {}
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
@ -59,7 +59,13 @@ inline std::pair<string_view, string_view> parse_pair(string_view attr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T to_integer(string_view s) {
|
template <typename T> T to_integer(string_view s) {
|
||||||
return std::is_signed<T>::value ? T(std::stol(string(s))) : T(std::stoul(string(s)));
|
const string str(s);
|
||||||
|
try {
|
||||||
|
return std::is_signed<T>::value ? T(std::stol(str)) : T(std::stoul(str));
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
throw std::invalid_argument("Invalid integer \"" + str + "\" in description");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -519,20 +525,20 @@ Description::Entry::removeAttribute(std::vector<string>::iterator it) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::addSSRC(uint32_t ssrc, std::optional<string> name,
|
void Description::Media::addSSRC(uint32_t ssrc, std::optional<string> name,
|
||||||
std::optional<string> msid) {
|
std::optional<string> msid, std::optional<string> trackID) {
|
||||||
if (name)
|
if (name)
|
||||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
|
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
|
||||||
else
|
else
|
||||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
|
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
|
||||||
|
|
||||||
if (msid)
|
if (msid)
|
||||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " + *msid);
|
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " + trackID.value_or(*msid));
|
||||||
|
|
||||||
mSsrcs.emplace_back(ssrc);
|
mSsrcs.emplace_back(ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<string> name,
|
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optional<string> name,
|
||||||
std::optional<string> msid) {
|
std::optional<string> msid, std::optional<string> trackID) {
|
||||||
auto it = mAttributes.begin();
|
auto it = mAttributes.begin();
|
||||||
while (it != mAttributes.end()) {
|
while (it != mAttributes.end()) {
|
||||||
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
||||||
@ -540,7 +546,7 @@ void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, std::optio
|
|||||||
} else
|
} else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
addSSRC(ssrc, std::move(name), std::move(msid));
|
addSSRC(ssrc, std::move(name), std::move(msid), std::move(trackID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Description::Media::removeSSRC(uint32_t oldSSRC) {
|
void Description::Media::removeSSRC(uint32_t oldSSRC) {
|
||||||
@ -823,7 +829,7 @@ void Description::Media::parseSdpLine(string_view line) {
|
|||||||
} else if (key == "rtcp-mux") {
|
} else if (key == "rtcp-mux") {
|
||||||
// always added
|
// always added
|
||||||
} else if (key == "ssrc") {
|
} else if (key == "ssrc") {
|
||||||
mSsrcs.emplace_back(std::stoul(string(value)));
|
mSsrcs.emplace_back(to_integer<uint32_t>(value));
|
||||||
} else {
|
} else {
|
||||||
Entry::parseSdpLine(line);
|
Entry::parseSdpLine(line);
|
||||||
}
|
}
|
||||||
@ -843,7 +849,7 @@ std::vector<uint32_t> Description::Media::getSSRCs() {
|
|||||||
for (auto &val : mAttributes) {
|
for (auto &val : mAttributes) {
|
||||||
PLOG_DEBUG << val;
|
PLOG_DEBUG << val;
|
||||||
if (val.find("ssrc:") == 0) {
|
if (val.find("ssrc:") == 0) {
|
||||||
vec.emplace_back(std::stoul(string(val.substr(5, val.find(" ")))));
|
vec.emplace_back(to_integer<uint32_t>(val.substr(5, val.find(" "))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
|
@ -108,7 +108,7 @@ shared_ptr<NalUnits> H264RtpPacketizer::splitMessage(binary_ptr message) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index++;
|
|
||||||
unsigned long long naluStartIndex = index;
|
unsigned long long naluStartIndex = index;
|
||||||
|
|
||||||
while (index < message->size()) {
|
while (index < message->size()) {
|
||||||
|
@ -103,11 +103,11 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
// Pick a STUN server
|
// Pick a STUN server
|
||||||
for (auto &server : servers) {
|
for (auto &server : servers) {
|
||||||
if (!server.hostname.empty() && server.type == IceServer::Type::Stun) {
|
if (!server.hostname.empty() && server.type == IceServer::Type::Stun) {
|
||||||
if (server.service.empty())
|
if (server.port == 0)
|
||||||
server.service = "3478"; // STUN UDP port
|
server.port = 3478; // STUN UDP port
|
||||||
PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.service << "\"";
|
PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.port << "\"";
|
||||||
jconfig.stun_server_host = server.hostname.c_str();
|
jconfig.stun_server_host = server.hostname.c_str();
|
||||||
jconfig.stun_server_port = uint16_t(std::stoul(server.service));
|
jconfig.stun_server_port = server.port;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,13 +119,13 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
int k = 0;
|
int k = 0;
|
||||||
for (auto &server : servers) {
|
for (auto &server : servers) {
|
||||||
if (!server.hostname.empty() && server.type == IceServer::Type::Turn) {
|
if (!server.hostname.empty() && server.type == IceServer::Type::Turn) {
|
||||||
if (server.service.empty())
|
if (server.port == 0)
|
||||||
server.service = "3478"; // TURN UDP port
|
server.port = 3478; // TURN UDP port
|
||||||
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.service << "\"";
|
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port << "\"";
|
||||||
turn_servers[k].host = server.hostname.c_str();
|
turn_servers[k].host = server.hostname.c_str();
|
||||||
turn_servers[k].username = server.username.c_str();
|
turn_servers[k].username = server.username.c_str();
|
||||||
turn_servers[k].password = server.password.c_str();
|
turn_servers[k].password = server.password.c_str();
|
||||||
turn_servers[k].port = uint16_t(std::stoul(server.service));
|
turn_servers[k].port = server.port;
|
||||||
if (++k >= MAX_TURN_SERVERS_COUNT)
|
if (++k >= MAX_TURN_SERVERS_COUNT)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -402,7 +402,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
if (config.proxyServer.has_value()) {
|
if (config.proxyServer.has_value()) {
|
||||||
ProxyServer proxyServer = config.proxyServer.value();
|
ProxyServer proxyServer = config.proxyServer.value();
|
||||||
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-type", proxyServer.type, nullptr);
|
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-type", proxyServer.type, nullptr);
|
||||||
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-ip", proxyServer.ip.c_str(), nullptr);
|
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-ip", proxyServer.hostname.c_str(), nullptr);
|
||||||
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-port", proxyServer.port, nullptr);
|
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-port", proxyServer.port, nullptr);
|
||||||
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-username", proxyServer.username.c_str(),
|
g_object_set(G_OBJECT(mNiceAgent.get()), "proxy-username", proxyServer.username.c_str(),
|
||||||
nullptr);
|
nullptr);
|
||||||
@ -422,8 +422,8 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
continue;
|
continue;
|
||||||
if (server.type != IceServer::Type::Stun)
|
if (server.type != IceServer::Type::Stun)
|
||||||
continue;
|
continue;
|
||||||
if (server.service.empty())
|
if (server.port == 0)
|
||||||
server.service = "3478"; // STUN UDP port
|
server.port = 3478; // STUN UDP port
|
||||||
|
|
||||||
struct addrinfo hints = {};
|
struct addrinfo hints = {};
|
||||||
hints.ai_family = AF_INET; // IPv4
|
hints.ai_family = AF_INET; // IPv4
|
||||||
@ -431,9 +431,10 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
hints.ai_protocol = IPPROTO_UDP;
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
struct addrinfo *result = nullptr;
|
struct addrinfo *result = nullptr;
|
||||||
if (getaddrinfo(server.hostname.c_str(), server.service.c_str(), &hints, &result) != 0) {
|
if (getaddrinfo(server.hostname.c_str(), std::to_string(server.port).c_str(), &hints,
|
||||||
|
&result) != 0) {
|
||||||
PLOG_WARNING << "Unable to resolve STUN server address: " << server.hostname << ':'
|
PLOG_WARNING << "Unable to resolve STUN server address: " << server.hostname << ':'
|
||||||
<< server.service;
|
<< server.port;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +445,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
|
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
|
||||||
servbuffer, MAX_NUMERICNODE_LEN,
|
servbuffer, MAX_NUMERICNODE_LEN,
|
||||||
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
||||||
PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.service
|
PLOG_INFO << "Using STUN server \"" << server.hostname << ":" << server.port
|
||||||
<< "\"";
|
<< "\"";
|
||||||
g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server", nodebuffer, nullptr);
|
g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server", nodebuffer, nullptr);
|
||||||
g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server-port",
|
g_object_set(G_OBJECT(mNiceAgent.get()), "stun-server-port",
|
||||||
@ -466,8 +467,8 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
continue;
|
continue;
|
||||||
if (server.type != IceServer::Type::Turn)
|
if (server.type != IceServer::Type::Turn)
|
||||||
continue;
|
continue;
|
||||||
if (server.service.empty())
|
if (server.port == 0)
|
||||||
server.service = server.relayType == IceServer::RelayType::TurnTls ? "5349" : "3478";
|
server.port = server.relayType == IceServer::RelayType::TurnTls ? 5349 : 3478;
|
||||||
|
|
||||||
struct addrinfo hints = {};
|
struct addrinfo hints = {};
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
@ -477,9 +478,10 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
server.relayType == IceServer::RelayType::TurnUdp ? IPPROTO_UDP : IPPROTO_TCP;
|
server.relayType == IceServer::RelayType::TurnUdp ? IPPROTO_UDP : IPPROTO_TCP;
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
struct addrinfo *result = nullptr;
|
struct addrinfo *result = nullptr;
|
||||||
if (getaddrinfo(server.hostname.c_str(), server.service.c_str(), &hints, &result) != 0) {
|
if (getaddrinfo(server.hostname.c_str(), std::to_string(server.port).c_str(), &hints,
|
||||||
|
&result) != 0) {
|
||||||
PLOG_WARNING << "Unable to resolve TURN server address: " << server.hostname << ':'
|
PLOG_WARNING << "Unable to resolve TURN server address: " << server.hostname << ':'
|
||||||
<< server.service;
|
<< server.port;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +492,7 @@ IceTransport::IceTransport(const Configuration &config, candidate_callback candi
|
|||||||
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
|
if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
|
||||||
servbuffer, MAX_NUMERICNODE_LEN,
|
servbuffer, MAX_NUMERICNODE_LEN,
|
||||||
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
||||||
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.service
|
PLOG_INFO << "Using TURN server \"" << server.hostname << ":" << server.port
|
||||||
<< "\"";
|
<< "\"";
|
||||||
NiceRelayType niceRelayType;
|
NiceRelayType niceRelayType;
|
||||||
switch (server.relayType) {
|
switch (server.relayType) {
|
||||||
|
@ -25,18 +25,39 @@ Processor::Processor(size_t limit) : mTasks(limit) {}
|
|||||||
Processor::~Processor() { join(); }
|
Processor::~Processor() { join(); }
|
||||||
|
|
||||||
void Processor::join() {
|
void Processor::join() {
|
||||||
std::unique_lock lock(mMutex);
|
// We need to detect situations where the thread pool does not execute a pending task at exit
|
||||||
mCondition.wait(lock, [this]() { return !mPending && mTasks.empty(); });
|
std::optional<unsigned int> counter;
|
||||||
|
while (true) {
|
||||||
|
std::shared_future<void> pending;
|
||||||
|
{
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
if (!mPending // no pending task
|
||||||
|
|| (counter && *counter == mCounter)) { // or no scheduled task after the last one
|
||||||
|
|
||||||
|
// Processing is stopped, clear everything and return
|
||||||
|
mPending.reset();
|
||||||
|
while (!mTasks.empty())
|
||||||
|
mTasks.pop();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = *mPending;
|
||||||
|
counter = mCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the pending task
|
||||||
|
pending.wait();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Processor::schedule() {
|
void Processor::schedule() {
|
||||||
std::unique_lock lock(mMutex);
|
std::unique_lock lock(mMutex);
|
||||||
if (auto next = mTasks.tryPop()) {
|
if (auto next = mTasks.tryPop()) {
|
||||||
ThreadPool::Instance().enqueue(std::move(*next));
|
mPending = ThreadPool::Instance().enqueue(std::move(*next)).share();
|
||||||
|
++mCounter;
|
||||||
} else {
|
} else {
|
||||||
// No more tasks
|
mPending.reset(); // No more tasks
|
||||||
mPending = false;
|
|
||||||
mCondition.notify_all();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +54,10 @@ protected:
|
|||||||
const init_token mInitToken = Init::Token();
|
const init_token mInitToken = Init::Token();
|
||||||
|
|
||||||
Queue<std::function<void()>> mTasks;
|
Queue<std::function<void()>> mTasks;
|
||||||
bool mPending = false; // true iff a task is pending in the thread pool
|
std::optional<std::shared_future<void>> mPending; // future of the pending task
|
||||||
|
unsigned int mCounter = 0; // Number of scheduled tasks
|
||||||
|
|
||||||
mutable std::mutex mMutex;
|
mutable std::mutex mMutex;
|
||||||
std::condition_variable mCondition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class F, class... Args> void Processor::enqueue(F &&f, Args &&...args) {
|
template <class F, class... Args> void Processor::enqueue(F &&f, Args &&...args) {
|
||||||
@ -65,12 +65,12 @@ template <class F, class... Args> void Processor::enqueue(F &&f, Args &&...args)
|
|||||||
auto bound = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
auto bound = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
auto task = [this, bound = std::move(bound)]() mutable {
|
auto task = [this, bound = std::move(bound)]() mutable {
|
||||||
scope_guard guard(std::bind(&Processor::schedule, this)); // chain the next task
|
scope_guard guard(std::bind(&Processor::schedule, this)); // chain the next task
|
||||||
return bound();
|
bound();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!mPending) {
|
if (!mPending) {
|
||||||
ThreadPool::Instance().enqueue(std::move(task));
|
mPending = ThreadPool::Instance().enqueue(std::move(task)).share();
|
||||||
mPending = true;
|
++mCounter;
|
||||||
} else {
|
} else {
|
||||||
mTasks.push(std::move(task));
|
mTasks.push(std::move(task));
|
||||||
}
|
}
|
||||||
|
@ -588,7 +588,6 @@ int SctpTransport::handleWrite(byte *data, size_t len, uint8_t /*tos*/, uint8_t
|
|||||||
std::unique_lock lock(mWriteMutex);
|
std::unique_lock lock(mWriteMutex);
|
||||||
PLOG_VERBOSE << "Handle write, len=" << len;
|
PLOG_VERBOSE << "Handle write, len=" << len;
|
||||||
|
|
||||||
auto message = make_message(data, data + len);
|
|
||||||
if (!outgoing(make_message(data, data + len)))
|
if (!outgoing(make_message(data, data + len)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -96,6 +96,10 @@ std::function<void()> ThreadPool::dequeue() {
|
|||||||
mCondition.wait(lock);
|
mCondition.wait(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!mTasks.empty())
|
||||||
|
mTasks.pop();
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +100,16 @@ auto ThreadPool::schedule(clock::duration delay, F &&f, Args &&...args)
|
|||||||
template <class F, class... Args>
|
template <class F, class... Args>
|
||||||
auto ThreadPool::schedule(clock::time_point time, F &&f, Args &&...args)
|
auto ThreadPool::schedule(clock::time_point time, F &&f, Args &&...args)
|
||||||
-> invoke_future_t<F, Args...> {
|
-> invoke_future_t<F, Args...> {
|
||||||
std::unique_lock lock(mMutex);
|
|
||||||
using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
|
using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
|
||||||
|
std::unique_lock lock(mMutex);
|
||||||
|
if (mJoining) {
|
||||||
|
std::promise<R> promise;
|
||||||
|
std::future<R> result = promise.get_future();
|
||||||
|
promise.set_exception(std::make_exception_ptr(
|
||||||
|
std::runtime_error("Scheduled a task while joining the thread pool")));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
auto bound = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
auto bound = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||||
auto task = std::make_shared<std::packaged_task<R()>>([bound = std::move(bound)]() mutable {
|
auto task = std::make_shared<std::packaged_task<R()>>([bound = std::move(bound)]() mutable {
|
||||||
try {
|
try {
|
||||||
|
BIN
test/uwp/benchmark/Logo.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
test/uwp/benchmark/SmallLogo.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
test/uwp/benchmark/SmallLogo44x44.png
Normal file
After Width: | Height: | Size: 265 B |
BIN
test/uwp/benchmark/SplashScreen.png
Normal file
After Width: | Height: | Size: 909 B |
BIN
test/uwp/benchmark/StoreLogo.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
test/uwp/benchmark/Windows_TemporaryKey.pfx
Normal file
42
test/uwp/benchmark/package.appxManifest
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
|
||||||
|
xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
|
||||||
|
IgnorableNamespaces="uap mp">
|
||||||
|
|
||||||
|
<Identity Name="EF284012-D73C-360F-A800-2D2910675E38" Publisher="CN=CMake" Version="1.0.0.0" />
|
||||||
|
<mp:PhoneIdentity PhoneProductId="EF284012-D73C-360F-A800-2D2910675E38" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>datachannel-benchmark</DisplayName>
|
||||||
|
<PublisherDisplayName>CMake</PublisherDisplayName>
|
||||||
|
<Logo>StoreLogo.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||||
|
</Dependencies>
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate" />
|
||||||
|
</Resources>
|
||||||
|
<Applications>
|
||||||
|
<Application
|
||||||
|
Id="App"
|
||||||
|
Executable="benchmark.exe"
|
||||||
|
EntryPoint="datachannel-benchmark.App"
|
||||||
|
desktop4:Subsystem="console"
|
||||||
|
desktop4:SupportsMultipleInstances="true"
|
||||||
|
iot2:Subsystem="console"
|
||||||
|
iot2:SupportsMultipleInstances="true">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="datachannel-benchmark"
|
||||||
|
Description="datachannel-benchmark"
|
||||||
|
BackgroundColor="#336699"
|
||||||
|
Square150x150Logo="Logo.png"
|
||||||
|
Square44x44Logo="SmallLogo44x44.png">
|
||||||
|
<uap:SplashScreen Image="SplashScreen.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
</Package>
|
BIN
test/uwp/tests/Logo.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
test/uwp/tests/SmallLogo.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
test/uwp/tests/SmallLogo44x44.png
Normal file
After Width: | Height: | Size: 265 B |
BIN
test/uwp/tests/SplashScreen.png
Normal file
After Width: | Height: | Size: 909 B |
BIN
test/uwp/tests/StoreLogo.png
Normal file
After Width: | Height: | Size: 227 B |
BIN
test/uwp/tests/Windows_TemporaryKey.pfx
Normal file
42
test/uwp/tests/package.appxManifest
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
|
||||||
|
xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
|
||||||
|
IgnorableNamespaces="uap mp">
|
||||||
|
|
||||||
|
<Identity Name="7D85E652-0312-3746-8F5A-315F52839776" Publisher="CN=CMake" Version="1.0.0.0" />
|
||||||
|
<mp:PhoneIdentity PhoneProductId="7D85E652-0312-3746-8F5A-315F52839776" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>datachannel-tests</DisplayName>
|
||||||
|
<PublisherDisplayName>CMake</PublisherDisplayName>
|
||||||
|
<Logo>StoreLogo.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||||
|
</Dependencies>
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate" />
|
||||||
|
</Resources>
|
||||||
|
<Applications>
|
||||||
|
<Application
|
||||||
|
Id="App"
|
||||||
|
Executable="tests.exe"
|
||||||
|
EntryPoint="datachannel-tests.App"
|
||||||
|
desktop4:Subsystem="console"
|
||||||
|
desktop4:SupportsMultipleInstances="true"
|
||||||
|
iot2:Subsystem="console"
|
||||||
|
iot2:SupportsMultipleInstances="true">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="datachannel-tests"
|
||||||
|
Description="datachannel-tests"
|
||||||
|
BackgroundColor="#336699"
|
||||||
|
Square150x150Logo="Logo.png"
|
||||||
|
Square44x44Logo="SmallLogo44x44.png">
|
||||||
|
<uap:SplashScreen Image="SplashScreen.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
</Package>
|