- clang format + naming improved
This commit is contained in:
@@ -15,8 +15,7 @@
|
|||||||
#define LOG_SUBSYSTEM "audio"
|
#define LOG_SUBSYSTEM "audio"
|
||||||
|
|
||||||
|
|
||||||
AudioManager::AudioManager()
|
AudioManager::AudioManager() : mTerminal(nullptr), mAudioMonitoring(nullptr)
|
||||||
:mTerminal(nullptr), mAudioMonitoring(nullptr)
|
|
||||||
{
|
{
|
||||||
mPlayer.setDelegate(this);
|
mPlayer.setDelegate(this);
|
||||||
}
|
}
|
||||||
@@ -102,8 +101,7 @@ void AudioManager::start(int usageId)
|
|||||||
if (outputIndex >= enumerator->count())
|
if (outputIndex >= enumerator->count())
|
||||||
outputIndex = 0;
|
outputIndex = 0;
|
||||||
|
|
||||||
mAudioOutput = Audio::POutputDevice(
|
mAudioOutput = Audio::POutputDevice(Audio::OutputDevice::make(enumerator->idAt(outputIndex)));
|
||||||
Audio::OutputDevice::make(enumerator->idAt(outputIndex)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mAudioOutput = Audio::POutputDevice(new Audio::NullOutputDevice());
|
mAudioOutput = Audio::POutputDevice(new Audio::NullOutputDevice());
|
||||||
@@ -196,9 +194,7 @@ void AudioManager::stopPlayFile(int usageId)
|
|||||||
mPlayer.release(usageId);
|
mPlayer.release(usageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioManager::onFilePlayed(Audio::Player::PlaylistItem& item)
|
void AudioManager::onFilePlayed(Audio::Player::PlaylistItem& item) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioManager::process()
|
void AudioManager::process()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include "../engine/media/MT_Box.h"
|
#include "../engine/media/MT_Box.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
AudioPrefix_Ring = 1,
|
AudioPrefix_Ring = 1,
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ const std::string Status_NoAudioManager = "no audio manager";
|
|||||||
|
|
||||||
#define LOG_SUBSYSTEM "agent"
|
#define LOG_SUBSYSTEM "agent"
|
||||||
|
|
||||||
AgentImpl::AgentImpl()
|
AgentImpl::AgentImpl() : mShutdown(false), mEventListChangeCondVar()
|
||||||
:mShutdown(false), mEventListChangeCondVar()
|
|
||||||
{
|
{
|
||||||
#if defined(TARGET_ANDROID) || defined(TARGET_WIN)
|
#if defined(TARGET_ANDROID) || defined(TARGET_WIN)
|
||||||
ice::GLogger.useDebugWindow(true);
|
ice::GLogger.useDebugWindow(true);
|
||||||
@@ -84,69 +83,52 @@ std::string AgentImpl::command(const std::string& command)
|
|||||||
}
|
}
|
||||||
if (cmd == "config")
|
if (cmd == "config")
|
||||||
processConfig(d, answer);
|
processConfig(d, answer);
|
||||||
else
|
else if (cmd == "start")
|
||||||
if (cmd == "start")
|
|
||||||
processStart(d, answer);
|
processStart(d, answer);
|
||||||
else
|
else if (cmd == "stop")
|
||||||
if (cmd == "stop")
|
|
||||||
processStop(d, answer);
|
processStop(d, answer);
|
||||||
else
|
else if (cmd == "account_create")
|
||||||
if (cmd == "account_create")
|
|
||||||
processCreateAccount(d, answer);
|
processCreateAccount(d, answer);
|
||||||
else
|
else if (cmd == "account_start")
|
||||||
if (cmd == "account_start")
|
|
||||||
processStartAccount(d, answer);
|
processStartAccount(d, answer);
|
||||||
else
|
else if (cmd == "account_setuserinfo")
|
||||||
if (cmd == "account_setuserinfo")
|
|
||||||
processSetUserInfoToAccount(d, answer);
|
processSetUserInfoToAccount(d, answer);
|
||||||
else
|
else if (cmd == "session_create")
|
||||||
if (cmd == "session_create") {
|
{
|
||||||
// For Bugsnag test
|
// For Bugsnag test
|
||||||
// int* v = nullptr;
|
// int* v = nullptr;
|
||||||
// *v = 0;
|
// *v = 0;
|
||||||
processCreateSession(d, answer);
|
processCreateSession(d, answer);
|
||||||
}
|
}
|
||||||
else
|
else if (cmd == "session_start")
|
||||||
if (cmd == "session_start")
|
|
||||||
processStartSession(d, answer);
|
processStartSession(d, answer);
|
||||||
else
|
else if (cmd == "session_stop")
|
||||||
if (cmd == "session_stop")
|
|
||||||
processStopSession(d, answer);
|
processStopSession(d, answer);
|
||||||
else
|
else if (cmd == "session_accept")
|
||||||
if (cmd == "session_accept")
|
|
||||||
processAcceptSession(d, answer);
|
processAcceptSession(d, answer);
|
||||||
else
|
else if (cmd == "session_destroy")
|
||||||
if (cmd == "session_destroy")
|
|
||||||
processDestroySession(d, answer);
|
processDestroySession(d, answer);
|
||||||
else
|
else if (cmd == "session_use_stream")
|
||||||
if (cmd == "session_use_stream")
|
|
||||||
processUseStreamForSession(d, answer);
|
processUseStreamForSession(d, answer);
|
||||||
else
|
else if (cmd == "wait_for_event")
|
||||||
if (cmd == "wait_for_event")
|
|
||||||
processWaitForEvent(d, answer);
|
processWaitForEvent(d, answer);
|
||||||
else
|
else if (cmd == "session_get_media_stats")
|
||||||
if (cmd == "session_get_media_stats")
|
|
||||||
processGetMediaStats(d, answer);
|
processGetMediaStats(d, answer);
|
||||||
else
|
else if (cmd == "agent_network_changed")
|
||||||
if (cmd == "agent_network_changed")
|
|
||||||
processNetworkChanged(d, answer);
|
processNetworkChanged(d, answer);
|
||||||
else
|
else if (cmd == "agent_add_root_cert")
|
||||||
if (cmd == "agent_add_root_cert")
|
|
||||||
processAddRootCert(d, answer);
|
processAddRootCert(d, answer);
|
||||||
else
|
else if (cmd == "detach_log")
|
||||||
if (cmd == "detach_log")
|
|
||||||
{
|
{
|
||||||
GLogger.closeFile();
|
GLogger.closeFile();
|
||||||
answer["status"] = Status_Ok;
|
answer["status"] = Status_Ok;
|
||||||
}
|
}
|
||||||
else
|
else if (cmd == "attach_log")
|
||||||
if (cmd == "attach_log")
|
|
||||||
{
|
{
|
||||||
GLogger.openFile();
|
GLogger.openFile();
|
||||||
answer["status"] = Status_Ok;
|
answer["status"] = Status_Ok;
|
||||||
}
|
}
|
||||||
else
|
else if (cmd == "log_message")
|
||||||
if (cmd == "log_message")
|
|
||||||
processLogMessage(d, answer);
|
processLogMessage(d, answer);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -177,7 +159,10 @@ void AgentImpl::processConfig(JsonCpp::Value &d, JsonCpp::Value &answer)
|
|||||||
std::unique_lock<std::recursive_mutex> l(mAgentMutex);
|
std::unique_lock<std::recursive_mutex> l(mAgentMutex);
|
||||||
|
|
||||||
std::string transport = d["transport"].asString();
|
std::string transport = d["transport"].asString();
|
||||||
config()[CONFIG_TRANSPORT] = (transport == "any") ? TransportType_Any : (transport == "udp" ? TransportType_Udp : (transport == "tcp" ? TransportType_Tcp : TransportType_Tls));
|
config()[CONFIG_TRANSPORT] =
|
||||||
|
(transport == "any")
|
||||||
|
? TransportType_Any
|
||||||
|
: (transport == "udp" ? TransportType_Udp : (transport == "tcp" ? TransportType_Tcp : TransportType_Tls));
|
||||||
config()[CONFIG_IPV4] = d["ipv4"].asBool();
|
config()[CONFIG_IPV4] = d["ipv4"].asBool();
|
||||||
config()[CONFIG_IPV6] = d["ipv6"].asBool();
|
config()[CONFIG_IPV6] = d["ipv6"].asBool();
|
||||||
|
|
||||||
@@ -347,7 +332,8 @@ void AgentImpl::processStartSession(JsonCpp::Value& request, JsonCpp::Value& ans
|
|||||||
// Ensure audio provider is here
|
// Ensure audio provider is here
|
||||||
PSession session = sessionIter->second;
|
PSession session = sessionIter->second;
|
||||||
PDataProvider audioProvider = std::make_shared<AudioProvider>(*this, *mTerminal);
|
PDataProvider audioProvider = std::make_shared<AudioProvider>(*this, *mTerminal);
|
||||||
audioProvider->setState(audioProvider->state() | static_cast<int>(StreamState::Grabbing) | static_cast<int>(StreamState::Playing));
|
audioProvider->setState(audioProvider->state() | static_cast<int>(StreamState::Grabbing) |
|
||||||
|
static_cast<int>(StreamState::Playing));
|
||||||
|
|
||||||
/*#if defined(USE_AQUA_LIBRARY)
|
/*#if defined(USE_AQUA_LIBRARY)
|
||||||
std::string path_faults = request["path_faults"].asString();
|
std::string path_faults = request["path_faults"].asString();
|
||||||
@@ -372,7 +358,8 @@ void AgentImpl::processStartSession(JsonCpp::Value& request, JsonCpp::Value& ans
|
|||||||
{ "specp", "32"}
|
{ "specp", "32"}
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::string config = "-avlp on -smtnrm on -decor off -mprio off -npnt auto -voip off -enorm off -g711 on -spfrcor off -grad off -tmc on -miter 1 -trim a 10 -output json";
|
// std::string config = "-avlp on -smtnrm on -decor off -mprio off -npnt auto -voip off -enorm off -g711 on
|
||||||
|
-spfrcor off -grad off -tmc on -miter 1 -trim a 10 -output json";
|
||||||
// if (temp_path.size())
|
// if (temp_path.size())
|
||||||
// config += " -fau " + temp_path;
|
// config += " -fau " + temp_path;
|
||||||
|
|
||||||
@@ -512,8 +499,7 @@ void AgentImpl::processGetMediaStats(JsonCpp::Value& request, JsonCpp::Value& an
|
|||||||
{
|
{
|
||||||
PSession session = sessionIter->second;
|
PSession session = sessionIter->second;
|
||||||
VariantMap result;
|
VariantMap result;
|
||||||
session->getSessionInfo(Session::InfoOptions::Detailed,
|
session->getSessionInfo(Session::InfoOptions::Detailed, result);
|
||||||
result);
|
|
||||||
|
|
||||||
if (result.exists(SessionInfo_AudioCodec))
|
if (result.exists(SessionInfo_AudioCodec))
|
||||||
answer["codec"] = result[SessionInfo_AudioCodec].asStdString();
|
answer["codec"] = result[SessionInfo_AudioCodec].asStdString();
|
||||||
@@ -566,11 +552,13 @@ void AgentImpl::processAddRootCert(JsonCpp::Value& request, JsonCpp::Value& answ
|
|||||||
std::string pem = request["cert"].asString();
|
std::string pem = request["cert"].asString();
|
||||||
|
|
||||||
std::string::size_type pb = 0, pe = 0;
|
std::string::size_type pb = 0, pe = 0;
|
||||||
while (pb != std::string::npos && pe != std::string::npos) {
|
while (pb != std::string::npos && pe != std::string::npos)
|
||||||
|
{
|
||||||
pb = pem.find(BeginCertificate, pb);
|
pb = pem.find(BeginCertificate, pb);
|
||||||
pe = pem.find(EndCertificate, pe);
|
pe = pem.find(EndCertificate, pe);
|
||||||
|
|
||||||
if (pb != std::string::npos && pe != std::string::npos && pe > pb) {
|
if (pb != std::string::npos && pe != std::string::npos && pe > pb)
|
||||||
|
{
|
||||||
std::string cert = pem.substr(pb, pe - pb + EndCertificate.size());
|
std::string cert = pem.substr(pb, pe - pb + EndCertificate.size());
|
||||||
addRootCert(ByteBuffer(cert.c_str(), cert.size()));
|
addRootCert(ByteBuffer(cert.c_str(), cert.size()));
|
||||||
|
|
||||||
@@ -600,7 +588,8 @@ void AgentImpl::stopAgentAndThread()
|
|||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Stop worker thread
|
// Stop worker thread
|
||||||
if (mThread)
|
if (mThread)
|
||||||
@@ -644,8 +633,8 @@ void AgentImpl::processUseStreamForSession(JsonCpp::Value& request, JsonCpp::Val
|
|||||||
std::string actionText = request["media_action"].asString(),
|
std::string actionText = request["media_action"].asString(),
|
||||||
directionText = request["media_direction"].asString();
|
directionText = request["media_direction"].asString();
|
||||||
|
|
||||||
MT::Stream::MediaDirection direction = directionText == "incoming" ? MT::Stream::MediaDirection::Incoming
|
MT::Stream::MediaDirection direction =
|
||||||
: MT::Stream::MediaDirection::Outgoing;
|
directionText == "incoming" ? MT::Stream::MediaDirection::Incoming : MT::Stream::MediaDirection::Outgoing;
|
||||||
std::string path = request["path"].asString();
|
std::string path = request["path"].asString();
|
||||||
|
|
||||||
// Try to open file
|
// Try to open file
|
||||||
@@ -672,8 +661,7 @@ void AgentImpl::processUseStreamForSession(JsonCpp::Value& request, JsonCpp::Val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (actionText == "write")
|
||||||
if (actionText == "write")
|
|
||||||
{
|
{
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
@@ -693,8 +681,7 @@ void AgentImpl::processUseStreamForSession(JsonCpp::Value& request, JsonCpp::Val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (actionText == "mirror")
|
||||||
if (actionText == "mirror")
|
|
||||||
{
|
{
|
||||||
prov->setupMirror(request["enable"].asBool());
|
prov->setupMirror(request["enable"].asBool());
|
||||||
answer["status"] = Status_Ok;
|
answer["status"] = Status_Ok;
|
||||||
@@ -707,7 +694,8 @@ void AgentImpl::processUseStreamForSession(JsonCpp::Value& request, JsonCpp::Val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentImpl::onMedia(const void* data, int length, MT::Stream::MediaDirection direction, void* context, void* userTag)
|
void AgentImpl::onMedia(const void* data, int length, MT::Stream::MediaDirection direction, void* context,
|
||||||
|
void* userTag)
|
||||||
{
|
{
|
||||||
/*switch (direction)
|
/*switch (direction)
|
||||||
{
|
{
|
||||||
@@ -718,7 +706,9 @@ void AgentImpl::onMedia(const void* data, int length, MT::Stream::MediaDirection
|
|||||||
|
|
||||||
|
|
||||||
// Called on new incoming session; providers shoukld
|
// Called on new incoming session; providers shoukld
|
||||||
#define EVENT_WITH_NAME(X) JsonCpp::Value v; v["event_name"] = X;
|
#define EVENT_WITH_NAME(X) \
|
||||||
|
JsonCpp::Value v; \
|
||||||
|
v["event_name"] = X;
|
||||||
|
|
||||||
PDataProvider AgentImpl::onProviderNeeded(const std::string& name)
|
PDataProvider AgentImpl::onProviderNeeded(const std::string& name)
|
||||||
{
|
{
|
||||||
@@ -856,8 +846,7 @@ void AgentImpl::onCheckFinished(PSession s, const char* description)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called when log message must be recorded
|
// Called when log message must be recorded
|
||||||
void AgentImpl::onLog(const char* /*msg*/)
|
void AgentImpl::onLog(const char* /*msg*/) {}
|
||||||
{}
|
|
||||||
|
|
||||||
// Called when problem with SIP connection(s) detected
|
// Called when problem with SIP connection(s) detected
|
||||||
void AgentImpl::onSipConnectionFailed()
|
void AgentImpl::onSipConnectionFailed()
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ public:
|
|||||||
void onSipConnectionFailed() override;
|
void onSipConnectionFailed() override;
|
||||||
|
|
||||||
// Called on incoming & outgoing audio for voice sessions
|
// Called on incoming & outgoing audio for voice sessions
|
||||||
void onMedia(const void* data, int length, MT::Stream::MediaDirection direction, void* context, void* userTag) override;
|
void onMedia(const void* data, int length, MT::Stream::MediaDirection direction, void* context,
|
||||||
|
void* userTag) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,27 +1,16 @@
|
|||||||
#include "Agent_Interface.h"
|
#include "Agent_Interface.h"
|
||||||
#include "Agent_Impl.h"
|
#include "Agent_Impl.h"
|
||||||
Agent::Agent()
|
Agent::Agent() : mContext(new AgentImpl());
|
||||||
:mContext(new AgentImpl());
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Agent::~Agent()
|
Agent::~Agent() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
void Agent::write(const std::string& command) {}
|
||||||
|
|
||||||
void Agent::write(const std::string& command)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Agent::waitForData(int milliseconds)
|
bool Agent::waitForData(int milliseconds)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Agent::read()
|
std::string Agent::read() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ using namespace Audio;
|
|||||||
|
|
||||||
// -------------------- AndroidEnumerator -----------------------------
|
// -------------------- AndroidEnumerator -----------------------------
|
||||||
|
|
||||||
AndroidEnumerator::AndroidEnumerator()
|
AndroidEnumerator::AndroidEnumerator() {}
|
||||||
{}
|
|
||||||
|
|
||||||
AndroidEnumerator::~AndroidEnumerator()
|
AndroidEnumerator::~AndroidEnumerator() {}
|
||||||
{}
|
|
||||||
|
|
||||||
int AndroidEnumerator::indexOfDefaultDevice()
|
int AndroidEnumerator::indexOfDefaultDevice()
|
||||||
{
|
{
|
||||||
@@ -40,26 +38,21 @@ std::string AndroidEnumerator::nameAt(int index)
|
|||||||
return "Audio";
|
return "Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidEnumerator::open(int direction)
|
void AndroidEnumerator::open(int direction) {}
|
||||||
{}
|
|
||||||
|
|
||||||
void AndroidEnumerator::close()
|
void AndroidEnumerator::close() {}
|
||||||
{}
|
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
||||||
OpenSLEngine::OpenSLEngine()
|
OpenSLEngine::OpenSLEngine() {}
|
||||||
{}
|
|
||||||
|
|
||||||
OpenSLEngine::~OpenSLEngine()
|
OpenSLEngine::~OpenSLEngine() {}
|
||||||
{}
|
|
||||||
|
|
||||||
void OpenSLEngine::open()
|
void OpenSLEngine::open()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(mMutex);
|
std::unique_lock<std::mutex> l(mMutex);
|
||||||
if (++mUsageCounter == 1)
|
if (++mUsageCounter == 1)
|
||||||
internalOpen();
|
internalOpen();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::close()
|
void OpenSLEngine::close()
|
||||||
@@ -72,7 +65,9 @@ void OpenSLEngine::close()
|
|||||||
internalClose();
|
internalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_OPENSLES_ERROR if (resultCode != SL_RESULT_SUCCESS) throw Exception(ERR_OPENSLES, (int)resultCode)
|
#define CHECK_OPENSLES_ERROR \
|
||||||
|
if (resultCode != SL_RESULT_SUCCESS) \
|
||||||
|
throw Exception(ERR_OPENSLES, (int)resultCode)
|
||||||
|
|
||||||
void OpenSLEngine::internalOpen()
|
void OpenSLEngine::internalOpen()
|
||||||
{
|
{
|
||||||
@@ -118,25 +113,15 @@ OpenSLEngine& OpenSLEngine::instance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------- Input implementation ----------------
|
// --------------- Input implementation ----------------
|
||||||
AndroidInputDevice::AndroidInputDevice(int devId)
|
AndroidInputDevice::AndroidInputDevice(int devId) {}
|
||||||
{}
|
|
||||||
|
|
||||||
AndroidInputDevice::~AndroidInputDevice()
|
AndroidInputDevice::~AndroidInputDevice() {}
|
||||||
{}
|
|
||||||
|
|
||||||
static int RateToProbe[12][2] = {
|
static int RateToProbe[12][2] = {
|
||||||
{ SL_SAMPLINGRATE_16, 16000 },
|
{SL_SAMPLINGRATE_16, 16000}, {SL_SAMPLINGRATE_8, 8000}, {SL_SAMPLINGRATE_32, 32000},
|
||||||
{ SL_SAMPLINGRATE_8, 8000 },
|
{SL_SAMPLINGRATE_44_1, 44100}, {SL_SAMPLINGRATE_11_025, 10025}, {SL_SAMPLINGRATE_22_05, 22050},
|
||||||
{ SL_SAMPLINGRATE_32, 32000 },
|
{SL_SAMPLINGRATE_24, 24000}, {SL_SAMPLINGRATE_48, 48000}, {SL_SAMPLINGRATE_64, 64000},
|
||||||
{ SL_SAMPLINGRATE_44_1, 44100 },
|
{SL_SAMPLINGRATE_88_2, 88200}, {SL_SAMPLINGRATE_96, 96000}, {SL_SAMPLINGRATE_192, 192000}};
|
||||||
{ SL_SAMPLINGRATE_11_025, 10025 },
|
|
||||||
{ SL_SAMPLINGRATE_22_05, 22050 },
|
|
||||||
{ SL_SAMPLINGRATE_24, 24000 },
|
|
||||||
{ SL_SAMPLINGRATE_48, 48000 },
|
|
||||||
{ SL_SAMPLINGRATE_64, 64000 },
|
|
||||||
{ SL_SAMPLINGRATE_88_2, 88200 },
|
|
||||||
{ SL_SAMPLINGRATE_96, 96000 },
|
|
||||||
{ SL_SAMPLINGRATE_192, 192000} };
|
|
||||||
|
|
||||||
bool AndroidInputDevice::open()
|
bool AndroidInputDevice::open()
|
||||||
{
|
{
|
||||||
@@ -192,8 +177,7 @@ bool AndroidInputDevice::fakeMode()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidInputDevice::setFakeMode(bool fakemode)
|
void AndroidInputDevice::setFakeMode(bool fakemode) {}
|
||||||
{}
|
|
||||||
|
|
||||||
int AndroidInputDevice::readBuffer(void* buffer)
|
int AndroidInputDevice::readBuffer(void* buffer)
|
||||||
{
|
{
|
||||||
@@ -206,7 +190,13 @@ int AndroidInputDevice::readBuffer(void* buffer)
|
|||||||
return mSdkRateCache.read(buffer, AUDIO_MIC_BUFFER_SIZE);
|
return mSdkRateCache.read(buffer, AUDIO_MIC_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_SL_INTERFACE(INTF, ERR) {if (!INTF) throw Exception(ERR_OPENSLES, ERR); if (!(*INTF)) throw Exception(ERR_OPENSLES, ERR);}
|
#define CHECK_SL_INTERFACE(INTF, ERR) \
|
||||||
|
{ \
|
||||||
|
if (!INTF) \
|
||||||
|
throw Exception(ERR_OPENSLES, ERR); \
|
||||||
|
if (!(*INTF)) \
|
||||||
|
throw Exception(ERR_OPENSLES, ERR); \
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
||||||
{
|
{
|
||||||
@@ -214,18 +204,22 @@ void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
|||||||
SLuint32 nrOfChannels = 1;
|
SLuint32 nrOfChannels = 1;
|
||||||
|
|
||||||
// Prepare audio source
|
// Prepare audio source
|
||||||
SLDataLocator_IODevice devDescription = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
SLDataLocator_IODevice devDescription = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
|
||||||
|
SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
||||||
SLDataSource audioSource = {&devDescription, NULL};
|
SLDataSource audioSource = {&devDescription, NULL};
|
||||||
|
|
||||||
// Source flags
|
// Source flags
|
||||||
SLuint32 speakersFlags = nrOfChannels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
SLuint32 speakersFlags =
|
||||||
|
nrOfChannels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
||||||
|
|
||||||
// Buffer queue
|
// Buffer queue
|
||||||
SLDataLocator_AndroidSimpleBufferQueue queueDescription = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
SLDataLocator_AndroidSimpleBufferQueue queueDescription = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||||
|
|
||||||
// Audio format
|
// Audio format
|
||||||
SLDataFormat_PCM formatDescription = { SL_DATAFORMAT_PCM, nrOfChannels, (SLuint32)rateCode, SL_PCMSAMPLEFORMAT_FIXED_16,
|
SLDataFormat_PCM formatDescription = {SL_DATAFORMAT_PCM, nrOfChannels,
|
||||||
SL_PCMSAMPLEFORMAT_FIXED_16, (SLuint32)speakersFlags, SL_BYTEORDER_LITTLEENDIAN };
|
(SLuint32)rateCode, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||||
|
SL_PCMSAMPLEFORMAT_FIXED_16, (SLuint32)speakersFlags,
|
||||||
|
SL_BYTEORDER_LITTLEENDIAN};
|
||||||
|
|
||||||
SLDataSink audioSink = {&queueDescription, &formatDescription};
|
SLDataSink audioSink = {&queueDescription, &formatDescription};
|
||||||
|
|
||||||
@@ -238,9 +232,9 @@ void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
|||||||
SLEngineItf engine_interface = OpenSLEngine::instance().getNativeEngine();
|
SLEngineItf engine_interface = OpenSLEngine::instance().getNativeEngine();
|
||||||
CHECK_SL_INTERFACE(engine_interface, -1);
|
CHECK_SL_INTERFACE(engine_interface, -1);
|
||||||
|
|
||||||
resultCode = (*engine_interface)->CreateAudioRecorder(
|
resultCode = (*engine_interface)
|
||||||
OpenSLEngine::instance().getNativeEngine(),
|
->CreateAudioRecorder(OpenSLEngine::instance().getNativeEngine(), &mRecorderObject, &audioSource,
|
||||||
&mRecorderObject, &audioSource, &audioSink, 2, interfacesList, interfacesRequirements);
|
&audioSink, 2, interfacesList, interfacesRequirements);
|
||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
CHECK_SL_INTERFACE(mRecorderObject, -2);
|
CHECK_SL_INTERFACE(mRecorderObject, -2);
|
||||||
|
|
||||||
@@ -258,7 +252,8 @@ void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
|||||||
CHECK_SL_INTERFACE(mRecorderInterface, -3);
|
CHECK_SL_INTERFACE(mRecorderInterface, -3);
|
||||||
|
|
||||||
// Now buffer queue interface...
|
// Now buffer queue interface...
|
||||||
resultCode = (*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mRecorderBufferInterface);
|
resultCode =
|
||||||
|
(*mRecorderObject)->GetInterface(mRecorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mRecorderBufferInterface);
|
||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
CHECK_SL_INTERFACE(mRecorderBufferInterface, -4);
|
CHECK_SL_INTERFACE(mRecorderBufferInterface, -4);
|
||||||
|
|
||||||
@@ -277,7 +272,8 @@ void AndroidInputDevice::internalOpen(int rateCode, int rate)
|
|||||||
|
|
||||||
// Setup buffers
|
// Setup buffers
|
||||||
for (int i = 0; i < AUDIO_MIC_BUFFER_COUNT; i++)
|
for (int i = 0; i < AUDIO_MIC_BUFFER_COUNT; i++)
|
||||||
(*mRecorderBufferInterface)->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + i * mBufferSize, mBufferSize);
|
(*mRecorderBufferInterface)
|
||||||
|
->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + i * mBufferSize, mBufferSize);
|
||||||
|
|
||||||
// Start finally
|
// Start finally
|
||||||
resultCode = (*mRecorderInterface)->SetRecordState(mRecorderInterface, SL_RECORDSTATE_RECORDING);
|
resultCode = (*mRecorderInterface)->SetRecordState(mRecorderInterface, SL_RECORDSTATE_RECORDING);
|
||||||
@@ -302,8 +298,7 @@ void AndroidInputDevice::internalClose()
|
|||||||
{
|
{
|
||||||
(*mRecorderInterface)->GetRecordState(mRecorderInterface, &state);
|
(*mRecorderInterface)->GetRecordState(mRecorderInterface, &state);
|
||||||
SyncHelper::delay(1);
|
SyncHelper::delay(1);
|
||||||
}
|
} while (state == SL_RECORDSTATE_RECORDING);
|
||||||
while (state == SL_RECORDSTATE_RECORDING);
|
|
||||||
}
|
}
|
||||||
(*mRecorderObject)->Destroy(mRecorderObject);
|
(*mRecorderObject)->Destroy(mRecorderObject);
|
||||||
}
|
}
|
||||||
@@ -331,9 +326,8 @@ void AndroidInputDevice::handleCallback(SLAndroidSimpleBufferQueueItf bq)
|
|||||||
{
|
{
|
||||||
char* resampled = (char*)alloca(Format().sizeFromTime(10));
|
char* resampled = (char*)alloca(Format().sizeFromTime(10));
|
||||||
int processed = 0;
|
int processed = 0;
|
||||||
int outlen = mResampler->processBuffer(mDeviceRateCache.data(), tenMsSize, processed, resampled, Format().sizeFromTime(10));
|
int outlen = mResampler->processBuffer(mDeviceRateCache.data(), tenMsSize, processed, resampled,
|
||||||
if (outlen > 0)
|
Format().sizeFromTime(10)); if (outlen > 0) mSdkRateCache.add(resampled, (int)Format().sizeFromTime(10));
|
||||||
mSdkRateCache.add(resampled, (int)Format().sizeFromTime(10));
|
|
||||||
mDeviceRateCache.erase(tenMsSize);
|
mDeviceRateCache.erase(tenMsSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +340,8 @@ void AndroidInputDevice::handleCallback(SLAndroidSimpleBufferQueueItf bq)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Re-enqueue used buffer
|
// Re-enqueue used buffer
|
||||||
(*mRecorderBufferInterface)->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
(*mRecorderBufferInterface)
|
||||||
|
->Enqueue(mRecorderBufferInterface, mRecorderBuffer.data() + mRecorderBufferIndex * mBufferSize, mBufferSize);
|
||||||
mRecorderBufferIndex++;
|
mRecorderBufferIndex++;
|
||||||
mRecorderBufferIndex %= AUDIO_MIC_BUFFER_COUNT;
|
mRecorderBufferIndex %= AUDIO_MIC_BUFFER_COUNT;
|
||||||
}
|
}
|
||||||
@@ -359,7 +354,8 @@ void AndroidInputDevice::DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void *
|
|||||||
reinterpret_cast<AndroidInputDevice*>(context)->handleCallback(bq);
|
reinterpret_cast<AndroidInputDevice*>(context)->handleCallback(bq);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ AndroidOutputDevice -----------------
|
// ------------ AndroidOutputDevice -----------------
|
||||||
@@ -414,9 +410,7 @@ bool AndroidOutputDevice::fakeMode()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidOutputDevice::setFakeMode(bool fakemode)
|
void AndroidOutputDevice::setFakeMode(bool fakemode) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
||||||
{
|
{
|
||||||
@@ -430,8 +424,8 @@ void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
|||||||
|
|
||||||
const SLInterfaceID interfacesList[] = {SL_IID_VOLUME};
|
const SLInterfaceID interfacesList[] = {SL_IID_VOLUME};
|
||||||
const SLboolean interfaceRequirements[] = {SL_BOOLEAN_FALSE};
|
const SLboolean interfaceRequirements[] = {SL_BOOLEAN_FALSE};
|
||||||
resultCode = (*OpenSLEngine::instance().getNativeEngine())->CreateOutputMix(
|
resultCode = (*OpenSLEngine::instance().getNativeEngine())
|
||||||
OpenSLEngine::instance().getNativeEngine(), &mMixer, 1, interfacesList,
|
->CreateOutputMix(OpenSLEngine::instance().getNativeEngine(), &mMixer, 1, interfacesList,
|
||||||
interfaceRequirements);
|
interfaceRequirements);
|
||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
|
|
||||||
@@ -440,13 +434,12 @@ void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
|||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
|
|
||||||
// Prepare mixer configuration
|
// Prepare mixer configuration
|
||||||
SLuint32 speakers =
|
SLuint32 speakers = channels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
||||||
channels > 1 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER;
|
|
||||||
|
|
||||||
// Describe audio format
|
// Describe audio format
|
||||||
SLDataFormat_PCM pcm_format = {SL_DATAFORMAT_PCM, channels, (SLuint32) rateId,
|
SLDataFormat_PCM pcm_format = {
|
||||||
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
SL_DATAFORMAT_PCM, channels, (SLuint32)rateId, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||||
speakers, SL_BYTEORDER_LITTLEENDIAN};
|
SL_PCMSAMPLEFORMAT_FIXED_16, speakers, SL_BYTEORDER_LITTLEENDIAN};
|
||||||
|
|
||||||
// Describe audio source - buffers + audio format
|
// Describe audio source - buffers + audio format
|
||||||
SLDataSource audio_source = {&queue_desc, &pcm_format};
|
SLDataSource audio_source = {&queue_desc, &pcm_format};
|
||||||
@@ -456,14 +449,13 @@ void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
|||||||
SLDataSink audio_sink = {&mixer_desc, NULL};
|
SLDataSink audio_sink = {&mixer_desc, NULL};
|
||||||
|
|
||||||
// Create player instance
|
// Create player instance
|
||||||
const SLInterfaceID playerInterfaces[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
const SLInterfaceID playerInterfaces[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME,
|
||||||
SL_IID_VOLUME,
|
|
||||||
SL_IID_ANDROIDCONFIGURATION};
|
SL_IID_ANDROIDCONFIGURATION};
|
||||||
const SLboolean playerInterfacesReqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
const SLboolean playerInterfacesReqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||||
|
|
||||||
resultCode = (*OpenSLEngine::instance().getNativeEngine())->CreateAudioPlayer(
|
resultCode = (*OpenSLEngine::instance().getNativeEngine())
|
||||||
OpenSLEngine::instance().getNativeEngine(), &mPlayer,
|
->CreateAudioPlayer(OpenSLEngine::instance().getNativeEngine(), &mPlayer, &audio_source,
|
||||||
&audio_source, &audio_sink, 3, playerInterfaces, playerInterfacesReqs);
|
&audio_sink, 3, playerInterfaces, playerInterfacesReqs);
|
||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
|
|
||||||
// Get android config interface
|
// Get android config interface
|
||||||
@@ -472,8 +464,8 @@ void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
|||||||
if (resultCode == SL_RESULT_SUCCESS)
|
if (resultCode == SL_RESULT_SUCCESS)
|
||||||
{
|
{
|
||||||
SLint32 streamType = voice ? SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA;
|
SLint32 streamType = voice ? SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA;
|
||||||
resultCode = (*mAndroidConfig)->SetConfiguration(mAndroidConfig, SL_ANDROID_KEY_STREAM_TYPE,
|
resultCode = (*mAndroidConfig)
|
||||||
&streamType, sizeof(SLint32));
|
->SetConfiguration(mAndroidConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
|
||||||
if (resultCode != SL_RESULT_SUCCESS)
|
if (resultCode != SL_RESULT_SUCCESS)
|
||||||
ICELogCritical(<< "Failed to set audio destination with error " << (unsigned)resultCode);
|
ICELogCritical(<< "Failed to set audio destination with error " << (unsigned)resultCode);
|
||||||
}
|
}
|
||||||
@@ -489,8 +481,7 @@ void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
|||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
|
|
||||||
// Get the buffer queue interface
|
// Get the buffer queue interface
|
||||||
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
resultCode = (*mPlayer)->GetInterface(mPlayer, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mBufferQueue);
|
||||||
&mBufferQueue);
|
|
||||||
CHECK_OPENSLES_ERROR;
|
CHECK_OPENSLES_ERROR;
|
||||||
|
|
||||||
// Setup callback
|
// Setup callback
|
||||||
@@ -503,8 +494,7 @@ void AndroidOutputDevice::internalOpen(int rateId, int rate, bool voice)
|
|||||||
|
|
||||||
mBufferIndex = 0;
|
mBufferIndex = 0;
|
||||||
for (int i = 0; i < AUDIO_SPK_BUFFER_COUNT; i++)
|
for (int i = 0; i < AUDIO_SPK_BUFFER_COUNT; i++)
|
||||||
(*mBufferQueue)->Enqueue(mBufferQueue, mPlayBuffer.data() + i * mBufferSize,
|
(*mBufferQueue)->Enqueue(mBufferQueue, mPlayBuffer.data() + i * mBufferSize, (SLuint32)mBufferSize);
|
||||||
(SLuint32)mBufferSize);
|
|
||||||
|
|
||||||
// Set the player's state to playing
|
// Set the player's state to playing
|
||||||
resultCode = (*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_PLAYING);
|
resultCode = (*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_PLAYING);
|
||||||
@@ -521,12 +511,15 @@ void AndroidOutputDevice::internalClose()
|
|||||||
{
|
{
|
||||||
mInShutdown = true;
|
mInShutdown = true;
|
||||||
ICELogInfo(<< "Stop player");
|
ICELogInfo(<< "Stop player");
|
||||||
if (mPlayerControl) {
|
if (mPlayerControl)
|
||||||
if (*mPlayerControl) {
|
{
|
||||||
|
if (*mPlayerControl)
|
||||||
|
{
|
||||||
SLuint32 state = SL_PLAYSTATE_PLAYING;
|
SLuint32 state = SL_PLAYSTATE_PLAYING;
|
||||||
(*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_STOPPED);
|
(*mPlayerControl)->SetPlayState(mPlayerControl, SL_PLAYSTATE_STOPPED);
|
||||||
|
|
||||||
while (state != SL_PLAYSTATE_STOPPED) {
|
while (state != SL_PLAYSTATE_STOPPED)
|
||||||
|
{
|
||||||
(*mPlayerControl)->GetPlayState(mPlayerControl, &state);
|
(*mPlayerControl)->GetPlayState(mPlayerControl, &state);
|
||||||
SyncHelper::delay(1);
|
SyncHelper::delay(1);
|
||||||
}
|
}
|
||||||
@@ -593,7 +586,8 @@ void AndroidOutputDevice::DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void*
|
|||||||
reinterpret_cast<AndroidOutputDevice*>(context)->handleCallback(bq);
|
reinterpret_cast<AndroidOutputDevice*>(context)->handleCallback(bq);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TARGET_ANDROID
|
#endif // TARGET_ANDROID
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ namespace Audio
|
|||||||
|
|
||||||
void handleCallback(SLAndroidSimpleBufferQueueItf bq);
|
void handleCallback(SLAndroidSimpleBufferQueueItf bq);
|
||||||
static void DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
|
static void DeviceCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class OpenSLEngine : public OsEngine
|
class OpenSLEngine : public OsEngine
|
||||||
@@ -139,7 +138,7 @@ namespace Audio
|
|||||||
void internalOpen();
|
void internalOpen();
|
||||||
void internalClose();
|
void internalClose();
|
||||||
};
|
};
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif // TARGET_ANDROID
|
#endif // TARGET_ANDROID
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,9 @@ using namespace Audio;
|
|||||||
|
|
||||||
// -------------------- AndroidEnumerator -----------------------------
|
// -------------------- AndroidEnumerator -----------------------------
|
||||||
|
|
||||||
AndroidEnumerator::AndroidEnumerator()
|
AndroidEnumerator::AndroidEnumerator() {}
|
||||||
{}
|
|
||||||
|
|
||||||
AndroidEnumerator::~AndroidEnumerator()
|
AndroidEnumerator::~AndroidEnumerator() {}
|
||||||
{}
|
|
||||||
|
|
||||||
int AndroidEnumerator::indexOfDefaultDevice()
|
int AndroidEnumerator::indexOfDefaultDevice()
|
||||||
{
|
{
|
||||||
@@ -44,15 +42,12 @@ std::string AndroidEnumerator::nameAt(int index)
|
|||||||
return "Audio";
|
return "Audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidEnumerator::open(int direction)
|
void AndroidEnumerator::open(int direction) {}
|
||||||
{}
|
|
||||||
|
|
||||||
void AndroidEnumerator::close()
|
void AndroidEnumerator::close() {}
|
||||||
{}
|
|
||||||
|
|
||||||
// --------------- Input implementation ----------------
|
// --------------- Input implementation ----------------
|
||||||
AndroidInputDevice::AndroidInputDevice(int devId)
|
AndroidInputDevice::AndroidInputDevice(int devId) {}
|
||||||
{}
|
|
||||||
|
|
||||||
AndroidInputDevice::~AndroidInputDevice()
|
AndroidInputDevice::~AndroidInputDevice()
|
||||||
{
|
{
|
||||||
@@ -94,13 +89,14 @@ void AndroidInputDevice::close()
|
|||||||
if (mRecordingStream != nullptr)
|
if (mRecordingStream != nullptr)
|
||||||
{
|
{
|
||||||
mRecordingStream->close();
|
mRecordingStream->close();
|
||||||
delete mRecordingStream; mRecordingStream = nullptr;
|
delete mRecordingStream;
|
||||||
|
mRecordingStream = nullptr;
|
||||||
}
|
}
|
||||||
mActive = false;
|
mActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
oboe::DataCallbackResult
|
oboe::DataCallbackResult AndroidInputDevice::onAudioReady(oboe::AudioStream* audioStream, void* audioData,
|
||||||
AndroidInputDevice::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames)
|
int32_t numFrames)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(mMutex);
|
std::unique_lock<std::mutex> l(mMutex);
|
||||||
|
|
||||||
@@ -126,8 +122,7 @@ bool AndroidInputDevice::fakeMode()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidInputDevice::setFakeMode(bool fakemode)
|
void AndroidInputDevice::setFakeMode(bool fakemode) {}
|
||||||
{}
|
|
||||||
|
|
||||||
int AndroidInputDevice::readBuffer(void* buffer)
|
int AndroidInputDevice::readBuffer(void* buffer)
|
||||||
{
|
{
|
||||||
@@ -211,7 +206,8 @@ void AndroidOutputDevice::close()
|
|||||||
if (mPlayingStream != nullptr)
|
if (mPlayingStream != nullptr)
|
||||||
{
|
{
|
||||||
mPlayingStream->close();
|
mPlayingStream->close();
|
||||||
delete mPlayingStream; mPlayingStream = nullptr;
|
delete mPlayingStream;
|
||||||
|
mPlayingStream = nullptr;
|
||||||
}
|
}
|
||||||
mEndTime = now_ms();
|
mEndTime = now_ms();
|
||||||
mActive = false;
|
mActive = false;
|
||||||
@@ -230,11 +226,10 @@ bool AndroidOutputDevice::fakeMode()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidOutputDevice::setFakeMode(bool /*fakemode*/)
|
void AndroidOutputDevice::setFakeMode(bool /*fakemode*/) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
oboe::DataCallbackResult AndroidOutputDevice::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames)
|
oboe::DataCallbackResult AndroidOutputDevice::onAudioReady(oboe::AudioStream* audioStream, void* audioData,
|
||||||
|
int32_t numFrames)
|
||||||
{
|
{
|
||||||
if (mInShutdown)
|
if (mInShutdown)
|
||||||
return oboe::DataCallbackResult::Stop;
|
return oboe::DataCallbackResult::Stop;
|
||||||
@@ -276,10 +271,8 @@ oboe::DataCallbackResult AndroidOutputDevice::onAudioReady(oboe::AudioStream *au
|
|||||||
mHeartbeatLast = t;
|
mHeartbeatLast = t;
|
||||||
else if (t - mHeartbeatLast >= 5000.0f)
|
else if (t - mHeartbeatLast >= 5000.0f)
|
||||||
{
|
{
|
||||||
ICELogInfo(<< "[spk-heartbeat] xruns=" << mXRunLast
|
ICELogInfo(<< "[spk-heartbeat] xruns=" << mXRunLast << " bufFrames=" << audioStream->getBufferSizeInFrames()
|
||||||
<< " bufFrames=" << audioStream->getBufferSizeInFrames()
|
<< " burst=" << mBurstFrames << " rate=" << mDeviceRate);
|
||||||
<< " burst=" << mBurstFrames
|
|
||||||
<< " rate=" << mDeviceRate);
|
|
||||||
mHeartbeatLast = t;
|
mHeartbeatLast = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,8 +283,10 @@ oboe::DataCallbackResult AndroidOutputDevice::onAudioReady(oboe::AudioStream *au
|
|||||||
// stream down and calls this on its own thread after the stream is closed. Rebuild
|
// stream down and calls this on its own thread after the stream is closed. Rebuild
|
||||||
// on the new default route so audio doesn't silently die mid-call.
|
// on the new default route so audio doesn't silently die mid-call.
|
||||||
// See https://github.com/google/oboe/blob/master/docs/notes/disconnect.md
|
// See https://github.com/google/oboe/blob/master/docs/notes/disconnect.md
|
||||||
void AndroidOutputDevice::onErrorAfterClose(oboe::AudioStream *stream, oboe::Result result) {
|
void AndroidOutputDevice::onErrorAfterClose(oboe::AudioStream* stream, oboe::Result result)
|
||||||
if (result == oboe::Result::ErrorDisconnected && !mInShutdown) {
|
{
|
||||||
|
if (result == oboe::Result::ErrorDisconnected && !mInShutdown)
|
||||||
|
{
|
||||||
ICELogInfo(<< "Output stream disconnected; restarting on the new route");
|
ICELogInfo(<< "Output stream disconnected; restarting on the new route");
|
||||||
// close() and open() each take mMutex internally; this callback holds none.
|
// close() and open() each take mMutex internally; this callback holds none.
|
||||||
close();
|
close();
|
||||||
|
|||||||
@@ -57,8 +57,7 @@ namespace Audio
|
|||||||
int readBuffer(void* buffer);
|
int readBuffer(void* buffer);
|
||||||
bool active() const;
|
bool active() const;
|
||||||
|
|
||||||
oboe::DataCallbackResult
|
oboe::DataCallbackResult onAudioReady(oboe::AudioStream* audioStream, void* audioData, int32_t numFrames);
|
||||||
onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames);
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -107,7 +106,7 @@ class AndroidOutputDevice: public OutputDevice, public oboe::AudioStreamCallback
|
|||||||
// Statistics
|
// Statistics
|
||||||
float mRequestedFrames = 0.0, mStartTime = 0.0, mEndTime = 0.0;
|
float mRequestedFrames = 0.0, mStartTime = 0.0, mEndTime = 0.0;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif // TARGET_ANDROID
|
#endif // TARGET_ANDROID
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ static inline short Float32ToInt16(Float32 v)
|
|||||||
int r = int(v * 32768);
|
int r = int(v * 32768);
|
||||||
if (r >= 32768)
|
if (r >= 32768)
|
||||||
return (short)32767;
|
return (short)32767;
|
||||||
else
|
else if (r < -32768)
|
||||||
if (r < -32768)
|
|
||||||
return (short)-32768;
|
return (short)-32768;
|
||||||
else
|
else
|
||||||
return (short)r;
|
return (short)r;
|
||||||
@@ -73,10 +72,7 @@ static void propertyListenerCallback(void *inUserData, AudioQueueRef queueObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CoreAudioUnit::CoreAudioUnit()
|
CoreAudioUnit::CoreAudioUnit() : mUnit(0) {}
|
||||||
:mUnit(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreAudioUnit::open(bool voice)
|
void CoreAudioUnit::open(bool voice)
|
||||||
{
|
{
|
||||||
@@ -84,9 +80,7 @@ void CoreAudioUnit::open(bool voice)
|
|||||||
#ifdef TARGET_IOS
|
#ifdef TARGET_IOS
|
||||||
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
|
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
|
||||||
/* We want to be able to open playback and recording streams */
|
/* We want to be able to open playback and recording streams */
|
||||||
ostatus = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
|
ostatus = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
|
||||||
sizeof(audioCategory),
|
|
||||||
&audioCategory);
|
|
||||||
if (ostatus != kAudioSessionNoError)
|
if (ostatus != kAudioSessionNoError)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot set audio session to PlaybackAndRecord category, error" << ostatus);
|
ICELogError(<< "Cannot set audio session to PlaybackAndRecord category, error" << ostatus);
|
||||||
@@ -101,7 +95,8 @@ void CoreAudioUnit::open(bool voice)
|
|||||||
#ifdef TARGET_IOS
|
#ifdef TARGET_IOS
|
||||||
desc.componentSubType = voice ? kAudioUnitSubType_VoiceProcessingIO : kAudioUnitSubType_RemoteIO;
|
desc.componentSubType = voice ? kAudioUnitSubType_VoiceProcessingIO : kAudioUnitSubType_RemoteIO;
|
||||||
#else
|
#else
|
||||||
desc.componentSubType = kAudioUnitSubType_HALOutput;//voice ? kAudioUnitSubType_VoiceProcessingIO : kAudioUnitSubType_DefaultOutput;
|
desc.componentSubType =
|
||||||
|
kAudioUnitSubType_HALOutput; // voice ? kAudioUnitSubType_VoiceProcessingIO : kAudioUnitSubType_DefaultOutput;
|
||||||
#endif
|
#endif
|
||||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||||
desc.componentFlags = 0;
|
desc.componentFlags = 0;
|
||||||
@@ -153,12 +148,8 @@ AudioStreamBasicDescription CoreAudioUnit::getFormat(int scope, int bus)
|
|||||||
|
|
||||||
void CoreAudioUnit::setFormat(AudioStreamBasicDescription& format, int scope, int bus)
|
void CoreAudioUnit::setFormat(AudioStreamBasicDescription& format, int scope, int bus)
|
||||||
{
|
{
|
||||||
OSStatus ostatus = AudioUnitSetProperty(mUnit,
|
OSStatus ostatus =
|
||||||
kAudioUnitProperty_StreamFormat,
|
AudioUnitSetProperty(mUnit, kAudioUnitProperty_StreamFormat, scope, bus, &format, sizeof(format));
|
||||||
scope,
|
|
||||||
bus,
|
|
||||||
&format,
|
|
||||||
sizeof(format));
|
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot set stream format, error " << int(ostatus));
|
ICELogError(<< "Cannot set stream format, error " << int(ostatus));
|
||||||
@@ -181,12 +172,8 @@ bool CoreAudioUnit::getEnabled(int scope, int bus)
|
|||||||
void CoreAudioUnit::setEnabled(bool enabled, int scope, int bus)
|
void CoreAudioUnit::setEnabled(bool enabled, int scope, int bus)
|
||||||
{
|
{
|
||||||
UInt32 enable = enabled ? 1 : 0;
|
UInt32 enable = enabled ? 1 : 0;
|
||||||
OSStatus ostatus = AudioUnitSetProperty(mUnit,
|
OSStatus ostatus =
|
||||||
kAudioOutputUnitProperty_EnableIO,
|
AudioUnitSetProperty(mUnit, kAudioOutputUnitProperty_EnableIO, scope, bus, &enable, sizeof(enable));
|
||||||
scope,
|
|
||||||
bus,
|
|
||||||
&enable,
|
|
||||||
sizeof(enable));
|
|
||||||
|
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
{
|
{
|
||||||
@@ -197,12 +184,8 @@ void CoreAudioUnit::setEnabled(bool enabled, int scope, int bus)
|
|||||||
|
|
||||||
void CoreAudioUnit::makeCurrent(AudioDeviceID deviceId, int scope, int bus)
|
void CoreAudioUnit::makeCurrent(AudioDeviceID deviceId, int scope, int bus)
|
||||||
{
|
{
|
||||||
OSStatus ostatus = AudioUnitSetProperty(mUnit,
|
OSStatus ostatus =
|
||||||
kAudioOutputUnitProperty_CurrentDevice,
|
AudioUnitSetProperty(mUnit, kAudioOutputUnitProperty_CurrentDevice, scope, bus, &deviceId, sizeof(deviceId));
|
||||||
scope,
|
|
||||||
bus,
|
|
||||||
&deviceId,
|
|
||||||
sizeof(deviceId));
|
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot make device " << int(deviceId) << " current, error " << ostatus);
|
ICELogError(<< "Cannot make device " << int(deviceId) << " current, error " << ostatus);
|
||||||
@@ -213,12 +196,7 @@ void CoreAudioUnit::makeCurrent(AudioDeviceID deviceId, int scope, int bus)
|
|||||||
|
|
||||||
void CoreAudioUnit::setCallback(AURenderCallbackStruct cb, int callbackType, int scope, int bus)
|
void CoreAudioUnit::setCallback(AURenderCallbackStruct cb, int callbackType, int scope, int bus)
|
||||||
{
|
{
|
||||||
OSStatus ostatus = AudioUnitSetProperty(mUnit,
|
OSStatus ostatus = AudioUnitSetProperty(mUnit, callbackType, scope, bus, &cb, sizeof(cb));
|
||||||
callbackType,
|
|
||||||
scope,
|
|
||||||
bus,
|
|
||||||
&cb,
|
|
||||||
sizeof(cb));
|
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot set callback pointer, error " << int(ostatus));
|
ICELogError(<< "Cannot set callback pointer, error " << int(ostatus));
|
||||||
@@ -230,7 +208,8 @@ void CoreAudioUnit::setBufferFrameSizeInMilliseconds(int ms)
|
|||||||
{
|
{
|
||||||
#ifdef TARGET_IOS
|
#ifdef TARGET_IOS
|
||||||
Float32 preferredBufferSize = Float32(ms) / 1000; // in seconds
|
Float32 preferredBufferSize = Float32(ms) / 1000; // in seconds
|
||||||
OSStatus ostatus = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
|
OSStatus ostatus = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration,
|
||||||
|
sizeof(preferredBufferSize), &preferredBufferSize);
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot set audio buffer length to " << ms << " milliseconds");
|
ICELogError(<< "Cannot set audio buffer length to " << ms << " milliseconds");
|
||||||
@@ -245,12 +224,8 @@ int CoreAudioUnit::getBufferFrameSize()
|
|||||||
{
|
{
|
||||||
UInt32 bufsize = 0;
|
UInt32 bufsize = 0;
|
||||||
UInt32 size = sizeof(UInt32);
|
UInt32 size = sizeof(UInt32);
|
||||||
OSStatus ostatus = AudioUnitGetProperty(mUnit,
|
OSStatus ostatus = AudioUnitGetProperty(mUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
|
||||||
kAudioDevicePropertyBufferFrameSize,
|
Bus_Speaker, &bufsize, &size);
|
||||||
kAudioUnitScope_Global,
|
|
||||||
Bus_Speaker,
|
|
||||||
&bufsize,
|
|
||||||
&size);
|
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot obtain input buffer size , error " << int(ostatus));
|
ICELogError(<< "Cannot obtain input buffer size , error " << int(ostatus));
|
||||||
@@ -274,11 +249,8 @@ AudioUnit CoreAudioUnit::getHandle()
|
|||||||
return mUnit;
|
return mUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
OSStatus MacDevice::outputCallback( void *inRefCon,
|
OSStatus MacDevice::outputCallback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
AudioUnitRenderActionFlags *ioActionFlags,
|
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||||
const AudioTimeStamp *inTimeStamp,
|
|
||||||
UInt32 inBusNumber,
|
|
||||||
UInt32 inNumberFrames,
|
|
||||||
AudioBufferList* ioData)
|
AudioBufferList* ioData)
|
||||||
{
|
{
|
||||||
MacDevice* d = reinterpret_cast<MacDevice*>(inRefCon);
|
MacDevice* d = reinterpret_cast<MacDevice*>(inRefCon);
|
||||||
@@ -293,8 +265,7 @@ OSStatus MacDevice::outputCallback( void *inRefCon,
|
|||||||
AudioBuffer& ab = ioData->mBuffers[0];
|
AudioBuffer& ab = ioData->mBuffers[0];
|
||||||
if (ab.mNumberChannels == 1)
|
if (ab.mNumberChannels == 1)
|
||||||
{
|
{
|
||||||
ICELogMedia(<< "CoreAudio output callback for mono " << (int)ab.mDataByteSize <<
|
ICELogMedia(<< "CoreAudio output callback for mono " << (int)ab.mDataByteSize << " bytes");
|
||||||
" bytes");
|
|
||||||
memset(ab.mData, 0, ab.mDataByteSize);
|
memset(ab.mData, 0, ab.mDataByteSize);
|
||||||
d->provideAudioToSpeaker(ab.mNumberChannels, ab.mData, ab.mDataByteSize);
|
d->provideAudioToSpeaker(ab.mNumberChannels, ab.mData, ab.mDataByteSize);
|
||||||
|
|
||||||
@@ -303,8 +274,7 @@ OSStatus MacDevice::outputCallback( void *inRefCon,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ICELogMedia(<< "CoreAudio output callback for stereo " << (int)ab.mDataByteSize <<
|
ICELogMedia(<< "CoreAudio output callback for stereo " << (int)ab.mDataByteSize << " bytes")
|
||||||
" bytes")
|
|
||||||
// Iterate requested buffers
|
// Iterate requested buffers
|
||||||
for (unsigned i = 0; i < ioData->mNumberBuffers; i++)
|
for (unsigned i = 0; i < ioData->mNumberBuffers; i++)
|
||||||
{
|
{
|
||||||
@@ -325,11 +295,8 @@ OSStatus MacDevice::outputCallback( void *inRefCon,
|
|||||||
|
|
||||||
static char GlobalInputBuffer[AUDIO_MIC_BUFFER_COUNT * AUDIO_MIC_BUFFER_SIZE];
|
static char GlobalInputBuffer[AUDIO_MIC_BUFFER_COUNT * AUDIO_MIC_BUFFER_SIZE];
|
||||||
|
|
||||||
OSStatus MacDevice::inputCallback(void *inRefCon,
|
OSStatus MacDevice::inputCallback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
AudioUnitRenderActionFlags *ioActionFlags,
|
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||||
const AudioTimeStamp *inTimeStamp,
|
|
||||||
UInt32 inBusNumber,
|
|
||||||
UInt32 inNumberFrames,
|
|
||||||
AudioBufferList* ioData)
|
AudioBufferList* ioData)
|
||||||
{
|
{
|
||||||
// ICELogDebug(<< "CoreAudio input callback");
|
// ICELogDebug(<< "CoreAudio input callback");
|
||||||
@@ -346,11 +313,7 @@ OSStatus MacDevice::inputCallback(void *inRefCon,
|
|||||||
b.mDataByteSize = inNumberFrames * d->mStreamFormat.mChannelsPerFrame;
|
b.mDataByteSize = inNumberFrames * d->mStreamFormat.mChannelsPerFrame;
|
||||||
|
|
||||||
// Render the unit to get input data
|
// Render the unit to get input data
|
||||||
ostatus = AudioUnitRender(d->mAudioUnit.getHandle(),
|
ostatus = AudioUnitRender(d->mAudioUnit.getHandle(), ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames,
|
||||||
ioActionFlags,
|
|
||||||
inTimeStamp,
|
|
||||||
inBusNumber,
|
|
||||||
inNumberFrames,
|
|
||||||
d->mInputBufferList);
|
d->mInputBufferList);
|
||||||
|
|
||||||
if (ostatus != noErr)
|
if (ostatus != noErr)
|
||||||
@@ -365,10 +328,7 @@ OSStatus MacDevice::inputCallback(void *inRefCon,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_IOS
|
#ifdef TARGET_IOS
|
||||||
void MacDevice::propListener(void *inClientData,
|
void MacDevice::propListener(void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inData)
|
||||||
AudioSessionPropertyID inID,
|
|
||||||
UInt32 inDataSize,
|
|
||||||
const void * inData)
|
|
||||||
{
|
{
|
||||||
MacDevice* d = reinterpret_cast<MacDevice*>(inClientData);
|
MacDevice* d = reinterpret_cast<MacDevice*>(inClientData);
|
||||||
CFDictionaryRef routeDictionary;
|
CFDictionaryRef routeDictionary;
|
||||||
@@ -388,7 +348,6 @@ void MacDevice::propListener(void *inClientData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Audio route changed. Nothing to do in this implementation.
|
// Audio route changed. Nothing to do in this implementation.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacDevice::interruptionListener(void* inClientData, UInt32 inInterruption)
|
void MacDevice::interruptionListener(void* inClientData, UInt32 inInterruption)
|
||||||
@@ -409,9 +368,7 @@ void MacDevice::interruptionListener(void *inClientData, UInt32 inInterruption)
|
|||||||
*/
|
*/
|
||||||
/* Make sure we set the correct audio category before restarting */
|
/* Make sure we set the correct audio category before restarting */
|
||||||
audioCategory = kAudioSessionCategory_PlayAndRecord;
|
audioCategory = kAudioSessionCategory_PlayAndRecord;
|
||||||
ostatus = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
|
ostatus = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
|
||||||
sizeof(audioCategory),
|
|
||||||
&audioCategory);
|
|
||||||
if (ostatus != kAudioSessionNoError)
|
if (ostatus != kAudioSessionNoError)
|
||||||
{
|
{
|
||||||
ICELogError(<< "Cannot set the audio session category, error " << ostatus);
|
ICELogError(<< "Cannot set the audio session category, error " << ostatus);
|
||||||
@@ -420,8 +377,7 @@ void MacDevice::interruptionListener(void *inClientData, UInt32 inInterruption)
|
|||||||
// Start stream
|
// Start stream
|
||||||
d->startStream();
|
d->startStream();
|
||||||
}
|
}
|
||||||
else
|
else if (inInterruption == kAudioSessionBeginInterruption)
|
||||||
if (inInterruption == kAudioSessionBeginInterruption)
|
|
||||||
{
|
{
|
||||||
d->stopStream();
|
d->stopStream();
|
||||||
}
|
}
|
||||||
@@ -429,16 +385,13 @@ void MacDevice::interruptionListener(void *inClientData, UInt32 inInterruption)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
MacDevice::MacDevice(int devId)
|
MacDevice::MacDevice(int devId)
|
||||||
:mDeviceId(devId), mCapture(false), mRender(false), mActive(false),
|
: mDeviceId(devId), mCapture(false), mRender(false), mActive(false), mConnection(nullptr), mUsageCount(0)
|
||||||
mConnection(nullptr), mUsageCount(0)
|
|
||||||
{
|
{
|
||||||
mInputBuffer.setCapacity(AUDIO_MIC_BUFFER_COUNT * AUDIO_MIC_BUFFER_SIZE);
|
mInputBuffer.setCapacity(AUDIO_MIC_BUFFER_COUNT * AUDIO_MIC_BUFFER_SIZE);
|
||||||
mOutputBuffer.setCapacity(AUDIO_SPK_BUFFER_SIZE);
|
mOutputBuffer.setCapacity(AUDIO_SPK_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
MacDevice::~MacDevice()
|
MacDevice::~MacDevice() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DataConnection* MacDevice::connection()
|
DataConnection* MacDevice::connection()
|
||||||
{
|
{
|
||||||
@@ -582,7 +535,8 @@ bool MacDevice::createUnit(bool voice)
|
|||||||
// Start resample
|
// Start resample
|
||||||
mRenderResampler.start(mStreamFormat.mChannelsPerFrame, AUDIO_SAMPLERATE, mStreamFormat.mSampleRate);
|
mRenderResampler.start(mStreamFormat.mChannelsPerFrame, AUDIO_SAMPLERATE, mStreamFormat.mSampleRate);
|
||||||
|
|
||||||
// Set current render format - it is format required by unit from application; scope is Input and bus is 0 (speaker)
|
// Set current render format - it is format required by unit from application; scope is Input and bus is 0
|
||||||
|
// (speaker)
|
||||||
// mAudioUnit.setFormat(mRenderInputFormat, kAudioUnitScope_Input, Bus_Speaker);
|
// mAudioUnit.setFormat(mRenderInputFormat, kAudioUnitScope_Input, Bus_Speaker);
|
||||||
|
|
||||||
// Configure callback
|
// Configure callback
|
||||||
@@ -597,7 +551,8 @@ bool MacDevice::createUnit(bool voice)
|
|||||||
AURenderCallbackStruct cb;
|
AURenderCallbackStruct cb;
|
||||||
cb.inputProc = inputCallback;
|
cb.inputProc = inputCallback;
|
||||||
cb.inputProcRefCon = this;
|
cb.inputProcRefCon = this;
|
||||||
mAudioUnit.setCallback(cb, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, Bus_Microphone); //!!!
|
mAudioUnit.setCallback(cb, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global,
|
||||||
|
Bus_Microphone); //!!!
|
||||||
#ifdef TARGET_OSX
|
#ifdef TARGET_OSX
|
||||||
AudioBuffer* ab;
|
AudioBuffer* ab;
|
||||||
UInt32 size, bufsize;
|
UInt32 size, bufsize;
|
||||||
@@ -663,7 +618,8 @@ void MacDevice::startStream()
|
|||||||
|
|
||||||
// Share audio chain
|
// Share audio chain
|
||||||
// UInt32 allowMixing = YES;
|
// UInt32 allowMixing = YES;
|
||||||
//AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (allowMixing), &allowMixing);
|
// AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (allowMixing),
|
||||||
|
// &allowMixing);
|
||||||
|
|
||||||
// Activate audio chain
|
// Activate audio chain
|
||||||
AudioSessionSetActive(true);
|
AudioSessionSetActive(true);
|
||||||
@@ -721,15 +677,9 @@ protected:
|
|||||||
|
|
||||||
MacDeviceList* MacDeviceList::mInstance = NULL;
|
MacDeviceList* MacDeviceList::mInstance = NULL;
|
||||||
|
|
||||||
MacDeviceList::MacDeviceList()
|
MacDeviceList::MacDeviceList() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
MacDeviceList::~MacDeviceList() {}
|
||||||
|
|
||||||
MacDeviceList::~MacDeviceList()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MacDeviceList& MacDeviceList::instance()
|
MacDeviceList& MacDeviceList::instance()
|
||||||
{
|
{
|
||||||
@@ -754,8 +704,7 @@ PMacDevice MacDeviceList::findDevice(int devId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Share list of opened devices
|
// Share list of opened devices
|
||||||
MacInputDevice::MacInputDevice(int devId)
|
MacInputDevice::MacInputDevice(int devId) : InputDevice()
|
||||||
:InputDevice()
|
|
||||||
{
|
{
|
||||||
// Look for MacDevice
|
// Look for MacDevice
|
||||||
mDevice = MacDeviceList::instance().findDevice(devId);
|
mDevice = MacDeviceList::instance().findDevice(devId);
|
||||||
@@ -784,8 +733,7 @@ Format MacInputDevice::getFormat()
|
|||||||
return mDevice->getFormat();
|
return mDevice->getFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
MacOutputDevice::MacOutputDevice(int devId)
|
MacOutputDevice::MacOutputDevice(int devId) : OutputDevice()
|
||||||
:OutputDevice()
|
|
||||||
{
|
{
|
||||||
// Look for MacDevice
|
// Look for MacDevice
|
||||||
mDevice = MacDeviceList::instance().findDevice(devId);
|
mDevice = MacDeviceList::instance().findDevice(devId);
|
||||||
@@ -814,16 +762,9 @@ Format MacOutputDevice::getFormat()
|
|||||||
return mDevice->getFormat();
|
return mDevice->getFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
MacEnumerator::MacEnumerator()
|
MacEnumerator::MacEnumerator() : mDefaultInput(0), mDefaultOutput(0) {}
|
||||||
:mDefaultInput(0), mDefaultOutput(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
MacEnumerator::~MacEnumerator() {}
|
||||||
|
|
||||||
MacEnumerator::~MacEnumerator()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacEnumerator::open(int direction)
|
void MacEnumerator::open(int direction)
|
||||||
{
|
{
|
||||||
@@ -841,8 +782,7 @@ void MacEnumerator::open(int direction)
|
|||||||
addr.mSelector = kAudioHardwarePropertyDevices;
|
addr.mSelector = kAudioHardwarePropertyDevices;
|
||||||
addr.mScope = kAudioObjectPropertyScopeGlobal;
|
addr.mScope = kAudioObjectPropertyScopeGlobal;
|
||||||
addr.mElement = kAudioObjectPropertyElementMaster;
|
addr.mElement = kAudioObjectPropertyElementMaster;
|
||||||
osstatus = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
|
osstatus = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0, NULL, &devSize);
|
||||||
0, NULL, &devSize);
|
|
||||||
if (osstatus != noErr)
|
if (osstatus != noErr)
|
||||||
{
|
{
|
||||||
devSize = 0;
|
devSize = 0;
|
||||||
@@ -854,8 +794,8 @@ void MacEnumerator::open(int direction)
|
|||||||
deviceIds.resize(devCount);
|
deviceIds.resize(devCount);
|
||||||
|
|
||||||
// Get actual list
|
// Get actual list
|
||||||
osstatus = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
|
osstatus =
|
||||||
0, NULL, &devSize, (void *)&deviceIds.front());
|
AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &devSize, (void*)&deviceIds.front());
|
||||||
if (osstatus != noErr)
|
if (osstatus != noErr)
|
||||||
return;
|
return;
|
||||||
for (unsigned i = 0; i < deviceIds.size(); i++)
|
for (unsigned i = 0; i < deviceIds.size(); i++)
|
||||||
@@ -887,13 +827,12 @@ void MacEnumerator::open(int direction)
|
|||||||
addr.mElement = kAudioObjectPropertyElementMaster;
|
addr.mElement = kAudioObjectPropertyElementMaster;
|
||||||
size = sizeof(devId);
|
size = sizeof(devId);
|
||||||
|
|
||||||
osstatus = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
osstatus = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, (void*)&devId);
|
||||||
&addr, 0, NULL, &size, (void *)&devId);
|
|
||||||
|
|
||||||
if (osstatus == noErr)
|
if (osstatus == noErr)
|
||||||
{
|
{
|
||||||
std::vector<DeviceInfo>::iterator r = std::find_if(mDeviceList.begin(), mDeviceList.end(),
|
std::vector<DeviceInfo>::iterator r = std::find_if(
|
||||||
[devId] (const DeviceInfo& di) { return di.mId == devId;});
|
mDeviceList.begin(), mDeviceList.end(), [devId](const DeviceInfo& di) { return di.mId == devId; });
|
||||||
if (r != mDeviceList.end())
|
if (r != mDeviceList.end())
|
||||||
mDefaultInput = r - mDeviceList.begin();
|
mDefaultInput = r - mDeviceList.begin();
|
||||||
}
|
}
|
||||||
@@ -903,13 +842,11 @@ void MacEnumerator::open(int direction)
|
|||||||
if (direction == mySpeaker)
|
if (direction == mySpeaker)
|
||||||
{
|
{
|
||||||
addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||||
osstatus = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
osstatus = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, (void*)&devId);
|
||||||
&addr, 0, NULL,
|
|
||||||
&size, (void *)&devId);
|
|
||||||
if (osstatus == noErr)
|
if (osstatus == noErr)
|
||||||
{
|
{
|
||||||
std::vector<DeviceInfo>::iterator r = std::find_if(mDeviceList.begin(), mDeviceList.end(),
|
std::vector<DeviceInfo>::iterator r = std::find_if(
|
||||||
[devId](const DeviceInfo& di) { return di.mId == devId;});
|
mDeviceList.begin(), mDeviceList.end(), [devId](const DeviceInfo& di) { return di.mId == devId; });
|
||||||
if (r != mDeviceList.end())
|
if (r != mDeviceList.end())
|
||||||
mDefaultOutput = r - mDeviceList.begin();
|
mDefaultOutput = r - mDeviceList.begin();
|
||||||
}
|
}
|
||||||
@@ -984,7 +921,8 @@ void MacEnumerator::getInfo(DeviceInfo &di)
|
|||||||
di.mOutputCount += buf->mBuffers[idx].mNumberChannels;
|
di.mOutputCount += buf->mBuffers[idx].mNumberChannels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(buf); buf = NULL;
|
free(buf);
|
||||||
|
buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get default sample rate */
|
/* Get default sample rate */
|
||||||
@@ -1009,10 +947,7 @@ void MacEnumerator::getInfo(DeviceInfo &di)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacEnumerator::close()
|
void MacEnumerator::close() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int MacEnumerator::count()
|
int MacEnumerator::count()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ namespace Audio
|
|||||||
class AudioException : public Exception
|
class AudioException : public Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioException(int code, OSStatus subcode)
|
AudioException(int code, OSStatus subcode) : Exception(code, int(subcode)) {}
|
||||||
:Exception(code, int(subcode))
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// #ifndef AudioDeviceID
|
// #ifndef AudioDeviceID
|
||||||
@@ -59,7 +57,11 @@ protected:
|
|||||||
bool mCanChangeInputVolume;
|
bool mCanChangeInputVolume;
|
||||||
int mInputCount, mOutputCount;
|
int mInputCount, mOutputCount;
|
||||||
int mDefaultRate;
|
int mDefaultRate;
|
||||||
DeviceInfo(): mId(0), mCanChangeOutputVolume(false), mCanChangeInputVolume(false), mInputCount(0), mOutputCount(0), mDefaultRate(16000) {}
|
DeviceInfo()
|
||||||
|
: mId(0), mCanChangeOutputVolume(false), mCanChangeInputVolume(false), mInputCount(0), mOutputCount(0),
|
||||||
|
mDefaultRate(16000)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
std::vector<DeviceInfo> mDeviceList;
|
std::vector<DeviceInfo> mDeviceList;
|
||||||
unsigned mDefaultInput, mDefaultOutput;
|
unsigned mDefaultInput, mDefaultOutput;
|
||||||
@@ -117,7 +119,8 @@ protected:
|
|||||||
|
|
||||||
CoreAudioUnit mAudioUnit;
|
CoreAudioUnit mAudioUnit;
|
||||||
AudioComponent mComponent;
|
AudioComponent mComponent;
|
||||||
AudioStreamBasicDescription mCaptureInputFormat, mCaptureOutputFormat, mRenderInputFormat, mRenderOutputFormat, mStreamFormat;
|
AudioStreamBasicDescription mCaptureInputFormat, mCaptureOutputFormat, mRenderInputFormat, mRenderOutputFormat,
|
||||||
|
mStreamFormat;
|
||||||
AudioBufferList* mInputBufferList;
|
AudioBufferList* mInputBufferList;
|
||||||
DataConnection* mConnection;
|
DataConnection* mConnection;
|
||||||
SpeexResampler mCaptureResampler, mRenderResampler;
|
SpeexResampler mCaptureResampler, mRenderResampler;
|
||||||
@@ -130,27 +133,17 @@ protected:
|
|||||||
void setupStreamFormat();
|
void setupStreamFormat();
|
||||||
bool createResampleUnit(AudioStreamBasicDescription format);
|
bool createResampleUnit(AudioStreamBasicDescription format);
|
||||||
|
|
||||||
static OSStatus outputCallback( void *inRefCon,
|
static OSStatus outputCallback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
AudioUnitRenderActionFlags *ioActionFlags,
|
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||||
const AudioTimeStamp *inTimeStamp,
|
|
||||||
UInt32 inBusNumber,
|
|
||||||
UInt32 inNumberFrames,
|
|
||||||
AudioBufferList* ioData);
|
AudioBufferList* ioData);
|
||||||
|
|
||||||
static OSStatus inputCallback(void *inRefCon,
|
static OSStatus inputCallback(void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
AudioUnitRenderActionFlags *ioActionFlags,
|
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||||
const AudioTimeStamp *inTimeStamp,
|
|
||||||
UInt32 inBusNumber,
|
|
||||||
UInt32 inNumberFrames,
|
|
||||||
AudioBufferList* ioData);
|
AudioBufferList* ioData);
|
||||||
#ifdef TARGET_IOS
|
#ifdef TARGET_IOS
|
||||||
static void propListener(void *inClientData,
|
static void propListener(void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inData);
|
||||||
AudioSessionPropertyID inID,
|
|
||||||
UInt32 inDataSize,
|
|
||||||
const void * inData);
|
|
||||||
static void interruptionListener(void* inClientData, UInt32 inInterruption);
|
static void interruptionListener(void* inClientData, UInt32 inInterruption);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<MacDevice> PMacDevice;
|
typedef std::shared_ptr<MacDevice> PMacDevice;
|
||||||
@@ -168,9 +161,9 @@ public:
|
|||||||
bool fakeMode();
|
bool fakeMode();
|
||||||
void setFakeMode(bool fakemode);
|
void setFakeMode(bool fakemode);
|
||||||
int readBuffer(void* buffer);
|
int readBuffer(void* buffer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PMacDevice mDevice;
|
PMacDevice mDevice;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacOutputDevice : public OutputDevice
|
class MacOutputDevice : public OutputDevice
|
||||||
@@ -190,7 +183,7 @@ protected:
|
|||||||
PMacDevice mDevice;
|
PMacDevice mDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif // TARGET_OSX
|
#endif // TARGET_OSX
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
|
|
||||||
using namespace Audio;
|
using namespace Audio;
|
||||||
|
|
||||||
DataWindow::DataWindow()
|
DataWindow::DataWindow() {}
|
||||||
{}
|
|
||||||
|
|
||||||
DataWindow::~DataWindow()
|
DataWindow::~DataWindow()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,5 +47,5 @@ protected:
|
|||||||
size_t mFilled = 0;
|
size_t mFilled = 0;
|
||||||
size_t mCapacity = 0;
|
size_t mCapacity = 0;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Audio
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ using namespace Audio;
|
|||||||
|
|
||||||
// --- DevicePair ---
|
// --- DevicePair ---
|
||||||
DevicePair::DevicePair()
|
DevicePair::DevicePair()
|
||||||
:mConfig(nullptr), mDelegate(nullptr), mAec(false), mAgc(false), mAecFilter(AUDIO_MIC_BUFFER_LENGTH*10, AUDIO_MIC_BUFFER_LENGTH, AUDIO_SAMPLERATE), mAgcFilter(AUDIO_CHANNELS),
|
: mConfig(nullptr), mDelegate(nullptr), mAec(false), mAgc(false),
|
||||||
|
mAecFilter(AUDIO_MIC_BUFFER_LENGTH * 10, AUDIO_MIC_BUFFER_LENGTH, AUDIO_SAMPLERATE), mAgcFilter(AUDIO_CHANNELS),
|
||||||
mMonitoring(nullptr)
|
mMonitoring(nullptr)
|
||||||
{
|
{
|
||||||
mInputBuffer.setCapacity(AUDIO_MIC_BUFFER_SIZE * (AUDIO_MIC_BUFFER_COUNT + 1));
|
mInputBuffer.setCapacity(AUDIO_MIC_BUFFER_SIZE * (AUDIO_MIC_BUFFER_COUNT + 1));
|
||||||
@@ -176,7 +177,6 @@ void DevicePair::onMicData(const Format& f, const void* buffer, int length)
|
|||||||
|
|
||||||
for (int blockIndex = 0; blockIndex < blocks; blockIndex++)
|
for (int blockIndex = 0; blockIndex < blocks; blockIndex++)
|
||||||
{
|
{
|
||||||
|
|
||||||
size_t wasProcessed = 0;
|
size_t wasProcessed = 0;
|
||||||
|
|
||||||
size_t wasProduced = mMicResampler.resample(f.mRate, // Source rate
|
size_t wasProduced = mMicResampler.resample(f.mRate, // Source rate
|
||||||
@@ -193,7 +193,6 @@ void DevicePair::onMicData(const Format& f, const void* buffer, int length)
|
|||||||
|
|
||||||
mInputBuffer.erase((int)Format().sizeFromTime(AUDIO_MIC_BUFFER_LENGTH));
|
mInputBuffer.erase((int)Format().sizeFromTime(AUDIO_MIC_BUFFER_LENGTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevicePair::onSpkData(const Format& f, void* buffer, int length)
|
void DevicePair::onSpkData(const Format& f, void* buffer, int length)
|
||||||
@@ -215,7 +214,6 @@ void DevicePair::onSpkData(const Format& f, void* buffer, int length)
|
|||||||
int required = length - mOutputNativeData.filled();
|
int required = length - mOutputNativeData.filled();
|
||||||
if (required > 0)
|
if (required > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Find how much blocks must be received from RTP/decoder side
|
// Find how much blocks must be received from RTP/decoder side
|
||||||
int nativeBufferSize = (int)nativeFormat.sizeFromTime(AUDIO_SPK_BUFFER_LENGTH);
|
int nativeBufferSize = (int)nativeFormat.sizeFromTime(AUDIO_SPK_BUFFER_LENGTH);
|
||||||
int blocks = required / nativeBufferSize;
|
int blocks = required / nativeBufferSize;
|
||||||
@@ -240,10 +238,8 @@ void DevicePair::onSpkData(const Format& f, void* buffer, int length)
|
|||||||
|
|
||||||
// Resample these 10 milliseconds it to native format
|
// Resample these 10 milliseconds it to native format
|
||||||
size_t wasProcessed = 0;
|
size_t wasProcessed = 0;
|
||||||
size_t wasProduced = mSpkResampler.resample(Format().mRate,
|
size_t wasProduced = mSpkResampler.resample(Format().mRate, mOutput10msBuffer.data(),
|
||||||
mOutput10msBuffer.data(),
|
mOutput10msBuffer.capacity(), wasProcessed, f.mRate,
|
||||||
mOutput10msBuffer.capacity(),
|
|
||||||
wasProcessed, f.mRate,
|
|
||||||
mOutputNativeData.mutableData() + mOutputNativeData.filled(),
|
mOutputNativeData.mutableData() + mOutputNativeData.filled(),
|
||||||
mOutputNativeData.capacity() - mOutputNativeData.filled());
|
mOutputNativeData.capacity() - mOutputNativeData.filled());
|
||||||
mOutputNativeData.setFilled(mOutputNativeData.filled() + wasProduced);
|
mOutputNativeData.setFilled(mOutputNativeData.filled() + wasProduced);
|
||||||
|
|||||||
@@ -80,6 +80,6 @@ namespace Audio
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<DevicePair> PDevicePair;
|
typedef std::shared_ptr<DevicePair> PDevicePair;
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -57,10 +57,7 @@ protected:
|
|||||||
|
|
||||||
DSoundInit gDSoundInit;
|
DSoundInit gDSoundInit;
|
||||||
|
|
||||||
DSoundInit::DSoundInit()
|
DSoundInit::DSoundInit() : mRefCount(0) {}
|
||||||
:mRefCount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DSoundInit::~DSoundInit()
|
DSoundInit::~DSoundInit()
|
||||||
{
|
{
|
||||||
@@ -82,10 +79,15 @@ void DSoundInit::load()
|
|||||||
if (!mRoutines.mInstance)
|
if (!mRoutines.mInstance)
|
||||||
throw std::logic_error("Cannot load dsound.dll");
|
throw std::logic_error("Cannot load dsound.dll");
|
||||||
|
|
||||||
mRoutines.DirectSoundCaptureCreate8 = (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE8 *, LPUNKNOWN))::GetProcAddress(mRoutines.mInstance, "DirectSoundCaptureCreate8");
|
mRoutines.DirectSoundCaptureCreate8 =
|
||||||
mRoutines.DirectSoundCaptureEnumerateW = (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))::GetProcAddress(mRoutines.mInstance, "DirectSoundCaptureEnumerateW");
|
(HRESULT(WINAPI*)(LPGUID, LPDIRECTSOUNDCAPTURE8*, LPUNKNOWN))::GetProcAddress(mRoutines.mInstance,
|
||||||
mRoutines.DirectSoundCreate8 = (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND8 *, LPUNKNOWN))::GetProcAddress(mRoutines.mInstance, "DirectSoundCreate8");
|
"DirectSoundCaptureCreate8");
|
||||||
mRoutines.DirectSoundEnumerateW = (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))::GetProcAddress(mRoutines.mInstance, "DirectSoundEnumerateW");
|
mRoutines.DirectSoundCaptureEnumerateW = (HRESULT(WINAPI*)(LPDSENUMCALLBACKW, LPVOID))::GetProcAddress(
|
||||||
|
mRoutines.mInstance, "DirectSoundCaptureEnumerateW");
|
||||||
|
mRoutines.DirectSoundCreate8 = (HRESULT(WINAPI*)(LPGUID, LPDIRECTSOUND8*, LPUNKNOWN))::GetProcAddress(
|
||||||
|
mRoutines.mInstance, "DirectSoundCreate8");
|
||||||
|
mRoutines.DirectSoundEnumerateW =
|
||||||
|
(HRESULT(WINAPI*)(LPDSENUMCALLBACKW, LPVOID))::GetProcAddress(mRoutines.mInstance, "DirectSoundEnumerateW");
|
||||||
mRoutines.GetDeviceID = (HRESULT(WINAPI*)(LPCGUID, LPGUID))GetProcAddress(mRoutines.mInstance, "GetDeviceID");
|
mRoutines.GetDeviceID = (HRESULT(WINAPI*)(LPCGUID, LPGUID))GetProcAddress(mRoutines.mInstance, "GetDeviceID");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,10 +108,7 @@ void DSoundInit::unload()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------- VistaEnumerator ---------------------
|
// --------------- VistaEnumerator ---------------------
|
||||||
VistaEnumerator::VistaEnumerator()
|
VistaEnumerator::VistaEnumerator() : mCollection(NULL), mDefaultDevice(NULL), mEnumerator(NULL), mDirection(eCapture) {}
|
||||||
:mCollection(NULL), mDefaultDevice(NULL), mEnumerator(NULL), mDirection(eCapture)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VistaEnumerator::~VistaEnumerator()
|
VistaEnumerator::~VistaEnumerator()
|
||||||
{
|
{
|
||||||
@@ -123,10 +122,8 @@ void VistaEnumerator::open(int direction)
|
|||||||
|
|
||||||
mDirection = (direction == myMicrophone) ? eCapture : eRender;
|
mDirection = (direction == myMicrophone) ? eCapture : eRender;
|
||||||
|
|
||||||
HRESULT hr = CoCreateInstance(
|
HRESULT hr =
|
||||||
CLSID_MMDeviceEnumerator, NULL,
|
CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&mEnumerator);
|
||||||
CLSCTX_ALL, IID_IMMDeviceEnumerator,
|
|
||||||
(void**)&mEnumerator);
|
|
||||||
if (!mEnumerator)
|
if (!mEnumerator)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -258,26 +255,23 @@ int VistaEnumerator::indexOfDefaultDevice()
|
|||||||
|
|
||||||
if (mDirection == mySpeaker)
|
if (mDirection == mySpeaker)
|
||||||
{
|
{
|
||||||
if (waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
if (waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID,
|
||||||
|
(DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
||||||
waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
if (waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID,
|
||||||
|
(DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
||||||
waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
||||||
}
|
}
|
||||||
return devID;
|
return devID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------- XpEnumerator ---------------
|
// -------------- XpEnumerator ---------------
|
||||||
XpEnumerator::XpEnumerator()
|
XpEnumerator::XpEnumerator() : mDirection(-1) {}
|
||||||
:mDirection(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
XpEnumerator::~XpEnumerator()
|
XpEnumerator::~XpEnumerator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void XpEnumerator::open(int direction)
|
void XpEnumerator::open(int direction)
|
||||||
{
|
{
|
||||||
@@ -308,9 +302,7 @@ void XpEnumerator::open(int direction)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XpEnumerator::close()
|
void XpEnumerator::close() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int XpEnumerator::count()
|
int XpEnumerator::count()
|
||||||
{
|
{
|
||||||
@@ -333,12 +325,14 @@ int XpEnumerator::indexOfDefaultDevice()
|
|||||||
|
|
||||||
if (mDirection == mySpeaker)
|
if (mDirection == mySpeaker)
|
||||||
{
|
{
|
||||||
if (waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
if (waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID,
|
||||||
|
(DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
||||||
waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
if (waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR)&devID,
|
||||||
|
(DWORD_PTR)&status) != MMSYSERR_NOERROR)
|
||||||
waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&devID, (DWORD_PTR)&status);
|
||||||
}
|
}
|
||||||
return devID;
|
return devID;
|
||||||
@@ -346,10 +340,11 @@ int XpEnumerator::indexOfDefaultDevice()
|
|||||||
|
|
||||||
// -------- DSoundInputDevice ---------------
|
// -------- DSoundInputDevice ---------------
|
||||||
DSoundInputDevice::DSoundInputDevice(GUID deviceId)
|
DSoundInputDevice::DSoundInputDevice(GUID deviceId)
|
||||||
:mSimulate(false), mBufferIndex(0), mGUID(deviceId), mThreadHandle(0), mDenoiser(AUDIO_SAMPLERATE), mEnableDenoiser(true),
|
: mSimulate(false), mBufferIndex(0), mGUID(deviceId), mThreadHandle(0), mDenoiser(AUDIO_SAMPLERATE),
|
||||||
mNullAudio(AUDIO_MIC_BUFFER_LENGTH, AUDIO_MIC_BUFFER_COUNT)
|
mEnableDenoiser(true), mNullAudio(AUDIO_MIC_BUFFER_LENGTH, AUDIO_MIC_BUFFER_COUNT)
|
||||||
#ifdef AUDIO_DUMPINPUT
|
#ifdef AUDIO_DUMPINPUT
|
||||||
,mDump(AUDIO_SAMPLERATE)
|
,
|
||||||
|
mDump(AUDIO_SAMPLERATE)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
gDSoundInit.load();
|
gDSoundInit.load();
|
||||||
@@ -389,8 +384,7 @@ bool DSoundInputDevice::isSimulate() const
|
|||||||
|
|
||||||
void DSoundInputDevice::openDevice()
|
void DSoundInputDevice::openDevice()
|
||||||
{
|
{
|
||||||
ICELogInfo(<< "Open DirectSound audio input.")
|
ICELogInfo(<< "Open DirectSound audio input.")::CoInitialize(NULL);
|
||||||
::CoInitialize(NULL);
|
|
||||||
Lock l(mGuard);
|
Lock l(mGuard);
|
||||||
// Ensure if GUID is not null
|
// Ensure if GUID is not null
|
||||||
if (IsEqualGUID(mGUID, GUID_NULL))
|
if (IsEqualGUID(mGUID, GUID_NULL))
|
||||||
@@ -404,7 +398,10 @@ void DSoundInputDevice::openDevice()
|
|||||||
mDump.open(L"audioinput.wav");
|
mDump.open(L"audioinput.wav");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mNextBuffer = 0; mDevice = NULL; IUnknown* unk = NULL; mBuffer = NULL;
|
mNextBuffer = 0;
|
||||||
|
mDevice = NULL;
|
||||||
|
IUnknown* unk = NULL;
|
||||||
|
mBuffer = NULL;
|
||||||
DSoundHelper::checkComResult(gDSoundInit.mRoutines.DirectSoundCaptureCreate8(&mGUID, &mDevice, NULL));
|
DSoundHelper::checkComResult(gDSoundInit.mRoutines.DirectSoundCaptureCreate8(&mGUID, &mDevice, NULL));
|
||||||
|
|
||||||
WAVEFORMATEX wfx;
|
WAVEFORMATEX wfx;
|
||||||
@@ -414,7 +411,8 @@ void DSoundInputDevice::openDevice()
|
|||||||
wfx.nChannels = AUDIO_CHANNELS;
|
wfx.nChannels = AUDIO_CHANNELS;
|
||||||
wfx.nSamplesPerSec = AUDIO_SAMPLERATE;
|
wfx.nSamplesPerSec = AUDIO_SAMPLERATE;
|
||||||
wfx.wBitsPerSample = 16;
|
wfx.wBitsPerSample = 16;
|
||||||
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;;
|
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
|
||||||
|
;
|
||||||
wfx.nAvgBytesPerSec = AUDIO_SAMPLERATE * 2 * AUDIO_CHANNELS;
|
wfx.nAvgBytesPerSec = AUDIO_SAMPLERATE * 2 * AUDIO_CHANNELS;
|
||||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
|
||||||
@@ -524,7 +522,8 @@ bool DSoundInputDevice::tryReadBuffer(void* buffer)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (::WaitForSingleObject(mEventArray[mNextBuffer].hEventNotify, AUDIO_MIC_BUFFER_COUNT * AUDIO_MIC_BUFFER_LENGTH * 4) != WAIT_OBJECT_0)
|
if (::WaitForSingleObject(mEventArray[mNextBuffer].hEventNotify,
|
||||||
|
AUDIO_MIC_BUFFER_COUNT * AUDIO_MIC_BUFFER_LENGTH * 4) != WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
setSimulate(true);
|
setSimulate(true);
|
||||||
return false;
|
return false;
|
||||||
@@ -547,7 +546,8 @@ bool DSoundInputDevice::tryReadBuffer(void* buffer)
|
|||||||
if (++mNextBuffer == AUDIO_MIC_BUFFER_COUNT)
|
if (++mNextBuffer == AUDIO_MIC_BUFFER_COUNT)
|
||||||
mNextBuffer = 0;
|
mNextBuffer = 0;
|
||||||
|
|
||||||
LPVOID ptr1 = NULL, ptr2 = NULL; DWORD len1 = 0, len2 = 0;
|
LPVOID ptr1 = NULL, ptr2 = NULL;
|
||||||
|
DWORD len1 = 0, len2 = 0;
|
||||||
DSoundHelper::checkComResult(mBuffer->Lock(mReadOffset, AUDIO_MIC_BUFFER_SIZE, &ptr1, &len1, &ptr2, &len2, 0));
|
DSoundHelper::checkComResult(mBuffer->Lock(mReadOffset, AUDIO_MIC_BUFFER_SIZE, &ptr1, &len1, &ptr2, &len2, 0));
|
||||||
|
|
||||||
// Copy&Enqueue captured data to mQueue
|
// Copy&Enqueue captured data to mQueue
|
||||||
@@ -585,8 +585,7 @@ void DSoundInputDevice::setSimulate(bool s)
|
|||||||
{
|
{
|
||||||
if (!mSimulate && s)
|
if (!mSimulate && s)
|
||||||
mNullAudio.start();
|
mNullAudio.start();
|
||||||
else
|
else if (mSimulate && !s)
|
||||||
if (mSimulate && !s)
|
|
||||||
mNullAudio.stop();
|
mNullAudio.stop();
|
||||||
|
|
||||||
mSimulate = s;
|
mSimulate = s;
|
||||||
@@ -642,10 +641,8 @@ void DSoundInputDevice::threadProc(void* arg)
|
|||||||
|
|
||||||
|
|
||||||
DSoundOutputDevice::DSoundOutputDevice(GUID deviceId)
|
DSoundOutputDevice::DSoundOutputDevice(GUID deviceId)
|
||||||
:mDevice(NULL), mPrimaryBuffer(NULL), mBuffer(NULL),
|
: mDevice(NULL), mPrimaryBuffer(NULL), mBuffer(NULL), mWriteOffset(0), mPlayedSamples(0), mTotalPlayed(0), mTail(0),
|
||||||
mWriteOffset(0), mPlayedSamples(0), mTotalPlayed(0), mTail(0),
|
mThreadHandle(0), mSimulate(false), mGUID(deviceId), mNullAudio(AUDIO_SPK_BUFFER_LENGTH, AUDIO_SPK_BUFFER_COUNT)
|
||||||
mThreadHandle(0), mSimulate(false), mGUID(deviceId),
|
|
||||||
mNullAudio(AUDIO_SPK_BUFFER_LENGTH, AUDIO_SPK_BUFFER_COUNT)
|
|
||||||
{
|
{
|
||||||
gDSoundInit.load();
|
gDSoundInit.load();
|
||||||
mShutdownSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
mShutdownSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
@@ -751,8 +748,10 @@ void DSoundOutputDevice::openDevice()
|
|||||||
DSoundHelper::checkComResult(mDevice->CreateSoundBuffer(&dsbd, &mBuffer, NULL));
|
DSoundHelper::checkComResult(mDevice->CreateSoundBuffer(&dsbd, &mBuffer, NULL));
|
||||||
|
|
||||||
// Fill the buffer with silence
|
// Fill the buffer with silence
|
||||||
LPVOID ptr1 = NULL, ptr2 = NULL; DWORD len1 = 0, len2 = 0;
|
LPVOID ptr1 = NULL, ptr2 = NULL;
|
||||||
DSoundHelper::checkComResult(mBuffer->Lock(0, AUDIO_SPK_BUFFER_SIZE * AUDIO_SPK_BUFFER_COUNT, &ptr1, &len1, &ptr2, &len2, 0));
|
DWORD len1 = 0, len2 = 0;
|
||||||
|
DSoundHelper::checkComResult(
|
||||||
|
mBuffer->Lock(0, AUDIO_SPK_BUFFER_SIZE * AUDIO_SPK_BUFFER_COUNT, &ptr1, &len1, &ptr2, &len2, 0));
|
||||||
if (len1 && ptr1)
|
if (len1 && ptr1)
|
||||||
memset(ptr1, 0, len1);
|
memset(ptr1, 0, len1);
|
||||||
if (len2 && ptr2)
|
if (len2 && ptr2)
|
||||||
@@ -805,7 +804,8 @@ bool DSoundOutputDevice::getMediaFrame()
|
|||||||
mConnection->onSpkData(getFormat(), mMediaFrame, sizeof mMediaFrame);
|
mConnection->onSpkData(getFormat(), mMediaFrame, sizeof mMediaFrame);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -833,7 +833,8 @@ bool DSoundOutputDevice::process()
|
|||||||
offset %= mBufferSize;
|
offset %= mBufferSize;
|
||||||
|
|
||||||
// See what we can write
|
// See what we can write
|
||||||
LPVOID ptr1 = NULL, ptr2 = NULL; DWORD len1 = 0, len2 = 0;
|
LPVOID ptr1 = NULL, ptr2 = NULL;
|
||||||
|
DWORD len1 = 0, len2 = 0;
|
||||||
DSoundHelper::checkComResult(mBuffer->Lock(offset, AUDIO_SPK_BUFFER_SIZE, &ptr1, &len1, &ptr2, &len2, 0));
|
DSoundHelper::checkComResult(mBuffer->Lock(offset, AUDIO_SPK_BUFFER_SIZE, &ptr1, &len1, &ptr2, &len2, 0));
|
||||||
|
|
||||||
assert(ptr2 == NULL);
|
assert(ptr2 == NULL);
|
||||||
@@ -946,8 +947,7 @@ HRESULT DirectSoundPrivateCreate (OUT LPKSPROPERTYSET * ppKsPropertySet)
|
|||||||
// Find DllGetClassObject
|
// Find DllGetClassObject
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
pfnDllGetClassObject =
|
pfnDllGetClassObject = (LPFNDLLGETCLASSOBJECT)GetProcAddress(hLibDsound, "DllGetClassObject");
|
||||||
(LPFNDLLGETCLASSOBJECT)GetProcAddress ( hLibDsound, "DllGetClassObject" );
|
|
||||||
|
|
||||||
|
|
||||||
if (!pfnDllGetClassObject)
|
if (!pfnDllGetClassObject)
|
||||||
@@ -1008,14 +1008,9 @@ BOOL GetInfoFromDSoundGUID( GUID i_sGUID, int &dwWaveID)
|
|||||||
|
|
||||||
// On the first call the final size is unknown so pass the size of the struct in order to receive
|
// On the first call the final size is unknown so pass the size of the struct in order to receive
|
||||||
// "Type" and "DataFlow" values, ulBytesReturned will be populated with bytes required for struct+strings.
|
// "Type" and "DataFlow" values, ulBytesReturned will be populated with bytes required for struct+strings.
|
||||||
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice,
|
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice, DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION, NULL, 0,
|
||||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
&sDirectSoundDeviceDescription, sizeof(sDirectSoundDeviceDescription),
|
||||||
NULL,
|
&ulBytesReturned);
|
||||||
0,
|
|
||||||
&sDirectSoundDeviceDescription,
|
|
||||||
sizeof(sDirectSoundDeviceDescription),
|
|
||||||
&ulBytesReturned
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ulBytesReturned)
|
if (ulBytesReturned)
|
||||||
{
|
{
|
||||||
@@ -1024,14 +1019,8 @@ BOOL GetInfoFromDSoundGUID( GUID i_sGUID, int &dwWaveID)
|
|||||||
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA) new BYTE[ulBytesReturned];
|
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA) new BYTE[ulBytesReturned];
|
||||||
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
|
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
|
||||||
|
|
||||||
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice,
|
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice, DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION, NULL, 0,
|
||||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
psDirectSoundDeviceDescription, ulBytesReturned, &ulBytesReturned);
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
psDirectSoundDeviceDescription,
|
|
||||||
ulBytesReturned,
|
|
||||||
&ulBytesReturned
|
|
||||||
);
|
|
||||||
|
|
||||||
dwWaveID = psDirectSoundDeviceDescription->WaveDeviceId;
|
dwWaveID = psDirectSoundDeviceDescription->WaveDeviceId;
|
||||||
/*Description = psDirectSoundDeviceDescription->Description;
|
/*Description = psDirectSoundDeviceDescription->Description;
|
||||||
@@ -1053,16 +1042,10 @@ struct EnumResult
|
|||||||
GUID mGuid;
|
GUID mGuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOL CALLBACK DSEnumCallback(
|
BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext)
|
||||||
LPGUID lpGuid,
|
|
||||||
LPCTSTR lpcstrDescription,
|
|
||||||
LPCTSTR lpcstrModule,
|
|
||||||
LPVOID lpContext
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (lpGuid)
|
if (lpGuid)
|
||||||
{
|
{
|
||||||
|
|
||||||
int devId = -1;
|
int devId = -1;
|
||||||
GetInfoFromDSoundGUID(*lpGuid, devId);
|
GetInfoFromDSoundGUID(*lpGuid, devId);
|
||||||
EnumResult* er = (EnumResult*)lpContext;
|
EnumResult* er = (EnumResult*)lpContext;
|
||||||
|
|||||||
@@ -182,6 +182,6 @@ protected:
|
|||||||
|
|
||||||
static void threadProc(void* arg);
|
static void threadProc(void* arg);
|
||||||
};
|
};
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -39,9 +39,7 @@ void TimeSource::start()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeSource::stop()
|
void TimeSource::stop() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned TimeSource::time()
|
unsigned TimeSource::time()
|
||||||
{
|
{
|
||||||
@@ -103,7 +101,8 @@ unsigned TimeSource::time()
|
|||||||
|
|
||||||
// --- StubTimer ---
|
// --- StubTimer ---
|
||||||
StubTimer::StubTimer(int bufferTime, int bufferCount)
|
StubTimer::StubTimer(int bufferTime, int bufferCount)
|
||||||
:mBufferTime(bufferTime), mBufferCount(bufferCount), mTimeSource(bufferTime, bufferCount), mActive(false), mCurrentTime(0)
|
: mBufferTime(bufferTime), mBufferCount(bufferCount), mTimeSource(bufferTime, bufferCount), mActive(false),
|
||||||
|
mCurrentTime(0)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_WIN
|
#ifdef TARGET_WIN
|
||||||
mStubSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
mStubSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|||||||
@@ -73,6 +73,6 @@ namespace Audio
|
|||||||
#endif
|
#endif
|
||||||
bool mActive;
|
bool mActive;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,14 +24,9 @@
|
|||||||
|
|
||||||
using namespace Audio;
|
using namespace Audio;
|
||||||
|
|
||||||
Device::Device()
|
Device::Device() : mConnection(nullptr) {}
|
||||||
:mConnection(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Device::~Device()
|
Device::~Device() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Device::setConnection(DataConnection* connection)
|
void Device::setConnection(DataConnection* connection)
|
||||||
@@ -44,13 +39,9 @@ DataConnection* Device::connection()
|
|||||||
return mConnection;
|
return mConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputDevice::InputDevice()
|
InputDevice::InputDevice() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
InputDevice::~InputDevice()
|
InputDevice::~InputDevice() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
InputDevice* InputDevice::make(int devId)
|
InputDevice* InputDevice::make(int devId)
|
||||||
{
|
{
|
||||||
@@ -71,13 +62,9 @@ InputDevice* InputDevice::make(int devId)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputDevice::OutputDevice()
|
OutputDevice::OutputDevice() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputDevice::~OutputDevice()
|
OutputDevice::~OutputDevice() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputDevice* OutputDevice::make(int devId)
|
OutputDevice* OutputDevice::make(int devId)
|
||||||
{
|
{
|
||||||
@@ -100,13 +87,9 @@ OutputDevice* OutputDevice::make(int devId)
|
|||||||
|
|
||||||
|
|
||||||
// --- Enumerator ---
|
// --- Enumerator ---
|
||||||
Enumerator::Enumerator()
|
Enumerator::Enumerator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Enumerator::~Enumerator()
|
Enumerator::~Enumerator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int Enumerator::nameToIndex(const std::tstring& name)
|
int Enumerator::nameToIndex(const std::tstring& name)
|
||||||
{
|
{
|
||||||
@@ -119,7 +102,6 @@ int Enumerator::nameToIndex(const std::tstring& name)
|
|||||||
|
|
||||||
Enumerator* Enumerator::make(bool useNull)
|
Enumerator* Enumerator::make(bool useNull)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (useNull)
|
if (useNull)
|
||||||
return new NullEnumerator();
|
return new NullEnumerator();
|
||||||
#ifndef USE_NULL_AUDIO
|
#ifndef USE_NULL_AUDIO
|
||||||
|
|||||||
@@ -27,34 +27,18 @@ struct Format
|
|||||||
int mRate;
|
int mRate;
|
||||||
int mChannels;
|
int mChannels;
|
||||||
|
|
||||||
Format()
|
Format() : mRate(AUDIO_SAMPLERATE), mChannels(AUDIO_CHANNELS) {}
|
||||||
:mRate(AUDIO_SAMPLERATE), mChannels(AUDIO_CHANNELS)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Format(int rate, int channels)
|
Format(int rate, int channels) : mRate(rate), mChannels(channels) {}
|
||||||
:mRate(rate), mChannels(channels)
|
|
||||||
{}
|
|
||||||
|
|
||||||
size_t samplesFromSize(size_t length) const
|
size_t samplesFromSize(size_t length) const { return length / 2 / mChannels; }
|
||||||
{
|
|
||||||
return length / 2 / mChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns milliseconds
|
// Returns milliseconds
|
||||||
float timeFromSize(size_t length) const
|
float timeFromSize(size_t length) const { return float(samplesFromSize(length) / (mRate / 1000.0)); }
|
||||||
{
|
|
||||||
return float(samplesFromSize(length) / (mRate / 1000.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
float sizeFromTime(size_t milliseconds) const
|
float sizeFromTime(size_t milliseconds) const { return float((milliseconds * mRate) / 500.0 * mChannels); }
|
||||||
{
|
|
||||||
return float((milliseconds * mRate) / 500.0 * mChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t sizeFromTime(std::chrono::milliseconds ms) const
|
size_t sizeFromTime(std::chrono::milliseconds ms) const { return sizeFromTime(ms.count()); }
|
||||||
{
|
|
||||||
return sizeFromTime(ms.count());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString()
|
std::string toString()
|
||||||
{
|
{
|
||||||
@@ -63,26 +47,13 @@ struct Format
|
|||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const Format& rhs) const
|
bool operator==(const Format& rhs) const { return mRate == rhs.mRate && mChannels == rhs.mChannels; }
|
||||||
{
|
|
||||||
return mRate == rhs.mRate && mChannels == rhs.mChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator != (const Format& rhs) const
|
bool operator!=(const Format& rhs) const { return mRate != rhs.mRate || mChannels != rhs.mChannels; }
|
||||||
{
|
|
||||||
return mRate != rhs.mRate || mChannels != rhs.mChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rate() const
|
int rate() const { return mRate; }
|
||||||
{
|
|
||||||
return mRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int channels() const
|
|
||||||
{
|
|
||||||
return mChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int channels() const { return mChannels; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class DataConnection
|
class DataConnection
|
||||||
@@ -105,6 +76,7 @@ public:
|
|||||||
virtual bool open() = 0;
|
virtual bool open() = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
virtual Format getFormat() = 0;
|
virtual Format getFormat() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DataConnection* mConnection;
|
DataConnection* mConnection;
|
||||||
};
|
};
|
||||||
@@ -156,6 +128,6 @@ public:
|
|||||||
|
|
||||||
static OsEngine* instance();
|
static OsEngine* instance();
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ Mixer::Stream::Stream()
|
|||||||
mData.setCapacity(AUDIO_SPK_BUFFER_SIZE * AUDIO_SPK_BUFFER_COUNT);
|
mData.setCapacity(AUDIO_SPK_BUFFER_SIZE * AUDIO_SPK_BUFFER_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mixer::Stream::~Stream()
|
Mixer::Stream::~Stream() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mixer::Stream::setSsrc(unsigned ssrc)
|
void Mixer::Stream::setSsrc(unsigned ssrc)
|
||||||
{
|
{
|
||||||
@@ -73,7 +71,9 @@ void Mixer::Stream::addPcm(int rate, const void* input, int length)
|
|||||||
if (mTempBuffer.size() < outputSize)
|
if (mTempBuffer.size() < outputSize)
|
||||||
mTempBuffer.resize(outputSize);
|
mTempBuffer.resize(outputSize);
|
||||||
|
|
||||||
Resampler* resampler = (rate == 8000) ? &mResampler8 : ((rate == 16000) ? &mResampler16 : ((rate == 32000) ? &mResampler32 : &mResampler48));
|
Resampler* resampler = (rate == 8000)
|
||||||
|
? &mResampler8
|
||||||
|
: ((rate == 16000) ? &mResampler16 : ((rate == 32000) ? &mResampler32 : &mResampler48));
|
||||||
size_t inputProcessed = 0;
|
size_t inputProcessed = 0;
|
||||||
resampler->processBuffer(input, length, inputProcessed, mTempBuffer.mutableData(), outputSize);
|
resampler->processBuffer(input, length, inputProcessed, mTempBuffer.mutableData(), outputSize);
|
||||||
// inputProcessed result value is ignored here - rate will be 8/16/32/48k, inputProcessed is equal to length
|
// inputProcessed result value is ignored here - rate will be 8/16/32/48k, inputProcessed is equal to length
|
||||||
@@ -88,9 +88,7 @@ Mixer::Mixer()
|
|||||||
mOutput.setCapacity(32768);
|
mOutput.setCapacity(32768);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mixer::~Mixer()
|
Mixer::~Mixer() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mixer::unregisterChannel(void* channel)
|
void Mixer::unregisterChannel(void* channel)
|
||||||
{
|
{
|
||||||
@@ -143,9 +141,7 @@ Mixer::Stream* Mixer::allocateChannel(void* context, unsigned ssrc)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mixer::addPcm(void* context, unsigned ssrc,
|
void Mixer::addPcm(void* context, unsigned ssrc, const void* inputData, int inputLength, int inputRate, bool fadeOut)
|
||||||
const void* inputData, int inputLength,
|
|
||||||
int inputRate, bool fadeOut)
|
|
||||||
{
|
{
|
||||||
assert(inputRate == 8000 || inputRate == 16000 || inputRate == 32000);
|
assert(inputRate == 8000 || inputRate == 16000 || inputRate == 32000);
|
||||||
|
|
||||||
@@ -241,8 +237,7 @@ void Mixer::mix()
|
|||||||
audio.data().erase(audio.data().filled());
|
audio.data().erase(audio.data().filled());
|
||||||
// ICELogSpecial(<<"Length of mixer stream " << audio.data().filled());
|
// ICELogSpecial(<<"Length of mixer stream " << audio.data().filled());
|
||||||
}
|
}
|
||||||
else
|
else if (activeCounter == 2)
|
||||||
if (activeCounter == 2)
|
|
||||||
{
|
{
|
||||||
Stream& audio1 = *channelList[0];
|
Stream& audio1 = *channelList[0];
|
||||||
Stream& audio2 = *channelList[1];
|
Stream& audio2 = *channelList[1];
|
||||||
@@ -301,8 +296,7 @@ void Mixer::mix()
|
|||||||
mOutput.add(outputBuffer, outputCounter * 2);
|
mOutput.add(outputBuffer, outputCounter * 2);
|
||||||
outputCounter = 0;
|
outputCounter = 0;
|
||||||
}
|
}
|
||||||
}
|
} while (sourceCounter);
|
||||||
while (sourceCounter);
|
|
||||||
|
|
||||||
processed = 0;
|
processed = 0;
|
||||||
for (int i = 0; i < activeCounter; i++)
|
for (int i = 0; i < activeCounter; i++)
|
||||||
@@ -354,4 +348,3 @@ int Mixer::available()
|
|||||||
{
|
{
|
||||||
return mOutput.filled();
|
return mOutput.filled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,7 @@ namespace Audio
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
DataWindow mData;
|
DataWindow mData;
|
||||||
Resampler mResampler8,
|
Resampler mResampler8, mResampler16, mResampler32, mResampler48;
|
||||||
mResampler16,
|
|
||||||
mResampler32,
|
|
||||||
mResampler48;
|
|
||||||
bool mActive;
|
bool mActive;
|
||||||
void* mContext;
|
void* mContext;
|
||||||
unsigned mSSRC;
|
unsigned mSSRC;
|
||||||
@@ -67,6 +64,6 @@ namespace Audio
|
|||||||
int mixAndGetPcm(Audio::DataWindow& output);
|
int mixAndGetPcm(Audio::DataWindow& output);
|
||||||
int available();
|
int available();
|
||||||
};
|
};
|
||||||
} //end of namespace
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -49,15 +49,13 @@ void NullTimer::run()
|
|||||||
// Sleep for mInterval - mTail milliseconds
|
// Sleep for mInterval - mTail milliseconds
|
||||||
std::this_thread::sleep_for(mInterval - mTail);
|
std::this_thread::sleep_for(mInterval - mTail);
|
||||||
|
|
||||||
mTail = mTail + std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - timestamp);
|
mTail =
|
||||||
|
mTail + std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------- NullInputDevice -------------------------
|
// --------------------- NullInputDevice -------------------------
|
||||||
NullInputDevice::NullInputDevice()
|
NullInputDevice::NullInputDevice() : mBuffer(nullptr) {}
|
||||||
:mBuffer(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NullInputDevice::~NullInputDevice()
|
NullInputDevice::~NullInputDevice()
|
||||||
{
|
{
|
||||||
@@ -69,7 +67,8 @@ bool NullInputDevice::open()
|
|||||||
ICELogInfo(<< "Starting NullInputDevice for " << AUDIO_MIC_BUFFER_LENGTH << "ms buffers");
|
ICELogInfo(<< "Starting NullInputDevice for " << AUDIO_MIC_BUFFER_LENGTH << "ms buffers");
|
||||||
mBuffer = malloc(AUDIO_MIC_BUFFER_SIZE);
|
mBuffer = malloc(AUDIO_MIC_BUFFER_SIZE);
|
||||||
memset(mBuffer, 0, AUDIO_MIC_BUFFER_SIZE);
|
memset(mBuffer, 0, AUDIO_MIC_BUFFER_SIZE);
|
||||||
mTimeCounter = 0; mDataCounter = 0;
|
mTimeCounter = 0;
|
||||||
|
mDataCounter = 0;
|
||||||
|
|
||||||
// Creation of timer starts it also. So first onTimerSignal can come even before open() returns.
|
// Creation of timer starts it also. So first onTimerSignal can come even before open() returns.
|
||||||
mTimer = std::make_shared<NullTimer>(std::chrono::milliseconds(AUDIO_MIC_BUFFER_LENGTH), this, "null_mic");
|
mTimer = std::make_shared<NullTimer>(std::chrono::milliseconds(AUDIO_MIC_BUFFER_LENGTH), this, "null_mic");
|
||||||
@@ -109,10 +108,7 @@ void NullInputDevice::onTimerSignal(NullTimer& timer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------------- NullOutputDevice --------------------------
|
// --------------------- NullOutputDevice --------------------------
|
||||||
NullOutputDevice::NullOutputDevice()
|
NullOutputDevice::NullOutputDevice() : mBuffer(nullptr) {}
|
||||||
:mBuffer(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NullOutputDevice::~NullOutputDevice()
|
NullOutputDevice::~NullOutputDevice()
|
||||||
{
|
{
|
||||||
@@ -122,7 +118,8 @@ NullOutputDevice::~NullOutputDevice()
|
|||||||
|
|
||||||
bool NullOutputDevice::open()
|
bool NullOutputDevice::open()
|
||||||
{
|
{
|
||||||
mTimeCounter = 0; mDataCounter = 0;
|
mTimeCounter = 0;
|
||||||
|
mDataCounter = 0;
|
||||||
mBuffer = malloc(AUDIO_SPK_BUFFER_SIZE);
|
mBuffer = malloc(AUDIO_SPK_BUFFER_SIZE);
|
||||||
// Creation of timer starts it also. So first onSpkData() can come before open() returns even.
|
// Creation of timer starts it also. So first onSpkData() can come before open() returns even.
|
||||||
mTimer = std::make_shared<NullTimer>(std::chrono::milliseconds(AUDIO_SPK_BUFFER_LENGTH), this, "null_spk");
|
mTimer = std::make_shared<NullTimer>(std::chrono::milliseconds(AUDIO_SPK_BUFFER_LENGTH), this, "null_spk");
|
||||||
@@ -132,7 +129,8 @@ bool NullOutputDevice::open()
|
|||||||
void NullOutputDevice::internalClose()
|
void NullOutputDevice::internalClose()
|
||||||
{
|
{
|
||||||
mTimer.reset();
|
mTimer.reset();
|
||||||
free(mBuffer); mBuffer = nullptr;
|
free(mBuffer);
|
||||||
|
mBuffer = nullptr;
|
||||||
ICELogInfo(<< "Pseudoplayed " << mTimeCounter << " milliseconds, " << mDataCounter << " bytes.");
|
ICELogInfo(<< "Pseudoplayed " << mTimeCounter << " milliseconds, " << mDataCounter << " bytes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,17 +154,13 @@ void NullOutputDevice::onTimerSignal(NullTimer &timer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- NullEnumerator --------------------------
|
// ---------------------- NullEnumerator --------------------------
|
||||||
NullEnumerator::NullEnumerator()
|
NullEnumerator::NullEnumerator() {}
|
||||||
{}
|
|
||||||
|
|
||||||
NullEnumerator::~NullEnumerator()
|
NullEnumerator::~NullEnumerator() {}
|
||||||
{}
|
|
||||||
|
|
||||||
void NullEnumerator::open(int direction)
|
void NullEnumerator::open(int direction) {}
|
||||||
{}
|
|
||||||
|
|
||||||
void NullEnumerator::close()
|
void NullEnumerator::close() {}
|
||||||
{}
|
|
||||||
|
|
||||||
int NullEnumerator::count()
|
int NullEnumerator::count()
|
||||||
{
|
{
|
||||||
@@ -191,4 +185,3 @@ int NullEnumerator::indexOfDefaultDevice()
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ protected:
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Interval is in milliseconds. */
|
/* Interval is in milliseconds. */
|
||||||
NullTimer(std::chrono::milliseconds interval, Delegate* delegate, const char* name = nullptr);
|
NullTimer(std::chrono::milliseconds interval, Delegate* delegate, const char* name = nullptr);
|
||||||
@@ -60,6 +61,7 @@ protected:
|
|||||||
int64_t mDataCounter = 0, mTimeCounter = 0;
|
int64_t mDataCounter = 0, mTimeCounter = 0;
|
||||||
|
|
||||||
void internalClose();
|
void internalClose();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NullOutputDevice();
|
NullOutputDevice();
|
||||||
virtual ~NullOutputDevice();
|
virtual ~NullOutputDevice();
|
||||||
@@ -86,6 +88,6 @@ public:
|
|||||||
int indexOfDefaultDevice() override;
|
int indexOfDefaultDevice() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,14 +11,9 @@
|
|||||||
|
|
||||||
using namespace Audio;
|
using namespace Audio;
|
||||||
// -------------- Player -----------
|
// -------------- Player -----------
|
||||||
Player::Player()
|
Player::Player() : mDelegate(nullptr), mPlayedTime(0) {}
|
||||||
:mDelegate(nullptr), mPlayedTime(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Player::~Player()
|
Player::~Player() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::setDelegate(EndOfAudioDelegate* d)
|
void Player::setDelegate(EndOfAudioDelegate* d)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace Audio
|
|||||||
class Player : public DataConnection
|
class Player : public DataConnection
|
||||||
{
|
{
|
||||||
friend class DevicePair;
|
friend class DevicePair;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct PlaylistItem
|
struct PlaylistItem
|
||||||
{
|
{
|
||||||
@@ -67,5 +68,5 @@ namespace Audio
|
|||||||
int releasePlayed();
|
int releasePlayed();
|
||||||
void retrieveUsageIds(std::vector<int>& ids);
|
void retrieveUsageIds(std::vector<int>& ids);
|
||||||
};
|
};
|
||||||
}
|
} // namespace Audio
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ AgcFilter::AgcFilter(int channels)
|
|||||||
c.mIgain = 65536;
|
c.mIgain = 65536;
|
||||||
if (level > 1.0f)
|
if (level > 1.0f)
|
||||||
level = 1.0f;
|
level = 1.0f;
|
||||||
else
|
else if (level < 0.5f)
|
||||||
if (level < 0.5f)
|
|
||||||
level = 0.5f;
|
level = 0.5f;
|
||||||
|
|
||||||
c.mIpeak = (int)(SHRT_MAX * level * 65536);
|
c.mIpeak = (int)(SHRT_MAX * level * 65536);
|
||||||
@@ -45,9 +44,7 @@ AgcFilter::AgcFilter(int channels)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AgcFilter::~AgcFilter()
|
AgcFilter::~AgcFilter() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AgcFilter::process(void* pcm, int length)
|
void AgcFilter::process(void* pcm, int length)
|
||||||
{
|
{
|
||||||
@@ -139,12 +136,12 @@ static void CheckWRACode(unsigned errorcode)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AecFilter::AecFilter(int tailTime, int frameTime, int rate)
|
AecFilter::AecFilter(int tailTime, int frameTime, int rate) : mCtx(nullptr), mFrameTime(frameTime), mRate(rate)
|
||||||
:mCtx(nullptr), mFrameTime(frameTime), mRate(rate)
|
|
||||||
{
|
{
|
||||||
#ifdef USE_SPEEX_AEC
|
#ifdef USE_SPEEX_AEC
|
||||||
if (AUDIO_CHANNELS == 2)
|
if (AUDIO_CHANNELS == 2)
|
||||||
mCtx = speex_echo_state_init_mc(frameTime * (mRate / 1000), tailTime * (mRate / 1000), AUDIO_CHANNELS, AUDIO_CHANNELS );
|
mCtx = speex_echo_state_init_mc(frameTime * (mRate / 1000), tailTime * (mRate / 1000), AUDIO_CHANNELS,
|
||||||
|
AUDIO_CHANNELS);
|
||||||
else
|
else
|
||||||
mCtx = speex_echo_state_init(frameTime * (mRate / 1000), tailTime * (mRate / 1000));
|
mCtx = speex_echo_state_init(frameTime * (mRate / 1000), tailTime * (mRate / 1000));
|
||||||
int tmp = rate;
|
int tmp = rate;
|
||||||
@@ -184,7 +181,8 @@ void AecFilter::fromMic(void *data)
|
|||||||
#ifdef USE_WEBRTC_AEC
|
#ifdef USE_WEBRTC_AEC
|
||||||
short* inputframe = (short*)ALLOCA(framesize);
|
short* inputframe = (short*)ALLOCA(framesize);
|
||||||
memcpy(inputframe, (char*)data + framesize * i, framesize);
|
memcpy(inputframe, (char*)data + framesize * i, framesize);
|
||||||
CheckWRACode(WebRtcAec_Process(mCtx, (short*)inputframe, NULL, (short*)data+framesize/2*i, NULL, mFrameTime * mRate / 1000, 0,0));
|
CheckWRACode(WebRtcAec_Process(mCtx, (short*)inputframe, NULL, (short*)data + framesize / 2 * i, NULL,
|
||||||
|
mFrameTime * mRate / 1000, 0, 0));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,8 +203,7 @@ int AecFilter::frametime()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DenoiseFilter::DenoiseFilter(int rate)
|
DenoiseFilter::DenoiseFilter(int rate) : mRate(rate)
|
||||||
:mRate(rate)
|
|
||||||
{
|
{
|
||||||
mCtx = speex_preprocess_state_init(mRate / 100, mRate);
|
mCtx = speex_preprocess_state_init(mRate / 100, mRate);
|
||||||
}
|
}
|
||||||
@@ -235,4 +232,3 @@ int DenoiseFilter::rate()
|
|||||||
{
|
{
|
||||||
return mRate;
|
return mRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace Audio
|
|||||||
};
|
};
|
||||||
std::vector<Channel> mChannelList;
|
std::vector<Channel> mChannelList;
|
||||||
void processChannel(short* pcm, int nrOfSamples, int channelIndex);
|
void processChannel(short* pcm, int nrOfSamples, int channelIndex);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AgcFilter(int channels);
|
AgcFilter(int channels);
|
||||||
~AgcFilter();
|
~AgcFilter();
|
||||||
@@ -64,6 +65,6 @@ namespace Audio
|
|||||||
int mRate; /// Duration of single audio frame (in milliseconds)
|
int mRate; /// Duration of single audio frame (in milliseconds)
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ namespace Audio
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
SpeexResampler::SpeexResampler()
|
SpeexResampler::SpeexResampler() {}
|
||||||
{}
|
|
||||||
|
|
||||||
void SpeexResampler::start(int channels, int sourceRate, int destRate)
|
void SpeexResampler::start(int channels, int sourceRate, int destRate)
|
||||||
{
|
{
|
||||||
@@ -59,8 +58,8 @@ SpeexResampler::~SpeexResampler()
|
|||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SpeexResampler::processBuffer(const void* src, size_t sourceLength, size_t& sourceProcessed,
|
size_t SpeexResampler::processBuffer(const void* src, size_t sourceLength, size_t& sourceProcessed, void* dest,
|
||||||
void* dest, size_t destCapacity)
|
size_t destCapacity)
|
||||||
{
|
{
|
||||||
assert(mSourceRate != 0 && mDestRate != 0);
|
assert(mSourceRate != 0 && mDestRate != 0);
|
||||||
|
|
||||||
@@ -77,8 +76,7 @@ size_t SpeexResampler::processBuffer(const void* src, size_t sourceLength, size_
|
|||||||
|
|
||||||
if (!mContext)
|
if (!mContext)
|
||||||
{
|
{
|
||||||
mContext = speex_resampler_init(mChannels, mSourceRate, mDestRate,
|
mContext = speex_resampler_init(mChannels, mSourceRate, mDestRate, AUDIO_RESAMPLER_QUALITY, &mErrorCode);
|
||||||
AUDIO_RESAMPLER_QUALITY, &mErrorCode);
|
|
||||||
if (!mContext)
|
if (!mContext)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -103,11 +101,9 @@ size_t SpeexResampler::processBuffer(const void* src, size_t sourceLength, size_
|
|||||||
unsigned inLen = sourceLength / (sizeof(short) * mChannels);
|
unsigned inLen = sourceLength / (sizeof(short) * mChannels);
|
||||||
outLen /= sizeof(short) * mChannels;
|
outLen /= sizeof(short) * mChannels;
|
||||||
assert(mContext != NULL);
|
assert(mContext != NULL);
|
||||||
spx_uint32_t in_len = static_cast<spx_uint32_t>(inLen),
|
spx_uint32_t in_len = static_cast<spx_uint32_t>(inLen), out_len = static_cast<spx_uint32_t>(outLen);
|
||||||
out_len = static_cast<spx_uint32_t>(outLen);
|
|
||||||
|
|
||||||
int speexCode = speex_resampler_process_interleaved_int((SpeexResamplerState *)mContext,
|
int speexCode = speex_resampler_process_interleaved_int((SpeexResamplerState*)mContext, (spx_int16_t*)src, &in_len,
|
||||||
(spx_int16_t*)src, &in_len,
|
|
||||||
(spx_int16_t*)dest, &out_len);
|
(spx_int16_t*)dest, &out_len);
|
||||||
assert(speexCode == RESAMPLER_ERR_SUCCESS);
|
assert(speexCode == RESAMPLER_ERR_SUCCESS);
|
||||||
|
|
||||||
@@ -186,7 +182,8 @@ Resampler48kTo16k::~Resampler48kTo16k()
|
|||||||
|
|
||||||
int Resampler48kTo16k::process(const void* source, int sourceLen, void* dest, int destLen)
|
int Resampler48kTo16k::process(const void* source, int sourceLen, void* dest, int destLen)
|
||||||
{
|
{
|
||||||
const short* input = (const short*)source; int inputLen = sourceLen / 2;
|
const short* input = (const short*)source;
|
||||||
|
int inputLen = sourceLen / 2;
|
||||||
short* output = (short*)dest; // int outputCapacity = destLen / 2;
|
short* output = (short*)dest; // int outputCapacity = destLen / 2;
|
||||||
assert(inputLen % 480 == 0);
|
assert(inputLen % 480 == 0);
|
||||||
int frames = inputLen / 480;
|
int frames = inputLen / 480;
|
||||||
@@ -209,7 +206,8 @@ Resampler16kto48k::~Resampler16kto48k()
|
|||||||
|
|
||||||
int Resampler16kto48k::process(const void* source, int sourceLen, void* dest, int destLen)
|
int Resampler16kto48k::process(const void* source, int sourceLen, void* dest, int destLen)
|
||||||
{
|
{
|
||||||
const WebRtc_Word16* input = (const WebRtc_Word16*)source; int inputLen = sourceLen / 2;
|
const WebRtc_Word16* input = (const WebRtc_Word16*)source;
|
||||||
|
int inputLen = sourceLen / 2;
|
||||||
WebRtc_Word16* output = (WebRtc_Word16*)dest; // int outputCapacity = destLen / 2;
|
WebRtc_Word16* output = (WebRtc_Word16*)dest; // int outputCapacity = destLen / 2;
|
||||||
assert(inputLen % 160 == 0);
|
assert(inputLen % 160 == 0);
|
||||||
int frames = inputLen / 160;
|
int frames = inputLen / 160;
|
||||||
@@ -222,15 +220,9 @@ int Resampler16kto48k::process(const void *source, int sourceLen, void *dest, in
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ---------------- UniversalResampler -------------------
|
// ---------------- UniversalResampler -------------------
|
||||||
UniversalResampler::UniversalResampler()
|
UniversalResampler::UniversalResampler() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
UniversalResampler::~UniversalResampler() {}
|
||||||
|
|
||||||
UniversalResampler::~UniversalResampler()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t UniversalResampler::resample(int sourceRate, const void* sourceBuffer, size_t sourceLength,
|
size_t UniversalResampler::resample(int sourceRate, const void* sourceBuffer, size_t sourceLength,
|
||||||
size_t& sourceProcessed, int destRate, void* destBuffer, size_t destCapacity)
|
size_t& sourceProcessed, int destRate, void* destBuffer, size_t destCapacity)
|
||||||
@@ -252,10 +244,7 @@ size_t UniversalResampler::resample(int sourceRate, const void *sourceBuffer, si
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniversalResampler::preload()
|
void UniversalResampler::preload() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t UniversalResampler::getDestLength(int sourceRate, int destRate, size_t sourceLength)
|
size_t UniversalResampler::getDestLength(int sourceRate, int destRate, size_t sourceLength)
|
||||||
{
|
{
|
||||||
@@ -289,4 +278,4 @@ PResampler UniversalResampler::findResampler(int sourceRate, int destRate)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // namespace Audio
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ namespace Audio
|
|||||||
void stop();
|
void stop();
|
||||||
bool isOpened() const;
|
bool isOpened() const;
|
||||||
|
|
||||||
size_t processBuffer(const void* source, size_t sourceLength, size_t& sourceProcessed,
|
size_t processBuffer(const void* source, size_t sourceLength, size_t& sourceProcessed, void* dest,
|
||||||
void* dest, size_t destCapacity);
|
size_t destCapacity);
|
||||||
int sourceRate() const;
|
int sourceRate() const;
|
||||||
int destRate() const;
|
int destRate() const;
|
||||||
size_t getDestLength(size_t sourceLen) const;
|
size_t getDestLength(size_t sourceLen) const;
|
||||||
@@ -39,9 +39,7 @@ namespace Audio
|
|||||||
protected:
|
protected:
|
||||||
void* mContext = nullptr;
|
void* mContext = nullptr;
|
||||||
int mErrorCode = 0;
|
int mErrorCode = 0;
|
||||||
int mSourceRate = 0,
|
int mSourceRate = 0, mDestRate = 0, mChannels = 0;
|
||||||
mDestRate = 0,
|
|
||||||
mChannels = 0;
|
|
||||||
short mLastSample = 0;
|
short mLastSample = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,6 +82,7 @@ namespace Audio
|
|||||||
Resampler48kTo16k();
|
Resampler48kTo16k();
|
||||||
~Resampler48kTo16k();
|
~Resampler48kTo16k();
|
||||||
int process(const void* source, int sourceLen, void* dest, int destLen);
|
int process(const void* source, int sourceLen, void* dest, int destLen);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WebRtc_Word32 mTemp[496];
|
WebRtc_Word32 mTemp[496];
|
||||||
WebRtcSpl_State48khzTo16khz mContext;
|
WebRtcSpl_State48khzTo16khz mContext;
|
||||||
@@ -101,6 +100,6 @@ namespace Audio
|
|||||||
WebRtcSpl_State16khzTo48khz mContext;
|
WebRtcSpl_State16khzTo48khz mContext;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
} // end of namespace
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
#define DWORD unsigned int
|
#define DWORD unsigned int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
WORD wFormatTag;
|
WORD wFormatTag;
|
||||||
WORD nChannels;
|
WORD nChannels;
|
||||||
DWORD nSamplesPerSec;
|
DWORD nSamplesPerSec;
|
||||||
@@ -27,8 +28,7 @@ typedef struct {
|
|||||||
WORD nBlockAlign;
|
WORD nBlockAlign;
|
||||||
WORD wBitsPerSample;
|
WORD wBitsPerSample;
|
||||||
WORD cbSize;
|
WORD cbSize;
|
||||||
}
|
} WaveFormatEx;
|
||||||
WaveFormatEx;
|
|
||||||
|
|
||||||
#define WAVE_FORMAT_PCM 1
|
#define WAVE_FORMAT_PCM 1
|
||||||
|
|
||||||
@@ -39,15 +39,12 @@ WaveFormatEx;
|
|||||||
using namespace Audio;
|
using namespace Audio;
|
||||||
|
|
||||||
// ---------------------- WavFileReader -------------------------
|
// ---------------------- WavFileReader -------------------------
|
||||||
WavFileReader::WavFileReader()
|
WavFileReader::WavFileReader() : mSamplerate(0), mLastError(0), mChannels(0), mBits(0), mDataLength(0)
|
||||||
:mSamplerate(0), mLastError(0), mChannels(0), mBits(0), mDataLength(0)
|
|
||||||
{
|
{
|
||||||
mDataOffset = 0;
|
mDataOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WavFileReader::~WavFileReader()
|
WavFileReader::~WavFileReader() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#define THROW_READERROR throw Exception(ERR_WAVFILE_FAILED);
|
#define THROW_READERROR throw Exception(ERR_WAVFILE_FAILED);
|
||||||
|
|
||||||
@@ -234,8 +231,7 @@ size_t WavFileReader::read(short* buffer, size_t samples)
|
|||||||
size_t readBytes = tryReadBuffer(temp, requiredBytes);
|
size_t readBytes = tryReadBuffer(temp, requiredBytes);
|
||||||
|
|
||||||
size_t processedBytes = 0;
|
size_t processedBytes = 0;
|
||||||
size_t result = mResampler.processBuffer(temp, readBytes, processedBytes,
|
size_t result = mResampler.processBuffer(temp, readBytes, processedBytes, buffer, samples * 2 * AUDIO_CHANNELS);
|
||||||
buffer, samples * 2 * AUDIO_CHANNELS);
|
|
||||||
|
|
||||||
if (useHeap)
|
if (useHeap)
|
||||||
free(temp);
|
free(temp);
|
||||||
@@ -304,9 +300,7 @@ unsigned WavFileReader::lastError() const
|
|||||||
|
|
||||||
#define BITS_PER_CHANNEL 16
|
#define BITS_PER_CHANNEL 16
|
||||||
|
|
||||||
WavFileWriter::WavFileWriter()
|
WavFileWriter::WavFileWriter() : mLengthOffset(0), mSamplerate(AUDIO_SAMPLERATE), mChannels(1), mWritten(0) {}
|
||||||
:mLengthOffset(0), mSamplerate(AUDIO_SAMPLERATE), mChannels(1), mWritten(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
WavFileWriter::~WavFileWriter()
|
WavFileWriter::~WavFileWriter()
|
||||||
{
|
{
|
||||||
@@ -358,7 +352,8 @@ bool WavFileWriter::open(const std::filesystem::path& p, int samplerate, int cha
|
|||||||
writeBuffer(wavefmt, 8);
|
writeBuffer(wavefmt, 8);
|
||||||
|
|
||||||
// Set the format description
|
// Set the format description
|
||||||
uint32_t dwFmtSize = 16; /*= 16L*/;
|
uint32_t dwFmtSize = 16; /*= 16L*/
|
||||||
|
;
|
||||||
writeBuffer(&dwFmtSize, sizeof(dwFmtSize));
|
writeBuffer(&dwFmtSize, sizeof(dwFmtSize));
|
||||||
|
|
||||||
WaveFormatEx format;
|
WaveFormatEx format;
|
||||||
@@ -435,4 +430,3 @@ std::filesystem::path WavFileWriter::path() const
|
|||||||
LOCK;
|
LOCK;
|
||||||
return mPath;
|
return mPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,11 +73,11 @@ protected:
|
|||||||
mutable std::recursive_mutex mFileMtx; /// Mutex to protect this instance.
|
mutable std::recursive_mutex mFileMtx; /// Mutex to protect this instance.
|
||||||
size_t mWritten = 0; /// Amount of written data (in bytes)
|
size_t mWritten = 0; /// Amount of written data (in bytes)
|
||||||
size_t mLengthOffset = 0; /// Position of length field.
|
size_t mLengthOffset = 0; /// Position of length field.
|
||||||
int mSamplerate = 0,
|
int mSamplerate = 0, mChannels = 0;
|
||||||
mChannels = 0;
|
|
||||||
|
|
||||||
void checkWriteResult(int result);
|
void checkWriteResult(int result);
|
||||||
void writeBuffer(const void* buffer, size_t sz);
|
void writeBuffer(const void* buffer, size_t sz);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WavFileWriter();
|
WavFileWriter();
|
||||||
~WavFileWriter();
|
~WavFileWriter();
|
||||||
@@ -91,6 +91,6 @@ public:
|
|||||||
|
|
||||||
typedef std::shared_ptr<WavFileWriter> PWavFileWriter;
|
typedef std::shared_ptr<WavFileWriter> PWavFileWriter;
|
||||||
|
|
||||||
}
|
} // namespace Audio
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ WmmeInputDevice::Buffer::~Buffer()
|
|||||||
GlobalUnlock(mHeaderHandle);
|
GlobalUnlock(mHeaderHandle);
|
||||||
GlobalFree(mHeaderHandle);
|
GlobalFree(mHeaderHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmmeInputDevice::Buffer::prepare(HWAVEIN device)
|
bool WmmeInputDevice::Buffer::prepare(HWAVEIN device)
|
||||||
@@ -93,8 +92,8 @@ void* WmmeInputDevice::Buffer::data()
|
|||||||
|
|
||||||
|
|
||||||
WmmeInputDevice::WmmeInputDevice(int deviceId)
|
WmmeInputDevice::WmmeInputDevice(int deviceId)
|
||||||
:mDevHandle(NULL), mDoneSignal(INVALID_HANDLE_VALUE), mFakeMode(false),
|
: mDevHandle(NULL), mDoneSignal(INVALID_HANDLE_VALUE), mFakeMode(false), mBufferIndex(0), mDeviceIndex(deviceId),
|
||||||
mBufferIndex(0), mDeviceIndex(deviceId), mThreadHandle(0)
|
mThreadHandle(0)
|
||||||
{
|
{
|
||||||
mDoneSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
mDoneSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
mShutdownSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
mShutdownSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
@@ -113,7 +112,8 @@ bool WmmeInputDevice::fakeMode()
|
|||||||
return mFakeMode;
|
return mFakeMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK WmmeInputDevice::callbackProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
void CALLBACK WmmeInputDevice::callbackProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
|
||||||
|
DWORD_PTR dwParam2)
|
||||||
{
|
{
|
||||||
WmmeInputDevice* impl;
|
WmmeInputDevice* impl;
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
@@ -147,7 +147,8 @@ void WmmeInputDevice::openDevice()
|
|||||||
|
|
||||||
// Open wavein
|
// Open wavein
|
||||||
|
|
||||||
MMRESULT mmres = waveInOpen(&mDevHandle, mDeviceIndex, &wfx, (DWORD_PTR)callbackProc, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
MMRESULT mmres =
|
||||||
|
waveInOpen(&mDevHandle, mDeviceIndex, &wfx, (DWORD_PTR)callbackProc, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||||||
if (mmres != MMSYSERR_NOERROR)
|
if (mmres != MMSYSERR_NOERROR)
|
||||||
{
|
{
|
||||||
mFakeMode = true;
|
mFakeMode = true;
|
||||||
@@ -216,7 +217,6 @@ void WmmeInputDevice::close()
|
|||||||
::SetEvent(mShutdownSignal);
|
::SetEvent(mShutdownSignal);
|
||||||
::WaitForSingleObject(mThreadHandle, INFINITE);
|
::WaitForSingleObject(mThreadHandle, INFINITE);
|
||||||
mThreadHandle = 0;
|
mThreadHandle = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmmeInputDevice::tryReadBuffer(void* buffer)
|
bool WmmeInputDevice::tryReadBuffer(void* buffer)
|
||||||
@@ -287,8 +287,7 @@ void WmmeInputDevice::threadProc(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- WmmeOutputDevice ---
|
// --- WmmeOutputDevice ---
|
||||||
WmmeOutputDevice::Buffer::Buffer()
|
WmmeOutputDevice::Buffer::Buffer() : mHeaderHandle(NULL), mDataHandle(NULL), mData(NULL), mHeader(NULL)
|
||||||
:mHeaderHandle(NULL), mDataHandle(NULL), mData(NULL), mHeader(NULL)
|
|
||||||
{
|
{
|
||||||
mHeaderHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, AUDIO_SPK_BUFFER_SIZE);
|
mHeaderHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, AUDIO_SPK_BUFFER_SIZE);
|
||||||
if (!mHeaderHandle)
|
if (!mHeaderHandle)
|
||||||
@@ -354,7 +353,8 @@ WmmeOutputDevice::~WmmeOutputDevice()
|
|||||||
close();
|
close();
|
||||||
|
|
||||||
// Destroy used signals
|
// Destroy used signals
|
||||||
CloseHandle(mDoneSignal); CloseHandle(mShutdownSignal);
|
CloseHandle(mDoneSignal);
|
||||||
|
CloseHandle(mShutdownSignal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmmeOutputDevice::open()
|
bool WmmeOutputDevice::open()
|
||||||
@@ -432,8 +432,7 @@ bool WmmeOutputDevice::areBuffersFinished()
|
|||||||
bool result = true;
|
bool result = true;
|
||||||
for (unsigned i = 0; i < AUDIO_SPK_BUFFER_COUNT && result; i++)
|
for (unsigned i = 0; i < AUDIO_SPK_BUFFER_COUNT && result; i++)
|
||||||
{
|
{
|
||||||
bool finished = mBufferList[i].mHeader->dwFlags & WHDR_DONE ||
|
bool finished = mBufferList[i].mHeader->dwFlags & WHDR_DONE || !mBufferList[i].mHeader->dwFlags;
|
||||||
!mBufferList[i].mHeader->dwFlags;
|
|
||||||
if (finished)
|
if (finished)
|
||||||
{
|
{
|
||||||
/* if (mBufferList[i].mHeader->dwFlags & WHDR_PREPARED)
|
/* if (mBufferList[i].mHeader->dwFlags & WHDR_PREPARED)
|
||||||
@@ -488,8 +487,7 @@ void WmmeOutputDevice::threadProc(void* arg)
|
|||||||
exitCount++;
|
exitCount++;
|
||||||
}
|
}
|
||||||
impl->mBufferIndex = (impl->mBufferIndex + i) % AUDIO_SPK_BUFFER_COUNT;
|
impl->mBufferIndex = (impl->mBufferIndex + i) % AUDIO_SPK_BUFFER_COUNT;
|
||||||
}
|
} while (!exitSignal || exitCount < AUDIO_SPK_BUFFER_COUNT);
|
||||||
while (!exitSignal || exitCount < AUDIO_SPK_BUFFER_COUNT);
|
|
||||||
impl->closeDevice();
|
impl->closeDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +538,8 @@ bool WmmeOutputDevice::closing()
|
|||||||
return mClosing;
|
return mClosing;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK WmmeOutputDevice::callbackProc(HWAVEOUT hwo, UINT msg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
void CALLBACK WmmeOutputDevice::callbackProc(HWAVEOUT hwo, UINT msg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
|
||||||
|
DWORD_PTR dwParam2)
|
||||||
{
|
{
|
||||||
WmmeOutputDevice* impl;
|
WmmeOutputDevice* impl;
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ namespace Audio
|
|||||||
void openDevice();
|
void openDevice();
|
||||||
void closeDevice();
|
void closeDevice();
|
||||||
|
|
||||||
static void CALLBACK callbackProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
static void CALLBACK callbackProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
|
||||||
|
DWORD_PTR dwParam2);
|
||||||
static void threadProc(void* arg);
|
static void threadProc(void* arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,12 +103,14 @@ namespace Audio
|
|||||||
class Buffer
|
class Buffer
|
||||||
{
|
{
|
||||||
friend class WmmeOutputDevice;
|
friend class WmmeOutputDevice;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Buffer();
|
Buffer();
|
||||||
~Buffer();
|
~Buffer();
|
||||||
bool prepare(HWAVEOUT device);
|
bool prepare(HWAVEOUT device);
|
||||||
bool unprepare(HWAVEOUT device);
|
bool unprepare(HWAVEOUT device);
|
||||||
bool write(HWAVEOUT device);
|
bool write(HWAVEOUT device);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WAVEHDR* mHeader;
|
WAVEHDR* mHeader;
|
||||||
void* mData;
|
void* mData;
|
||||||
@@ -121,9 +124,7 @@ namespace Audio
|
|||||||
Buffer mBufferList[AUDIO_SPK_BUFFER_COUNT];
|
Buffer mBufferList[AUDIO_SPK_BUFFER_COUNT];
|
||||||
unsigned mPlayedTime; /// Amount of played time in milliseconds
|
unsigned mPlayedTime; /// Amount of played time in milliseconds
|
||||||
bool mClosing;
|
bool mClosing;
|
||||||
HANDLE mDoneSignal,
|
HANDLE mDoneSignal, mShutdownSignal, mThreadHandle;
|
||||||
mShutdownSignal,
|
|
||||||
mThreadHandle;
|
|
||||||
volatile bool mShutdownMarker;
|
volatile bool mShutdownMarker;
|
||||||
|
|
||||||
volatile LONG mPlayedCount;
|
volatile LONG mPlayedCount;
|
||||||
@@ -134,14 +135,13 @@ namespace Audio
|
|||||||
void closeDevice();
|
void closeDevice();
|
||||||
bool areBuffersFinished();
|
bool areBuffersFinished();
|
||||||
|
|
||||||
static void CALLBACK callbackProc(HWAVEOUT hwo, UINT msg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
static void CALLBACK callbackProc(HWAVEOUT hwo, UINT msg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
|
||||||
|
DWORD_PTR dwParam2);
|
||||||
static void threadProc(void* arg);
|
static void threadProc(void* arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Audio
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
#include "Audio_iOS.h"
|
#include "Audio_iOS.h"
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,11 @@
|
|||||||
class IosInputDevice : public InputDevice
|
class IosInputDevice : public InputDevice
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IosInputDevice();
|
IosInputDevice();
|
||||||
~IosInputDevice();
|
~IosInputDevice();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void open();
|
void open();
|
||||||
void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,22 +35,19 @@ public:
|
|||||||
NATDecorator(UserAgent& endpoint);
|
NATDecorator(UserAgent& endpoint);
|
||||||
virtual ~NATDecorator();
|
virtual ~NATDecorator();
|
||||||
|
|
||||||
virtual void decorateMessage(resip::SipMessage &msg, const resip::Tuple &source, const resip::Tuple &destination, const resip::Data& sigcompId);
|
virtual void decorateMessage(resip::SipMessage& msg, const resip::Tuple& source, const resip::Tuple& destination,
|
||||||
|
const resip::Data& sigcompId);
|
||||||
virtual void rollbackMessage(resip::SipMessage& msg);
|
virtual void rollbackMessage(resip::SipMessage& msg);
|
||||||
virtual MessageDecorator* clone() const;
|
virtual MessageDecorator* clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NATDecorator::NATDecorator(UserAgent& ua)
|
NATDecorator::NATDecorator(UserAgent& ua) : mUserAgent(ua), mViaPort(0), mContactsPort(0) {}
|
||||||
:mUserAgent(ua), mViaPort(0), mContactsPort(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NATDecorator::~NATDecorator()
|
NATDecorator::~NATDecorator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void NATDecorator::decorateMessage(resip::SipMessage &msg, const resip::Tuple &source, const resip::Tuple &destination, const resip::Data& sigcompId)
|
void NATDecorator::decorateMessage(resip::SipMessage& msg, const resip::Tuple& source, const resip::Tuple& destination,
|
||||||
|
const resip::Data& sigcompId)
|
||||||
{
|
{
|
||||||
// Make a copy to allow rollback
|
// Make a copy to allow rollback
|
||||||
mMessage = msg;
|
mMessage = msg;
|
||||||
@@ -153,17 +150,14 @@ resip::MessageDecorator* NATDecorator::clone() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Account::Account(PVariantMap config, UserAgent& agent)
|
Account::Account(PVariantMap config, UserAgent& agent)
|
||||||
:mAgent(agent), mId(0), mConfig(config), mRegistrationState(RegistrationState::None),
|
: mAgent(agent), mId(0), mConfig(config), mRegistrationState(RegistrationState::None), mRegistration(NULL)
|
||||||
mRegistration(NULL)
|
|
||||||
{
|
{
|
||||||
mProfile = std::make_shared<resip::UserProfile>(agent.mProfile);
|
mProfile = std::make_shared<resip::UserProfile>(agent.mProfile);
|
||||||
mId = Account::generateId();
|
mId = Account::generateId();
|
||||||
setup(*config);
|
setup(*config);
|
||||||
}
|
}
|
||||||
|
|
||||||
Account::~Account()
|
Account::~Account() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Account::setup(VariantMap& config)
|
void Account::setup(VariantMap& config)
|
||||||
{
|
{
|
||||||
@@ -176,8 +170,8 @@ void Account::setup(VariantMap &config)
|
|||||||
mProfile->setDigestCredential(resip::Data(config[CONFIG_DOMAIN].asStdString()),
|
mProfile->setDigestCredential(resip::Data(config[CONFIG_DOMAIN].asStdString()),
|
||||||
resip::Data(config[CONFIG_USERNAME].asStdString()),
|
resip::Data(config[CONFIG_USERNAME].asStdString()),
|
||||||
resip::Data(config[CONFIG_PASSWORD].asStdString()));
|
resip::Data(config[CONFIG_PASSWORD].asStdString()));
|
||||||
ICELogInfo( << "Credentials are set to domain " << config[CONFIG_DOMAIN].asStdString() <<
|
ICELogInfo(<< "Credentials are set to domain " << config[CONFIG_DOMAIN].asStdString() << ", username to "
|
||||||
", username to " << config[CONFIG_USERNAME].asStdString());
|
<< config[CONFIG_USERNAME].asStdString());
|
||||||
|
|
||||||
// Proxy
|
// Proxy
|
||||||
mProfile->unsetOutboundProxy();
|
mProfile->unsetOutboundProxy();
|
||||||
@@ -266,10 +260,12 @@ void Account::start()
|
|||||||
|
|
||||||
// Create registration
|
// Create registration
|
||||||
mRegistration = new ResipSession(*mAgent.mDum);
|
mRegistration = new ResipSession(*mAgent.mDum);
|
||||||
auto regmessage = mAgent.mDum->makeRegistration(mProfile->getDefaultFrom(), mProfile, mConfig->at(CONFIG_REGISTERDURATION).asInt(), mRegistration);
|
auto regmessage = mAgent.mDum->makeRegistration(mProfile->getDefaultFrom(), mProfile,
|
||||||
|
mConfig->at(CONFIG_REGISTERDURATION).asInt(), mRegistration);
|
||||||
|
|
||||||
for (UserInfo::const_iterator iter = mUserInfo.begin(); iter != mUserInfo.end(); iter++)
|
for (UserInfo::const_iterator iter = mUserInfo.begin(); iter != mUserInfo.end(); iter++)
|
||||||
regmessage->header(resip::ExtensionHeader(iter->first.c_str())).push_back(resip::StringCategory(iter->second.c_str()));
|
regmessage->header(resip::ExtensionHeader(iter->first.c_str()))
|
||||||
|
.push_back(resip::StringCategory(iter->second.c_str()));
|
||||||
|
|
||||||
mRegistrationState = RegistrationState::Registering;
|
mRegistrationState = RegistrationState::Registering;
|
||||||
|
|
||||||
@@ -305,8 +301,7 @@ void Account::stop()
|
|||||||
mRegistrationHandle->removeAll();
|
mRegistrationHandle->removeAll();
|
||||||
mRegistrationHandle = resip::ClientRegistrationHandle();
|
mRegistrationHandle = resip::ClientRegistrationHandle();
|
||||||
}
|
}
|
||||||
else
|
else if (mRegistration)
|
||||||
if (mRegistration)
|
|
||||||
{
|
{
|
||||||
mRegistration->end();
|
mRegistration->end();
|
||||||
}
|
}
|
||||||
@@ -361,7 +356,8 @@ void Account::publishPresence(bool online, const std::string& content, int secon
|
|||||||
if (mPublication.isValid())
|
if (mPublication.isValid())
|
||||||
mPublication->update(&p);
|
mPublication->update(&p);
|
||||||
else
|
else
|
||||||
mAgent.mDum->send(mAgent.mDum->makePublication(contact(SecureScheme::TlsOnly), mProfile, p, resip::Symbols::Presence, seconds));
|
mAgent.mDum->send(mAgent.mDum->makePublication(contact(SecureScheme::TlsOnly), mProfile, p,
|
||||||
|
resip::Symbols::Presence, seconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::stopPublish()
|
void Account::stopPublish()
|
||||||
@@ -387,8 +383,8 @@ PClientObserver Account::observe(const std::string& target, const std::string& p
|
|||||||
if (mConfig->exists(CONFIG_SUBSCRIPTION_REFRESHTIME))
|
if (mConfig->exists(CONFIG_SUBSCRIPTION_REFRESHTIME))
|
||||||
refresh = CONFIG(CONFIG_SUBSCRIPTION_REFRESHTIME).asInt();
|
refresh = CONFIG(CONFIG_SUBSCRIPTION_REFRESHTIME).asInt();
|
||||||
|
|
||||||
msg = mAgent.mDum->makeSubscription(resip::NameAddr(resip::Data(target)), mProfile,
|
msg = mAgent.mDum->makeSubscription(resip::NameAddr(resip::Data(target)), mProfile, resip::Data(package), expires,
|
||||||
resip::Data(package), expires, refresh, observer->mSession);
|
refresh, observer->mSession);
|
||||||
msg->header(resip::h_Accepts) = mAgent.mDum->getMasterProfile()->getSupportedMimeTypes(resip::NOTIFY);
|
msg->header(resip::h_Accepts) = mAgent.mDum->getMasterProfile()->getSupportedMimeTypes(resip::NOTIFY);
|
||||||
|
|
||||||
mAgent.mClientObserverMap[observer->mSessionId] = observer;
|
mAgent.mClientObserverMap[observer->mSessionId] = observer;
|
||||||
@@ -413,8 +409,10 @@ int Account::sendMsg(const std::string& peer, const void* ptr, unsigned length,
|
|||||||
else
|
else
|
||||||
type = resip::Mime(resip::Data(mime), resip::Data());
|
type = resip::Mime(resip::Data(mime), resip::Data());
|
||||||
|
|
||||||
resip::ClientPagerMessageHandle msgHandle = mAgent.mDum->makePagerMessage(resip::NameAddr(resip::Data(peer)), mProfile, s);
|
resip::ClientPagerMessageHandle msgHandle =
|
||||||
unique_ptr<resip::Contents> contentPtr(new resip::PlainContents(resip::Data(std::string((const char*)ptr, length)),type));
|
mAgent.mDum->makePagerMessage(resip::NameAddr(resip::Data(peer)), mProfile, s);
|
||||||
|
unique_ptr<resip::Contents> contentPtr(
|
||||||
|
new resip::PlainContents(resip::Data(std::string((const char*)ptr, length)), type));
|
||||||
int result = s->sessionId();
|
int result = s->sessionId();
|
||||||
msgHandle->page(std::move(contentPtr));
|
msgHandle->page(std::move(contentPtr));
|
||||||
|
|
||||||
@@ -456,7 +454,8 @@ void Account::queryStunServerIp()
|
|||||||
if (!mConfig->exists(CONFIG_STUNSERVER_NAME))
|
if (!mConfig->exists(CONFIG_STUNSERVER_NAME))
|
||||||
{
|
{
|
||||||
// Send request to find STUN or TURN service
|
// Send request to find STUN or TURN service
|
||||||
std::string target = std::string(mConfig->at(CONFIG_RELAY).asBool() ? "_turn" : "_stun") + "._udp." + mConfig->at(CONFIG_DOMAIN).asStdString();
|
std::string target = std::string(mConfig->at(CONFIG_RELAY).asBool() ? "_turn" : "_stun") + "._udp." +
|
||||||
|
mConfig->at(CONFIG_DOMAIN).asStdString();
|
||||||
|
|
||||||
// Start lookup
|
// Start lookup
|
||||||
mAgent.mStack->getDnsStub().lookup<resip::RR_SRV>(resip::Data(target), this);
|
mAgent.mStack->getDnsStub().lookup<resip::RR_SRV>(resip::Data(target), this);
|
||||||
@@ -556,7 +555,8 @@ void Account::onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessa
|
|||||||
// bool streamTransport = mUsedTransport == resip::TCP || mUsedTransport == resip::TLS;
|
// bool streamTransport = mUsedTransport == resip::TCP || mUsedTransport == resip::TLS;
|
||||||
|
|
||||||
// Retry registration for stream based transport too
|
// Retry registration for stream based transport too
|
||||||
if ( (hostChanged || portChanged) && mRegistrationState == RegistrationState::Registering /*&& !streamTransport*/ && mConfig->at(CONFIG_EXTERNALIP).asBool())
|
if ((hostChanged || portChanged) && mRegistrationState == RegistrationState::Registering /*&& !streamTransport*/ &&
|
||||||
|
mConfig->at(CONFIG_EXTERNALIP).asBool())
|
||||||
{
|
{
|
||||||
// mRegistrationHandle->requestRefresh();
|
// mRegistrationHandle->requestRefresh();
|
||||||
// Unregister at first
|
// Unregister at first
|
||||||
@@ -585,8 +585,12 @@ void Account::onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessa
|
|||||||
const char* transportName = nullptr;
|
const char* transportName = nullptr;
|
||||||
switch (mUsedTransport)
|
switch (mUsedTransport)
|
||||||
{
|
{
|
||||||
case resip::TCP: transportName = "tcp"; break;
|
case resip::TCP:
|
||||||
case resip::TLS: transportName = "tls"; break;
|
transportName = "tcp";
|
||||||
|
break;
|
||||||
|
case resip::TLS:
|
||||||
|
transportName = "tls";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hostport.param(resip::p_transport) = resip::Data(transportName);
|
hostport.param(resip::p_transport) = resip::Data(transportName);
|
||||||
@@ -597,7 +601,8 @@ void Account::onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessa
|
|||||||
mProfile->setRegId(mConfig->at(CONFIG_REGID).asInt());
|
mProfile->setRegId(mConfig->at(CONFIG_REGID).asInt());
|
||||||
auto regmessage = mAgent.mDum->makeRegistration(mProfile->getDefaultFrom(), mProfile, UA_REGISTRATION_TIME);
|
auto regmessage = mAgent.mDum->makeRegistration(mProfile->getDefaultFrom(), mProfile, UA_REGISTRATION_TIME);
|
||||||
for (UserInfo::const_iterator iter = mUserInfo.begin(); iter != mUserInfo.end(); iter++)
|
for (UserInfo::const_iterator iter = mUserInfo.begin(); iter != mUserInfo.end(); iter++)
|
||||||
regmessage->header(resip::ExtensionHeader(iter->first.c_str())).push_back(resip::StringCategory(iter->second.c_str()));
|
regmessage->header(resip::ExtensionHeader(iter->first.c_str()))
|
||||||
|
.push_back(resip::StringCategory(iter->second.c_str()));
|
||||||
|
|
||||||
mAgent.mDum->send(regmessage);
|
mAgent.mDum->send(regmessage);
|
||||||
return;
|
return;
|
||||||
@@ -628,7 +633,8 @@ void Account::onDnsResult(const resip::DNSResult<resip::DnsHostRecord>& result)
|
|||||||
ICELogInfo(<< "Success to resolve STUN/TURN address to " << foundAddress.c_str());
|
ICELogInfo(<< "Success to resolve STUN/TURN address to " << foundAddress.c_str());
|
||||||
mConfig->at(CONFIG_STUNSERVER_IP) = std::string(foundAddress.c_str());
|
mConfig->at(CONFIG_STUNSERVER_IP) = std::string(foundAddress.c_str());
|
||||||
|
|
||||||
// Here the IP address of STUN/TURN server is found. If account is registered already - it means account is ready.
|
// Here the IP address of STUN/TURN server is found. If account is registered already - it means account is
|
||||||
|
// ready.
|
||||||
if (mRegistrationState == RegistrationState::Registered)
|
if (mRegistrationState == RegistrationState::Registered)
|
||||||
mAgent.onAccountStart(mAgent.getAccount(this));
|
mAgent.onAccountStart(mAgent.getAccount(this));
|
||||||
}
|
}
|
||||||
@@ -643,10 +649,7 @@ void Account::onDnsResult(const resip::DNSResult<resip::DnsHostRecord>& result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::onDnsResult(const resip::DNSResult<resip::DnsAAAARecord>&)
|
void Account::onDnsResult(const resip::DNSResult<resip::DnsAAAARecord>&) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Account::onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>& result)
|
void Account::onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>& result)
|
||||||
{
|
{
|
||||||
@@ -674,8 +677,8 @@ void Account::onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>& result)
|
|||||||
|
|
||||||
const char* host = result.records[index].target().c_str();
|
const char* host = result.records[index].target().c_str();
|
||||||
|
|
||||||
ICELogInfo( << "Success to find STUN/TURN server on " << result.records[index].target().c_str() <<
|
ICELogInfo(<< "Success to find STUN/TURN server on " << result.records[index].target().c_str() << ":"
|
||||||
":" << (int)result.records[index].port());
|
<< (int)result.records[index].port());
|
||||||
|
|
||||||
|
|
||||||
if (inet_addr(host) == INADDR_NONE)
|
if (inet_addr(host) == INADDR_NONE)
|
||||||
@@ -694,18 +697,11 @@ void Account::onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>& result)
|
|||||||
ICELogError(<< "Failed to find STUN or TURN service for specified domain.");
|
ICELogError(<< "Failed to find STUN or TURN service for specified domain.");
|
||||||
// mAgent::shutdown();
|
// mAgent::shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::onDnsResult(const resip::DNSResult<resip::DnsNaptrRecord>&)
|
void Account::onDnsResult(const resip::DNSResult<resip::DnsNaptrRecord>&) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
void Account::onDnsResult(const resip::DNSResult<resip::DnsCnameRecord>&) {}
|
||||||
|
|
||||||
void Account::onDnsResult(const resip::DNSResult<resip::DnsCnameRecord>&)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Account::isResponsibleFor(const resip::NameAddr& addr)
|
bool Account::isResponsibleFor(const resip::NameAddr& addr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class Account: public resip::DnsResultSink
|
|||||||
{
|
{
|
||||||
friend class UserAgent;
|
friend class UserAgent;
|
||||||
friend class NATDecorator;
|
friend class NATDecorator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Account(PVariantMap config, UserAgent& agent);
|
Account(PVariantMap config, UserAgent& agent);
|
||||||
~Account();
|
~Account();
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
#define LOG_SUBSYSTEM "engine"
|
#define LOG_SUBSYSTEM "engine"
|
||||||
|
|
||||||
AudioProvider::AudioProvider(UserAgent& agent, MT::Terminal& terminal)
|
AudioProvider::AudioProvider(UserAgent& agent, MT::Terminal& terminal)
|
||||||
:mUserAgent(agent), mTerminal(terminal), mState(0),
|
: mUserAgent(agent), mTerminal(terminal), mState(0), mRemoteTelephoneCodec(0), mRemoteNoSdp(false)
|
||||||
mRemoteTelephoneCodec(0), mRemoteNoSdp(false)
|
|
||||||
{
|
{
|
||||||
mActive = mfActive;
|
mActive = mfActive;
|
||||||
mRemoteState = msSendRecv;
|
mRemoteState = msSendRecv;
|
||||||
@@ -26,12 +25,11 @@ AudioProvider::AudioProvider(UserAgent& agent, MT::Terminal& terminal)
|
|||||||
if (mUserAgent.config().exists(CONFIG_CODEC_PRIORITY))
|
if (mUserAgent.config().exists(CONFIG_CODEC_PRIORITY))
|
||||||
mCodecPriority.setupFrom(mUserAgent.config()[CONFIG_CODEC_PRIORITY].asVMap());
|
mCodecPriority.setupFrom(mUserAgent.config()[CONFIG_CODEC_PRIORITY].asVMap());
|
||||||
mSrtpSuite = SRTP_NONE;
|
mSrtpSuite = SRTP_NONE;
|
||||||
setStateImpl((int)StreamState::SipRecv | (int)StreamState::SipSend | (int)StreamState::Receiving | (int)StreamState::Sending);
|
setStateImpl((int)StreamState::SipRecv | (int)StreamState::SipSend | (int)StreamState::Receiving |
|
||||||
|
(int)StreamState::Sending);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProvider::~AudioProvider()
|
AudioProvider::~AudioProvider() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AudioProvider::streamName()
|
std::string AudioProvider::streamName()
|
||||||
{
|
{
|
||||||
@@ -77,7 +75,8 @@ void AudioProvider::processData(const PDatagramSocket& s, const void* dataBuffe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This method is called by user agent to send ICE packet from mediasocket
|
// This method is called by user agent to send ICE packet from mediasocket
|
||||||
void AudioProvider::sendData(const PDatagramSocket& s, InternetAddress& destination, const void* buffer, unsigned int size)
|
void AudioProvider::sendData(const PDatagramSocket& s, InternetAddress& destination, const void* buffer,
|
||||||
|
unsigned int size)
|
||||||
{
|
{
|
||||||
s->sendDatagram(destination, buffer, size);
|
s->sendDatagram(destination, buffer, size);
|
||||||
}
|
}
|
||||||
@@ -124,20 +123,33 @@ void AudioProvider::updateSdpOffer(resip::SdpContents::Session::Medium& sdp, Sdp
|
|||||||
case mfActive:
|
case mfActive:
|
||||||
switch (mRemoteState)
|
switch (mRemoteState)
|
||||||
{
|
{
|
||||||
case msSendonly: attr = "recvonly"; break;
|
case msSendonly:
|
||||||
case msInactive: attr = "recvonly"; break;
|
attr = "recvonly";
|
||||||
|
break;
|
||||||
|
case msInactive:
|
||||||
|
attr = "recvonly";
|
||||||
|
break;
|
||||||
case msRecvonly:
|
case msRecvonly:
|
||||||
case msSendRecv: break; // Do nothing here
|
case msSendRecv:
|
||||||
|
break; // Do nothing here
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mfPaused:
|
case mfPaused:
|
||||||
switch (mRemoteState)
|
switch (mRemoteState)
|
||||||
{
|
{
|
||||||
case msRecvonly: attr = "sendonly"; break;
|
case msRecvonly:
|
||||||
case msSendonly: attr = "inactive"; break;
|
attr = "sendonly";
|
||||||
case msInactive: attr = "inactive"; break;
|
break;
|
||||||
case msSendRecv: attr = "sendonly"; break;
|
case msSendonly:
|
||||||
|
attr = "inactive";
|
||||||
|
break;
|
||||||
|
case msInactive:
|
||||||
|
attr = "inactive";
|
||||||
|
break;
|
||||||
|
case msSendRecv:
|
||||||
|
attr = "sendonly";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -367,9 +379,9 @@ void AudioProvider::setupMirror(bool enable)
|
|||||||
mActiveStream->setupMirror(enable);
|
mActiveStream->setupMirror(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioProvider::setStateImpl(unsigned int state) {
|
void AudioProvider::setStateImpl(unsigned int state)
|
||||||
|
{
|
||||||
mState = state;
|
mState = state;
|
||||||
if (mActiveStream)
|
if (mActiveStream)
|
||||||
mActiveStream->setState(state);
|
mActiveStream->setState(state);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class UserAgent;
|
|||||||
class AudioProvider : public DataProvider
|
class AudioProvider : public DataProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AudioProvider(UserAgent& agent, MT::Terminal& terminal);
|
AudioProvider(UserAgent& agent, MT::Terminal& terminal);
|
||||||
virtual ~AudioProvider();
|
virtual ~AudioProvider();
|
||||||
|
|
||||||
@@ -38,7 +37,8 @@ public:
|
|||||||
void processData(const PDatagramSocket& s, const void* dataBuffer, int dataSize, InternetAddress& source) override;
|
void processData(const PDatagramSocket& s, const void* dataBuffer, int dataSize, InternetAddress& source) override;
|
||||||
|
|
||||||
// This method is called by user agent to send ICE packet from mediasocket
|
// This method is called by user agent to send ICE packet from mediasocket
|
||||||
void sendData(const PDatagramSocket& s, InternetAddress& destination, const void* dataBuffer, unsigned int datasize) override;
|
void sendData(const PDatagramSocket& s, InternetAddress& destination, const void* dataBuffer,
|
||||||
|
unsigned int datasize) override;
|
||||||
|
|
||||||
// Updates SDP offer
|
// Updates SDP offer
|
||||||
void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) override;
|
void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) override;
|
||||||
@@ -96,9 +96,9 @@ protected:
|
|||||||
int mSrtpTag = 1; // RFC 4568 tag of the negotiated crypto attribute
|
int mSrtpTag = 1; // RFC 4568 tag of the negotiated crypto attribute
|
||||||
struct RemoteCodec
|
struct RemoteCodec
|
||||||
{
|
{
|
||||||
RemoteCodec(MT::Codec::Factory* factory, int payloadType)
|
RemoteCodec(MT::Codec::Factory* factory, int payloadType) : mFactory(factory), mRemotePayloadType(payloadType)
|
||||||
:mFactory(factory), mRemotePayloadType(payloadType)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
MT::Codec::Factory* mFactory;
|
MT::Codec::Factory* mFactory;
|
||||||
int mRemotePayloadType;
|
int mRemotePayloadType;
|
||||||
@@ -115,7 +115,6 @@ protected:
|
|||||||
|
|
||||||
// Implements setState() logic. This allows to be called from constructor (it is not virtual function)
|
// Implements setState() logic. This allows to be called from constructor (it is not virtual function)
|
||||||
void setStateImpl(unsigned state);
|
void setStateImpl(unsigned state);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,14 +44,12 @@ bool DataProvider::processSdpOffer(const resip::SdpContents::Session::Medium& me
|
|||||||
mRemoteState = msSendonly;
|
mRemoteState = msSendonly;
|
||||||
setState(state() & ~(int)StreamState::Sending);
|
setState(state() & ~(int)StreamState::Sending);
|
||||||
}
|
}
|
||||||
else
|
else if (media.exists("recvonly"))
|
||||||
if (media.exists("recvonly"))
|
|
||||||
{
|
{
|
||||||
mRemoteState = msRecvonly;
|
mRemoteState = msRecvonly;
|
||||||
setState(state() & ~(int)StreamState::Receiving);
|
setState(state() & ~(int)StreamState::Receiving);
|
||||||
}
|
}
|
||||||
else
|
else if (media.exists("inactive"))
|
||||||
if (media.exists("inactive"))
|
|
||||||
{
|
{
|
||||||
mRemoteState = msInactive;
|
mRemoteState = msInactive;
|
||||||
setState(state() & ~((int)StreamState::Sending | (int)StreamState::Receiving));
|
setState(state() & ~((int)StreamState::Sending | (int)StreamState::Receiving));
|
||||||
|
|||||||
@@ -45,10 +45,12 @@ public:
|
|||||||
virtual void setDestinationAddress(const RtpPair<InternetAddress>& addr) = 0;
|
virtual void setDestinationAddress(const RtpPair<InternetAddress>& addr) = 0;
|
||||||
|
|
||||||
// Processes incoming data
|
// Processes incoming data
|
||||||
virtual void processData(const PDatagramSocket& s, const void* dataBuffer, int dataSize, InternetAddress& address) = 0;
|
virtual void processData(const PDatagramSocket& s, const void* dataBuffer, int dataSize,
|
||||||
|
InternetAddress& address) = 0;
|
||||||
|
|
||||||
// This method is called by user agent to send ICE packet from mediasocket
|
// This method is called by user agent to send ICE packet from mediasocket
|
||||||
virtual void sendData(const PDatagramSocket& s, InternetAddress& destination, const void* dataBuffer, unsigned int datasize) = 0;
|
virtual void sendData(const PDatagramSocket& s, InternetAddress& destination, const void* dataBuffer,
|
||||||
|
unsigned int datasize) = 0;
|
||||||
|
|
||||||
// Updates SDP offer
|
// Updates SDP offer
|
||||||
virtual void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) = 0;
|
virtual void updateSdpOffer(resip::SdpContents::Session::Medium& sdp, SdpDirection direction) = 0;
|
||||||
|
|||||||
+137
-164
@@ -39,7 +39,9 @@
|
|||||||
|
|
||||||
#define LOG_SUBSYSTEM "engine"
|
#define LOG_SUBSYSTEM "engine"
|
||||||
#define LOCK Lock l(mGuard)
|
#define LOCK Lock l(mGuard)
|
||||||
#define CAST2RESIPSESSION(x) (x.isValid() ? (x->getAppDialogSet().isValid() ? dynamic_cast<ResipSession*>(x->getAppDialogSet().get()) : NULL) : NULL)
|
#define CAST2RESIPSESSION(x) \
|
||||||
|
(x.isValid() ? (x->getAppDialogSet().isValid() ? dynamic_cast<ResipSession*>(x->getAppDialogSet().get()) : NULL) \
|
||||||
|
: NULL)
|
||||||
|
|
||||||
typedef resip::SdpContents::Session::Medium Medium;
|
typedef resip::SdpContents::Session::Medium Medium;
|
||||||
typedef resip::SdpContents::Session::MediumContainer MediumContainer;
|
typedef resip::SdpContents::Session::MediumContainer MediumContainer;
|
||||||
@@ -47,10 +49,13 @@ typedef resip::SdpContents::Session::MediumContainer MediumContainer;
|
|||||||
class TransportLogger : public resip::Transport::SipMessageLoggingHandler
|
class TransportLogger : public resip::Transport::SipMessageLoggingHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void outboundMessage(const resip::Tuple &source, const resip::Tuple &destination, const resip::SipMessage &msg) override
|
void outboundMessage(const resip::Tuple& source, const resip::Tuple& destination,
|
||||||
|
const resip::SipMessage& msg) override
|
||||||
{
|
{
|
||||||
std::ostringstream dest_buffer; dest_buffer << destination;
|
std::ostringstream dest_buffer;
|
||||||
std::ostringstream msg_buffer; msg_buffer << msg;
|
dest_buffer << destination;
|
||||||
|
std::ostringstream msg_buffer;
|
||||||
|
msg_buffer << msg;
|
||||||
std::string msg_text = msg_buffer.str();
|
std::string msg_text = msg_buffer.str();
|
||||||
#if defined(TARGET_ANDROID)
|
#if defined(TARGET_ANDROID)
|
||||||
if (msg_text.size() > 512)
|
if (msg_text.size() > 512)
|
||||||
@@ -72,13 +77,18 @@ public:
|
|||||||
// Note: retransmissions store already encoded messages, so callback doesn't send SipMessage it sends
|
// Note: retransmissions store already encoded messages, so callback doesn't send SipMessage it sends
|
||||||
// the encoded version of the SipMessage instead. If you need a SipMessage you will need to
|
// the encoded version of the SipMessage instead. If you need a SipMessage you will need to
|
||||||
// re-parse back into a SipMessage in the callback handler.
|
// re-parse back into a SipMessage in the callback handler.
|
||||||
void outboundRetransmit(const resip::Tuple &source, const resip::Tuple &destination, const resip::SendData &data) override
|
void outboundRetransmit(const resip::Tuple& source, const resip::Tuple& destination,
|
||||||
{}
|
const resip::SendData& data) override
|
||||||
|
|
||||||
void inboundMessage(const resip::Tuple& source, const resip::Tuple& destination, const resip::SipMessage &msg) override
|
|
||||||
{
|
{
|
||||||
std::ostringstream source_buffer; source_buffer << source;
|
}
|
||||||
std::ostringstream msg_buffer; msg_buffer << msg;
|
|
||||||
|
void inboundMessage(const resip::Tuple& source, const resip::Tuple& destination,
|
||||||
|
const resip::SipMessage& msg) override
|
||||||
|
{
|
||||||
|
std::ostringstream source_buffer;
|
||||||
|
source_buffer << source;
|
||||||
|
std::ostringstream msg_buffer;
|
||||||
|
msg_buffer << msg;
|
||||||
std::string msg_text = msg_buffer.str();
|
std::string msg_text = msg_buffer.str();
|
||||||
#if defined(TARGET_ANDROID)
|
#if defined(TARGET_ANDROID)
|
||||||
if (msg_text.size() > 512)
|
if (msg_text.size() > 512)
|
||||||
@@ -95,7 +105,6 @@ public:
|
|||||||
ICELogDebug(<< "Received from " << source_buffer.str() << "\n" << strx::prefixLines(msg_buffer.str(), "--->"));
|
ICELogDebug(<< "Received from " << source_buffer.str() << "\n" << strx::prefixLines(msg_buffer.str(), "--->"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-------------- UserAgent -----------------------
|
//-------------- UserAgent -----------------------
|
||||||
@@ -160,11 +169,16 @@ void UserAgent::start()
|
|||||||
while (std::getline(ss, line))
|
while (std::getline(ss, line))
|
||||||
{
|
{
|
||||||
line = strx::trim(line);
|
line = strx::trim(line);
|
||||||
ice::NetworkAddress addr(line.c_str(), 0); addr.setPort(80); // Fake port to make ICEAddress initialized
|
ice::NetworkAddress addr(line.c_str(), 0);
|
||||||
|
addr.setPort(80); // Fake port to make ICEAddress initialized
|
||||||
switch (addr.family())
|
switch (addr.family())
|
||||||
{
|
{
|
||||||
case AF_INET: nslist.push_back(resip::GenericIPAddress(*addr.sockaddr4())); break;
|
case AF_INET:
|
||||||
case AF_INET6: nslist.push_back(resip::GenericIPAddress(*addr.sockaddr6())); break;
|
nslist.push_back(resip::GenericIPAddress(*addr.sockaddr4()));
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
nslist.push_back(resip::GenericIPAddress(*addr.sockaddr6()));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,8 +216,16 @@ void UserAgent::start()
|
|||||||
mTransportList.clear();
|
mTransportList.clear();
|
||||||
resip::InternalTransport* t;
|
resip::InternalTransport* t;
|
||||||
|
|
||||||
#define ADD_TRANSPORT4(X) if ((t = dynamic_cast<resip::InternalTransport*>(mStack->addTransport(X, 0, resip::V4)))) { /*t->setTransportLogger(this);*/ mTransportList.push_back(t);}
|
#define ADD_TRANSPORT4(X) \
|
||||||
#define ADD_TRANSPORT6(X) if ((t = dynamic_cast<resip::InternalTransport*>(mStack->addTransport(X, 0, resip::V6)))) { /*t->setTransportLogger(this);*/ mTransportList.push_back(t);}
|
if ((t = dynamic_cast<resip::InternalTransport*>(mStack->addTransport(X, 0, resip::V4)))) \
|
||||||
|
{ /*t->setTransportLogger(this);*/ \
|
||||||
|
mTransportList.push_back(t); \
|
||||||
|
}
|
||||||
|
#define ADD_TRANSPORT6(X) \
|
||||||
|
if ((t = dynamic_cast<resip::InternalTransport*>(mStack->addTransport(X, 0, resip::V6)))) \
|
||||||
|
{ /*t->setTransportLogger(this);*/ \
|
||||||
|
mTransportList.push_back(t); \
|
||||||
|
}
|
||||||
|
|
||||||
switch (mConfig[CONFIG_TRANSPORT].asInt())
|
switch (mConfig[CONFIG_TRANSPORT].asInt())
|
||||||
{
|
{
|
||||||
@@ -351,8 +373,10 @@ void UserAgent::refresh()
|
|||||||
|
|
||||||
void UserAgent::onDumCanBeDeleted()
|
void UserAgent::onDumCanBeDeleted()
|
||||||
{
|
{
|
||||||
delete mDum; mDum = nullptr;
|
delete mDum;
|
||||||
delete mStack; mStack = nullptr;
|
mDum = nullptr;
|
||||||
|
delete mStack;
|
||||||
|
mStack = nullptr;
|
||||||
|
|
||||||
mClientObserverMap.clear();
|
mClientObserverMap.clear();
|
||||||
mServerObserverMap.clear();
|
mServerObserverMap.clear();
|
||||||
@@ -371,14 +395,12 @@ void UserAgent::stop()
|
|||||||
mTransportList.clear();
|
mTransportList.clear();
|
||||||
|
|
||||||
// Dump statistics here
|
// Dump statistics here
|
||||||
ICELogInfo(<< "Remaining "
|
ICELogInfo(<< "Remaining " << Session::InstanceCounter.load() << " session(s), "
|
||||||
<< Session::InstanceCounter.load() << " session(s), "
|
|
||||||
<< ResipSession::InstanceCounter.load() << " resip DialogSet(s), "
|
<< ResipSession::InstanceCounter.load() << " resip DialogSet(s), "
|
||||||
<< resip::ClientRegistration::InstanceCounter.load() << " ClientRegistration(s)");
|
<< resip::ClientRegistration::InstanceCounter.load() << " ClientRegistration(s)");
|
||||||
|
|
||||||
mDum->shutdown(this);
|
mDum->shutdown(this);
|
||||||
onDumCanBeDeleted();
|
onDumCanBeDeleted();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -417,7 +439,8 @@ void UserAgent::process()
|
|||||||
this->onSipConnectionFailed();
|
this->onSipConnectionFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase one terminated session. The rule is : seession must not have references from resiprocate and reference count has to be 1.
|
// Erase one terminated session. The rule is : seession must not have references from resiprocate and reference
|
||||||
|
// count has to be 1.
|
||||||
{
|
{
|
||||||
Lock l(mGuard);
|
Lock l(mGuard);
|
||||||
SessionMap::iterator sessionIter;
|
SessionMap::iterator sessionIter;
|
||||||
@@ -456,7 +479,9 @@ void UserAgent::process()
|
|||||||
session.processQueuedOffer();
|
session.processQueuedOffer();
|
||||||
|
|
||||||
// Generate outgoing data while available
|
// Generate outgoing data while available
|
||||||
int iceStreamId = -1, iceComponentId = -1; void* iceTag = NULL; bool iceResponse;
|
int iceStreamId = -1, iceComponentId = -1;
|
||||||
|
void* iceTag = NULL;
|
||||||
|
bool iceResponse;
|
||||||
ice::PByteBuffer buffer;
|
ice::PByteBuffer buffer;
|
||||||
while ((buffer = session.mIceStack->generateOutgoingData(iceResponse, iceStreamId, iceComponentId, iceTag)))
|
while ((buffer = session.mIceStack->generateOutgoingData(iceResponse, iceStreamId, iceComponentId, iceTag)))
|
||||||
{
|
{
|
||||||
@@ -468,9 +493,11 @@ void UserAgent::process()
|
|||||||
if (stream.provider() && stream.iceInfo().mStreamId == iceStreamId)
|
if (stream.provider() && stream.iceInfo().mStreamId == iceStreamId)
|
||||||
{
|
{
|
||||||
// Send generated packet via provider's method to allow custom scheme of encryption
|
// Send generated packet via provider's method to allow custom scheme of encryption
|
||||||
ICELogDebug(<<"Sending ICE packet to " << buffer->remoteAddress().toStdString() << " with " << buffer->comment());
|
ICELogDebug(<< "Sending ICE packet to " << buffer->remoteAddress().toStdString() << " with "
|
||||||
|
<< buffer->comment());
|
||||||
|
|
||||||
RtpPair<PDatagramSocket>& pair = buffer->remoteAddress().family() == AF_INET6 ? stream.socket6() : stream.socket4();
|
RtpPair<PDatagramSocket>& pair =
|
||||||
|
buffer->remoteAddress().family() == AF_INET6 ? stream.socket6() : stream.socket4();
|
||||||
PDatagramSocket s = iceComponentId == ICE_RTP_ID ? pair.mRtp : pair.mRtcp;
|
PDatagramSocket s = iceComponentId == ICE_RTP_ID ? pair.mRtp : pair.mRtcp;
|
||||||
if (s)
|
if (s)
|
||||||
stream.provider()->sendData(s, buffer->remoteAddress(), buffer->data(), buffer->size());
|
stream.provider()->sendData(s, buffer->remoteAddress(), buffer->data(), buffer->size());
|
||||||
@@ -491,10 +518,12 @@ void UserAgent::addRootCert(const ByteBuffer& data)
|
|||||||
if (!mStack)
|
if (!mStack)
|
||||||
return;
|
return;
|
||||||
resip::Data b(data.data(), data.size());
|
resip::Data b(data.data(), data.size());
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
mStack->getSecurity()->addRootCertPEM(b);
|
mStack->getSecurity()->addRootCertPEM(b);
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch (...)
|
||||||
|
{
|
||||||
// Ignore silently
|
// Ignore silently
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,8 +567,7 @@ std::string UserAgent::formatSipAddress(const std::string& sip)
|
|||||||
{
|
{
|
||||||
if (sip.find("sip:") == std::string::npos && sip.find("sips:") == std::string::npos)
|
if (sip.find("sip:") == std::string::npos && sip.find("sips:") == std::string::npos)
|
||||||
result = "<sip:" + sip + ">";
|
result = "<sip:" + sip + ">";
|
||||||
else
|
else if (sip[0] != '<' && sip.find('<') == std::string::npos)
|
||||||
if (sip[0] != '<' && sip.find('<') == std::string::npos)
|
|
||||||
result = "<" + sip + ">";
|
result = "<" + sip + ">";
|
||||||
else
|
else
|
||||||
result = sip;
|
result = sip;
|
||||||
@@ -633,14 +661,9 @@ void UserAgent::onCandidateGathered(PSession s, const char* address)
|
|||||||
|
|
||||||
|
|
||||||
// Called when new connectivity check is finished
|
// Called when new connectivity check is finished
|
||||||
void UserAgent::onCheckFinished(PSession s, const char* description)
|
void UserAgent::onCheckFinished(PSession s, const char* description) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
void UserAgent::onLog(const char* msg) {}
|
||||||
|
|
||||||
void UserAgent::onLog(const char* msg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::sendOffer(Session* session)
|
void UserAgent::sendOffer(Session* session)
|
||||||
{
|
{
|
||||||
@@ -653,10 +676,12 @@ void UserAgent::sendOffer(Session* session)
|
|||||||
if (session->mOriginVersion == 1)
|
if (session->mOriginVersion == 1)
|
||||||
{
|
{
|
||||||
// Construct INVITE session
|
// Construct INVITE session
|
||||||
auto msg = mDum->makeInviteSession(session->mRemotePeer, session->account()->mProfile, &sdp, session->mResipSession);
|
auto msg =
|
||||||
|
mDum->makeInviteSession(session->mRemotePeer, session->account()->mProfile, &sdp, session->mResipSession);
|
||||||
|
|
||||||
// Include user headers
|
// Include user headers
|
||||||
for (Session::UserHeaders::const_iterator iter = session->mUserHeaders.begin(); iter != session->mUserHeaders.end(); iter++)
|
for (Session::UserHeaders::const_iterator iter = session->mUserHeaders.begin();
|
||||||
|
iter != session->mUserHeaders.end(); iter++)
|
||||||
{
|
{
|
||||||
const std::string& name = iter->first;
|
const std::string& name = iter->first;
|
||||||
const std::string& value = iter->second;
|
const std::string& value = iter->second;
|
||||||
@@ -723,41 +748,31 @@ void UserAgent::onFailure(resip::ClientRegistrationHandle h, const resip::SipMes
|
|||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
bool UserAgent::operator()(resip::Log::Level level,
|
bool UserAgent::operator()(resip::Log::Level level, const resip::Subsystem& subsystem, const resip::Data& appName,
|
||||||
const resip::Subsystem& subsystem,
|
const char* file, int line, const resip::Data& message,
|
||||||
const resip::Data& appName,
|
const resip::Data& messageWithHeaders, const resip::Data& instanceName)
|
||||||
const char* file,
|
|
||||||
int line,
|
|
||||||
const resip::Data& message,
|
|
||||||
const resip::Data& messageWithHeaders,
|
|
||||||
const resip::Data& instanceName)
|
|
||||||
{
|
{
|
||||||
std::string filename = file;
|
std::string filename = file;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << "File " << strx::extractFilename(filename).c_str() << ", line " << line << ": " << message.c_str();
|
ss << "File " << strx::extractFilename(filename).c_str() << ", line " << line << ": " << message.c_str();
|
||||||
if (level <= resip::Log::Crit)
|
if (level <= resip::Log::Crit)
|
||||||
ICELogCritical(<< ss.str())
|
ICELogCritical(<< ss.str()) else if (level <= resip::Log::Warning)
|
||||||
else
|
ICELogError(<< ss.str().c_str()) else if (level < resip::Log::Debug)
|
||||||
if (level <= resip::Log::Warning)
|
ICELogInfo(<< ss.str().c_str()) else ICELogDebug(<< ss.str().c_str()) return false;
|
||||||
ICELogError(<< ss.str().c_str())
|
|
||||||
else
|
|
||||||
if (level < resip::Log::Debug)
|
|
||||||
ICELogInfo(<< ss.str().c_str())
|
|
||||||
else
|
|
||||||
ICELogDebug(<< ss.str().c_str())
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region INVITE handler
|
#pragma region INVITE handler
|
||||||
|
|
||||||
|
|
||||||
/// called when an initial INVITE or the intial response to an outoing invite
|
/// called when an initial INVITE or the intial response to an outoing invite
|
||||||
void UserAgent::onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg)
|
void UserAgent::onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat,
|
||||||
|
const resip::SipMessage& msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg)
|
void UserAgent::onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat,
|
||||||
|
const resip::SipMessage& msg)
|
||||||
{
|
{
|
||||||
ResipSession* rs = CAST2RESIPSESSION(h);
|
ResipSession* rs = CAST2RESIPSESSION(h);
|
||||||
if (!rs)
|
if (!rs)
|
||||||
@@ -793,15 +808,11 @@ void UserAgent::onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Received a failure response from UAS
|
/// Received a failure response from UAS
|
||||||
void UserAgent::onFailure(resip::ClientInviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onFailure(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// called when an in-dialog provisional response is received that contains an SDP body
|
/// called when an in-dialog provisional response is received that contains an SDP body
|
||||||
void UserAgent::onEarlyMedia(resip::ClientInviteSessionHandle h, const resip::SipMessage&, const resip::SdpContents&)
|
void UserAgent::onEarlyMedia(resip::ClientInviteSessionHandle h, const resip::SipMessage&, const resip::SdpContents&) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// called when dialog enters the Early state - typically after getting 18x
|
/// called when dialog enters the Early state - typically after getting 18x
|
||||||
@@ -819,7 +830,6 @@ void UserAgent::onProvisional(resip::ClientInviteSessionHandle h, const resip::S
|
|||||||
int responseCode = msg.header(resip::h_StatusLine).statusCode();
|
int responseCode = msg.header(resip::h_StatusLine).statusCode();
|
||||||
onSessionProvisional(s, responseCode);
|
onSessionProvisional(s, responseCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -880,7 +890,8 @@ void UserAgent::onConnected(resip::InviteSessionHandle h, const resip::SipMessag
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UserAgent::onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* related)
|
void UserAgent::onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason,
|
||||||
|
const resip::SipMessage* related)
|
||||||
{
|
{
|
||||||
ResipSession* rs = CAST2RESIPSESSION(h);
|
ResipSession* rs = CAST2RESIPSESSION(h);
|
||||||
if (!rs)
|
if (!rs)
|
||||||
@@ -907,9 +918,7 @@ void UserAgent::onTerminated(resip::InviteSessionHandle h, resip::InviteSessionH
|
|||||||
|
|
||||||
/// called when a fork that was created through a 1xx never receives a 2xx
|
/// called when a fork that was created through a 1xx never receives a 2xx
|
||||||
/// because another fork answered and this fork was canceled by a proxy.
|
/// because another fork answered and this fork was canceled by a proxy.
|
||||||
void UserAgent::onForkDestroyed(resip::ClientInviteSessionHandle)
|
void UserAgent::onForkDestroyed(resip::ClientInviteSessionHandle) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// called when a 3xx with valid targets is encountered in an early dialog
|
/// called when a 3xx with valid targets is encountered in an early dialog
|
||||||
@@ -918,9 +927,7 @@ void UserAgent::onForkDestroyed(resip::ClientInviteSessionHandle)
|
|||||||
/// Basically an onTermintated that conveys more information.
|
/// Basically an onTermintated that conveys more information.
|
||||||
/// checking for 3xx respones in onTerminated will not work as there may
|
/// checking for 3xx respones in onTerminated will not work as there may
|
||||||
/// be no valid targets.
|
/// be no valid targets.
|
||||||
void UserAgent::onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called when an SDP answer is received - has nothing to do with user
|
/// Called when an SDP answer is received - has nothing to do with user
|
||||||
/// answering the call
|
/// answering the call
|
||||||
@@ -963,14 +970,14 @@ void UserAgent::onAnswer(resip::InviteSessionHandle h, const resip::SipMessage&
|
|||||||
std::list<resip::SdpContents::Session::Medium>::const_iterator mediaIter;
|
std::list<resip::SdpContents::Session::Medium>::const_iterator mediaIter;
|
||||||
unsigned streamIndex = 0;
|
unsigned streamIndex = 0;
|
||||||
for (mediaIter = sdp.session().media().begin(), streamIndex = 0;
|
for (mediaIter = sdp.session().media().begin(), streamIndex = 0;
|
||||||
mediaIter != sdp.session().media().end() && streamIndex < s->mStreamList.size();
|
mediaIter != sdp.session().media().end() && streamIndex < s->mStreamList.size(); ++mediaIter, ++streamIndex)
|
||||||
++mediaIter, ++streamIndex)
|
|
||||||
{
|
{
|
||||||
Session::Stream& stream = s->mStreamList[streamIndex];
|
Session::Stream& stream = s->mStreamList[streamIndex];
|
||||||
const resip::SdpContents::Session::Medium& remoteStream = *mediaIter;
|
const resip::SdpContents::Session::Medium& remoteStream = *mediaIter;
|
||||||
|
|
||||||
// Update remote default ip if available
|
// Update remote default ip if available
|
||||||
const std::list<resip::SdpContents::Session::Connection>& streamConnections = remoteStream.getMediumConnections();
|
const std::list<resip::SdpContents::Session::Connection>& streamConnections =
|
||||||
|
remoteStream.getMediumConnections();
|
||||||
if (streamConnections.size())
|
if (streamConnections.size())
|
||||||
remoteDefaultIP = streamConnections.front().getAddress().c_str();
|
remoteDefaultIP = streamConnections.front().getAddress().c_str();
|
||||||
|
|
||||||
@@ -1016,7 +1023,8 @@ void UserAgent::onAnswer(resip::InviteSessionHandle h, const resip::SipMessage&
|
|||||||
// Corresponding turn allocation will be removed in this case.
|
// Corresponding turn allocation will be removed in this case.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!s->mIceStack->processSdpOffer(stream.iceInfo().mStreamId, candidateVector, remoteDefaultIP, remoteDefaultPort, mConfig[CONFIG_DEFERRELAYED].asBool()))
|
if (!s->mIceStack->processSdpOffer(stream.iceInfo().mStreamId, candidateVector, remoteDefaultIP,
|
||||||
|
remoteDefaultPort, mConfig[CONFIG_DEFERRELAYED].asBool()))
|
||||||
iceAvailable = false;
|
iceAvailable = false;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@@ -1034,8 +1042,7 @@ void UserAgent::onAnswer(resip::InviteSessionHandle h, const resip::SipMessage&
|
|||||||
// See if remote stream has "rtcp" or "rtcp-mux" attributes
|
// See if remote stream has "rtcp" or "rtcp-mux" attributes
|
||||||
if (remoteStream.exists("rtcp"))
|
if (remoteStream.exists("rtcp"))
|
||||||
addr2.setPort(strx::toInt(remoteStream.getValues("rtcp").front().c_str(), remoteDefaultPort + 1));
|
addr2.setPort(strx::toInt(remoteStream.getValues("rtcp").front().c_str(), remoteDefaultPort + 1));
|
||||||
else
|
else if (remoteStream.exists("rtcp-mux"))
|
||||||
if (remoteStream.exists("rtcp-mux"))
|
|
||||||
addr2.setPort(remoteDefaultPort);
|
addr2.setPort(remoteDefaultPort);
|
||||||
stream.provider()->setDestinationAddress(RtpPair<InternetAddress>(addr, addr2));
|
stream.provider()->setDestinationAddress(RtpPair<InternetAddress>(addr, addr2));
|
||||||
mediasupported = true;
|
mediasupported = true;
|
||||||
@@ -1111,8 +1118,7 @@ void UserAgent::onOffer(resip::InviteSessionHandle h, const resip::SipMessage& m
|
|||||||
{
|
{
|
||||||
code = s->processSdp(version, iceAvailable, icePwd, iceUfrag, remoteIp, sdp.session().media());
|
code = s->processSdp(version, iceAvailable, icePwd, iceUfrag, remoteIp, sdp.session().media());
|
||||||
}
|
}
|
||||||
else
|
else if (version == s->mRemoteOriginVersion)
|
||||||
if (version == s->mRemoteOriginVersion)
|
|
||||||
{
|
{
|
||||||
// Timer, answer with previous SDP
|
// Timer, answer with previous SDP
|
||||||
// session->processTimer();
|
// session->processTimer();
|
||||||
@@ -1149,64 +1155,43 @@ void UserAgent::onOffer(resip::InviteSessionHandle h, const resip::SipMessage& m
|
|||||||
|
|
||||||
/// called when an Invite w/out SDP is sent, or any other context which
|
/// called when an Invite w/out SDP is sent, or any other context which
|
||||||
/// requires an SDP offer from the user
|
/// requires an SDP offer from the user
|
||||||
void UserAgent::onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called if an offer in a UPDATE or re-INVITE was rejected - not real
|
/// called if an offer in a UPDATE or re-INVITE was rejected - not real
|
||||||
/// useful. A SipMessage is provided if one is available
|
/// useful. A SipMessage is provided if one is available
|
||||||
void UserAgent::onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg)
|
void UserAgent::onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called when INFO message is received
|
/// called when INFO message is received
|
||||||
void UserAgent::onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called when response to INFO message is received
|
/// called when response to INFO message is received
|
||||||
void UserAgent::onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called when MESSAGE message is received
|
/// called when MESSAGE message is received
|
||||||
void UserAgent::onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called when response to MESSAGE message is received
|
/// called when response to MESSAGE message is received
|
||||||
void UserAgent::onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called when an REFER message is received. The refer is accepted or
|
/// called when an REFER message is received. The refer is accepted or
|
||||||
/// rejected using the server subscription. If the offer is accepted,
|
/// rejected using the server subscription. If the offer is accepted,
|
||||||
/// DialogUsageManager::makeInviteSessionFromRefer can be used to create an
|
/// DialogUsageManager::makeInviteSessionFromRefer can be used to create an
|
||||||
/// InviteSession that will send notify messages using the ServerSubscription
|
/// InviteSession that will send notify messages using the ServerSubscription
|
||||||
void UserAgent::onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg)
|
void UserAgent::onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// called when an REFER message receives a failure response
|
/// called when an REFER message receives a failure response
|
||||||
void UserAgent::onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg)
|
void UserAgent::onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// called when an REFER message receives an accepted response
|
/// called when an REFER message receives an accepted response
|
||||||
void UserAgent::onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg)
|
void UserAgent::onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle,
|
||||||
|
const resip::SipMessage& msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1227,13 +1212,9 @@ void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsHostRecord>& result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsAAAARecord>& result)
|
void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsAAAARecord>& result) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>& result)
|
void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsSrvRecord>& result) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsNaptrRecord>& result)
|
void UserAgent::onDnsResult(const resip::DNSResult<resip::DnsNaptrRecord>& result)
|
||||||
{
|
{
|
||||||
@@ -1281,28 +1262,20 @@ int UserAgent::onRequestRetry(resip::ClientPublicationHandle, int retrySeconds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UserAgent::onPublicationSuccess(PAccount account) {}
|
||||||
|
|
||||||
void UserAgent::onPublicationSuccess(PAccount account)
|
void UserAgent::onPublicationTerminated(PAccount account, int code) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onPublicationTerminated(PAccount account, int code)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Subscriptions
|
#pragma region Subscriptions
|
||||||
|
|
||||||
void UserAgent::onClientObserverStart(PClientObserver observer)
|
void UserAgent::onClientObserverStart(PClientObserver observer) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onClientObserverStop(PClientObserver observer, int code)
|
void UserAgent::onClientObserverStop(PClientObserver observer, int code) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onPresenceUpdate(PClientObserver observer, const std::string& peer, bool online, const std::string& content)
|
void UserAgent::onPresenceUpdate(PClientObserver observer, const std::string& peer, bool online,
|
||||||
|
const std::string& content)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1351,13 +1324,9 @@ void UserAgent::onTerminated(resip::ServerSubscriptionHandle h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onServerObserverStart(PServerObserver observer)
|
void UserAgent::onServerObserverStart(PServerObserver observer) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onServerObserverStop(PServerObserver observer, int code)
|
void UserAgent::onServerObserverStop(PServerObserver observer, int code) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify)
|
void UserAgent::onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify)
|
||||||
{
|
{
|
||||||
@@ -1393,8 +1362,7 @@ void UserAgent::onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMess
|
|||||||
bool online = pidf->getSimpleStatus(&body);
|
bool online = pidf->getSimpleStatus(&body);
|
||||||
onPresenceUpdate(observer, observer->peer(), online, std::string(body.c_str(), body.size()));
|
onPresenceUpdate(observer, observer->peer(), online, std::string(body.c_str(), body.size()));
|
||||||
}
|
}
|
||||||
else
|
else if (resip::MultipartRelatedContents* mr = dynamic_cast<resip::MultipartRelatedContents*>(contents))
|
||||||
if (resip::MultipartRelatedContents* mr = dynamic_cast<resip::MultipartRelatedContents*>(contents))
|
|
||||||
{
|
{
|
||||||
resip::MultipartRelatedContents::Parts& parts = mr->parts();
|
resip::MultipartRelatedContents::Parts& parts = mr->parts();
|
||||||
for (resip::MultipartRelatedContents::Parts::const_iterator i = parts.begin(); i != parts.end(); ++i)
|
for (resip::MultipartRelatedContents::Parts::const_iterator i = parts.begin(); i != parts.end(); ++i)
|
||||||
@@ -1448,8 +1416,7 @@ void UserAgent::onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (resip::Pidf* pidf = dynamic_cast<resip::Pidf*>(c))
|
||||||
if (resip::Pidf* pidf = dynamic_cast<resip::Pidf*>(c))
|
|
||||||
{
|
{
|
||||||
resip::Data body = pidf->getBodyData();
|
resip::Data body = pidf->getBodyData();
|
||||||
bool online = pidf->getSimpleStatus(&body);
|
bool online = pidf->getSimpleStatus(&body);
|
||||||
@@ -1459,7 +1426,8 @@ void UserAgent::onUpdate(resip::ClientSubscriptionHandle h, const resip::SipMess
|
|||||||
onPresenceUpdate(observer, entity.c_str(), online, std::string(body.c_str(), body.size()));
|
onPresenceUpdate(observer, entity.c_str(), online, std::string(body.c_str(), body.size()));
|
||||||
|
|
||||||
// Drop corresponding record from availableContacts
|
// Drop corresponding record from availableContacts
|
||||||
std::vector<resip::Data>::iterator ci = std::find(availableContacts.begin(), availableContacts.end(), entity);
|
std::vector<resip::Data>::iterator ci =
|
||||||
|
std::find(availableContacts.begin(), availableContacts.end(), entity);
|
||||||
if (ci != availableContacts.end())
|
if (ci != availableContacts.end())
|
||||||
availableContacts.erase(ci);
|
availableContacts.erase(ci);
|
||||||
}
|
}
|
||||||
@@ -1531,22 +1499,16 @@ void UserAgent::onNewSubscription(resip::ClientSubscriptionHandle h, const resip
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// called to allow app to adorn a message.
|
/// called to allow app to adorn a message.
|
||||||
void UserAgent::onReadyToSend(resip::ClientSubscriptionHandle, resip::SipMessage& msg)
|
void UserAgent::onReadyToSend(resip::ClientSubscriptionHandle, resip::SipMessage& msg) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UserAgent::onNotifyNotReceived(resip::ClientSubscriptionHandle)
|
void UserAgent::onNotifyNotReceived(resip::ClientSubscriptionHandle) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called when a TCP or TLS flow to the server has terminated. This can be caused by socket
|
/// Called when a TCP or TLS flow to the server has terminated. This can be caused by socket
|
||||||
/// errors, or missing CRLF keep alives pong responses from the server.
|
/// errors, or missing CRLF keep alives pong responses from the server.
|
||||||
// Called only if clientOutbound is enabled on the UserProfile and the first hop server
|
// Called only if clientOutbound is enabled on the UserProfile and the first hop server
|
||||||
/// supports RFC5626 (outbound).
|
/// supports RFC5626 (outbound).
|
||||||
/// Default implementation is to re-form the subscription using a new flow
|
/// Default implementation is to re-form the subscription using a new flow
|
||||||
void UserAgent::onFlowTerminated(resip::ClientSubscriptionHandle)
|
void UserAgent::onFlowTerminated(resip::ClientSubscriptionHandle) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region PagerHandler
|
#pragma region PagerHandler
|
||||||
@@ -1560,14 +1522,16 @@ void UserAgent::onSuccess(resip::ClientPagerMessageHandle h, const resip::SipMes
|
|||||||
onMessageSent(getAccount(status.header(resip::h_From)), s->sessionId(), s->remoteAddress(), s->tag());
|
onMessageSent(getAccount(status.header(resip::h_From)), s->sessionId(), s->remoteAddress(), s->tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onFailure(resip::ClientPagerMessageHandle h, const resip::SipMessage& status, std::unique_ptr<resip::Contents> contents)
|
void UserAgent::onFailure(resip::ClientPagerMessageHandle h, const resip::SipMessage& status,
|
||||||
|
std::unique_ptr<resip::Contents> contents)
|
||||||
{
|
{
|
||||||
if (!h.isValid())
|
if (!h.isValid())
|
||||||
return;
|
return;
|
||||||
ResipSession* s = CAST2RESIPSESSION(h);
|
ResipSession* s = CAST2RESIPSESSION(h);
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
onMessageFailed(getAccount(status.header(resip::h_From)), s->sessionId(), s->remoteAddress(), status.header(resip::h_StatusLine).statusCode(), s->tag());
|
onMessageFailed(getAccount(status.header(resip::h_From)), s->sessionId(), s->remoteAddress(),
|
||||||
|
status.header(resip::h_StatusLine).statusCode(), s->tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onMessageArrived(resip::ServerPagerMessageHandle h, const resip::SipMessage& message)
|
void UserAgent::onMessageArrived(resip::ServerPagerMessageHandle h, const resip::SipMessage& message)
|
||||||
@@ -1593,17 +1557,17 @@ void UserAgent::updateInterfaceList()
|
|||||||
// ICEImpl::ICENetworkHelper::instance().reload();
|
// ICEImpl::ICENetworkHelper::instance().reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onMessageArrived(PAccount /*account*/, const std::string& /*peer*/, const void* /*ptr*/, unsigned /*length*/)
|
void UserAgent::onMessageArrived(PAccount /*account*/, const std::string& /*peer*/, const void* /*ptr*/,
|
||||||
|
unsigned /*length*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onMessageFailed(PAccount /*account*/, int /*id*/, const std::string& /*peer*/, int /*code*/, void* /*tag*/)
|
void UserAgent::onMessageFailed(PAccount /*account*/, int /*id*/, const std::string& /*peer*/, int /*code*/,
|
||||||
|
void* /*tag*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserAgent::onMessageSent(PAccount /*account*/, int /*id*/, const std::string& /*peer*/, void* /*tag*/)
|
void UserAgent::onMessageSent(PAccount /*account*/, int /*id*/, const std::string& /*peer*/, void* /*tag*/) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantMap& UserAgent::config()
|
VariantMap& UserAgent::config()
|
||||||
{
|
{
|
||||||
@@ -1678,7 +1642,8 @@ PSession UserAgent::getUserSession(int sessionId)
|
|||||||
PAccount UserAgent::getAccount(const resip::NameAddr& myAddr)
|
PAccount UserAgent::getAccount(const resip::NameAddr& myAddr)
|
||||||
{
|
{
|
||||||
PAccount acc;
|
PAccount acc;
|
||||||
for (AccountSet::iterator accountIter = mAccountSet.begin(); accountIter != mAccountSet.end() && !acc; accountIter++)
|
for (AccountSet::iterator accountIter = mAccountSet.begin(); accountIter != mAccountSet.end() && !acc;
|
||||||
|
accountIter++)
|
||||||
if ((*accountIter)->isResponsibleFor(myAddr))
|
if ((*accountIter)->isResponsibleFor(myAddr))
|
||||||
acc = *accountIter;
|
acc = *accountIter;
|
||||||
|
|
||||||
@@ -1688,7 +1653,8 @@ PAccount UserAgent::getAccount(const resip::NameAddr& myAddr)
|
|||||||
PAccount UserAgent::getAccount(Account* account)
|
PAccount UserAgent::getAccount(Account* account)
|
||||||
{
|
{
|
||||||
PAccount acc;
|
PAccount acc;
|
||||||
for (AccountSet::iterator accountIter = mAccountSet.begin(); accountIter != mAccountSet.end() && !acc; accountIter++)
|
for (AccountSet::iterator accountIter = mAccountSet.begin(); accountIter != mAccountSet.end() && !acc;
|
||||||
|
accountIter++)
|
||||||
if (accountIter->get() == account)
|
if (accountIter->get() == account)
|
||||||
acc = *accountIter;
|
acc = *accountIter;
|
||||||
|
|
||||||
@@ -1697,7 +1663,14 @@ PAccount UserAgent::getAccount(Account* account)
|
|||||||
|
|
||||||
PAccount UserAgent::getAccount(int sessionId)
|
PAccount UserAgent::getAccount(int sessionId)
|
||||||
{
|
{
|
||||||
auto profileIter = std::find_if(mAccountSet.begin(), mAccountSet.end(), [=](const AccountSet::value_type& v) {if (v->mRegistration) return v->mRegistration->sessionId() == sessionId; else return false;});
|
auto profileIter = std::find_if(mAccountSet.begin(), mAccountSet.end(),
|
||||||
|
[=](const AccountSet::value_type& v)
|
||||||
|
{
|
||||||
|
if (v->mRegistration)
|
||||||
|
return v->mRegistration->sessionId() == sessionId;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
});
|
||||||
return (profileIter != mAccountSet.end()) ? *profileIter : PAccount();
|
return (profileIter != mAccountSet.end()) ? *profileIter : PAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ enum
|
|||||||
CONFIG_ICEUSERNAME, // Optional username for TURN server. String value.
|
CONFIG_ICEUSERNAME, // Optional username for TURN server. String value.
|
||||||
CONFIG_ICEPASSWORD, // Optional password for TURN server. String value.
|
CONFIG_ICEPASSWORD, // Optional password for TURN server. String value.
|
||||||
CONFIG_SIPS, // Marks if account credentials are sips: scheme. Boolean value.
|
CONFIG_SIPS, // Marks if account credentials are sips: scheme. Boolean value.
|
||||||
CONFIG_STUNSERVER_IP, // Optional IP address of STUN/TURN server. String value. It is better to use CONFIG_STUNSERVER_NAME.
|
CONFIG_STUNSERVER_IP, // Optional IP address of STUN/TURN server. String value. It is better to use
|
||||||
|
// CONFIG_STUNSERVER_NAME.
|
||||||
CONFIG_STUNSERVER_NAME, // Host name of STUN/TURN server. stun.xten.com for example. String value.
|
CONFIG_STUNSERVER_NAME, // Host name of STUN/TURN server. stun.xten.com for example. String value.
|
||||||
CONFIG_STUNSERVER_PORT, // Port number of STUN/TURN server. Integer value.
|
CONFIG_STUNSERVER_PORT, // Port number of STUN/TURN server. Integer value.
|
||||||
CONFIG_USERAGENT, // Name of user agent in SIP headers. String value.
|
CONFIG_USERAGENT, // Name of user agent in SIP headers. String value.
|
||||||
@@ -98,7 +99,8 @@ enum
|
|||||||
CONFIG_DNS_CACHE_TIME, // DNS cache time; default is 86400 seconds
|
CONFIG_DNS_CACHE_TIME, // DNS cache time; default is 86400 seconds
|
||||||
CONFIG_PRESENCE_ID, // Tuple ID used in presence publishing; determines source device
|
CONFIG_PRESENCE_ID, // Tuple ID used in presence publishing; determines source device
|
||||||
CONFIG_ROOTCERT, // Additional root cert in PEM format; string.
|
CONFIG_ROOTCERT, // Additional root cert in PEM format; string.
|
||||||
CONFIG_CACHECREDENTIALS, // Attempt to cache credentials that comes in response from PBX. Use them when possible to reduce number of steps of SIP transaction
|
CONFIG_CACHECREDENTIALS, // Attempt to cache credentials that comes in response from PBX. Use them when possible to
|
||||||
|
// reduce number of steps of SIP transaction
|
||||||
CONFIG_RTCP_ATTR, // Use "rtcp" attribute in sdp. Default value is true.
|
CONFIG_RTCP_ATTR, // Use "rtcp" attribute in sdp. Default value is true.
|
||||||
CONFIG_MULTIPLEXING, // Do rtp/rtcp multiplexing
|
CONFIG_MULTIPLEXING, // Do rtp/rtcp multiplexing
|
||||||
CONFIG_DEFERRELAYED, // Defer relayed media path
|
CONFIG_DEFERRELAYED, // Defer relayed media path
|
||||||
@@ -160,8 +162,10 @@ class UserAgent: public resip::ClientRegistrationHandler,
|
|||||||
friend class ResipSession;
|
friend class ResipSession;
|
||||||
friend class NATDecorator;
|
friend class NATDecorator;
|
||||||
friend class WatcherQueue;
|
friend class WatcherQueue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Compares two sip addresses. Returns true if they represent the same entity - user and domain are the same. Otherwise returns false. */
|
/* Compares two sip addresses. Returns true if they represent the same entity - user and domain are the same.
|
||||||
|
* Otherwise returns false. */
|
||||||
static bool compareSipAddresses(const std::string& sip1, const std::string& sip2);
|
static bool compareSipAddresses(const std::string& sip1, const std::string& sip2);
|
||||||
static std::string formatSipAddress(const std::string& sip);
|
static std::string formatSipAddress(const std::string& sip);
|
||||||
static bool isSipAddressValid(const std::string& sip);
|
static bool isSipAddressValid(const std::string& sip);
|
||||||
@@ -187,7 +191,8 @@ public:
|
|||||||
This is asynchronous method. onStop() event will be called later */
|
This is asynchronous method. onStop() event will be called later */
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
/* Emergency stop. Please always call shutdown() before this. Kills registration, sessions & presence - everything. onStop() is called in context of this method. */
|
/* Emergency stop. Please always call shutdown() before this. Kills registration, sessions & presence - everything.
|
||||||
|
* onStop() is called in context of this method. */
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
/* Checks if user agent is active (started). */
|
/* Checks if user agent is active (started). */
|
||||||
@@ -268,7 +273,8 @@ public:
|
|||||||
virtual void onClientObserverStop(PClientObserver observer, int code);
|
virtual void onClientObserverStop(PClientObserver observer, int code);
|
||||||
virtual void onServerObserverStop(PServerObserver observer, int code);
|
virtual void onServerObserverStop(PServerObserver observer, int code);
|
||||||
|
|
||||||
virtual void onPresenceUpdate(PClientObserver observer, const std::string& peer, bool online, const std::string& content);
|
virtual void onPresenceUpdate(PClientObserver observer, const std::string& peer, bool online,
|
||||||
|
const std::string& content);
|
||||||
virtual void onMessageArrived(PAccount account, const std::string& peer, const void* ptr, unsigned length);
|
virtual void onMessageArrived(PAccount account, const std::string& peer, const void* ptr, unsigned length);
|
||||||
virtual void onMessageFailed(PAccount account, int id, const std::string& peer, int code, void* tag);
|
virtual void onMessageFailed(PAccount account, int id, const std::string& peer, int code, void* tag);
|
||||||
virtual void onMessageSent(PAccount account, int id, const std::string& peer, void* tag);
|
virtual void onMessageSent(PAccount account, int id, const std::string& peer, void* tag);
|
||||||
@@ -280,14 +286,17 @@ public:
|
|||||||
// InviteSessionHandler implementation
|
// InviteSessionHandler implementation
|
||||||
#pragma region InviteSessionHandler implementation
|
#pragma region InviteSessionHandler implementation
|
||||||
/// called when an initial INVITE or the intial response to an outoing invite
|
/// called when an initial INVITE or the intial response to an outoing invite
|
||||||
virtual void onNewSession(resip::ClientInviteSessionHandle, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg) override;
|
virtual void onNewSession(resip::ClientInviteSessionHandle, resip::InviteSession::OfferAnswerType oat,
|
||||||
virtual void onNewSession(resip::ServerInviteSessionHandle, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg) override;
|
const resip::SipMessage& msg) override;
|
||||||
|
virtual void onNewSession(resip::ServerInviteSessionHandle, resip::InviteSession::OfferAnswerType oat,
|
||||||
|
const resip::SipMessage& msg) override;
|
||||||
|
|
||||||
/// Received a failure response from UAS
|
/// Received a failure response from UAS
|
||||||
virtual void onFailure(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override;
|
virtual void onFailure(resip::ClientInviteSessionHandle, const resip::SipMessage& msg) override;
|
||||||
|
|
||||||
/// called when an in-dialog provisional response is received that contains an SDP body
|
/// called when an in-dialog provisional response is received that contains an SDP body
|
||||||
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&) override;
|
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&,
|
||||||
|
const resip::SdpContents&) override;
|
||||||
|
|
||||||
/// called when dialog enters the Early state - typically after getting 18x
|
/// called when dialog enters the Early state - typically after getting 18x
|
||||||
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage&) override;
|
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage&) override;
|
||||||
@@ -298,7 +307,8 @@ public:
|
|||||||
/// called when a dialog initiated as a UAS enters the connected state
|
/// called when a dialog initiated as a UAS enters the connected state
|
||||||
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
|
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
|
||||||
|
|
||||||
virtual void onTerminated(resip::InviteSessionHandle, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* related=0) override;
|
virtual void onTerminated(resip::InviteSessionHandle, resip::InviteSessionHandler::TerminatedReason reason,
|
||||||
|
const resip::SipMessage* related = 0) override;
|
||||||
|
|
||||||
/// called when a fork that was created through a 1xx never receives a 2xx
|
/// called when a fork that was created through a 1xx never receives a 2xx
|
||||||
/// because another fork answered and this fork was canceled by a proxy.
|
/// because another fork answered and this fork was canceled by a proxy.
|
||||||
@@ -345,7 +355,8 @@ public:
|
|||||||
/// rejected using the server subscription. If the offer is accepted,
|
/// rejected using the server subscription. If the offer is accepted,
|
||||||
/// DialogUsageManager::makeInviteSessionFromRefer can be used to create an
|
/// DialogUsageManager::makeInviteSessionFromRefer can be used to create an
|
||||||
/// InviteSession that will send notify messages using the ServerSubscription
|
/// InviteSession that will send notify messages using the ServerSubscription
|
||||||
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg) override;
|
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle,
|
||||||
|
const resip::SipMessage& msg) override;
|
||||||
|
|
||||||
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
|
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
|
||||||
|
|
||||||
@@ -353,7 +364,8 @@ public:
|
|||||||
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
|
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg) override;
|
||||||
|
|
||||||
/// called when an REFER message receives an accepted response
|
/// called when an REFER message receives an accepted response
|
||||||
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg) override;
|
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle,
|
||||||
|
const resip::SipMessage& msg) override;
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
// ClientRegistrationHandler implementation
|
// ClientRegistrationHandler implementation
|
||||||
@@ -377,14 +389,9 @@ public:
|
|||||||
|
|
||||||
#pragma region ExternalLogger implementation
|
#pragma region ExternalLogger implementation
|
||||||
/** return true to also do default logging, false to suppress default logging. */
|
/** return true to also do default logging, false to suppress default logging. */
|
||||||
virtual bool operator()(resip::Log::Level level,
|
virtual bool operator()(resip::Log::Level level, const resip::Subsystem& subsystem, const resip::Data& appName,
|
||||||
const resip::Subsystem& subsystem,
|
const char* file, int line, const resip::Data& message,
|
||||||
const resip::Data& appName,
|
const resip::Data& messageWithHeaders, const resip::Data& instanceName) override;
|
||||||
const char* file,
|
|
||||||
int line,
|
|
||||||
const resip::Data& message,
|
|
||||||
const resip::Data& messageWithHeaders,
|
|
||||||
const resip::Data& instanceName) override;
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region DnsResultSink implementation
|
#pragma region DnsResultSink implementation
|
||||||
@@ -438,11 +445,13 @@ public:
|
|||||||
|
|
||||||
#pragma region PagerHandler
|
#pragma region PagerHandler
|
||||||
void onSuccess(resip::ClientPagerMessageHandle, const resip::SipMessage& status) override;
|
void onSuccess(resip::ClientPagerMessageHandle, const resip::SipMessage& status) override;
|
||||||
void onFailure(resip::ClientPagerMessageHandle, const resip::SipMessage& status, std::unique_ptr<resip::Contents> contents) override;
|
void onFailure(resip::ClientPagerMessageHandle, const resip::SipMessage& status,
|
||||||
|
std::unique_ptr<resip::Contents> contents) override;
|
||||||
void onMessageArrived(resip::ServerPagerMessageHandle, const resip::SipMessage& message) override;
|
void onMessageArrived(resip::ServerPagerMessageHandle, const resip::SipMessage& message) override;
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
void onDumCanBeDeleted() override;
|
void onDumCanBeDeleted() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Mutex to protect this instance
|
// Mutex to protect this instance
|
||||||
Mutex mGuard;
|
Mutex mGuard;
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
#include "EP_NetworkQueue.h"
|
#include "EP_NetworkQueue.h"
|
||||||
#include "EP_Engine.h"
|
#include "EP_Engine.h"
|
||||||
|
|
||||||
WatcherQueue::WatcherQueue(UserAgent& ua)
|
WatcherQueue::WatcherQueue(UserAgent& ua) : mActiveId(0), mAgent(ua) {}
|
||||||
:mActiveId(0), mAgent(ua)
|
|
||||||
{}
|
|
||||||
|
|
||||||
WatcherQueue::~WatcherQueue()
|
WatcherQueue::~WatcherQueue() {}
|
||||||
{}
|
|
||||||
|
|
||||||
int WatcherQueue::add(const std::string& peer, const std::string& package, void* tag)
|
int WatcherQueue::add(const std::string& peer, const std::string& package, void* tag)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ public:
|
|||||||
void* mTag = nullptr; // User tag
|
void* mTag = nullptr; // User tag
|
||||||
int mId = 0; // Related session ID - it is always non-zero (zero is here for initialization only)
|
int mId = 0; // Related session ID - it is always non-zero (zero is here for initialization only)
|
||||||
|
|
||||||
Item()
|
Item() {}
|
||||||
{}
|
|
||||||
|
|
||||||
bool scheduled()
|
bool scheduled()
|
||||||
{
|
{
|
||||||
return mState == State_ScheduledToAdd || mState == State_ScheduledToDelete || mState == State_ScheduledToRefresh;
|
return mState == State_ScheduledToAdd || mState == State_ScheduledToDelete ||
|
||||||
|
mState == State_ScheduledToRefresh;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
WatcherQueue(UserAgent& agent);
|
WatcherQueue(UserAgent& agent);
|
||||||
|
|||||||
@@ -9,13 +9,9 @@
|
|||||||
#include <resip/stack/Pidf.hxx>
|
#include <resip/stack/Pidf.hxx>
|
||||||
#include <resip/dum/ClientSubscription.hxx>
|
#include <resip/dum/ClientSubscription.hxx>
|
||||||
|
|
||||||
ClientObserver::ClientObserver()
|
ClientObserver::ClientObserver() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientObserver::~ClientObserver()
|
ClientObserver::~ClientObserver() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientObserver::refresh()
|
void ClientObserver::refresh()
|
||||||
{
|
{
|
||||||
@@ -27,8 +23,7 @@ void ClientObserver::stop()
|
|||||||
{
|
{
|
||||||
if (mHandle.isValid())
|
if (mHandle.isValid())
|
||||||
mHandle->end();
|
mHandle->end();
|
||||||
else
|
else if (mSession)
|
||||||
if (mSession)
|
|
||||||
{
|
{
|
||||||
mSession->runTerminatedEvent(ResipSession::Type_Subscription);
|
mSession->runTerminatedEvent(ResipSession::Type_Subscription);
|
||||||
if (mSession)
|
if (mSession)
|
||||||
@@ -42,11 +37,7 @@ std::string ClientObserver::peer()
|
|||||||
return mPeer;
|
return mPeer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerObserver::ServerObserver()
|
ServerObserver::ServerObserver() : mState(State_Incoming) {}
|
||||||
:mState(State_Incoming)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerObserver::~ServerObserver()
|
ServerObserver::~ServerObserver()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class ClientObserver
|
|||||||
{
|
{
|
||||||
friend class Account;
|
friend class Account;
|
||||||
friend class UserAgent;
|
friend class UserAgent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClientObserver();
|
ClientObserver();
|
||||||
~ClientObserver();
|
~ClientObserver();
|
||||||
@@ -43,6 +44,7 @@ typedef std::shared_ptr<ClientObserver> PClientObserver;
|
|||||||
class ServerObserver
|
class ServerObserver
|
||||||
{
|
{
|
||||||
friend class UserAgent;
|
friend class UserAgent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServerObserver();
|
ServerObserver();
|
||||||
~ServerObserver();
|
~ServerObserver();
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ ReliableTunnel::ReliableTunnel(const char* streamname)
|
|||||||
mBandwidth = 0;
|
mBandwidth = 0;
|
||||||
mExitSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
mExitSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
mDataSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
mDataSignal = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReliableTunnel::~ReliableTunnel()
|
ReliableTunnel::~ReliableTunnel()
|
||||||
@@ -238,7 +237,8 @@ void ReliableTunnel::encrypt(void* dataPtr, int dataSize)
|
|||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
for (unsigned i = 0; i < dataSize / blockSize(); i++)
|
for (unsigned i = 0; i < dataSize / blockSize(); i++)
|
||||||
BF_ecb_encrypt((unsigned char*)dataPtr + i * blockSize(), (unsigned char*)dataPtr + i * blockSize(), &mCipher, BF_ENCRYPT);
|
BF_ecb_encrypt((unsigned char*)dataPtr + i * blockSize(), (unsigned char*)dataPtr + i * blockSize(), &mCipher,
|
||||||
|
BF_ENCRYPT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_CRYPTOPP
|
#ifdef USE_CRYPTOPP
|
||||||
@@ -254,7 +254,8 @@ void ReliableTunnel::decrypt(void* dataPtr, int dataSize)
|
|||||||
return;
|
return;
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
for (unsigned i = 0; i < dataSize / blockSize(); i++)
|
for (unsigned i = 0; i < dataSize / blockSize(); i++)
|
||||||
BF_ecb_encrypt((unsigned char*)dataPtr + i * blockSize(), (unsigned char*)dataPtr + i * blockSize(), &mCipher, BF_DECRYPT);
|
BF_ecb_encrypt((unsigned char*)dataPtr + i * blockSize(), (unsigned char*)dataPtr + i * blockSize(), &mCipher,
|
||||||
|
BF_DECRYPT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_CRYPTOPP
|
#ifdef USE_CRYPTOPP
|
||||||
|
|||||||
@@ -111,8 +111,7 @@ protected:
|
|||||||
// Mutex to protect queuing/sending outgoing data
|
// Mutex to protect queuing/sending outgoing data
|
||||||
resip::Mutex mOutgoingMtx;
|
resip::Mutex mOutgoingMtx;
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string> mNewQueued;
|
||||||
mNewQueued;
|
|
||||||
resip::Mutex mNewQueuedGuard;
|
resip::Mutex mNewQueuedGuard;
|
||||||
resip::Mutex mStackGuard;
|
resip::Mutex mStackGuard;
|
||||||
|
|
||||||
|
|||||||
@@ -16,18 +16,15 @@
|
|||||||
typedef resip::SdpContents::Session::Medium Medium;
|
typedef resip::SdpContents::Session::Medium Medium;
|
||||||
typedef resip::SdpContents::Session::MediumContainer MediumContainer;
|
typedef resip::SdpContents::Session::MediumContainer MediumContainer;
|
||||||
|
|
||||||
#define IS_MULTIPLEX() mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool() ? SocketHeap::DoMultiplexing : SocketHeap::DontMultiplexing
|
#define IS_MULTIPLEX() \
|
||||||
|
mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool() ? SocketHeap::DoMultiplexing : SocketHeap::DontMultiplexing
|
||||||
|
|
||||||
|
|
||||||
//------------ ResipSessionAppDialog ------------
|
//------------ ResipSessionAppDialog ------------
|
||||||
#pragma region ResipSessionAppDialog
|
#pragma region ResipSessionAppDialog
|
||||||
ResipSessionAppDialog::ResipSessionAppDialog(resip::HandleManager& ham) : AppDialog(ham)
|
ResipSessionAppDialog::ResipSessionAppDialog(resip::HandleManager& ham) : AppDialog(ham) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ResipSessionAppDialog::~ResipSessionAppDialog()
|
ResipSessionAppDialog::~ResipSessionAppDialog() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +91,8 @@ void ResipSession::runTerminatedEvent(Type type, int code, int reason)
|
|||||||
case Type_Subscription:
|
case Type_Subscription:
|
||||||
if (mSession)
|
if (mSession)
|
||||||
{
|
{
|
||||||
UserAgent::ClientObserverMap::iterator observerIter = mUserAgent->mClientObserverMap.find(mSession->sessionId());
|
UserAgent::ClientObserverMap::iterator observerIter =
|
||||||
|
mUserAgent->mClientObserverMap.find(mSession->sessionId());
|
||||||
if (observerIter != mUserAgent->mClientObserverMap.end())
|
if (observerIter != mUserAgent->mClientObserverMap.end())
|
||||||
mUserAgent->onClientObserverStop(observerIter->second, code);
|
mUserAgent->onClientObserverStop(observerIter->second, code);
|
||||||
}
|
}
|
||||||
@@ -186,14 +184,9 @@ std::shared_ptr<resip::UserProfile> ResipSession::selectUASUserProfile(const res
|
|||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Session::Stream
|
#pragma region Session::Stream
|
||||||
Session::Stream::Stream()
|
Session::Stream::Stream() : mRtcpAttr(false), mRtcpMuxAttr(false) {}
|
||||||
:mRtcpAttr(false), mRtcpMuxAttr(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Session::Stream::~Stream()
|
Session::Stream::~Stream() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::Stream::setProvider(PDataProvider provider)
|
void Session::Stream::setProvider(PDataProvider provider)
|
||||||
{
|
{
|
||||||
@@ -291,7 +284,8 @@ Session::~Session()
|
|||||||
clearProvidersAndSockets();
|
clearProvidersAndSockets();
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
InstanceCounter--;
|
InstanceCounter--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +360,8 @@ void Session::accept()
|
|||||||
|
|
||||||
Lock locksession(mGuard);
|
Lock locksession(mGuard);
|
||||||
|
|
||||||
// If ICE candidate gathering is not finished - just mark session as accepted. It will be accepted in ICE handling code.
|
// If ICE candidate gathering is not finished - just mark session as accepted. It will be accepted in ICE handling
|
||||||
|
// code.
|
||||||
mAcceptedByUser = true;
|
mAcceptedByUser = true;
|
||||||
|
|
||||||
if (mGatheredCandidates || mIceStack->state() == ice::IceNone)
|
if (mGatheredCandidates || mIceStack->state() == ice::IceNone)
|
||||||
@@ -473,7 +468,9 @@ void Session::getSessionInfo(Session::InfoOptions options, VariantMap& info)
|
|||||||
info[SessionInfo_SentRtp] = static_cast<int>(stat.mSentRtp);
|
info[SessionInfo_SentRtp] = static_cast<int>(stat.mSentRtp);
|
||||||
info[SessionInfo_SentRtcp] = static_cast<int>(stat.mSentRtcp);
|
info[SessionInfo_SentRtcp] = static_cast<int>(stat.mSentRtcp);
|
||||||
if (stat.mFirstRtpTime)
|
if (stat.mFirstRtpTime)
|
||||||
info[SessionInfo_Duration] = static_cast<int>(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - *(stat.mFirstRtpTime)).count());
|
info[SessionInfo_Duration] = static_cast<int>(
|
||||||
|
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - *(stat.mFirstRtpTime))
|
||||||
|
.count());
|
||||||
else
|
else
|
||||||
info[SessionInfo_Duration] = 0;
|
info[SessionInfo_Duration] = 0;
|
||||||
|
|
||||||
@@ -481,7 +478,8 @@ void Session::getSessionInfo(Session::InfoOptions options, VariantMap& info)
|
|||||||
info[SessionInfo_PacketLoss] = static_cast<int>((stat.mPacketLoss * 1000) / stat.mReceivedRtp);
|
info[SessionInfo_PacketLoss] = static_cast<int>((stat.mPacketLoss * 1000) / stat.mReceivedRtp);
|
||||||
|
|
||||||
if (media && mIceStack)
|
if (media && mIceStack)
|
||||||
info[SessionInfo_AudioPeer] = mIceStack->remoteAddress(media->iceInfo().mStreamId, media->iceInfo().mComponentId.mRtp).toStdString();
|
info[SessionInfo_AudioPeer] =
|
||||||
|
mIceStack->remoteAddress(media->iceInfo().mStreamId, media->iceInfo().mComponentId.mRtp).toStdString();
|
||||||
|
|
||||||
info[SessionInfo_Jitter] = stat.mJitter;
|
info[SessionInfo_Jitter] = stat.mJitter;
|
||||||
if (stat.mRttDelay.is_initialized())
|
if (stat.mRttDelay.is_initialized())
|
||||||
@@ -505,7 +503,8 @@ PAccount Session::account()
|
|||||||
return mAccount;
|
return mAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::onReceivedData(PDatagramSocket socket, InternetAddress& src, const void* receivedPtr, unsigned receivedSize)
|
void Session::onReceivedData(PDatagramSocket socket, InternetAddress& src, const void* receivedPtr,
|
||||||
|
unsigned receivedSize)
|
||||||
{
|
{
|
||||||
Lock l(mGuard);
|
Lock l(mGuard);
|
||||||
|
|
||||||
@@ -594,8 +593,7 @@ void Session::onGathered(ice::Stack* stack, void* tag)
|
|||||||
|
|
||||||
if (mRole == Initiator)
|
if (mRole == Initiator)
|
||||||
mUserAgent->sendOffer(this);
|
mUserAgent->sendOffer(this);
|
||||||
else
|
else if (mRole == Acceptor)
|
||||||
if (mRole == Acceptor)
|
|
||||||
{
|
{
|
||||||
// Mark session as gathered ICE candidates
|
// Mark session as gathered ICE candidates
|
||||||
mGatheredCandidates = true;
|
mGatheredCandidates = true;
|
||||||
@@ -675,8 +673,12 @@ void Session::buildSdp(resip::SdpContents &sdp, SdpDirection sdpDirection)
|
|||||||
ice::NetworkAddress defaultAddr = mIceStack->defaultAddress(mStreamList.front().iceInfo().mStreamId, ICE_RTP_ID);
|
ice::NetworkAddress defaultAddr = mIceStack->defaultAddress(mStreamList.front().iceInfo().mStreamId, ICE_RTP_ID);
|
||||||
|
|
||||||
// Set IP address for origin and connection
|
// Set IP address for origin and connection
|
||||||
sdp.session().origin().setAddress(resip::Data(defaultAddr.ip()), defaultAddr.family() == AF_INET ? resip::SdpContents::IP4 : resip::SdpContents::IP6);
|
sdp.session().origin().setAddress(resip::Data(defaultAddr.ip()), defaultAddr.family() == AF_INET
|
||||||
sdp.session().connection().setAddress(resip::Data(defaultAddr.ip()), defaultAddr.family() == AF_INET ? resip::SdpContents::IP4 : resip::SdpContents::IP6);
|
? resip::SdpContents::IP4
|
||||||
|
: resip::SdpContents::IP6);
|
||||||
|
sdp.session().connection().setAddress(resip::Data(defaultAddr.ip()), defaultAddr.family() == AF_INET
|
||||||
|
? resip::SdpContents::IP4
|
||||||
|
: resip::SdpContents::IP6);
|
||||||
|
|
||||||
// Add ICE credentials
|
// Add ICE credentials
|
||||||
if (mIceStack->state() > ice::IceNone)
|
if (mIceStack->state() > ice::IceNone)
|
||||||
@@ -698,15 +700,15 @@ void Session::buildSdp(resip::SdpContents &sdp, SdpDirection sdpDirection)
|
|||||||
rtcpPort = mIceStack->defaultAddress(mStreamList[i].iceInfo().mStreamId, ICE_RTCP_ID);
|
rtcpPort = mIceStack->defaultAddress(mStreamList[i].iceInfo().mStreamId, ICE_RTCP_ID);
|
||||||
|
|
||||||
// Define media stream SDP's header
|
// Define media stream SDP's header
|
||||||
resip::SdpContents::Session::Medium media(resip::Data(provider.streamName()), rtpPort.port(), 0, resip::Data(provider.streamProfile()));
|
resip::SdpContents::Session::Medium media(resip::Data(provider.streamName()), rtpPort.port(), 0,
|
||||||
|
resip::Data(provider.streamProfile()));
|
||||||
|
|
||||||
// Add "rtcp" attribute
|
// Add "rtcp" attribute
|
||||||
if (mUserAgent->mConfig[CONFIG_RTCP_ATTR].asBool())
|
if (mUserAgent->mConfig[CONFIG_RTCP_ATTR].asBool())
|
||||||
{
|
{
|
||||||
if (mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool())
|
if (mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool())
|
||||||
rtcpPort = rtpPort;
|
rtcpPort = rtpPort;
|
||||||
else
|
else if (rtcpPort.isEmpty())
|
||||||
if (rtcpPort.isEmpty())
|
|
||||||
{
|
{
|
||||||
rtcpPort = rtpPort;
|
rtcpPort = rtpPort;
|
||||||
rtcpPort.setPort(rtpPort.port() + 1);
|
rtcpPort.setPort(rtpPort.port() + 1);
|
||||||
@@ -797,10 +799,11 @@ void Session::addProvider(PDataProvider provider)
|
|||||||
ii.mPort4 = s.socket4().mRtp->localport();
|
ii.mPort4 = s.socket4().mRtp->localport();
|
||||||
ii.mPort6 = s.socket6().mRtp->localport();
|
ii.mPort6 = s.socket6().mRtp->localport();
|
||||||
|
|
||||||
ii.mComponentId.mRtp = mIceStack->addComponent(ii.mStreamId, NULL, s.socket4().mRtp->localport(),
|
ii.mComponentId.mRtp =
|
||||||
s.socket6().mRtp->localport());
|
mIceStack->addComponent(ii.mStreamId, NULL, s.socket4().mRtp->localport(), s.socket6().mRtp->localport());
|
||||||
if (!mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool())
|
if (!mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool())
|
||||||
ii.mComponentId.mRtcp = mIceStack->addComponent(ii.mStreamId, NULL, s.socket4().mRtcp->localport(), s.socket6().mRtcp->localport());
|
ii.mComponentId.mRtcp =
|
||||||
|
mIceStack->addComponent(ii.mStreamId, NULL, s.socket4().mRtcp->localport(), s.socket6().mRtcp->localport());
|
||||||
|
|
||||||
s.setIceInfo(ii);
|
s.setIceInfo(ii);
|
||||||
|
|
||||||
@@ -952,9 +955,9 @@ int Session::processSdp(uint64_t version, bool iceAvailable, std::string icePwd,
|
|||||||
targetAddr.mRtcp.setIp(remoteIp);
|
targetAddr.mRtcp.setIp(remoteIp);
|
||||||
if (stream.rtcpMuxAttr())
|
if (stream.rtcpMuxAttr())
|
||||||
targetAddr.mRtcp.setPort(remoteStream.port());
|
targetAddr.mRtcp.setPort(remoteStream.port());
|
||||||
else
|
else if (stream.rtcpAttr())
|
||||||
if (stream.rtcpAttr())
|
targetAddr.mRtcp.setPort(
|
||||||
targetAddr.mRtcp.setPort( strx::toInt(remoteStream.getValues("rtcp").front().c_str(), remoteStream.port() + 1 ) );
|
strx::toInt(remoteStream.getValues("rtcp").front().c_str(), remoteStream.port() + 1));
|
||||||
else
|
else
|
||||||
targetAddr.mRtcp.setPort(remoteStream.port() + 1);
|
targetAddr.mRtcp.setPort(remoteStream.port() + 1);
|
||||||
|
|
||||||
@@ -1005,13 +1008,15 @@ int Session::processSdp(uint64_t version, bool iceAvailable, std::string icePwd,
|
|||||||
|
|
||||||
// See what remote peer offers - offer only single ice component if it relies on multiplexing
|
// See what remote peer offers - offer only single ice component if it relies on multiplexing
|
||||||
if (!targetAddr.multiplexed() && !mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool())
|
if (!targetAddr.multiplexed() && !mUserAgent->mConfig[CONFIG_MULTIPLEXING].asBool())
|
||||||
ii.mComponentId.mRtcp = mIceStack->addComponent(ii.mStreamId, NULL, stream.socket4().mRtcp->localport(), stream.socket6().mRtcp->localport());
|
ii.mComponentId.mRtcp = mIceStack->addComponent(ii.mStreamId, NULL, stream.socket4().mRtcp->localport(),
|
||||||
|
stream.socket6().mRtcp->localport());
|
||||||
stream.setIceInfo(ii);
|
stream.setIceInfo(ii);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iceAvailable)
|
if (iceAvailable)
|
||||||
{
|
{
|
||||||
if (mIceStack->remotePassword(stream.iceInfo().mStreamId) != icePwd || mIceStack->remoteUfrag(stream.iceInfo().mStreamId) != iceUfrag)
|
if (mIceStack->remotePassword(stream.iceInfo().mStreamId) != icePwd ||
|
||||||
|
mIceStack->remoteUfrag(stream.iceInfo().mStreamId) != iceUfrag)
|
||||||
{
|
{
|
||||||
iceRestart = true;
|
iceRestart = true;
|
||||||
mIceStack->setRemotePassword(icePwd, stream.iceInfo().mStreamId);
|
mIceStack->setRemotePassword(icePwd, stream.iceInfo().mStreamId);
|
||||||
@@ -1032,9 +1037,11 @@ int Session::processSdp(uint64_t version, bool iceAvailable, std::string icePwd,
|
|||||||
if (candidateVector.empty())
|
if (candidateVector.empty())
|
||||||
iceAvailable = false;
|
iceAvailable = false;
|
||||||
|
|
||||||
// Ask ICE stack to process this information. This call will remove also second component if it is not defined in remote sdp.
|
// Ask ICE stack to process this information. This call will remove also second component if it is not defined
|
||||||
|
// in remote sdp.
|
||||||
if (iceAvailable)
|
if (iceAvailable)
|
||||||
iceAvailable = mIceStack->processSdpOffer(stream.iceInfo().mStreamId, candidateVector, remoteIp, remotePort, mUserAgent->mConfig[CONFIG_DEFERRELAYED].asBool());
|
iceAvailable = mIceStack->processSdpOffer(stream.iceInfo().mStreamId, candidateVector, remoteIp, remotePort,
|
||||||
|
mUserAgent->mConfig[CONFIG_DEFERRELAYED].asBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if there are compatible media streams
|
// See if there are compatible media streams
|
||||||
@@ -1132,11 +1139,10 @@ void Session::processQueuedOffer()
|
|||||||
//-------------- ResipSessionFactory ---------
|
//-------------- ResipSessionFactory ---------
|
||||||
#pragma region ResipSessionFactory
|
#pragma region ResipSessionFactory
|
||||||
|
|
||||||
ResipSessionFactory::ResipSessionFactory(UserAgent* agent)
|
ResipSessionFactory::ResipSessionFactory(UserAgent* agent) : mAgent(agent) {}
|
||||||
:mAgent(agent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
resip::AppDialogSet* ResipSessionFactory::createAppDialogSet(resip::DialogUsageManager& dum, const resip::SipMessage& msg)
|
resip::AppDialogSet* ResipSessionFactory::createAppDialogSet(resip::DialogUsageManager& dum,
|
||||||
|
const resip::SipMessage& msg)
|
||||||
{
|
{
|
||||||
ResipSession* s = new ResipSession(dum);
|
ResipSession* s = new ResipSession(dum);
|
||||||
s->setUa(mAgent);
|
s->setUa(mAgent);
|
||||||
|
|||||||
@@ -77,9 +77,7 @@ enum SessionInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Session :
|
class Session : public SocketSink, public ice::StageHandler
|
||||||
public SocketSink,
|
|
||||||
public ice::StageHandler
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class Command
|
class Command
|
||||||
@@ -91,8 +89,7 @@ public:
|
|||||||
// Describes ice stream/component
|
// Describes ice stream/component
|
||||||
struct IceInfo
|
struct IceInfo
|
||||||
{
|
{
|
||||||
IceInfo()
|
IceInfo() : mStreamId(-1)
|
||||||
:mStreamId(-1)
|
|
||||||
{
|
{
|
||||||
mPort4 = mPort6 = 0;
|
mPort4 = mPort6 = 0;
|
||||||
mComponentId.mRtp = mComponentId.mRtcp = -1;
|
mComponentId.mRtp = mComponentId.mRtcp = -1;
|
||||||
@@ -406,6 +403,7 @@ class ResipSessionFactory : public resip::AppDialogSetFactory
|
|||||||
public:
|
public:
|
||||||
ResipSessionFactory(UserAgent* agent);
|
ResipSessionFactory(UserAgent* agent);
|
||||||
virtual resip::AppDialogSet* createAppDialogSet(resip::DialogUsageManager& dum, const resip::SipMessage& msg);
|
virtual resip::AppDialogSet* createAppDialogSet(resip::DialogUsageManager& dum, const resip::SipMessage& msg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UserAgent* mAgent;
|
UserAgent* mAgent;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,12 +5,6 @@
|
|||||||
|
|
||||||
#include "HL_AsyncCommand.h"
|
#include "HL_AsyncCommand.h"
|
||||||
|
|
||||||
AsyncCommand::AsyncCommand()
|
AsyncCommand::AsyncCommand() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
AsyncCommand::~AsyncCommand() {}
|
||||||
|
|
||||||
AsyncCommand::~AsyncCommand()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
+108
-60
@@ -7,9 +7,11 @@ const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
"0123456789+/";
|
"0123456789+/";
|
||||||
|
|
||||||
class Base64 {
|
class Base64
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static bool Encode(const std::string &in, std::string *out) {
|
static bool Encode(const std::string& in, std::string* out)
|
||||||
|
{
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
size_t enc_len = 0;
|
size_t enc_len = 0;
|
||||||
unsigned char a3[3];
|
unsigned char a3[3];
|
||||||
@@ -20,12 +22,15 @@ class Base64 {
|
|||||||
int input_len = in.size();
|
int input_len = in.size();
|
||||||
std::string::const_iterator input = in.begin();
|
std::string::const_iterator input = in.begin();
|
||||||
|
|
||||||
while (input_len--) {
|
while (input_len--)
|
||||||
|
{
|
||||||
a3[i++] = *(input++);
|
a3[i++] = *(input++);
|
||||||
if (i == 3) {
|
if (i == 3)
|
||||||
|
{
|
||||||
a3_to_a4(a4, a3);
|
a3_to_a4(a4, a3);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
(*out)[enc_len++] = kBase64Alphabet[a4[i]];
|
(*out)[enc_len++] = kBase64Alphabet[a4[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,18 +38,22 @@ class Base64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i) {
|
if (i)
|
||||||
for (j = i; j < 3; j++) {
|
{
|
||||||
|
for (j = i; j < 3; j++)
|
||||||
|
{
|
||||||
a3[j] = '\0';
|
a3[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
a3_to_a4(a4, a3);
|
a3_to_a4(a4, a3);
|
||||||
|
|
||||||
for (j = 0; j < i + 1; j++) {
|
for (j = 0; j < i + 1; j++)
|
||||||
|
{
|
||||||
(*out)[enc_len++] = kBase64Alphabet[a4[j]];
|
(*out)[enc_len++] = kBase64Alphabet[a4[j]];
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((i++ < 3)) {
|
while ((i++ < 3))
|
||||||
|
{
|
||||||
(*out)[enc_len++] = '=';
|
(*out)[enc_len++] = '=';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +61,8 @@ class Base64 {
|
|||||||
return (enc_len == out->size());
|
return (enc_len == out->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Encode(const char *input, size_t input_length, char *out, size_t out_length) {
|
static bool Encode(const char* input, size_t input_length, char* out, size_t out_length)
|
||||||
|
{
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
char* out_begin = out;
|
char* out_begin = out;
|
||||||
unsigned char a3[3];
|
unsigned char a3[3];
|
||||||
@@ -60,14 +70,18 @@ class Base64 {
|
|||||||
|
|
||||||
size_t encoded_length = EncodedLength(input_length);
|
size_t encoded_length = EncodedLength(input_length);
|
||||||
|
|
||||||
if (out_length < encoded_length) return false;
|
if (out_length < encoded_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
while (input_length--) {
|
while (input_length--)
|
||||||
|
{
|
||||||
a3[i++] = *input++;
|
a3[i++] = *input++;
|
||||||
if (i == 3) {
|
if (i == 3)
|
||||||
|
{
|
||||||
a3_to_a4(a4, a3);
|
a3_to_a4(a4, a3);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
*out++ = kBase64Alphabet[a4[i]];
|
*out++ = kBase64Alphabet[a4[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,18 +89,22 @@ class Base64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i) {
|
if (i)
|
||||||
for (j = i; j < 3; j++) {
|
{
|
||||||
|
for (j = i; j < 3; j++)
|
||||||
|
{
|
||||||
a3[j] = '\0';
|
a3[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
a3_to_a4(a4, a3);
|
a3_to_a4(a4, a3);
|
||||||
|
|
||||||
for (j = 0; j < i + 1; j++) {
|
for (j = 0; j < i + 1; j++)
|
||||||
|
{
|
||||||
*out++ = kBase64Alphabet[a4[j]];
|
*out++ = kBase64Alphabet[a4[j]];
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((i++ < 3)) {
|
while ((i++ < 3))
|
||||||
|
{
|
||||||
*out++ = '=';
|
*out++ = '=';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +112,8 @@ class Base64 {
|
|||||||
return (out == (out_begin + encoded_length));
|
return (out == (out_begin + encoded_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Decode(const std::string &in, std::string *out) {
|
static bool Decode(const std::string& in, std::string* out)
|
||||||
|
{
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
size_t dec_len = 0;
|
size_t dec_len = 0;
|
||||||
unsigned char a3[3];
|
unsigned char a3[3];
|
||||||
@@ -105,20 +124,25 @@ class Base64 {
|
|||||||
|
|
||||||
out->resize(DecodedLength(in));
|
out->resize(DecodedLength(in));
|
||||||
|
|
||||||
while (input_len--) {
|
while (input_len--)
|
||||||
if (*input == '=') {
|
{
|
||||||
|
if (*input == '=')
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
a4[i++] = *(input++);
|
a4[i++] = *(input++);
|
||||||
if (i == 4) {
|
if (i == 4)
|
||||||
for (i = 0; i <4; i++) {
|
{
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
a4[i] = b64_lookup(a4[i]);
|
a4[i] = b64_lookup(a4[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
a4_to_a3(a3, a4);
|
a4_to_a3(a3, a4);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
(*out)[dec_len++] = a3[i];
|
(*out)[dec_len++] = a3[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,18 +150,22 @@ class Base64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i) {
|
if (i)
|
||||||
for (j = i; j < 4; j++) {
|
{
|
||||||
|
for (j = i; j < 4; j++)
|
||||||
|
{
|
||||||
a4[j] = '\0';
|
a4[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 4; j++) {
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
a4[j] = b64_lookup(a4[j]);
|
a4[j] = b64_lookup(a4[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
a4_to_a3(a3, a4);
|
a4_to_a3(a3, a4);
|
||||||
|
|
||||||
for (j = 0; j < i - 1; j++) {
|
for (j = 0; j < i - 1; j++)
|
||||||
|
{
|
||||||
(*out)[dec_len++] = a3[j];
|
(*out)[dec_len++] = a3[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,7 +173,8 @@ class Base64 {
|
|||||||
return (dec_len == out->size());
|
return (dec_len == out->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Decode(const char *input, size_t input_length, char *out, size_t out_length) {
|
static bool Decode(const char* input, size_t input_length, char* out, size_t out_length)
|
||||||
|
{
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
char* out_begin = out;
|
char* out_begin = out;
|
||||||
unsigned char a3[3];
|
unsigned char a3[3];
|
||||||
@@ -153,22 +182,28 @@ class Base64 {
|
|||||||
|
|
||||||
size_t decoded_length = DecodedLength(input, input_length);
|
size_t decoded_length = DecodedLength(input, input_length);
|
||||||
|
|
||||||
if (out_length < decoded_length) return false;
|
if (out_length < decoded_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
while (input_length--) {
|
while (input_length--)
|
||||||
if (*input == '=') {
|
{
|
||||||
|
if (*input == '=')
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
a4[i++] = *(input++);
|
a4[i++] = *(input++);
|
||||||
if (i == 4) {
|
if (i == 4)
|
||||||
for (i = 0; i <4; i++) {
|
{
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
a4[i] = b64_lookup(a4[i]);
|
a4[i] = b64_lookup(a4[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
a4_to_a3(a3, a4);
|
a4_to_a3(a3, a4);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
*out++ = a3[i];
|
*out++ = a3[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,18 +211,22 @@ class Base64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i) {
|
if (i)
|
||||||
for (j = i; j < 4; j++) {
|
{
|
||||||
|
for (j = i; j < 4; j++)
|
||||||
|
{
|
||||||
a4[j] = '\0';
|
a4[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < 4; j++) {
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
a4[j] = b64_lookup(a4[j]);
|
a4[j] = b64_lookup(a4[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
a4_to_a3(a3, a4);
|
a4_to_a3(a3, a4);
|
||||||
|
|
||||||
for (j = 0; j < i - 1; j++) {
|
for (j = 0; j < i - 1; j++)
|
||||||
|
{
|
||||||
*out++ = a3[j];
|
*out++ = a3[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,62 +234,71 @@ class Base64 {
|
|||||||
return (out == (out_begin + decoded_length));
|
return (out == (out_begin + decoded_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodedLength(const char *in, size_t in_length) {
|
static int DecodedLength(const char* in, size_t in_length)
|
||||||
|
{
|
||||||
int numEq = 0;
|
int numEq = 0;
|
||||||
|
|
||||||
const char* in_end = in + in_length;
|
const char* in_end = in + in_length;
|
||||||
while (*--in_end == '=') ++numEq;
|
while (*--in_end == '=')
|
||||||
|
++numEq;
|
||||||
|
|
||||||
return ((6 * in_length) / 8) - numEq;
|
return ((6 * in_length) / 8) - numEq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int DecodedLength(const std::string &in) {
|
static int DecodedLength(const std::string& in)
|
||||||
|
{
|
||||||
int numEq = 0;
|
int numEq = 0;
|
||||||
int n = in.size();
|
int n = in.size();
|
||||||
|
|
||||||
for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it) {
|
for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it)
|
||||||
|
{
|
||||||
++numEq;
|
++numEq;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((6 * n) / 8) - numEq;
|
return ((6 * n) / 8) - numEq;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int EncodedLength(size_t length) {
|
inline static int EncodedLength(size_t length) { return (length + 2 - ((length + 2) % 3)) / 3 * 4; }
|
||||||
return (length + 2 - ((length + 2) % 3)) / 3 * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int EncodedLength(const std::string &in) {
|
inline static int EncodedLength(const std::string& in) { return EncodedLength(in.length()); }
|
||||||
return EncodedLength(in.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void StripPadding(std::string *in) {
|
inline static void StripPadding(std::string* in)
|
||||||
while (!in->empty() && *(in->rbegin()) == '=') in->resize(in->size() - 1);
|
{
|
||||||
|
while (!in->empty() && *(in->rbegin()) == '=')
|
||||||
|
in->resize(in->size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static inline void a3_to_a4(unsigned char * a4, unsigned char * a3) {
|
static inline void a3_to_a4(unsigned char* a4, unsigned char* a3)
|
||||||
|
{
|
||||||
a4[0] = (a3[0] & 0xfc) >> 2;
|
a4[0] = (a3[0] & 0xfc) >> 2;
|
||||||
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
|
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
|
||||||
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
|
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
|
||||||
a4[3] = (a3[2] & 0x3f);
|
a4[3] = (a3[2] & 0x3f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void a4_to_a3(unsigned char * a3, unsigned char * a4) {
|
static inline void a4_to_a3(unsigned char* a3, unsigned char* a4)
|
||||||
|
{
|
||||||
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
|
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
|
||||||
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
|
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
|
||||||
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
|
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned char b64_lookup(unsigned char c) {
|
static inline unsigned char b64_lookup(unsigned char c)
|
||||||
if(c >='A' && c <='Z') return c - 'A';
|
{
|
||||||
if(c >='a' && c <='z') return c - 71;
|
if (c >= 'A' && c <= 'Z')
|
||||||
if(c >='0' && c <='9') return c + 4;
|
return c - 'A';
|
||||||
if(c == '+') return 62;
|
if (c >= 'a' && c <= 'z')
|
||||||
if(c == '/') return 63;
|
return c - 71;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c + 4;
|
||||||
|
if (c == '+')
|
||||||
|
return 62;
|
||||||
|
if (c == '/')
|
||||||
|
return 63;
|
||||||
return 255;
|
return 255;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // HL_BASE64_H
|
#endif // HL_BASE64_H
|
||||||
+141
-128
@@ -40,25 +40,14 @@ namespace Calc
|
|||||||
class Item
|
class Item
|
||||||
{
|
{
|
||||||
friend class Calc::Parser;
|
friend class Calc::Parser;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isVariable() const
|
bool isVariable() const { return mType == Type::Var; }
|
||||||
{
|
bool isFixed() const { return mType == Type::Number || mType == Type::String; }
|
||||||
return mType == Type::Var;
|
|
||||||
}
|
|
||||||
bool isFixed() const
|
|
||||||
{
|
|
||||||
return mType == Type::Number || mType == Type::String;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOperation() const
|
bool isOperation() const { return mType >= Type::And && mType <= Type::Div; }
|
||||||
{
|
|
||||||
return mType >= Type::And && mType <= Type::Div;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasBrackets() const
|
bool hasBrackets() const { return mHasBrackets; }
|
||||||
{
|
|
||||||
return mHasBrackets;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getOperatorLevel() const
|
int getOperatorLevel() const
|
||||||
{
|
{
|
||||||
@@ -94,25 +83,13 @@ namespace Calc
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() const
|
Type getType() const { return mType; }
|
||||||
{
|
|
||||||
return mType;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getName() const
|
std::string getName() const { return mName; }
|
||||||
{
|
|
||||||
return mName;
|
|
||||||
}
|
|
||||||
|
|
||||||
Variant& value()
|
Variant& value() { return mValue; }
|
||||||
{
|
|
||||||
return mValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<PItem>& children()
|
std::vector<PItem>& children() { return mChildren; }
|
||||||
{
|
|
||||||
return mChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> NameMap;
|
typedef std::map<std::string, std::string> NameMap;
|
||||||
|
|
||||||
@@ -126,21 +103,54 @@ namespace Calc
|
|||||||
oss << " ";
|
oss << " ";
|
||||||
switch (mType)
|
switch (mType)
|
||||||
{
|
{
|
||||||
case Type::Number: oss << mValue.asStdString(); break;
|
case Type::Number:
|
||||||
case Type::String: oss << '"' << mValue.asStdString() << '"'; break;
|
oss << mValue.asStdString();
|
||||||
case Type::Var: { NameMap::const_iterator iter = nm.find(mName); oss << ((iter != nm.end()) ? iter->second : mName);} break;
|
break;
|
||||||
case Type::Add: oss << "+"; break;
|
case Type::String:
|
||||||
case Type::Mul: oss << "*"; break;
|
oss << '"' << mValue.asStdString() << '"';
|
||||||
case Type::Div: oss << "/"; break;
|
break;
|
||||||
case Type::Sub: oss << "-"; break;
|
case Type::Var:
|
||||||
case Type::Equal: oss << "=="; break;
|
{
|
||||||
case Type::NotEqual: oss << "!="; break;
|
NameMap::const_iterator iter = nm.find(mName);
|
||||||
case Type::Less: oss << "<"; break;
|
oss << ((iter != nm.end()) ? iter->second : mName);
|
||||||
case Type::LessOrEqual: oss << "<="; break;
|
}
|
||||||
case Type::Greater: oss << ">"; break;
|
break;
|
||||||
case Type::GreatorOrEqual: oss << ">="; break;
|
case Type::Add:
|
||||||
case Type::Or: oss << "or"; break;
|
oss << "+";
|
||||||
case Type::And: oss << "and"; break;
|
break;
|
||||||
|
case Type::Mul:
|
||||||
|
oss << "*";
|
||||||
|
break;
|
||||||
|
case Type::Div:
|
||||||
|
oss << "/";
|
||||||
|
break;
|
||||||
|
case Type::Sub:
|
||||||
|
oss << "-";
|
||||||
|
break;
|
||||||
|
case Type::Equal:
|
||||||
|
oss << "==";
|
||||||
|
break;
|
||||||
|
case Type::NotEqual:
|
||||||
|
oss << "!=";
|
||||||
|
break;
|
||||||
|
case Type::Less:
|
||||||
|
oss << "<";
|
||||||
|
break;
|
||||||
|
case Type::LessOrEqual:
|
||||||
|
oss << "<=";
|
||||||
|
break;
|
||||||
|
case Type::Greater:
|
||||||
|
oss << ">";
|
||||||
|
break;
|
||||||
|
case Type::GreatorOrEqual:
|
||||||
|
oss << ">=";
|
||||||
|
break;
|
||||||
|
case Type::Or:
|
||||||
|
oss << "or";
|
||||||
|
break;
|
||||||
|
case Type::And:
|
||||||
|
oss << "and";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("operator expected");
|
throw std::runtime_error("operator expected");
|
||||||
}
|
}
|
||||||
@@ -167,23 +177,56 @@ namespace Calc
|
|||||||
switch (mType)
|
switch (mType)
|
||||||
{
|
{
|
||||||
case Type::Number:
|
case Type::Number:
|
||||||
case Type::String: result = mValue; break;
|
case Type::String:
|
||||||
|
result = mValue;
|
||||||
case Type::Var: { auto iter = vm.find(mName); if (iter != vm.end()) return iter->second; else throw std::runtime_error("Variable " + mName + " did not find."); }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type::Add: result = left + right; break;
|
case Type::Var:
|
||||||
case Type::Mul: result = left * right; break;
|
{
|
||||||
case Type::Div: result = left / right; break;
|
auto iter = vm.find(mName);
|
||||||
case Type::Sub: result = left - right; break;
|
if (iter != vm.end())
|
||||||
case Type::Equal: result = left == right; break;
|
return iter->second;
|
||||||
case Type::NotEqual: result = left != right; break;
|
else
|
||||||
case Type::Less: result = left < right; break;
|
throw std::runtime_error("Variable " + mName + " did not find.");
|
||||||
case Type::LessOrEqual: result = left <= right; break;
|
}
|
||||||
case Type::Greater: result = left > right; break;
|
break;
|
||||||
case Type::GreatorOrEqual: result = left >= right; break;
|
|
||||||
case Type::Or: result = left.asBool() || right.asBool(); break;
|
case Type::Add:
|
||||||
case Type::And: result = left.asBool() && right.asBool(); break;
|
result = left + right;
|
||||||
|
break;
|
||||||
|
case Type::Mul:
|
||||||
|
result = left * right;
|
||||||
|
break;
|
||||||
|
case Type::Div:
|
||||||
|
result = left / right;
|
||||||
|
break;
|
||||||
|
case Type::Sub:
|
||||||
|
result = left - right;
|
||||||
|
break;
|
||||||
|
case Type::Equal:
|
||||||
|
result = left == right;
|
||||||
|
break;
|
||||||
|
case Type::NotEqual:
|
||||||
|
result = left != right;
|
||||||
|
break;
|
||||||
|
case Type::Less:
|
||||||
|
result = left < right;
|
||||||
|
break;
|
||||||
|
case Type::LessOrEqual:
|
||||||
|
result = left <= right;
|
||||||
|
break;
|
||||||
|
case Type::Greater:
|
||||||
|
result = left > right;
|
||||||
|
break;
|
||||||
|
case Type::GreatorOrEqual:
|
||||||
|
result = left >= right;
|
||||||
|
break;
|
||||||
|
case Type::Or:
|
||||||
|
result = left.asBool() || right.asBool();
|
||||||
|
break;
|
||||||
|
case Type::And:
|
||||||
|
result = left.asBool() && right.asBool();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@@ -204,7 +247,7 @@ namespace Calc
|
|||||||
std::vector<PItem> mChildren;
|
std::vector<PItem> mChildren;
|
||||||
bool mHasBrackets = false;
|
bool mHasBrackets = false;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Ast
|
||||||
|
|
||||||
static bool ishex(int c)
|
static bool ishex(int c)
|
||||||
{
|
{
|
||||||
@@ -234,15 +277,9 @@ namespace Calc
|
|||||||
LexemType mType = LexemType::None;
|
LexemType mType = LexemType::None;
|
||||||
std::string mValue;
|
std::string mValue;
|
||||||
|
|
||||||
operator bool () const
|
operator bool() const { return mType != LexemType::None; }
|
||||||
{
|
|
||||||
return mType != LexemType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const
|
std::string toString() const { return std::to_string((int)mType) + " : " + mValue; }
|
||||||
{
|
|
||||||
return std::to_string((int)mType) + " : " + mValue;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Lexem mCurrentLexem;
|
Lexem mCurrentLexem;
|
||||||
|
|
||||||
@@ -252,20 +289,16 @@ namespace Calc
|
|||||||
|
|
||||||
if (c == '(')
|
if (c == '(')
|
||||||
mCurrentLexem.mType = LexemType::OpenBracket;
|
mCurrentLexem.mType = LexemType::OpenBracket;
|
||||||
else
|
else if (c == ')')
|
||||||
if (c == ')')
|
|
||||||
mCurrentLexem.mType = LexemType::CloseBracket;
|
mCurrentLexem.mType = LexemType::CloseBracket;
|
||||||
else
|
else if (isdigit(c))
|
||||||
if (isdigit(c))
|
|
||||||
mCurrentLexem.mType = LexemType::Dec;
|
mCurrentLexem.mType = LexemType::Dec;
|
||||||
else
|
else if (isalpha(c))
|
||||||
if (isalpha(c))
|
|
||||||
mCurrentLexem.mType = LexemType::Var;
|
mCurrentLexem.mType = LexemType::Var;
|
||||||
else
|
else if (c == '+' || c == '-' || c == '/' || c == '*' || c == '=' || c == '<' || c == '>' || c == '&' ||
|
||||||
if (c == '+' || c == '-' || c == '/' || c == '*' || c == '=' || c == '<' || c == '>' || c == '&' || c == '|')
|
c == '|')
|
||||||
mCurrentLexem.mType = LexemType::Oper;
|
mCurrentLexem.mType = LexemType::Oper;
|
||||||
else
|
else if (c == '"')
|
||||||
if (c == '"')
|
|
||||||
mCurrentLexem.mType = LexemType::Str;
|
mCurrentLexem.mType = LexemType::Str;
|
||||||
else
|
else
|
||||||
return Lexem();
|
return Lexem();
|
||||||
@@ -283,15 +316,9 @@ namespace Calc
|
|||||||
|
|
||||||
if (mCurrentLexem.mType == LexemType::Oper)
|
if (mCurrentLexem.mType == LexemType::Oper)
|
||||||
{
|
{
|
||||||
if (mCurrentLexem.mValue == "+" ||
|
if (mCurrentLexem.mValue == "+" || mCurrentLexem.mValue == "-" || mCurrentLexem.mValue == "*" ||
|
||||||
mCurrentLexem.mValue == "-" ||
|
mCurrentLexem.mValue == "/" || mCurrentLexem.mValue == ">=" || mCurrentLexem.mValue == "<=" ||
|
||||||
mCurrentLexem.mValue == "*" ||
|
mCurrentLexem.mValue == "==" || mCurrentLexem.mValue == "||" || mCurrentLexem.mValue == "&&")
|
||||||
mCurrentLexem.mValue == "/" ||
|
|
||||||
mCurrentLexem.mValue == ">=" ||
|
|
||||||
mCurrentLexem.mValue == "<=" ||
|
|
||||||
mCurrentLexem.mValue == "==" ||
|
|
||||||
mCurrentLexem.mValue == "||" ||
|
|
||||||
mCurrentLexem.mValue == "&&")
|
|
||||||
{
|
{
|
||||||
// Lexem finished
|
// Lexem finished
|
||||||
result = mCurrentLexem;
|
result = mCurrentLexem;
|
||||||
@@ -357,8 +384,7 @@ namespace Calc
|
|||||||
case LexemType::Dec:
|
case LexemType::Dec:
|
||||||
if (c == 'x' && mCurrentLexem.mValue == "0")
|
if (c == 'x' && mCurrentLexem.mValue == "0")
|
||||||
mCurrentLexem.mType = LexemType::Hex;
|
mCurrentLexem.mType = LexemType::Hex;
|
||||||
else
|
else if (isdigit(c) || c == '.')
|
||||||
if (isdigit(c) || c == '.')
|
|
||||||
{
|
{
|
||||||
mCurrentLexem.mValue.push_back(c);
|
mCurrentLexem.mValue.push_back(c);
|
||||||
}
|
}
|
||||||
@@ -414,14 +440,14 @@ namespace Calc
|
|||||||
|
|
||||||
if (putback)
|
if (putback)
|
||||||
input.putback(c);
|
input.putback(c);
|
||||||
else
|
else if (!result)
|
||||||
if (!result)
|
|
||||||
c = input.get();
|
c = input.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNumericLexem();
|
checkNumericLexem();
|
||||||
|
|
||||||
// Recover partially processed lexem - maybe we finish processing at all but there is dec / float / string / variable
|
// Recover partially processed lexem - maybe we finish processing at all but there is dec / float / string /
|
||||||
|
// variable
|
||||||
if (mCurrentLexem.mType != LexemType::None && result.mType == LexemType::None)
|
if (mCurrentLexem.mType != LexemType::None && result.mType == LexemType::None)
|
||||||
result = mCurrentLexem;
|
result = mCurrentLexem;
|
||||||
|
|
||||||
@@ -441,38 +467,27 @@ namespace Calc
|
|||||||
case LexemType::Oper:
|
case LexemType::Oper:
|
||||||
if (l.mValue == "-")
|
if (l.mValue == "-")
|
||||||
result->mType = Ast::Type::Sub;
|
result->mType = Ast::Type::Sub;
|
||||||
else
|
else if (l.mValue == "+")
|
||||||
if (l.mValue == "+")
|
|
||||||
result->mType = Ast::Type::Add;
|
result->mType = Ast::Type::Add;
|
||||||
else
|
else if (l.mValue == "*")
|
||||||
if (l.mValue == "*")
|
|
||||||
result->mType = Ast::Type::Mul;
|
result->mType = Ast::Type::Mul;
|
||||||
else
|
else if (l.mValue == "/")
|
||||||
if (l.mValue == "/")
|
|
||||||
result->mType = Ast::Type::Div;
|
result->mType = Ast::Type::Div;
|
||||||
else
|
else if (l.mValue == "<")
|
||||||
if (l.mValue == "<")
|
|
||||||
result->mType = Ast::Type::Less;
|
result->mType = Ast::Type::Less;
|
||||||
else
|
else if (l.mValue == "<=")
|
||||||
if (l.mValue == "<=")
|
|
||||||
result->mType = Ast::Type::LessOrEqual;
|
result->mType = Ast::Type::LessOrEqual;
|
||||||
else
|
else if (l.mValue == ">")
|
||||||
if (l.mValue == ">")
|
|
||||||
result->mType = Ast::Type::Greater;
|
result->mType = Ast::Type::Greater;
|
||||||
else
|
else if (l.mValue == ">=")
|
||||||
if (l.mValue == ">=")
|
|
||||||
result->mType = Ast::Type::GreatorOrEqual;
|
result->mType = Ast::Type::GreatorOrEqual;
|
||||||
else
|
else if (l.mValue == "==")
|
||||||
if (l.mValue == "==")
|
|
||||||
result->mType = Ast::Type::Equal;
|
result->mType = Ast::Type::Equal;
|
||||||
else
|
else if (l.mValue == "!=")
|
||||||
if (l.mValue == "!=")
|
|
||||||
result->mType = Ast::Type::NotEqual;
|
result->mType = Ast::Type::NotEqual;
|
||||||
else
|
else if (l.mValue == "&&")
|
||||||
if (l.mValue == "&&")
|
|
||||||
result->mType = Ast::Type::And;
|
result->mType = Ast::Type::And;
|
||||||
else
|
else if (l.mValue == "||")
|
||||||
if (l.mValue == "||")
|
|
||||||
result->mType = Ast::Type::Or;
|
result->mType = Ast::Type::Or;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -509,11 +524,11 @@ namespace Calc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Lexem mLexem;
|
Lexem mLexem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ast::PItem parseExpression(std::istream& input)
|
Ast::PItem parseExpression(std::istream& input)
|
||||||
{
|
{
|
||||||
Ast::PItem operationNode(nullptr), leftNode(nullptr), rightNode(nullptr),
|
Ast::PItem operationNode(nullptr), leftNode(nullptr), rightNode(nullptr), currentOperation(nullptr);
|
||||||
currentOperation(nullptr);
|
|
||||||
|
|
||||||
// While we have lexem
|
// While we have lexem
|
||||||
while (mLexem = getLexem(input))
|
while (mLexem = getLexem(input))
|
||||||
@@ -545,8 +560,7 @@ namespace Calc
|
|||||||
throw std::runtime_error("Open bracket or constant / number / string / variable expected.");
|
throw std::runtime_error("Open bracket or constant / number / string / variable expected.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (!operationNode)
|
||||||
if (!operationNode)
|
|
||||||
{
|
{
|
||||||
// Well, there is left node already
|
// Well, there is left node already
|
||||||
// See operation here
|
// See operation here
|
||||||
@@ -573,10 +587,12 @@ namespace Calc
|
|||||||
// Parse rest of expression
|
// Parse rest of expression
|
||||||
rightNode = parseExpression(input);
|
rightNode = parseExpression(input);
|
||||||
|
|
||||||
// If right part of expression is operation - make left side child of right part - to allow calculation in right order
|
// If right part of expression is operation - make left side child of right part - to allow calculation
|
||||||
|
// in right order
|
||||||
if (operationNode)
|
if (operationNode)
|
||||||
{
|
{
|
||||||
if (rightNode->isOperation() && rightNode->getOperatorLevel() <= operationNode->getOperatorLevel() && !rightNode->hasBrackets())
|
if (rightNode->isOperation() &&
|
||||||
|
rightNode->getOperatorLevel() <= operationNode->getOperatorLevel() && !rightNode->hasBrackets())
|
||||||
{
|
{
|
||||||
// Get left child of right expression - make it our right child
|
// Get left child of right expression - make it our right child
|
||||||
operationNode->children().push_back(leftNode);
|
operationNode->children().push_back(leftNode);
|
||||||
@@ -599,10 +615,7 @@ namespace Calc
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ast::PItem parse(std::istream& input)
|
Ast::PItem parse(std::istream& input) { return nullptr; }
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void testLexemParser(const std::string& test)
|
void testLexemParser(const std::string& test)
|
||||||
{
|
{
|
||||||
@@ -620,7 +633,7 @@ namespace Calc
|
|||||||
public:
|
public:
|
||||||
Variant eval(Ast::PItem ast);
|
Variant eval(Ast::PItem ast);
|
||||||
};
|
};
|
||||||
}
|
} // namespace Calc
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -49,8 +49,10 @@ void CrashReporter::init(const std::string& appname, const std::string& version,
|
|||||||
|
|
||||||
CrInstall = (CrInstallProc)::GetProcAddress(CrLibraryHandle, "crInstallW");
|
CrInstall = (CrInstallProc)::GetProcAddress(CrLibraryHandle, "crInstallW");
|
||||||
CrUninstall = (CrUninstallProc)::GetProcAddress(CrLibraryHandle, "crUninstall");
|
CrUninstall = (CrUninstallProc)::GetProcAddress(CrLibraryHandle, "crUninstall");
|
||||||
CrInstallIntoCurrentThread = (CrInstallIntoCurrentThreadProc)::GetProcAddress(CrLibraryHandle, "crInstallToCurrentThread2");
|
CrInstallIntoCurrentThread =
|
||||||
CrUninstallFromCurrentThread = (CrUninstallFromCurrentThreadProc)::GetProcAddress(CrLibraryHandle, "crUninstallFromCurrentThread");
|
(CrInstallIntoCurrentThreadProc)::GetProcAddress(CrLibraryHandle, "crInstallToCurrentThread2");
|
||||||
|
CrUninstallFromCurrentThread =
|
||||||
|
(CrUninstallFromCurrentThreadProc)::GetProcAddress(CrLibraryHandle, "crUninstallFromCurrentThread");
|
||||||
CrGetLastErrorMsg = (CrGetLastErrorMsgProc)::GetProcAddress(CrLibraryHandle, "crGetLastErrorMsgW");
|
CrGetLastErrorMsg = (CrGetLastErrorMsgProc)::GetProcAddress(CrLibraryHandle, "crGetLastErrorMsgW");
|
||||||
#else
|
#else
|
||||||
CrInstall = &crInstallW;
|
CrInstall = &crInstallW;
|
||||||
@@ -70,8 +72,7 @@ void CrashReporter::init(const std::string& appname, const std::string& version,
|
|||||||
{
|
{
|
||||||
std::wstring appname, version, url;
|
std::wstring appname, version, url;
|
||||||
} unicode;
|
} unicode;
|
||||||
unicode.appname = StringHelper::makeTstring(appname),
|
unicode.appname = StringHelper::makeTstring(appname), unicode.version = StringHelper::makeTstring(version),
|
||||||
unicode.version = StringHelper::makeTstring(version),
|
|
||||||
unicode.url = StringHelper::makeTstring(url);
|
unicode.url = StringHelper::makeTstring(url);
|
||||||
|
|
||||||
if (unicode.appname.empty())
|
if (unicode.appname.empty())
|
||||||
@@ -103,7 +104,8 @@ void CrashReporter::init(const std::string& appname, const std::string& version,
|
|||||||
wchar_t errorMsg[512] = L"";
|
wchar_t errorMsg[512] = L"";
|
||||||
CrGetLastErrorMsg(errorMsg, 512);
|
CrGetLastErrorMsg(errorMsg, 512);
|
||||||
OutputDebugStringW(errorMsg);
|
OutputDebugStringW(errorMsg);
|
||||||
//LogCritical("Core", << "Failed to install CrashReporter with code " << nResult << " and message " << errorMsg);
|
// LogCritical("Core", << "Failed to install CrashReporter with code " << nResult << " and message " <<
|
||||||
|
// errorMsg);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -120,7 +122,8 @@ void CrashReporter::free()
|
|||||||
CrUninstallFromCurrentThread = nullptr;
|
CrUninstallFromCurrentThread = nullptr;
|
||||||
CrGetLastErrorMsg = nullptr;
|
CrGetLastErrorMsg = nullptr;
|
||||||
#if defined(CRASHRPT_DYNAMIC)
|
#if defined(CRASHRPT_DYNAMIC)
|
||||||
::FreeLibrary(CrLibraryHandle); CrLibraryHandle = NULL;
|
::FreeLibrary(CrLibraryHandle);
|
||||||
|
CrLibraryHandle = NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -129,8 +132,8 @@ void CrashReporter::free()
|
|||||||
bool CrashReporter::isLoaded()
|
bool CrashReporter::isLoaded()
|
||||||
{
|
{
|
||||||
#if defined(TARGET_WIN)
|
#if defined(TARGET_WIN)
|
||||||
return !(!CrInstall || !CrUninstall || !CrGetLastErrorMsg ||
|
return !(!CrInstall || !CrUninstall || !CrGetLastErrorMsg || !CrInstallIntoCurrentThread ||
|
||||||
!CrInstallIntoCurrentThread || !CrUninstallFromCurrentThread);
|
!CrUninstallFromCurrentThread);
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
@@ -174,20 +177,12 @@ CrashReporterGuard::~CrashReporterGuard()
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
CrashReporterThreadPoint::CrashReporterThreadPoint()
|
CrashReporterThreadPoint::CrashReporterThreadPoint() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CrashReporterThreadPoint::~CrashReporterThreadPoint()
|
CrashReporterThreadPoint::~CrashReporterThreadPoint() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CrashReporterGuard::CrashReporterGuard()
|
CrashReporterGuard::CrashReporterGuard() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CrashReporterGuard::~CrashReporterGuard()
|
CrashReporterGuard::~CrashReporterGuard() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class SE_Exception
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
unsigned int nSE;
|
unsigned int nSE;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SE_Exception() {}
|
SE_Exception() {}
|
||||||
SE_Exception(unsigned int n) : nSE(n) {}
|
SE_Exception(unsigned int n) : nSE(n) {}
|
||||||
|
|||||||
@@ -2,12 +2,9 @@
|
|||||||
#include "HL_String.h"
|
#include "HL_String.h"
|
||||||
|
|
||||||
// --------- CsvFile ----------------
|
// --------- CsvFile ----------------
|
||||||
CsvReader::CsvReader(std::istream& stream)
|
CsvReader::CsvReader(std::istream& stream) : mInputStream(stream) {}
|
||||||
:mInputStream(stream)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CsvReader::~CsvReader()
|
CsvReader::~CsvReader() {}
|
||||||
{}
|
|
||||||
|
|
||||||
std::istream& CsvReader::stream() const
|
std::istream& CsvReader::stream() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ enum
|
|||||||
class Exception : public std::exception
|
class Exception : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Exception(int code, int subcode = 0)
|
Exception(int code, int subcode = 0) : mCode(code), mSubcode(subcode)
|
||||||
:mCode(code), mSubcode(subcode)
|
|
||||||
{
|
{
|
||||||
std::snprintf(mMessage, sizeof(mMessage), "%d-%d", code, subcode);
|
std::snprintf(mMessage, sizeof(mMessage), "%d-%d", code, subcode);
|
||||||
}
|
}
|
||||||
@@ -53,29 +52,18 @@ public:
|
|||||||
strncpy(mMessage, message, (sizeof mMessage) - 1);
|
strncpy(mMessage, message, (sizeof mMessage) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Exception(const Exception& src)
|
Exception(const Exception& src) : mCode(src.mCode), mSubcode(src.mSubcode)
|
||||||
:mCode(src.mCode), mSubcode(src.mSubcode)
|
|
||||||
{
|
{
|
||||||
memcpy(mMessage, src.mMessage, sizeof mMessage);
|
memcpy(mMessage, src.mMessage, sizeof mMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Exception()
|
~Exception() {}
|
||||||
{ }
|
|
||||||
|
|
||||||
int code() const
|
int code() const { return mCode; }
|
||||||
{
|
|
||||||
return mCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
int subcode() const
|
int subcode() const { return mSubcode; }
|
||||||
{
|
|
||||||
return mSubcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* what() const noexcept
|
const char* what() const noexcept { return mMessage; }
|
||||||
{
|
|
||||||
return mMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int mCode = 0, mSubcode = 0;
|
int mCode = 0, mSubcode = 0;
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ size_t FileHelper::getFreespace(const std::string& path)
|
|||||||
size_t r = static_cast<size_t>(-1);
|
size_t r = static_cast<size_t>(-1);
|
||||||
|
|
||||||
#if defined(TARGET_LINUX)
|
#if defined(TARGET_LINUX)
|
||||||
struct statvfs stats; memset(&stats, 0, sizeof stats);
|
struct statvfs stats;
|
||||||
|
memset(&stats, 0, sizeof stats);
|
||||||
|
|
||||||
int retcode = statvfs(path.c_str(), &stats);
|
int retcode = statvfs(path.c_str(), &stats);
|
||||||
if (retcode == 0)
|
if (retcode == 0)
|
||||||
@@ -124,7 +125,8 @@ std::string FileHelper::expandUserHome(const std::string &path)
|
|||||||
{
|
{
|
||||||
home_dir = std::getenv("HOMEDRIVE");
|
home_dir = std::getenv("HOMEDRIVE");
|
||||||
const char* homepath = std::getenv("HOMEPATH");
|
const char* homepath = std::getenv("HOMEPATH");
|
||||||
if (home_dir && homepath) {
|
if (home_dir && homepath)
|
||||||
|
{
|
||||||
std::string fullpath(home_dir);
|
std::string fullpath(home_dir);
|
||||||
fullpath += homepath;
|
fullpath += homepath;
|
||||||
return fullpath + path.substr(1);
|
return fullpath + path.substr(1);
|
||||||
|
|||||||
@@ -102,8 +102,7 @@ bool Packet::parseV3(const ByteBuffer& packet)
|
|||||||
|
|
||||||
if (!sourceAddr4.isEmpty())
|
if (!sourceAddr4.isEmpty())
|
||||||
mSourceAddress = sourceAddr4;
|
mSourceAddress = sourceAddr4;
|
||||||
else
|
else if (!sourceAddr6.isEmpty())
|
||||||
if (!sourceAddr6.isEmpty())
|
|
||||||
mSourceAddress = sourceAddr6;
|
mSourceAddress = sourceAddr6;
|
||||||
|
|
||||||
if (!mSourceAddress.isEmpty())
|
if (!mSourceAddress.isEmpty())
|
||||||
@@ -111,8 +110,7 @@ bool Packet::parseV3(const ByteBuffer& packet)
|
|||||||
|
|
||||||
if (!destAddr4.isEmpty())
|
if (!destAddr4.isEmpty())
|
||||||
mDestinationAddress = destAddr4;
|
mDestinationAddress = destAddr4;
|
||||||
else
|
else if (!destAddr6.isEmpty())
|
||||||
if (!destAddr6.isEmpty())
|
|
||||||
mDestinationAddress = destAddr6;
|
mDestinationAddress = destAddr6;
|
||||||
|
|
||||||
if (!mDestinationAddress.isEmpty())
|
if (!mDestinationAddress.isEmpty())
|
||||||
@@ -148,16 +146,53 @@ bool Packet::parseV2(const ByteBuffer &packet)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WRITE_CHUNK_UCHAR(T, V) {w.writeUShort((uint16_t)mVendorId); w.writeUShort((uint16_t)T); w.writeUShort(1); w.writeUChar((uint8_t)V);}
|
#define WRITE_CHUNK_UCHAR(T, V) \
|
||||||
#define WRITE_CHUNK_USHORT(T, V) {w.writeUShort((uint16_t)mVendorId); w.writeUShort((uint16_t)T); w.writeUShort(2); w.writeUShort((uint16_t)V);}
|
{ \
|
||||||
#define WRITE_CHUNK_UINT(T, V) {w.writeUShort((uint16_t)mVendorId); w.writeUShort((uint16_t)T); w.writeUShort(4); w.writeUInt((uint32_t)V);}
|
w.writeUShort((uint16_t)mVendorId); \
|
||||||
#define WRITE_CHUNK_IP4(T, V) {w.writeUShort((uint16_t)mVendorId); w.writeUShort((uint16_t)T); w.writeUShort(4); w.writeIp(V);}
|
w.writeUShort((uint16_t)T); \
|
||||||
#define WRITE_CHUNK_IP6(T, V) {w.writeUShort((uint16_t)mVendorId); w.writeUShort((uint16_t)T); w.writeUShort(8); w.writeIp(V);}
|
w.writeUShort(1); \
|
||||||
#define WRITE_CHUNK_BUFFER(T, V) {w.writeUShort((uint16_t)mVendorId); w.writeUShort((uint16_t)T); w.writeUShort(8); w.writeBuffer(V.data(), V.size());}
|
w.writeUChar((uint8_t)V); \
|
||||||
|
}
|
||||||
|
#define WRITE_CHUNK_USHORT(T, V) \
|
||||||
|
{ \
|
||||||
|
w.writeUShort((uint16_t)mVendorId); \
|
||||||
|
w.writeUShort((uint16_t)T); \
|
||||||
|
w.writeUShort(2); \
|
||||||
|
w.writeUShort((uint16_t)V); \
|
||||||
|
}
|
||||||
|
#define WRITE_CHUNK_UINT(T, V) \
|
||||||
|
{ \
|
||||||
|
w.writeUShort((uint16_t)mVendorId); \
|
||||||
|
w.writeUShort((uint16_t)T); \
|
||||||
|
w.writeUShort(4); \
|
||||||
|
w.writeUInt((uint32_t)V); \
|
||||||
|
}
|
||||||
|
#define WRITE_CHUNK_IP4(T, V) \
|
||||||
|
{ \
|
||||||
|
w.writeUShort((uint16_t)mVendorId); \
|
||||||
|
w.writeUShort((uint16_t)T); \
|
||||||
|
w.writeUShort(4); \
|
||||||
|
w.writeIp(V); \
|
||||||
|
}
|
||||||
|
#define WRITE_CHUNK_IP6(T, V) \
|
||||||
|
{ \
|
||||||
|
w.writeUShort((uint16_t)mVendorId); \
|
||||||
|
w.writeUShort((uint16_t)T); \
|
||||||
|
w.writeUShort(8); \
|
||||||
|
w.writeIp(V); \
|
||||||
|
}
|
||||||
|
#define WRITE_CHUNK_BUFFER(T, V) \
|
||||||
|
{ \
|
||||||
|
w.writeUShort((uint16_t)mVendorId); \
|
||||||
|
w.writeUShort((uint16_t)T); \
|
||||||
|
w.writeUShort(8); \
|
||||||
|
w.writeBuffer(V.data(), V.size()); \
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer Packet::buildV3()
|
ByteBuffer Packet::buildV3()
|
||||||
{
|
{
|
||||||
ByteBuffer r; r.resize(mBody.size() + 512);
|
ByteBuffer r;
|
||||||
|
r.resize(mBody.size() + 512);
|
||||||
BufferWriter w(r);
|
BufferWriter w(r);
|
||||||
|
|
||||||
// Signature
|
// Signature
|
||||||
@@ -174,8 +209,7 @@ ByteBuffer Packet::buildV3()
|
|||||||
{
|
{
|
||||||
if (mSourceAddress.isV4())
|
if (mSourceAddress.isV4())
|
||||||
WRITE_CHUNK_IP4(ChunkType::IP4SourceAddress, mSourceAddress)
|
WRITE_CHUNK_IP4(ChunkType::IP4SourceAddress, mSourceAddress)
|
||||||
else
|
else if (mSourceAddress.isV6())
|
||||||
if (mSourceAddress.isV6())
|
|
||||||
WRITE_CHUNK_IP6(ChunkType::IP6SourceAddress, mSourceAddress);
|
WRITE_CHUNK_IP6(ChunkType::IP6SourceAddress, mSourceAddress);
|
||||||
|
|
||||||
WRITE_CHUNK_USHORT(ChunkType::SourcePort, mSourceAddress.port());
|
WRITE_CHUNK_USHORT(ChunkType::SourcePort, mSourceAddress.port());
|
||||||
@@ -186,8 +220,7 @@ ByteBuffer Packet::buildV3()
|
|||||||
{
|
{
|
||||||
if (mDestinationAddress.isV4())
|
if (mDestinationAddress.isV4())
|
||||||
WRITE_CHUNK_IP4(ChunkType::IP4DestinationAddress, mDestinationAddress)
|
WRITE_CHUNK_IP4(ChunkType::IP4DestinationAddress, mDestinationAddress)
|
||||||
else
|
else if (mDestinationAddress.isV6())
|
||||||
if (mDestinationAddress.isV6())
|
|
||||||
WRITE_CHUNK_IP6(ChunkType::IP6DestinationAddress, mDestinationAddress);
|
WRITE_CHUNK_IP6(ChunkType::IP6DestinationAddress, mDestinationAddress);
|
||||||
|
|
||||||
WRITE_CHUNK_USHORT(ChunkType::DestinationPort, mDestinationAddress.port());
|
WRITE_CHUNK_USHORT(ChunkType::DestinationPort, mDestinationAddress.port());
|
||||||
@@ -216,7 +249,9 @@ ByteBuffer Packet::buildV3()
|
|||||||
|
|
||||||
r.resize(w.offset());
|
r.resize(w.offset());
|
||||||
|
|
||||||
w.rewind(); w.skip(4); w.writeUShort((uint16_t)r.size());
|
w.rewind();
|
||||||
|
w.skip(4);
|
||||||
|
w.writeUShort((uint16_t)r.size());
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,13 +62,9 @@ namespace HEP
|
|||||||
bool parseV2(const ByteBuffer& packet);
|
bool parseV2(const ByteBuffer& packet);
|
||||||
ByteBuffer buildV3();
|
ByteBuffer buildV3();
|
||||||
|
|
||||||
uint8_t
|
uint8_t mIpProtocolFamily, mIpProtocolId;
|
||||||
mIpProtocolFamily,
|
|
||||||
mIpProtocolId;
|
|
||||||
|
|
||||||
InternetAddress
|
InternetAddress mSourceAddress, mDestinationAddress;
|
||||||
mSourceAddress,
|
|
||||||
mDestinationAddress;
|
|
||||||
|
|
||||||
timeval mTimestamp;
|
timeval mTimestamp;
|
||||||
ProtocolId mProtocolType;
|
ProtocolId mProtocolType;
|
||||||
@@ -80,6 +76,6 @@ namespace HEP
|
|||||||
uint32_t mBodyOffset = 0;
|
uint32_t mBodyOffset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace HEP
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+888
-1069
File diff suppressed because it is too large
Load Diff
@@ -36,4 +36,3 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
#endif // HL_IUUP_H
|
#endif // HL_IUUP_H
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,3 @@
|
|||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,13 @@
|
|||||||
using ice::GLogger;
|
using ice::GLogger;
|
||||||
using ice::LogLock;
|
using ice::LogLock;
|
||||||
|
|
||||||
using ice::LL_MEDIA;
|
|
||||||
using ice::LL_DEBUG;
|
|
||||||
using ice::LL_INFO;
|
|
||||||
using ice::LL_CRITICAL;
|
using ice::LL_CRITICAL;
|
||||||
|
using ice::LL_DEBUG;
|
||||||
|
using ice::LL_ERROR;
|
||||||
|
using ice::LL_INFO;
|
||||||
|
using ice::LL_MEDIA;
|
||||||
using ice::LL_NONE;
|
using ice::LL_NONE;
|
||||||
using ice::LL_SPECIAL;
|
using ice::LL_SPECIAL;
|
||||||
using ice::LL_ERROR;
|
|
||||||
using ice::LogLevelHelper;
|
using ice::LogLevelHelper;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -53,8 +53,7 @@ NetworkFrame::Payload NetworkFrame::GetUdpPayloadForEthernet(const Packet& data)
|
|||||||
result.mData += sizeof(VlanHeader);
|
result.mData += sizeof(VlanHeader);
|
||||||
result.mLength -= sizeof(VlanHeader);
|
result.mLength -= sizeof(VlanHeader);
|
||||||
proto = ntohs(vlan->mData);
|
proto = ntohs(vlan->mData);
|
||||||
}
|
} while (proto == 0x8100);
|
||||||
while (proto == 0x8100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip MPLS headers
|
// Skip MPLS headers
|
||||||
@@ -187,17 +186,13 @@ NetworkFrame::Payload NetworkFrame::GetUdpPayloadForIp4(const Packet& data)
|
|||||||
struct Ip6Header
|
struct Ip6Header
|
||||||
{
|
{
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
uint8_t traffic_class_hi:4,
|
uint8_t traffic_class_hi : 4, version : 4;
|
||||||
version:4;
|
uint8_t flow_label_hi : 4, traffic_class_lo : 4;
|
||||||
uint8_t flow_label_hi:4,
|
|
||||||
traffic_class_lo:4;
|
|
||||||
uint16_t flow_label_lo;
|
uint16_t flow_label_lo;
|
||||||
|
|
||||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||||
uint8_t version:4,
|
uint8_t version : 4, traffic_class_hi : 4;
|
||||||
traffic_class_hi:4;
|
uint8_t traffic_class_lo : 4, flow_label_hi : 4;
|
||||||
uint8_t traffic_class_lo:4,
|
|
||||||
flow_label_hi:4;
|
|
||||||
uint16_t flow_label_lo;
|
uint16_t flow_label_lo;
|
||||||
#else
|
#else
|
||||||
#error "Please fix endianness defines"
|
#error "Please fix endianness defines"
|
||||||
|
|||||||
@@ -12,18 +12,11 @@ public:
|
|||||||
const uint8_t* mData;
|
const uint8_t* mData;
|
||||||
size_t mLength;
|
size_t mLength;
|
||||||
|
|
||||||
Packet(const uint8_t* data, size_t length)
|
Packet(const uint8_t* data, size_t length) : mData(data), mLength(length) {}
|
||||||
:mData(data), mLength(length)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Packet()
|
Packet() : mData(nullptr), mLength(0) {}
|
||||||
:mData(nullptr), mLength(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool is_empty() const
|
bool is_empty() const { return mData == nullptr || mLength == 0; }
|
||||||
{
|
|
||||||
return mData == nullptr || mLength == 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Payload
|
struct Payload
|
||||||
@@ -82,18 +75,11 @@ public:
|
|||||||
uint8_t mTtl; /* time to live */
|
uint8_t mTtl; /* time to live */
|
||||||
uint8_t mProtocol; /* protocol */
|
uint8_t mProtocol; /* protocol */
|
||||||
uint16_t mChecksum; /* checksum */
|
uint16_t mChecksum; /* checksum */
|
||||||
in_addr mSource,
|
in_addr mSource, mDestination; /* source and dest address */
|
||||||
mDestination; /* source and dest address */
|
|
||||||
|
|
||||||
int headerLength() const
|
int headerLength() const { return (mVhl & 0x0f) * 4; }
|
||||||
{
|
|
||||||
return (mVhl & 0x0f) * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int version() const
|
int version() const { return mVhl >> 4; }
|
||||||
{
|
|
||||||
return mVhl >> 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
const in_addr& source4() const { return mSource; }
|
const in_addr& source4() const { return mSource; }
|
||||||
const in_addr& dest4() const { return mDestination; }
|
const in_addr& dest4() const { return mDestination; }
|
||||||
@@ -132,6 +118,5 @@ public:
|
|||||||
uint16_t mChecksum; /* checksum */
|
uint16_t mChecksum; /* checksum */
|
||||||
uint16_t mUrgentPointer; /* urgent pointer */
|
uint16_t mUrgentPointer; /* urgent pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,9 +22,7 @@
|
|||||||
|
|
||||||
#define LOG_SUBSYSTEM "network"
|
#define LOG_SUBSYSTEM "network"
|
||||||
|
|
||||||
DatagramSocket::DatagramSocket()
|
DatagramSocket::DatagramSocket() : mFamily(AF_INET), mHandle(INVALID_SOCKET), mLocalPort(0) {}
|
||||||
:mFamily(AF_INET), mHandle(INVALID_SOCKET), mLocalPort(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
DatagramSocket::~DatagramSocket()
|
DatagramSocket::~DatagramSocket()
|
||||||
{
|
{
|
||||||
@@ -41,8 +39,10 @@ void DatagramSocket::open(int family)
|
|||||||
mHandle = ::socket(mFamily, SOCK_DGRAM, IPPROTO_UDP);
|
mHandle = ::socket(mFamily, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (mHandle != INVALID_SOCKET)
|
if (mHandle != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
sockaddr_in addr4; sockaddr_in6 addr6;
|
sockaddr_in addr4;
|
||||||
memset(&addr4, 0, sizeof(addr4)); memset(&addr6, 0, sizeof(addr6));
|
sockaddr_in6 addr6;
|
||||||
|
memset(&addr4, 0, sizeof(addr4));
|
||||||
|
memset(&addr6, 0, sizeof(addr6));
|
||||||
socklen_t l = mFamily == AF_INET ? sizeof(addr4) : sizeof(addr6);
|
socklen_t l = mFamily == AF_INET ? sizeof(addr4) : sizeof(addr6);
|
||||||
int retcode = getsockname(mHandle, (mFamily == AF_INET ? (sockaddr*)&addr4 : (sockaddr*)&addr6), &l);
|
int retcode = getsockname(mHandle, (mFamily == AF_INET ? (sockaddr*)&addr4 : (sockaddr*)&addr6), &l);
|
||||||
if (!retcode)
|
if (!retcode)
|
||||||
@@ -62,7 +62,8 @@ void DatagramSocket::sendDatagram(InternetAddress &dest, const void *packetData,
|
|||||||
if (mHandle == INVALID_SOCKET)
|
if (mHandle == INVALID_SOCKET)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*int sent = */::sendto(mHandle, (const char*)packetData, packetSize, 0, dest.genericsockaddr(), dest.sockaddrLen());
|
/*int sent = */ ::sendto(mHandle, (const char*)packetData, packetSize, 0, dest.genericsockaddr(),
|
||||||
|
dest.sockaddrLen());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned DatagramSocket::recvDatagram(InternetAddress& src, void* packetBuffer, unsigned packetCapacity)
|
unsigned DatagramSocket::recvDatagram(InternetAddress& src, void* packetBuffer, unsigned packetCapacity)
|
||||||
@@ -76,8 +77,14 @@ unsigned DatagramSocket::recvDatagram(InternetAddress &src, void *packetBuffer,
|
|||||||
sockaddr_in6 addr_6 = {AF_INET6, 0, 0, {0}, 0};
|
sockaddr_in6 addr_6 = {AF_INET6, 0, 0, {0}, 0};
|
||||||
switch (mFamily)
|
switch (mFamily)
|
||||||
{
|
{
|
||||||
case AF_INET: addr = (sockaddr*)&addr_4; addrLen = sizeof(addr_4); break;
|
case AF_INET:
|
||||||
case AF_INET6: addr = (sockaddr*)&addr_6; addrLen = sizeof(addr_6); break;
|
addr = (sockaddr*)&addr_4;
|
||||||
|
addrLen = sizeof(addr_4);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
addr = (sockaddr*)&addr_6;
|
||||||
|
addrLen = sizeof(addr_6);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@@ -152,9 +159,7 @@ DatagramAgreggator::DatagramAgreggator()
|
|||||||
mMaxHandle = 0;
|
mMaxHandle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DatagramAgreggator::~DatagramAgreggator()
|
DatagramAgreggator::~DatagramAgreggator() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatagramAgreggator::addSocket(PDatagramSocket socket)
|
void DatagramAgreggator::addSocket(PDatagramSocket socket)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ class NetworkSocket
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int localport() = 0;
|
virtual int localport() = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DatagramSocket
|
class DatagramSocket
|
||||||
{
|
{
|
||||||
friend class SocketHeap;
|
friend class SocketHeap;
|
||||||
friend class DatagramAgreggator;
|
friend class DatagramAgreggator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DatagramSocket();
|
DatagramSocket();
|
||||||
virtual ~DatagramSocket();
|
virtual ~DatagramSocket();
|
||||||
|
|||||||
+293
-181
@@ -97,9 +97,11 @@
|
|||||||
#define OPTIONAL_MUTABLE_CONSTEXPR constexpr
|
#define OPTIONAL_MUTABLE_CONSTEXPR constexpr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace std{
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
namespace experimental{
|
namespace experimental
|
||||||
|
{
|
||||||
|
|
||||||
// BEGIN workaround for missing is_trivially_destructible
|
// BEGIN workaround for missing is_trivially_destructible
|
||||||
#if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
|
#if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
|
||||||
@@ -139,11 +141,17 @@ template <class T, class U>
|
|||||||
struct is_assignable
|
struct is_assignable
|
||||||
{
|
{
|
||||||
template<class X, class Y>
|
template<class X, class Y>
|
||||||
constexpr static bool has_assign(...) { return false; }
|
constexpr static bool has_assign(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template<class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true))>
|
template<class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true))>
|
||||||
// the comma operator is necessary for the cases where operator= returns void
|
// the comma operator is necessary for the cases where operator= returns void
|
||||||
constexpr static bool has_assign(bool) { return true; }
|
constexpr static bool has_assign(bool)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr static bool value = has_assign<T, U>(true);
|
constexpr static bool value = has_assign<T, U>(true);
|
||||||
};
|
};
|
||||||
@@ -153,12 +161,14 @@ template <class T>
|
|||||||
struct is_nothrow_move_assignable
|
struct is_nothrow_move_assignable
|
||||||
{
|
{
|
||||||
template<class X, bool has_any_move_assign>
|
template<class X, bool has_any_move_assign>
|
||||||
struct has_nothrow_move_assign {
|
struct has_nothrow_move_assign
|
||||||
|
{
|
||||||
constexpr static bool value = false;
|
constexpr static bool value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class X>
|
template<class X>
|
||||||
struct has_nothrow_move_assign<X, true> {
|
struct has_nothrow_move_assign<X, true>
|
||||||
|
{
|
||||||
constexpr static bool value = noexcept(std::declval<X&>() = std::declval<X&&>());
|
constexpr static bool value = noexcept(std::declval<X&>() = std::declval<X&&>());
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,27 +180,31 @@ struct is_nothrow_move_assignable
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 20.5.4, optional for object types
|
// 20.5.4, optional for object types
|
||||||
template <class T> class optional;
|
template<class T>
|
||||||
|
class optional;
|
||||||
|
|
||||||
// 20.5.5, optional for lvalue reference types
|
// 20.5.5, optional for lvalue reference types
|
||||||
template <class T> class optional<T&>;
|
template<class T>
|
||||||
|
class optional<T&>;
|
||||||
|
|
||||||
|
|
||||||
// workaround: std utility functions aren't constexpr yet
|
// workaround: std utility functions aren't constexpr yet
|
||||||
template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept
|
template<class T>
|
||||||
|
inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<T&&>(t);
|
return static_cast<T&&>(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept
|
template<class T>
|
||||||
|
inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept
|
||||||
{
|
{
|
||||||
static_assert(!std::is_lvalue_reference<T>::value, "!!");
|
static_assert(!std::is_lvalue_reference<T>::value, "!!");
|
||||||
return static_cast<T&&>(t);
|
return static_cast<T&&>(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
|
template<class T>
|
||||||
|
inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<typename std::remove_reference<T>::type&&>(t);
|
return static_cast<typename std::remove_reference<T>::type&&>(t);
|
||||||
}
|
}
|
||||||
@@ -211,10 +225,16 @@ template <typename T>
|
|||||||
struct has_overloaded_addressof
|
struct has_overloaded_addressof
|
||||||
{
|
{
|
||||||
template<class X>
|
template<class X>
|
||||||
constexpr static bool has_overload(...) { return false; }
|
constexpr static bool has_overload(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template<class X, size_t S = sizeof(std::declval<X&>().operator&())>
|
template<class X, size_t S = sizeof(std::declval<X&>().operator&())>
|
||||||
constexpr static bool has_overload(bool) { return true; }
|
constexpr static bool has_overload(bool)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr static bool value = has_overload<T>(true);
|
constexpr static bool value = has_overload<T>(true);
|
||||||
};
|
};
|
||||||
@@ -234,29 +254,39 @@ T* static_addressof(T& ref)
|
|||||||
|
|
||||||
// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
|
// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
|
||||||
template<class U>
|
template<class U>
|
||||||
constexpr U convert(U v) { return v; }
|
constexpr U convert(U v)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail_
|
||||||
|
|
||||||
|
|
||||||
constexpr struct trivial_init_t{} trivial_init{};
|
constexpr struct trivial_init_t
|
||||||
|
{
|
||||||
|
} trivial_init{};
|
||||||
|
|
||||||
|
|
||||||
// 20.5.6, In-place construction
|
// 20.5.6, In-place construction
|
||||||
constexpr struct in_place_t{} in_place{};
|
constexpr struct in_place_t
|
||||||
|
{
|
||||||
|
} in_place{};
|
||||||
|
|
||||||
|
|
||||||
// 20.5.7, Disengaged state indicator
|
// 20.5.7, Disengaged state indicator
|
||||||
struct nullopt_t
|
struct nullopt_t
|
||||||
{
|
{
|
||||||
struct init{};
|
struct init
|
||||||
|
{
|
||||||
|
};
|
||||||
constexpr explicit nullopt_t(init) {}
|
constexpr explicit nullopt_t(init) {}
|
||||||
};
|
};
|
||||||
constexpr nullopt_t nullopt{nullopt_t::init()};
|
constexpr nullopt_t nullopt{nullopt_t::init()};
|
||||||
|
|
||||||
|
|
||||||
// 20.5.8, class bad_optional_access
|
// 20.5.8, class bad_optional_access
|
||||||
class bad_optional_access : public logic_error {
|
class bad_optional_access : public logic_error
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {}
|
explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {}
|
||||||
explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {}
|
explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {}
|
||||||
@@ -272,7 +302,9 @@ union storage_t
|
|||||||
constexpr storage_t(trivial_init_t) noexcept : dummy_() {};
|
constexpr storage_t(trivial_init_t) noexcept : dummy_() {};
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
|
constexpr storage_t(Args&&... args) : value_(constexpr_forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~storage_t() {}
|
~storage_t() {}
|
||||||
};
|
};
|
||||||
@@ -287,7 +319,9 @@ union constexpr_storage_t
|
|||||||
constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_() {};
|
constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_() {};
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
|
constexpr constexpr_storage_t(Args&&... args) : value_(constexpr_forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~constexpr_storage_t() = default;
|
~constexpr_storage_t() = default;
|
||||||
};
|
};
|
||||||
@@ -305,14 +339,22 @@ struct optional_base
|
|||||||
|
|
||||||
explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
|
explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
|
||||||
|
|
||||||
template <class... Args> explicit optional_base(in_place_t, Args&&... args)
|
template<class... Args>
|
||||||
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
|
explicit optional_base(in_place_t, Args&&... args) : init_(true), storage_(constexpr_forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
|
template<class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
|
||||||
explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
|
explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
|
||||||
: init_(true), storage_(il, std::forward<Args>(args)...) {}
|
: init_(true), storage_(il, std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~optional_base() { if (init_) storage_.value_.T::~T(); }
|
~optional_base()
|
||||||
|
{
|
||||||
|
if (init_)
|
||||||
|
storage_.value_.T::~T();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -328,23 +370,28 @@ struct constexpr_optional_base
|
|||||||
|
|
||||||
explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
|
explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
|
||||||
|
|
||||||
template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
|
template<class... Args>
|
||||||
: init_(true), storage_(constexpr_forward<Args>(args)...) {}
|
explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
|
||||||
|
: init_(true), storage_(constexpr_forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
|
template<class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
|
||||||
OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
|
OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il,
|
||||||
: init_(true), storage_(il, std::forward<Args>(args)...) {}
|
Args&&... args)
|
||||||
|
: init_(true), storage_(il, std::forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~constexpr_optional_base() = default;
|
~constexpr_optional_base() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
using OptionalBase = typename std::conditional<
|
using OptionalBase =
|
||||||
is_trivially_destructible<T>::value, // if possible
|
typename std::conditional<is_trivially_destructible<T>::value, // if possible
|
||||||
constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor
|
constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial
|
||||||
optional_base<typename std::remove_const<T>::type>
|
// destructor
|
||||||
>::type;
|
optional_base<typename std::remove_const<T>::type>>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@@ -372,8 +419,10 @@ class optional : private OptionalBase<T>
|
|||||||
T& contained_val() { return OptionalBase<T>::storage_.value_; }
|
T& contained_val() { return OptionalBase<T>::storage_.value_; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void clear() noexcept {
|
void clear() noexcept
|
||||||
if (initialized()) dataptr()->T::~T();
|
{
|
||||||
|
if (initialized())
|
||||||
|
dataptr()->T::~T();
|
||||||
OptionalBase<T>::init_ = false;
|
OptionalBase<T>::init_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,19 +449,19 @@ public:
|
|||||||
constexpr optional() noexcept : OptionalBase<T>() {};
|
constexpr optional() noexcept : OptionalBase<T>() {};
|
||||||
constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
|
constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
|
||||||
|
|
||||||
optional(const optional& rhs)
|
optional(const optional& rhs) : OptionalBase<T>()
|
||||||
: OptionalBase<T>()
|
{
|
||||||
|
if (rhs.initialized())
|
||||||
{
|
{
|
||||||
if (rhs.initialized()) {
|
|
||||||
::new (static_cast<void*>(dataptr())) T(*rhs);
|
::new (static_cast<void*>(dataptr())) T(*rhs);
|
||||||
OptionalBase<T>::init_ = true;
|
OptionalBase<T>::init_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional(optional&& rhs) noexcept(is_nothrow_move_constructible<T>::value)
|
optional(optional&& rhs) noexcept(is_nothrow_move_constructible<T>::value) : OptionalBase<T>()
|
||||||
: OptionalBase<T>()
|
{
|
||||||
|
if (rhs.initialized())
|
||||||
{
|
{
|
||||||
if (rhs.initialized()) {
|
|
||||||
::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
|
::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
|
||||||
OptionalBase<T>::init_ = true;
|
OptionalBase<T>::init_ = true;
|
||||||
}
|
}
|
||||||
@@ -424,11 +473,15 @@ public:
|
|||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit constexpr optional(in_place_t, Args&&... args)
|
explicit constexpr optional(in_place_t, Args&&... args)
|
||||||
: OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
|
: OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
|
template<class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
|
||||||
OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
|
OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
|
||||||
: OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {}
|
: OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// 20.5.4.2, Destructor
|
// 20.5.4.2, Destructor
|
||||||
~optional() = default;
|
~optional() = default;
|
||||||
@@ -442,31 +495,38 @@ public:
|
|||||||
|
|
||||||
optional& operator=(const optional& rhs)
|
optional& operator=(const optional& rhs)
|
||||||
{
|
{
|
||||||
if (initialized() == true && rhs.initialized() == false) clear();
|
if (initialized() == true && rhs.initialized() == false)
|
||||||
else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
|
clear();
|
||||||
else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
|
else if (initialized() == false && rhs.initialized() == true)
|
||||||
|
initialize(*rhs);
|
||||||
|
else if (initialized() == true && rhs.initialized() == true)
|
||||||
|
contained_val() = *rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional& operator=(optional&& rhs)
|
optional& operator=(optional&& rhs) noexcept(is_nothrow_move_assignable<T>::value &&
|
||||||
noexcept(is_nothrow_move_assignable<T>::value && is_nothrow_move_constructible<T>::value)
|
is_nothrow_move_constructible<T>::value)
|
||||||
{
|
{
|
||||||
if (initialized() == true && rhs.initialized() == false) clear();
|
if (initialized() == true && rhs.initialized() == false)
|
||||||
else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs));
|
clear();
|
||||||
else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs);
|
else if (initialized() == false && rhs.initialized() == true)
|
||||||
|
initialize(std::move(*rhs));
|
||||||
|
else if (initialized() == true && rhs.initialized() == true)
|
||||||
|
contained_val() = std::move(*rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class U>
|
template<class U>
|
||||||
auto operator=(U&& v)
|
auto operator=(U&& v) -> typename enable_if<is_same<typename decay<U>::type, T>::value, optional&>::type
|
||||||
-> typename enable_if
|
|
||||||
<
|
|
||||||
is_same<typename decay<U>::type, T>::value,
|
|
||||||
optional&
|
|
||||||
>::type
|
|
||||||
{
|
{
|
||||||
if (initialized()) { contained_val() = std::forward<U>(v); }
|
if (initialized())
|
||||||
else { initialize(std::forward<U>(v)); }
|
{
|
||||||
|
contained_val() = std::forward<U>(v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
initialize(std::forward<U>(v));
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,11 +546,24 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 20.5.4.4, Swap
|
// 20.5.4.4, Swap
|
||||||
void swap(optional<T>& rhs) noexcept(is_nothrow_move_constructible<T>::value && noexcept(swap(declval<T&>(), declval<T&>())))
|
void swap(optional<T>& rhs) noexcept(is_nothrow_move_constructible<T>::value &&
|
||||||
|
noexcept(swap(declval<T&>(), declval<T&>())))
|
||||||
{
|
{
|
||||||
if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); }
|
if (initialized() == true && rhs.initialized() == false)
|
||||||
else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); }
|
{
|
||||||
else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); }
|
rhs.initialize(std::move(**this));
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
else if (initialized() == false && rhs.initialized() == true)
|
||||||
|
{
|
||||||
|
initialize(std::move(*rhs));
|
||||||
|
rhs.clear();
|
||||||
|
}
|
||||||
|
else if (initialized() == true && rhs.initialized() == true)
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(**this, *rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 20.5.4.5, Observers
|
// 20.5.4.5, Observers
|
||||||
@@ -498,65 +571,70 @@ public:
|
|||||||
explicit constexpr operator bool() const noexcept { return initialized(); }
|
explicit constexpr operator bool() const noexcept { return initialized(); }
|
||||||
bool is_initialized() const noexcept { return initialized(); }
|
bool is_initialized() const noexcept { return initialized(); }
|
||||||
|
|
||||||
constexpr T const* operator ->() const {
|
constexpr T const* operator->() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); }
|
||||||
return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPTIONAL_HAS_MOVE_ACCESSORS == 1
|
#if OPTIONAL_HAS_MOVE_ACCESSORS == 1
|
||||||
|
|
||||||
OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
|
OPTIONAL_MUTABLE_CONSTEXPR T* operator->()
|
||||||
|
{
|
||||||
assert(initialized());
|
assert(initialized());
|
||||||
return dataptr();
|
return dataptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr T const& operator *() const& {
|
constexpr T const& operator*() const& { return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); }
|
||||||
return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
|
|
||||||
}
|
|
||||||
|
|
||||||
OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
|
OPTIONAL_MUTABLE_CONSTEXPR T& operator*() &
|
||||||
|
{
|
||||||
assert(initialized());
|
assert(initialized());
|
||||||
return contained_val();
|
return contained_val();
|
||||||
}
|
}
|
||||||
|
|
||||||
OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
|
OPTIONAL_MUTABLE_CONSTEXPR T&& operator*() &&
|
||||||
|
{
|
||||||
assert(initialized());
|
assert(initialized());
|
||||||
return constexpr_move(contained_val());
|
return constexpr_move(contained_val());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr T const& value() const& {
|
constexpr T const& value() const&
|
||||||
|
{
|
||||||
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
||||||
}
|
}
|
||||||
|
|
||||||
OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
|
OPTIONAL_MUTABLE_CONSTEXPR T& value() &
|
||||||
|
{
|
||||||
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
||||||
}
|
}
|
||||||
|
|
||||||
OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
|
OPTIONAL_MUTABLE_CONSTEXPR T&& value() &&
|
||||||
if (!initialized()) throw bad_optional_access("bad optional access");
|
{
|
||||||
|
if (!initialized())
|
||||||
|
throw bad_optional_access("bad optional access");
|
||||||
return std::move(contained_val());
|
return std::move(contained_val());
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
T* operator ->() {
|
T* operator->()
|
||||||
|
{
|
||||||
assert(initialized());
|
assert(initialized());
|
||||||
return dataptr();
|
return dataptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr T const& operator *() const {
|
constexpr T const& operator*() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); }
|
||||||
return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator *() {
|
T& operator*()
|
||||||
|
{
|
||||||
assert(initialized());
|
assert(initialized());
|
||||||
return contained_val();
|
return contained_val();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr T const& value() const {
|
constexpr T const& value() const
|
||||||
|
{
|
||||||
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
||||||
}
|
}
|
||||||
|
|
||||||
T& value() {
|
T& value()
|
||||||
|
{
|
||||||
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,7 +653,8 @@ public:
|
|||||||
template<class V>
|
template<class V>
|
||||||
OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
|
OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
|
||||||
{
|
{
|
||||||
return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
|
return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val())
|
||||||
|
: detail_::convert<T>(constexpr_forward<V>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -583,7 +662,8 @@ public:
|
|||||||
template<class V>
|
template<class V>
|
||||||
T value_or(V&& v) &&
|
T value_or(V&& v) &&
|
||||||
{
|
{
|
||||||
return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
|
return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val())
|
||||||
|
: detail_::convert<T>(constexpr_forward<V>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -597,7 +677,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -609,7 +688,6 @@ class optional<T&>
|
|||||||
T* ref;
|
T* ref;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// 20.5.5.1, construction/destruction
|
// 20.5.5.1, construction/destruction
|
||||||
constexpr optional() noexcept : ref(nullptr) {}
|
constexpr optional() noexcept : ref(nullptr) {}
|
||||||
|
|
||||||
@@ -628,7 +706,8 @@ public:
|
|||||||
~optional() = default;
|
~optional() = default;
|
||||||
|
|
||||||
// 20.5.5.2, mutation
|
// 20.5.5.2, mutation
|
||||||
optional& operator=(nullopt_t) noexcept {
|
optional& operator=(nullopt_t) noexcept
|
||||||
|
{
|
||||||
ref = nullptr;
|
ref = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -644,54 +723,32 @@ public:
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
auto operator=(U&& rhs) noexcept
|
auto operator=(U&& rhs) noexcept ->
|
||||||
-> typename enable_if
|
typename enable_if<is_same<typename decay<U>::type, optional<T&>>::value, optional&>::type
|
||||||
<
|
|
||||||
is_same<typename decay<U>::type, optional<T&>>::value,
|
|
||||||
optional&
|
|
||||||
>::type
|
|
||||||
{
|
{
|
||||||
ref = rhs.ref;
|
ref = rhs.ref;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
auto operator=(U&& rhs) noexcept
|
auto operator=(U&& rhs) noexcept ->
|
||||||
-> typename enable_if
|
typename enable_if<!is_same<typename decay<U>::type, optional<T&>>::value, optional&>::type = delete;
|
||||||
<
|
|
||||||
!is_same<typename decay<U>::type, optional<T&>>::value,
|
|
||||||
optional&
|
|
||||||
>::type
|
|
||||||
= delete;
|
|
||||||
|
|
||||||
void emplace(T& v) noexcept {
|
void emplace(T& v) noexcept { ref = detail_::static_addressof(v); }
|
||||||
ref = detail_::static_addressof(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void emplace(T&&) = delete;
|
void emplace(T&&) = delete;
|
||||||
|
|
||||||
|
|
||||||
void swap(optional<T&>& rhs) noexcept
|
void swap(optional<T&>& rhs) noexcept { std::swap(ref, rhs.ref); }
|
||||||
{
|
|
||||||
std::swap(ref, rhs.ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 20.5.5.3, observers
|
// 20.5.5.3, observers
|
||||||
constexpr T* operator->() const {
|
constexpr T* operator->() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); }
|
||||||
return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr T& operator*() const {
|
constexpr T& operator*() const { return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); }
|
||||||
return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr T& value() const {
|
constexpr T& value() const { return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); }
|
||||||
return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit constexpr operator bool() const noexcept {
|
explicit constexpr operator bool() const noexcept { return ref != nullptr; }
|
||||||
return ref != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class V>
|
template<class V>
|
||||||
constexpr typename decay<T>::type value_or(V&& v) const
|
constexpr typename decay<T>::type value_or(V&& v) const
|
||||||
@@ -709,280 +766,333 @@ class optional<T&&>
|
|||||||
|
|
||||||
|
|
||||||
// 20.5.8, Relational operators
|
// 20.5.8, Relational operators
|
||||||
template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
|
template<class T>
|
||||||
|
constexpr bool operator==(const optional<T>& x, const optional<T>& y)
|
||||||
{
|
{
|
||||||
return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
|
return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
|
||||||
{
|
{
|
||||||
return !(x == y);
|
return !(x == y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
|
template<class T>
|
||||||
|
constexpr bool operator<(const optional<T>& x, const optional<T>& y)
|
||||||
{
|
{
|
||||||
return (!y) ? false : (!x) ? true : *x < *y;
|
return (!y) ? false : (!x) ? true : *x < *y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
|
template<class T>
|
||||||
|
constexpr bool operator>(const optional<T>& x, const optional<T>& y)
|
||||||
{
|
{
|
||||||
return (y < x);
|
return (y < x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
|
||||||
{
|
{
|
||||||
return !(y < x);
|
return !(y < x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
|
||||||
{
|
{
|
||||||
return !(x < y);
|
return !(x < y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 20.5.9, Comparison with nullopt
|
// 20.5.9, Comparison with nullopt
|
||||||
template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
|
||||||
{
|
{
|
||||||
return (!x);
|
return (!x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
|
||||||
{
|
{
|
||||||
return (!x);
|
return (!x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
|
||||||
{
|
{
|
||||||
return bool(x);
|
return bool(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
|
||||||
{
|
{
|
||||||
return bool(x);
|
return bool(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
|
||||||
{
|
{
|
||||||
return bool(x);
|
return bool(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
|
||||||
{
|
{
|
||||||
return (!x);
|
return (!x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
|
||||||
{
|
{
|
||||||
return bool(x);
|
return bool(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
|
template<class T>
|
||||||
|
constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
|
||||||
{
|
{
|
||||||
return (!x);
|
return (!x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 20.5.10, Comparison with T
|
// 20.5.10, Comparison with T
|
||||||
template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator==(const optional<T>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x == v : false;
|
return bool(x) ? *x == v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
|
template<class T>
|
||||||
|
constexpr bool operator==(const T& v, const optional<T>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v == *x : false;
|
return bool(x) ? v == *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const optional<T>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x != v : true;
|
return bool(x) ? *x != v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const T& v, const optional<T>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v != *x : true;
|
return bool(x) ? v != *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator<(const optional<T>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x < v : true;
|
return bool(x) ? *x < v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
|
template<class T>
|
||||||
|
constexpr bool operator>(const T& v, const optional<T>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v > *x : true;
|
return bool(x) ? v > *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator>(const optional<T>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x > v : false;
|
return bool(x) ? *x > v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
|
template<class T>
|
||||||
|
constexpr bool operator<(const T& v, const optional<T>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v < *x : false;
|
return bool(x) ? v < *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const optional<T>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x >= v : false;
|
return bool(x) ? *x >= v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const T& v, const optional<T>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v <= *x : false;
|
return bool(x) ? v <= *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const optional<T>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x <= v : true;
|
return bool(x) ? *x <= v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const T& v, const optional<T>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v >= *x : true;
|
return bool(x) ? v >= *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Comparison of optional<T&> with T
|
// Comparison of optional<T&> with T
|
||||||
template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator==(const optional<T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x == v : false;
|
return bool(x) ? *x == v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator==(const T& v, const optional<T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v == *x : false;
|
return bool(x) ? v == *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const optional<T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x != v : true;
|
return bool(x) ? *x != v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const T& v, const optional<T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v != *x : true;
|
return bool(x) ? v != *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator<(const optional<T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x < v : true;
|
return bool(x) ? *x < v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator>(const T& v, const optional<T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v > *x : true;
|
return bool(x) ? v > *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator>(const optional<T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x > v : false;
|
return bool(x) ? *x > v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator<(const T& v, const optional<T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v < *x : false;
|
return bool(x) ? v < *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const optional<T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x >= v : false;
|
return bool(x) ? *x >= v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const T& v, const optional<T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v <= *x : false;
|
return bool(x) ? v <= *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const optional<T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x <= v : true;
|
return bool(x) ? *x <= v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const T& v, const optional<T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v >= *x : true;
|
return bool(x) ? v >= *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison of optional<T const&> with T
|
// Comparison of optional<T const&> with T
|
||||||
template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator==(const optional<const T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x == v : false;
|
return bool(x) ? *x == v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator==(const T& v, const optional<const T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v == *x : false;
|
return bool(x) ? v == *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const optional<const T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x != v : true;
|
return bool(x) ? *x != v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator!=(const T& v, const optional<const T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v != *x : true;
|
return bool(x) ? v != *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator<(const optional<const T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x < v : true;
|
return bool(x) ? *x < v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator>(const T& v, const optional<const T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v > *x : true;
|
return bool(x) ? v > *x : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator>(const optional<const T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x > v : false;
|
return bool(x) ? *x > v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator<(const T& v, const optional<const T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v < *x : false;
|
return bool(x) ? v < *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const optional<const T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x >= v : false;
|
return bool(x) ? *x >= v : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const T& v, const optional<const T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v <= *x : false;
|
return bool(x) ? v <= *x : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
|
template<class T>
|
||||||
|
constexpr bool operator<=(const optional<const T&>& x, const T& v)
|
||||||
{
|
{
|
||||||
return bool(x) ? *x <= v : true;
|
return bool(x) ? *x <= v : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
|
template<class T>
|
||||||
|
constexpr bool operator>=(const T& v, const optional<const T&>& x)
|
||||||
{
|
{
|
||||||
return bool(x) ? v >= *x : true;
|
return bool(x) ? v >= *x : true;
|
||||||
}
|
}
|
||||||
@@ -1020,7 +1130,8 @@ namespace std
|
|||||||
typedef typename hash<T>::result_type result_type;
|
typedef typename hash<T>::result_type result_type;
|
||||||
typedef std::experimental::optional<T> argument_type;
|
typedef std::experimental::optional<T> argument_type;
|
||||||
|
|
||||||
constexpr result_type operator()(argument_type const& arg) const {
|
constexpr result_type operator()(argument_type const& arg) const
|
||||||
|
{
|
||||||
return arg ? std::hash<T>{}(*arg) : result_type{};
|
return arg ? std::hash<T>{}(*arg) : result_type{};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1031,11 +1142,12 @@ namespace std
|
|||||||
typedef typename hash<T>::result_type result_type;
|
typedef typename hash<T>::result_type result_type;
|
||||||
typedef std::experimental::optional<T&> argument_type;
|
typedef std::experimental::optional<T&> argument_type;
|
||||||
|
|
||||||
constexpr result_type operator()(argument_type const& arg) const {
|
constexpr result_type operator()(argument_type const& arg) const
|
||||||
|
{
|
||||||
return arg ? std::hash<T>{}(*arg) : result_type{};
|
return arg ? std::hash<T>{}(*arg) : result_type{};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace std
|
||||||
|
|
||||||
#undef TR2_OPTIONAL_REQUIRES
|
#undef TR2_OPTIONAL_REQUIRES
|
||||||
#undef TR2_OPTIONAL_ASSERTED_EXPRESSION
|
#undef TR2_OPTIONAL_ASSERTED_EXPRESSION
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ int winVersion()
|
|||||||
static LONG WINAPI MyExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
|
static LONG WINAPI MyExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
|
||||||
{
|
{
|
||||||
// Open the file
|
// Open the file
|
||||||
HANDLE hFile = CreateFile( L"MiniDump.dmp", GENERIC_READ | GENERIC_WRITE,
|
HANDLE hFile =
|
||||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
CreateFile(L"MiniDump.dmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
||||||
{
|
{
|
||||||
@@ -60,8 +60,8 @@ static LONG WINAPI MyExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
|
|||||||
|
|
||||||
MINIDUMP_TYPE mdt = MiniDumpWithFullMemory;
|
MINIDUMP_TYPE mdt = MiniDumpWithFullMemory;
|
||||||
|
|
||||||
BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
|
BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, mdt,
|
||||||
hFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 );
|
(ExceptionInfo != 0) ? &mdei : 0, 0, 0);
|
||||||
|
|
||||||
// Close the file
|
// Close the file
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
#include "HL_Pointer.h"
|
#include "HL_Pointer.h"
|
||||||
|
|
||||||
UsageCounter::UsageCounter()
|
UsageCounter::UsageCounter() {}
|
||||||
{}
|
|
||||||
|
|
||||||
UsageCounter::~UsageCounter()
|
UsageCounter::~UsageCounter() {}
|
||||||
{}
|
|
||||||
|
|
||||||
int UsageCounter::obtain(int usageId)
|
int UsageCounter::obtain(int usageId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -124,15 +124,9 @@ namespace hl
|
|||||||
/// activeBlocks() is a genuine leak of referenced objects rather than a
|
/// activeBlocks() is a genuine leak of referenced objects rather than a
|
||||||
/// traffic peak that merely carved extra chunks. Covers every pooled
|
/// traffic peak that merely carved extra chunks. Covers every pooled
|
||||||
/// shared_ptr node (allocate_shared<RTPPacket> + jitter-buffer packets).
|
/// shared_ptr node (allocate_shared<RTPPacket> + jitter-buffer packets).
|
||||||
static std::int64_t activeBlocks() noexcept
|
static std::int64_t activeBlocks() noexcept { return s_activeBlocks.load(std::memory_order_relaxed); }
|
||||||
{
|
|
||||||
return s_activeBlocks.load(std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
/// Live oversized allocations that overflowed to ::operator new.
|
/// Live oversized allocations that overflowed to ::operator new.
|
||||||
static std::int64_t activeGlobalAllocations() noexcept
|
static std::int64_t activeGlobalAllocations() noexcept { return s_activeGlobal.load(std::memory_order_relaxed); }
|
||||||
{
|
|
||||||
return s_activeGlobal.load(std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
/// Total blocks ever carved (chunks x BlocksPerChunk) = high-water capacity.
|
/// Total blocks ever carved (chunks x BlocksPerChunk) = high-water capacity.
|
||||||
/// With cross-thread reclaim this PLATEAUS once the pool has covered the
|
/// With cross-thread reclaim this PLATEAUS once the pool has covered the
|
||||||
/// concurrent high-water; sustained linear growth means reclaim is not working.
|
/// concurrent high-water; sustained linear growth means reclaim is not working.
|
||||||
@@ -143,15 +137,9 @@ namespace hl
|
|||||||
/// Free blocks parked in the process-wide depot, i.e. reclaimed from a freeing
|
/// Free blocks parked in the process-wide depot, i.e. reclaimed from a freeing
|
||||||
/// thread and available to any allocating thread. Healthy steady state is a
|
/// thread and available to any allocating thread. Healthy steady state is a
|
||||||
/// non-zero, bounded value: it is the surplus that used to be stranded.
|
/// non-zero, bounded value: it is the surplus that used to be stranded.
|
||||||
static std::int64_t depotBlocks() noexcept
|
static std::int64_t depotBlocks() noexcept { return s_depotBlocks.load(std::memory_order_relaxed); }
|
||||||
{
|
|
||||||
return s_depotBlocks.load(std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
/// Approximate live pooled payload bytes (excludes per-block header).
|
/// Approximate live pooled payload bytes (excludes per-block header).
|
||||||
static std::int64_t activeBytes() noexcept
|
static std::int64_t activeBytes() noexcept { return activeBlocks() * static_cast<std::int64_t>(PayloadSize); }
|
||||||
{
|
|
||||||
return activeBlocks() * static_cast<std::int64_t>(PayloadSize);
|
|
||||||
}
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -174,10 +162,7 @@ namespace hl
|
|||||||
static_assert(PayloadSize >= 2 * sizeof(void*) + sizeof(std::size_t),
|
static_assert(PayloadSize >= 2 * sizeof(void*) + sizeof(std::size_t),
|
||||||
"pooled block payload must hold the free-list, depot and length slots");
|
"pooled block payload must hold the free-list, depot and length slots");
|
||||||
|
|
||||||
static uint64_t& tagOf(void* block) noexcept
|
static uint64_t& tagOf(void* block) noexcept { return *reinterpret_cast<uint64_t*>(block); }
|
||||||
{
|
|
||||||
return *reinterpret_cast<uint64_t*>(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*& nextOf(void* block) noexcept
|
static void*& nextOf(void* block) noexcept
|
||||||
{
|
{
|
||||||
@@ -324,29 +309,63 @@ namespace hl
|
|||||||
/// whether HL_RTP_POOL is compiled in. When pooling is disabled they return -1
|
/// whether HL_RTP_POOL is compiled in. When pooling is disabled they return -1
|
||||||
/// ("not applicable") since allocate_shared then behaves like make_shared.
|
/// ("not applicable") since allocate_shared then behaves like make_shared.
|
||||||
#if HL_RTP_POOL
|
#if HL_RTP_POOL
|
||||||
inline std::int64_t poolActiveBlocks() noexcept { return FixedBlockPool::activeBlocks(); }
|
inline std::int64_t poolActiveBlocks() noexcept
|
||||||
inline std::int64_t poolCapacityBlocks() noexcept { return FixedBlockPool::capacityBlocks(); }
|
{
|
||||||
inline std::int64_t poolDepotBlocks() noexcept { return FixedBlockPool::depotBlocks(); }
|
return FixedBlockPool::activeBlocks();
|
||||||
inline std::int64_t poolActiveGlobal() noexcept { return FixedBlockPool::activeGlobalAllocations(); }
|
}
|
||||||
inline std::int64_t poolActiveBytes() noexcept { return FixedBlockPool::activeBytes(); }
|
inline std::int64_t poolCapacityBlocks() noexcept
|
||||||
|
{
|
||||||
|
return FixedBlockPool::capacityBlocks();
|
||||||
|
}
|
||||||
|
inline std::int64_t poolDepotBlocks() noexcept
|
||||||
|
{
|
||||||
|
return FixedBlockPool::depotBlocks();
|
||||||
|
}
|
||||||
|
inline std::int64_t poolActiveGlobal() noexcept
|
||||||
|
{
|
||||||
|
return FixedBlockPool::activeGlobalAllocations();
|
||||||
|
}
|
||||||
|
inline std::int64_t poolActiveBytes() noexcept
|
||||||
|
{
|
||||||
|
return FixedBlockPool::activeBytes();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
inline std::int64_t poolActiveBlocks() noexcept { return -1; }
|
inline std::int64_t poolActiveBlocks() noexcept
|
||||||
inline std::int64_t poolCapacityBlocks() noexcept { return -1; }
|
{
|
||||||
inline std::int64_t poolDepotBlocks() noexcept { return -1; }
|
return -1;
|
||||||
inline std::int64_t poolActiveGlobal() noexcept { return -1; }
|
}
|
||||||
inline std::int64_t poolActiveBytes() noexcept { return -1; }
|
inline std::int64_t poolCapacityBlocks() noexcept
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
inline std::int64_t poolDepotBlocks() noexcept
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
inline std::int64_t poolActiveGlobal() noexcept
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
inline std::int64_t poolActiveBytes() noexcept
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @class PoolAllocator
|
/// @class PoolAllocator
|
||||||
/// A stateless, std-conforming Allocator suitable for std::allocate_shared. When HL_RTP_POOL is
|
/// A stateless, std-conforming Allocator suitable for std::allocate_shared. When HL_RTP_POOL is
|
||||||
/// enabled it serves single-node allocations from FixedBlockPool; otherwise (and for any request
|
/// enabled it serves single-node allocations from FixedBlockPool; otherwise (and for any request
|
||||||
/// that does not fit a pooled block) it delegates to the global allocator, matching make_shared.
|
/// that does not fit a pooled block) it delegates to the global allocator, matching make_shared.
|
||||||
template <class T> struct PoolAllocator
|
template<class T>
|
||||||
|
struct PoolAllocator
|
||||||
{
|
{
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
PoolAllocator() noexcept = default;
|
PoolAllocator() noexcept = default;
|
||||||
template <class U> PoolAllocator(const PoolAllocator<U>&) noexcept {}
|
template<class U>
|
||||||
|
PoolAllocator(const PoolAllocator<U>&) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
T* allocate(std::size_t n)
|
T* allocate(std::size_t n)
|
||||||
{
|
{
|
||||||
@@ -366,7 +385,15 @@ namespace hl
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U> bool operator==(const PoolAllocator<U>&) const noexcept { return true; }
|
template<class U>
|
||||||
template <class U> bool operator!=(const PoolAllocator<U>&) const noexcept { return false; }
|
bool operator==(const PoolAllocator<U>&) const noexcept
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template<class U>
|
||||||
|
bool operator!=(const PoolAllocator<U>&) const noexcept
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace hl
|
} // namespace hl
|
||||||
|
|||||||
@@ -85,10 +85,9 @@ std::string OsProcess::execCommand(const std::string& cmd)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdline,
|
std::shared_ptr<std::thread>
|
||||||
std::function<void(const std::string& line)> callback,
|
OsProcess::asyncExecCommand(const std::string& cmdline, std::function<void(const std::string& line)> callback,
|
||||||
std::function<void(const std::string& reason)> finished_callback,
|
std::function<void(const std::string& reason)> finished_callback, bool& finish_flag)
|
||||||
bool& finish_flag)
|
|
||||||
{
|
{
|
||||||
// std::cout << cmdline << std::endl;
|
// std::cout << cmdline << std::endl;
|
||||||
|
|
||||||
@@ -103,7 +102,8 @@ std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdl
|
|||||||
if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
|
if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
|
||||||
return std::shared_ptr<std::thread>();
|
return std::shared_ptr<std::thread>();
|
||||||
|
|
||||||
STARTUPINFOA si; memset(&si, 0, sizeof si);
|
STARTUPINFOA si;
|
||||||
|
memset(&si, 0, sizeof si);
|
||||||
si.cb = sizeof(STARTUPINFOA);
|
si.cb = sizeof(STARTUPINFOA);
|
||||||
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||||
si.hStdOutput = hPipeWrite;
|
si.hStdOutput = hPipeWrite;
|
||||||
@@ -117,8 +117,8 @@ std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdl
|
|||||||
strcpy(cmdbuffer, strx::replace(cmdline, "/", "\\").c_str());
|
strcpy(cmdbuffer, strx::replace(cmdline, "/", "\\").c_str());
|
||||||
|
|
||||||
|
|
||||||
BOOL fSuccess = CreateProcessA( nullptr, cmdbuffer, nullptr, nullptr, TRUE,
|
BOOL fSuccess =
|
||||||
CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);
|
CreateProcessA(nullptr, cmdbuffer, nullptr, nullptr, TRUE, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);
|
||||||
if (!fSuccess)
|
if (!fSuccess)
|
||||||
{
|
{
|
||||||
CloseHandle(hPipeWrite);
|
CloseHandle(hPipeWrite);
|
||||||
@@ -129,7 +129,8 @@ std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdl
|
|||||||
std::shared_ptr<std::thread> r = std::make_shared<std::thread>(
|
std::shared_ptr<std::thread> r = std::make_shared<std::thread>(
|
||||||
[&finish_flag, pi, callback, finished_callback, hPipeRead, hPipeWrite]()
|
[&finish_flag, pi, callback, finished_callback, hPipeRead, hPipeWrite]()
|
||||||
{
|
{
|
||||||
char buf[4096]; memset(buf, 0, sizeof buf);
|
char buf[4096];
|
||||||
|
memset(buf, 0, sizeof buf);
|
||||||
for (; !finish_flag;)
|
for (; !finish_flag;)
|
||||||
{
|
{
|
||||||
// Give some timeslice (50ms), so we won't waste 100% cpu.
|
// Give some timeslice (50ms), so we won't waste 100% cpu.
|
||||||
@@ -148,7 +149,9 @@ std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdl
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
int filled = strlen(buf);
|
int filled = strlen(buf);
|
||||||
if (!::ReadFile(hPipeRead, buf + filled, std::min(sizeof(buf) - 1 - filled, (size_t)dwAvail), &dwRead, nullptr) || !dwRead)
|
if (!::ReadFile(hPipeRead, buf + filled, std::min(sizeof(buf) - 1 - filled, (size_t)dwAvail),
|
||||||
|
&dwRead, nullptr) ||
|
||||||
|
!dwRead)
|
||||||
// error, the child process might ended
|
// error, the child process might ended
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -229,12 +232,12 @@ int OsProcess::execSystem(const std::string& cmd)
|
|||||||
#include "helper/HL_String.h"
|
#include "helper/HL_String.h"
|
||||||
#include "helper/HL_Sync.h"
|
#include "helper/HL_Sync.h"
|
||||||
|
|
||||||
std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdline,
|
std::shared_ptr<std::thread>
|
||||||
std::function<void(const std::string& line)> line_callback,
|
OsProcess::asyncExecCommand(const std::string& cmdline, std::function<void(const std::string& line)> line_callback,
|
||||||
std::function<void(const std::string& reason)> finished_callback,
|
std::function<void(const std::string& reason)> finished_callback, bool& finish_flag)
|
||||||
bool& finish_flag)
|
|
||||||
{
|
{
|
||||||
std::shared_ptr<std::thread> t = std::make_shared<std::thread>([cmdline, line_callback, finished_callback, &finish_flag]()
|
std::shared_ptr<std::thread> t = std::make_shared<std::thread>(
|
||||||
|
[cmdline, line_callback, finished_callback, &finish_flag]()
|
||||||
{
|
{
|
||||||
ThreadHelper::setName("OsProcess::asyncExecCommand");
|
ThreadHelper::setName("OsProcess::asyncExecCommand");
|
||||||
std::string cp = cmdline;
|
std::string cp = cmdline;
|
||||||
@@ -275,8 +278,7 @@ std::shared_ptr<std::thread> OsProcess::asyncExecCommand(const std::string& cmdl
|
|||||||
buffer[r] = 0;
|
buffer[r] = 0;
|
||||||
lines += std::string(buffer);
|
lines += std::string(buffer);
|
||||||
}
|
}
|
||||||
}
|
} while (r == sizeof(buffer) - 1);
|
||||||
while (r == sizeof(buffer) - 1);
|
|
||||||
|
|
||||||
if (lines.find('\n') != std::string::npos && line_callback)
|
if (lines.find('\n') != std::string::npos && line_callback)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,15 +11,13 @@ class OsProcess
|
|||||||
public:
|
public:
|
||||||
static std::string execCommand(const std::string& cmdline);
|
static std::string execCommand(const std::string& cmdline);
|
||||||
static int execSystem(const std::string& cmdline);
|
static int execSystem(const std::string& cmdline);
|
||||||
static std::shared_ptr<std::thread> asyncExecCommand(const std::string& cmdline,
|
static std::shared_ptr<std::thread>
|
||||||
std::function<void(const std::string& line)> line_callback,
|
asyncExecCommand(const std::string& cmdline, std::function<void(const std::string& line)> line_callback,
|
||||||
std::function<void(const std::string& reason)> finished_callback,
|
std::function<void(const std::string& reason)> finished_callback, bool& finish_flag);
|
||||||
bool& finish_flag);
|
|
||||||
#if defined(TARGET_OSX) || defined(TARGET_LINUX)
|
#if defined(TARGET_OSX) || defined(TARGET_LINUX)
|
||||||
static pid_t findPid(const std::string& cmdline);
|
static pid_t findPid(const std::string& cmdline);
|
||||||
static void killByPid(pid_t pid);
|
static void killByPid(pid_t pid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -59,10 +59,8 @@ struct RtcpHeader
|
|||||||
static std::string ipToString(uint32_t ip)
|
static std::string ipToString(uint32_t ip)
|
||||||
{
|
{
|
||||||
// ip in host byte order → dotted-decimal
|
// ip in host byte order → dotted-decimal
|
||||||
return std::to_string((ip >> 24) & 0xFF) + "." +
|
return std::to_string((ip >> 24) & 0xFF) + "." + std::to_string((ip >> 16) & 0xFF) + "." +
|
||||||
std::to_string((ip >> 16) & 0xFF) + "." +
|
std::to_string((ip >> 8) & 0xFF) + "." + std::to_string(ip & 0xFF);
|
||||||
std::to_string((ip >> 8) & 0xFF) + "." +
|
|
||||||
std::to_string( ip & 0xFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t stringToIp(const std::string& s)
|
static uint32_t stringToIp(const std::string& s)
|
||||||
@@ -152,7 +150,8 @@ int RtpHelper::findPayloadLength(const void* buffer, size_t length)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Header extension
|
// Header extension
|
||||||
if (h->x) {
|
if (h->x)
|
||||||
|
{
|
||||||
if (offset + 4 > length)
|
if (offset + 4 > length)
|
||||||
return -1;
|
return -1;
|
||||||
uint16_t extWords = (static_cast<uint16_t>(p[offset + 2]) << 8) | p[offset + 3];
|
uint16_t extWords = (static_cast<uint16_t>(p[offset + 2]) << 8) | p[offset + 3];
|
||||||
@@ -164,7 +163,8 @@ int RtpHelper::findPayloadLength(const void* buffer, size_t length)
|
|||||||
size_t payloadLen = length - offset;
|
size_t payloadLen = length - offset;
|
||||||
|
|
||||||
// Padding
|
// Padding
|
||||||
if (h->p && payloadLen > 0) {
|
if (h->p && payloadLen > 0)
|
||||||
|
{
|
||||||
uint8_t padBytes = p[length - 1];
|
uint8_t padBytes = p[length - 1];
|
||||||
if (padBytes > payloadLen)
|
if (padBytes > payloadLen)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -186,7 +186,8 @@ std::shared_ptr<jrtplib::RTPPacket> RtpDump::parseRtpData(const uint8_t* data, s
|
|||||||
if (!data || len < 12 || !RtpHelper::isRtp(data, len))
|
if (!data || len < 12 || !RtpHelper::isRtp(data, len))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
// Both are heap-allocated; RTPRawPacket takes ownership and deletes them
|
// Both are heap-allocated; RTPRawPacket takes ownership and deletes them
|
||||||
jrtplib::RTPIPAddress senderAddress = {jrtplib::RTPIPv4Address(uint32_t(0), uint16_t(0))};
|
jrtplib::RTPIPAddress senderAddress = {jrtplib::RTPIPv4Address(uint32_t(0), uint16_t(0))};
|
||||||
uint8_t* dataCopy = new uint8_t[len];
|
uint8_t* dataCopy = new uint8_t[len];
|
||||||
@@ -199,16 +200,15 @@ std::shared_ptr<jrtplib::RTPPacket> RtpDump::parseRtpData(const uint8_t* data, s
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return packet;
|
return packet;
|
||||||
} catch (const std::exception& e) {
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
ICELogInfo(<< "Failed to parse RTP packet: " << e.what());
|
ICELogInfo(<< "Failed to parse RTP packet: " << e.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpDump::RtpDump(const char* filename)
|
RtpDump::RtpDump(const char* filename) : mFilename(filename ? filename : "") {}
|
||||||
: mFilename(filename ? filename : "")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RtpDump::~RtpDump() = default;
|
RtpDump::~RtpDump() = default;
|
||||||
|
|
||||||
@@ -237,14 +237,19 @@ void RtpDump::load()
|
|||||||
|
|
||||||
// Parse source address from the text line
|
// Parse source address from the text line
|
||||||
size_t spacePos = textLine.find(' ');
|
size_t spacePos = textLine.find(' ');
|
||||||
if (spacePos != std::string::npos) {
|
if (spacePos != std::string::npos)
|
||||||
|
{
|
||||||
std::string addrPart = textLine.substr(spacePos + 1);
|
std::string addrPart = textLine.substr(spacePos + 1);
|
||||||
size_t slashPos = addrPart.find('/');
|
size_t slashPos = addrPart.find('/');
|
||||||
if (slashPos != std::string::npos) {
|
if (slashPos != std::string::npos)
|
||||||
|
{
|
||||||
mSourceIp = stringToIp(addrPart.substr(0, slashPos));
|
mSourceIp = stringToIp(addrPart.substr(0, slashPos));
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
mSourcePort = static_cast<uint16_t>(std::stoi(addrPart.substr(slashPos + 1)));
|
mSourcePort = static_cast<uint16_t>(std::stoi(addrPart.substr(slashPos + 1)));
|
||||||
} catch (...) {
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
mSourcePort = 0;
|
mSourcePort = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,21 +280,25 @@ void RtpDump::load()
|
|||||||
// --- 3. Packet records ---
|
// --- 3. Packet records ---
|
||||||
size_t packetCount = 0;
|
size_t packetCount = 0;
|
||||||
|
|
||||||
while (input.good() && input.peek() != EOF) {
|
while (input.good() && input.peek() != EOF)
|
||||||
|
{
|
||||||
// Packet header: length(2) + plen(2) + offset(4) = 8 bytes
|
// Packet header: length(2) + plen(2) + offset(4) = 8 bytes
|
||||||
uint16_t recLength, plen;
|
uint16_t recLength, plen;
|
||||||
uint32_t offsetMs;
|
uint32_t offsetMs;
|
||||||
|
|
||||||
input.read(reinterpret_cast<char*>(&recLength), 2);
|
input.read(reinterpret_cast<char*>(&recLength), 2);
|
||||||
if (input.gcount() != 2) break;
|
if (input.gcount() != 2)
|
||||||
|
break;
|
||||||
recLength = ntohs(recLength);
|
recLength = ntohs(recLength);
|
||||||
|
|
||||||
input.read(reinterpret_cast<char*>(&plen), 2);
|
input.read(reinterpret_cast<char*>(&plen), 2);
|
||||||
if (input.gcount() != 2) break;
|
if (input.gcount() != 2)
|
||||||
|
break;
|
||||||
plen = ntohs(plen);
|
plen = ntohs(plen);
|
||||||
|
|
||||||
input.read(reinterpret_cast<char*>(&offsetMs), 4);
|
input.read(reinterpret_cast<char*>(&offsetMs), 4);
|
||||||
if (input.gcount() != 4) break;
|
if (input.gcount() != 4)
|
||||||
|
break;
|
||||||
offsetMs = ntohl(offsetMs);
|
offsetMs = ntohl(offsetMs);
|
||||||
|
|
||||||
// All-zeros record signals end of file in some implementations
|
// All-zeros record signals end of file in some implementations
|
||||||
@@ -367,7 +376,8 @@ void RtpDump::add(const void* buffer, size_t len)
|
|||||||
uint32_t offsetMs = 0;
|
uint32_t offsetMs = 0;
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
if (!mRecording) {
|
if (!mRecording)
|
||||||
|
{
|
||||||
mRecording = true;
|
mRecording = true;
|
||||||
mRecordStart = now;
|
mRecordStart = now;
|
||||||
|
|
||||||
@@ -378,7 +388,9 @@ void RtpDump::add(const void* buffer, size_t len)
|
|||||||
auto usec = std::chrono::duration_cast<std::chrono::microseconds>(epoch - sec);
|
auto usec = std::chrono::duration_cast<std::chrono::microseconds>(epoch - sec);
|
||||||
mStartSec = static_cast<uint32_t>(sec.count());
|
mStartSec = static_cast<uint32_t>(sec.count());
|
||||||
mStartUsec = static_cast<uint32_t>(usec.count());
|
mStartUsec = static_cast<uint32_t>(usec.count());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - mRecordStart);
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - mRecordStart);
|
||||||
offsetMs = static_cast<uint32_t>(elapsed.count());
|
offsetMs = static_cast<uint32_t>(elapsed.count());
|
||||||
}
|
}
|
||||||
@@ -396,8 +408,7 @@ void RtpDump::add(const void* buffer, size_t len, uint32_t offsetMs)
|
|||||||
throw std::runtime_error("Packet too large: " + std::to_string(len));
|
throw std::runtime_error("Packet too large: " + std::to_string(len));
|
||||||
|
|
||||||
RtpData entry;
|
RtpData entry;
|
||||||
entry.mRawData.assign(static_cast<const uint8_t*>(buffer),
|
entry.mRawData.assign(static_cast<const uint8_t*>(buffer), static_cast<const uint8_t*>(buffer) + len);
|
||||||
static_cast<const uint8_t*>(buffer) + len);
|
|
||||||
entry.mOffsetMs = offsetMs;
|
entry.mOffsetMs = offsetMs;
|
||||||
entry.mPacket = parseRtpData(entry.mRawData.data(), entry.mRawData.size());
|
entry.mPacket = parseRtpData(entry.mRawData.data(), entry.mRawData.size());
|
||||||
|
|
||||||
@@ -414,9 +425,8 @@ void RtpDump::flush()
|
|||||||
throw std::runtime_error("Failed to open file for writing: " + mFilename);
|
throw std::runtime_error("Failed to open file for writing: " + mFilename);
|
||||||
|
|
||||||
// --- 1. Text header ---
|
// --- 1. Text header ---
|
||||||
std::string textLine = std::string(RTPDUMP_SHEBANG) + " " +
|
std::string textLine =
|
||||||
ipToString(mSourceIp) + "/" +
|
std::string(RTPDUMP_SHEBANG) + " " + ipToString(mSourceIp) + "/" + std::to_string(mSourcePort) + "\n";
|
||||||
std::to_string(mSourcePort) + "\n";
|
|
||||||
output.write(textLine.data(), static_cast<std::streamsize>(textLine.size()));
|
output.write(textLine.data(), static_cast<std::streamsize>(textLine.size()));
|
||||||
|
|
||||||
// --- 2. Binary file header (16 bytes) ---
|
// --- 2. Binary file header (16 bytes) ---
|
||||||
@@ -441,7 +451,8 @@ void RtpDump::flush()
|
|||||||
// --- 3. Packet records ---
|
// --- 3. Packet records ---
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
|
||||||
for (const auto& pkt : mPacketList) {
|
for (const auto& pkt : mPacketList)
|
||||||
|
{
|
||||||
if (pkt.mRawData.empty())
|
if (pkt.mRawData.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,9 @@ struct RtpPair
|
|||||||
T mRtp;
|
T mRtp;
|
||||||
T mRtcp;
|
T mRtcp;
|
||||||
|
|
||||||
RtpPair()
|
RtpPair() {}
|
||||||
{}
|
|
||||||
|
|
||||||
RtpPair(const T& rtp, const T& rtcp)
|
RtpPair(const T& rtp, const T& rtcp) : mRtp(rtp), mRtcp(rtcp) {}
|
||||||
:mRtp(rtp), mRtcp(rtcp)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool multiplexed() const { return mRtp == mRtcp; }
|
bool multiplexed() const { return mRtp == mRtcp; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class SafeSingleton
|
|||||||
protected:
|
protected:
|
||||||
static std::atomic<T*> SharedInstance;
|
static std::atomic<T*> SharedInstance;
|
||||||
static std::mutex mMutex;
|
static std::mutex mMutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static T& instance()
|
static T& instance()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,8 +31,7 @@
|
|||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
// ----------------------------- SocketSink -------------------------
|
// ----------------------------- SocketSink -------------------------
|
||||||
SocketSink::~SocketSink()
|
SocketSink::~SocketSink() {}
|
||||||
{}
|
|
||||||
|
|
||||||
// ----------------------------- SocketHeap -------------------------
|
// ----------------------------- SocketHeap -------------------------
|
||||||
|
|
||||||
@@ -121,9 +120,8 @@ RtpPair<PDatagramSocket> SocketHeap::allocSocketPair(int family, SocketSink *sin
|
|||||||
freeSocket(rtcp);
|
freeSocket(rtcp);
|
||||||
throw Exception(ERR_NET_FAILED);
|
throw Exception(ERR_NET_FAILED);
|
||||||
}
|
}
|
||||||
ICELogInfo(<< "Allocated socket pair " << (family == AF_INET ? "AF_INET" : "AF_INET6") << " "
|
ICELogInfo(<< "Allocated socket pair " << (family == AF_INET ? "AF_INET" : "AF_INET6") << " " << rtp->socket()
|
||||||
<< rtp->socket() << ":" << rtcp->socket()
|
<< ":" << rtcp->socket() << " at ports " << rtp->localport() << ":" << rtcp->localport());
|
||||||
<< " at ports " << rtp->localport() << ":"<< rtcp->localport());
|
|
||||||
|
|
||||||
return RtpPair<PDatagramSocket>(rtp, rtcp);
|
return RtpPair<PDatagramSocket>(rtp, rtcp);
|
||||||
}
|
}
|
||||||
@@ -260,7 +258,8 @@ void SocketHeap::thread()
|
|||||||
for (auto& socketIter : mSocketMap)
|
for (auto& socketIter : mSocketMap)
|
||||||
agreggator.addSocket(socketIter.second.mSocket);
|
agreggator.addSocket(socketIter.second.mSocket);
|
||||||
|
|
||||||
/* for (SocketMap::iterator socketIter = mSocketMap.begin(); socketIter != mSocketMap.end(); ++socketIter)
|
/* for (SocketMap::iterator socketIter = mSocketMap.begin(); socketIter != mSocketMap.end();
|
||||||
|
++socketIter)
|
||||||
{
|
{
|
||||||
// Add handle to set
|
// Add handle to set
|
||||||
agreggator.addSocket(socketIter->second.mSocket);
|
agreggator.addSocket(socketIter->second.mSocket);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ class SocketSink
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~SocketSink();
|
virtual ~SocketSink();
|
||||||
virtual void onReceivedData(PDatagramSocket socket, InternetAddress& src, const void* receivedPtr, unsigned receivedSize) = 0;
|
virtual void onReceivedData(PDatagramSocket socket, InternetAddress& src, const void* receivedPtr,
|
||||||
|
unsigned receivedSize) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class allocates new UDP sockets and tracks incoming packets on them. It runs in separate thread
|
// Class allocates new UDP sockets and tracks incoming packets on them. It runs in separate thread
|
||||||
@@ -49,7 +50,8 @@ public:
|
|||||||
// Returns used port number range
|
// Returns used port number range
|
||||||
void range(unsigned short& start, unsigned short& finish);
|
void range(unsigned short& start, unsigned short& finish);
|
||||||
|
|
||||||
// Attempts to allocate and return socket + allocated port number. REQUIRES pointer to data sink - it will be used to process incoming datagrams
|
// Attempts to allocate and return socket + allocated port number. REQUIRES pointer to data sink - it will be used
|
||||||
|
// to process incoming datagrams
|
||||||
PDatagramSocket allocSocket(int family, SocketSink* sink, int port = 0);
|
PDatagramSocket allocSocket(int family, SocketSink* sink, int port = 0);
|
||||||
RtpPair<PDatagramSocket> allocSocketPair(int family, SocketSink* sink, Multiplex m);
|
RtpPair<PDatagramSocket> allocSocketPair(int family, SocketSink* sink, Multiplex m);
|
||||||
|
|
||||||
@@ -69,18 +71,11 @@ protected:
|
|||||||
// Data sink pointer
|
// Data sink pointer
|
||||||
SocketSink* mSink;
|
SocketSink* mSink;
|
||||||
|
|
||||||
SocketItem()
|
SocketItem() : mSink(nullptr) {}
|
||||||
:mSink(nullptr)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
SocketItem(unsigned short portnumber, SocketSink* sink)
|
SocketItem(unsigned short portnumber, SocketSink* sink) : mSink(sink) { mSocket->mLocalPort = portnumber; }
|
||||||
:mSink(sink)
|
|
||||||
{
|
|
||||||
mSocket->mLocalPort = portnumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
~SocketItem()
|
~SocketItem() {}
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<SOCKET, SocketItem> SocketMap;
|
typedef std::map<SOCKET, SocketItem> SocketMap;
|
||||||
@@ -90,8 +85,7 @@ protected:
|
|||||||
Mutex mGuard;
|
Mutex mGuard;
|
||||||
SocketMap mSocketMap;
|
SocketMap mSocketMap;
|
||||||
PortVector mPortVector;
|
PortVector mPortVector;
|
||||||
unsigned short mStart,
|
unsigned short mStart, mFinish;
|
||||||
mFinish;
|
|
||||||
SocketVector mDeleteVector;
|
SocketVector mDeleteVector;
|
||||||
Mutex mDeleteGuard;
|
Mutex mDeleteGuard;
|
||||||
|
|
||||||
@@ -107,7 +101,6 @@ protected:
|
|||||||
|
|
||||||
// Processes mDeleteVector -> updates mSocketMap, removes socket items and closes sockets specified in mDeleteVector
|
// Processes mDeleteVector -> updates mSocketMap, removes socket items and closes sockets specified in mDeleteVector
|
||||||
void processDeleted();
|
void processDeleted();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,10 +13,7 @@ struct Average
|
|||||||
return mSum / mCount;
|
return mSum / mCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
T value() const
|
T value() const { return average(); }
|
||||||
{
|
|
||||||
return average();
|
|
||||||
}
|
|
||||||
|
|
||||||
void process(T value)
|
void process(T value)
|
||||||
{
|
{
|
||||||
@@ -43,10 +40,7 @@ struct TestResult
|
|||||||
mAverage.process(value);
|
mAverage.process(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_initialized() const
|
bool is_initialized() const { return mAverage.mCount > 0; }
|
||||||
{
|
|
||||||
return mAverage.mCount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
T current() const
|
T current() const
|
||||||
{
|
{
|
||||||
@@ -56,15 +50,9 @@ struct TestResult
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
T value() const
|
T value() const { return current(); }
|
||||||
{
|
|
||||||
return current();
|
|
||||||
}
|
|
||||||
|
|
||||||
T average() const
|
T average() const { return mAverage.average(); }
|
||||||
{
|
|
||||||
return mAverage.average();
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult<T>& operator=(T value)
|
TestResult<T>& operator=(T value)
|
||||||
{
|
{
|
||||||
@@ -72,10 +60,7 @@ struct TestResult
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator T()
|
operator T() { return mCurrent; }
|
||||||
{
|
|
||||||
return mCurrent;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,5 +20,4 @@ enum class StreamState
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -89,8 +89,7 @@ int strx::toInt(const char *s, int defaultValue, bool* isOk)
|
|||||||
*isOk = false;
|
*isOk = false;
|
||||||
result = defaultValue;
|
result = defaultValue;
|
||||||
}
|
}
|
||||||
else
|
else if (isOk)
|
||||||
if (isOk)
|
|
||||||
*isOk = true;
|
*isOk = true;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -105,8 +104,7 @@ uint64_t strx::toUint64(const char* s, uint64_t def, bool *isOk)
|
|||||||
*isOk = false;
|
*isOk = false;
|
||||||
result = def;
|
result = def;
|
||||||
}
|
}
|
||||||
else
|
else if (isOk)
|
||||||
if (isOk)
|
|
||||||
*isOk = true;
|
*isOk = true;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -131,7 +129,8 @@ static const char hexmap[] = "0123456789abcdef";
|
|||||||
|
|
||||||
std::string strx::toHex(const uint8_t* input, size_t inputLength)
|
std::string strx::toHex(const uint8_t* input, size_t inputLength)
|
||||||
{
|
{
|
||||||
std::string result; result.resize(inputLength * 2);
|
std::string result;
|
||||||
|
result.resize(inputLength * 2);
|
||||||
|
|
||||||
const char* p = (const char*)input;
|
const char* p = (const char*)input;
|
||||||
char* r = &result[0];
|
char* r = &result[0];
|
||||||
@@ -276,8 +275,10 @@ float strx::toFloat(const std::string &s, float v, bool* isOk)
|
|||||||
|
|
||||||
std::string strx::trim(const std::string& s)
|
std::string strx::trim(const std::string& s)
|
||||||
{
|
{
|
||||||
auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c) { return std::isspace(c) || c == '\r' || c == '\n'; });
|
auto wsfront =
|
||||||
auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c) { return std::isspace(c) || c == '\r' || c == '\n'; }).base();
|
std::find_if_not(s.begin(), s.end(), [](int c) { return std::isspace(c) || c == '\r' || c == '\n'; });
|
||||||
|
auto wsback =
|
||||||
|
std::find_if_not(s.rbegin(), s.rend(), [](int c) { return std::isspace(c) || c == '\r' || c == '\n'; }).base();
|
||||||
return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
|
return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +329,8 @@ static int hex2code(char s)
|
|||||||
|
|
||||||
std::string strx::fromHex2String(const std::string& s)
|
std::string strx::fromHex2String(const std::string& s)
|
||||||
{
|
{
|
||||||
std::string result; result.resize(s.size() / 2);
|
std::string result;
|
||||||
|
result.resize(s.size() / 2);
|
||||||
const char* t = s.c_str();
|
const char* t = s.c_str();
|
||||||
for (size_t i = 0; i < result.size(); i++)
|
for (size_t i = 0; i < result.size(); i++)
|
||||||
result[i] = static_cast<char>((hex2code(t[i * 2]) << 4) | hex2code(t[i * 2 + 1]));
|
result[i] = static_cast<char>((hex2code(t[i * 2]) << 4) | hex2code(t[i * 2 + 1]));
|
||||||
@@ -446,20 +448,18 @@ std::string strx::removeQuotes(const std::string& s)
|
|||||||
#if defined(TARGET_WIN)
|
#if defined(TARGET_WIN)
|
||||||
|
|
||||||
// MSVC++ lacks memmem support
|
// MSVC++ lacks memmem support
|
||||||
const void *memmem(const void *haystack, size_t haystack_len,
|
const void* memmem(const void* haystack, size_t haystack_len, const void* const needle, const size_t needle_len)
|
||||||
const void * const needle, const size_t needle_len)
|
|
||||||
{
|
{
|
||||||
if (!haystack || !haystack_len || !needle || !needle_len)
|
if (!haystack || !haystack_len || !needle || !needle_len)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
for (const char *h = (const char*)haystack;
|
for (const char* h = (const char*)haystack; haystack_len >= needle_len; ++h, --haystack_len)
|
||||||
haystack_len >= needle_len;
|
{
|
||||||
++h, --haystack_len) {
|
if (!memcmp(h, needle, needle_len))
|
||||||
if (!memcmp(h, needle, needle_len)) {
|
{
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -88,8 +88,7 @@ public:
|
|||||||
#if defined(TARGET_WIN)
|
#if defined(TARGET_WIN)
|
||||||
|
|
||||||
// MSVC++ lacks memmem support
|
// MSVC++ lacks memmem support
|
||||||
extern const void *memmem(const void *haystack, size_t haystack_len,
|
extern const void* memmem(const void* haystack, size_t haystack_len, const void* const needle, const size_t needle_len);
|
||||||
const void * const needle, const size_t needle_len);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -140,15 +140,9 @@ std::chrono::milliseconds chronox::ExecutionTime::getSpentTime() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------- BufferQueue -----------------
|
// --------------- BufferQueue -----------------
|
||||||
BufferQueue::BufferQueue()
|
BufferQueue::BufferQueue() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
BufferQueue::~BufferQueue() {}
|
||||||
|
|
||||||
BufferQueue::~BufferQueue()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferQueue::push(const void* data, int bytes)
|
void BufferQueue::push(const void* data, int bytes)
|
||||||
{
|
{
|
||||||
@@ -164,8 +158,7 @@ void BufferQueue::push(const void* data, int bytes)
|
|||||||
BufferQueue::PBlock BufferQueue::pull(int milliseconds)
|
BufferQueue::PBlock BufferQueue::pull(int milliseconds)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(mMutex);
|
std::unique_lock<std::mutex> l(mMutex);
|
||||||
mSignal.wait_for(l, std::chrono::milliseconds(milliseconds),
|
mSignal.wait_for(l, std::chrono::milliseconds(milliseconds), [this]() { return !mBlockList.empty(); });
|
||||||
[this]() { return !mBlockList.empty(); });
|
|
||||||
|
|
||||||
PBlock r;
|
PBlock r;
|
||||||
if (!mBlockList.empty())
|
if (!mBlockList.empty())
|
||||||
@@ -178,9 +171,7 @@ BufferQueue::PBlock BufferQueue::pull(int milliseconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------- Semaphore ---------------------
|
// ----------------- Semaphore ---------------------
|
||||||
Semaphore::Semaphore(unsigned int count)
|
Semaphore::Semaphore(unsigned int count) : m_count(count) {}
|
||||||
: m_count(count)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void Semaphore::notify()
|
void Semaphore::notify()
|
||||||
{
|
{
|
||||||
@@ -196,7 +187,8 @@ void Semaphore::wait()
|
|||||||
m_count--;
|
m_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Semaphore::waitFor(std::chrono::milliseconds timeout) {
|
bool Semaphore::waitFor(std::chrono::milliseconds timeout)
|
||||||
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mtx);
|
std::unique_lock<std::mutex> lock(m_mtx);
|
||||||
|
|
||||||
if (!m_cv.wait_for(lock, timeout, [this]() { return m_count > 0; }))
|
if (!m_cv.wait_for(lock, timeout, [this]() { return m_count > 0; }))
|
||||||
@@ -246,15 +238,18 @@ uint64_t TimerQueue::add(std::chrono::milliseconds milliseconds, std::function<v
|
|||||||
// 1 if the timer was cancelled.
|
// 1 if the timer was cancelled.
|
||||||
// 0 if you were too late to cancel (or the timer ID was never valid to
|
// 0 if you were too late to cancel (or the timer ID was never valid to
|
||||||
// start with)
|
// start with)
|
||||||
size_t TimerQueue::cancel(uint64_t id) {
|
size_t TimerQueue::cancel(uint64_t id)
|
||||||
|
{
|
||||||
// Instead of removing the item from the container (thus breaking the
|
// Instead of removing the item from the container (thus breaking the
|
||||||
// heap integrity), we set the item as having no handler, and put
|
// heap integrity), we set the item as having no handler, and put
|
||||||
// that handler on a new item at the top for immediate execution
|
// that handler on a new item at the top for immediate execution
|
||||||
// The timer thread will then ignore the original item, since it has no
|
// The timer thread will then ignore the original item, since it has no
|
||||||
// handler.
|
// handler.
|
||||||
std::unique_lock<std::mutex> lk(m_mtx);
|
std::unique_lock<std::mutex> lk(m_mtx);
|
||||||
for (auto&& item : m_items.getContainer()) {
|
for (auto&& item : m_items.getContainer())
|
||||||
if (item.id == id && item.handler) {
|
{
|
||||||
|
if (item.id == id && item.handler)
|
||||||
|
{
|
||||||
WorkItem newItem;
|
WorkItem newItem;
|
||||||
// Zero time, so it stays at the top for immediate execution
|
// Zero time, so it stays at the top for immediate execution
|
||||||
newItem.end = Clock::time_point();
|
newItem.end = Clock::time_point();
|
||||||
@@ -285,8 +280,10 @@ size_t TimerQueue::cancelAll()
|
|||||||
// Setting all "end" to 0 (for immediate execution) is ok,
|
// Setting all "end" to 0 (for immediate execution) is ok,
|
||||||
// since it maintains the heap integrity
|
// since it maintains the heap integrity
|
||||||
std::unique_lock<std::mutex> lk(m_mtx);
|
std::unique_lock<std::mutex> lk(m_mtx);
|
||||||
for (auto&& item : m_items.getContainer()) {
|
for (auto&& item : m_items.getContainer())
|
||||||
if (item.id) {
|
{
|
||||||
|
if (item.id)
|
||||||
|
{
|
||||||
item.end = Clock::time_point();
|
item.end = Clock::time_point();
|
||||||
item.id = 0;
|
item.id = 0;
|
||||||
}
|
}
|
||||||
@@ -307,9 +304,12 @@ void TimerQueue::run()
|
|||||||
if (end.first)
|
if (end.first)
|
||||||
{
|
{
|
||||||
// Timers found, so wait until it expires (or something else changes)
|
// Timers found, so wait until it expires (or something else changes)
|
||||||
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(end.second - std::chrono::steady_clock::now());
|
auto milliseconds =
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(end.second - std::chrono::steady_clock::now());
|
||||||
m_checkWork.waitFor(milliseconds);
|
m_checkWork.waitFor(milliseconds);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// No timers exist, so wait forever until something changes
|
// No timers exist, so wait forever until something changes
|
||||||
m_checkWork.wait();
|
m_checkWork.wait();
|
||||||
}
|
}
|
||||||
@@ -327,11 +327,15 @@ void TimerQueue::run()
|
|||||||
std::pair<bool, TimerQueue::Clock::time_point> TimerQueue::calcWaitTime()
|
std::pair<bool, TimerQueue::Clock::time_point> TimerQueue::calcWaitTime()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_mtx);
|
std::lock_guard<std::mutex> lk(m_mtx);
|
||||||
while (m_items.size()) {
|
while (m_items.size())
|
||||||
if (m_items.top().handler) {
|
{
|
||||||
|
if (m_items.top().handler)
|
||||||
|
{
|
||||||
// Item present, so return the new wait time
|
// Item present, so return the new wait time
|
||||||
return std::make_pair(true, m_items.top().end);
|
return std::make_pair(true, m_items.top().end);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Discard empty handlers (they were cancelled)
|
// Discard empty handlers (they were cancelled)
|
||||||
m_items.pop();
|
m_items.pop();
|
||||||
}
|
}
|
||||||
@@ -342,9 +346,11 @@ std::pair<bool, TimerQueue::Clock::time_point> TimerQueue::calcWaitTime()
|
|||||||
return std::make_pair(false, Clock::time_point());
|
return std::make_pair(false, Clock::time_point());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerQueue::checkWork() {
|
void TimerQueue::checkWork()
|
||||||
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mtx);
|
std::unique_lock<std::mutex> lk(m_mtx);
|
||||||
while (m_items.size() && m_items.top().end <= Clock::now()) {
|
while (m_items.size() && m_items.top().end <= Clock::now())
|
||||||
|
{
|
||||||
WorkItem item(std::move(m_items.top()));
|
WorkItem item(std::move(m_items.top()));
|
||||||
m_items.pop();
|
m_items.pop();
|
||||||
|
|
||||||
@@ -355,10 +361,12 @@ void TimerQueue::checkWork() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimerQueue::WorkItem::operator > (const TimerQueue::WorkItem& other) const {
|
bool TimerQueue::WorkItem::operator>(const TimerQueue::WorkItem& other) const
|
||||||
|
{
|
||||||
return end > other.end;
|
return end > other.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TimerQueue::WorkItem>& TimerQueue::Queue::getContainer() {
|
std::vector<TimerQueue::WorkItem>& TimerQueue::Queue::getContainer()
|
||||||
|
{
|
||||||
return this->c;
|
return this->c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
ExecutionTime();
|
ExecutionTime();
|
||||||
std::chrono::milliseconds getSpentTime() const;
|
std::chrono::milliseconds getSpentTime() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::chrono::milliseconds mStart;
|
std::chrono::milliseconds mStart;
|
||||||
};
|
};
|
||||||
@@ -158,8 +159,7 @@ private:
|
|||||||
|
|
||||||
std::mutex m_mtx;
|
std::mutex m_mtx;
|
||||||
// Inheriting from priority_queue, so we can access the internal container
|
// Inheriting from priority_queue, so we can access the internal container
|
||||||
class Queue : public std::priority_queue<WorkItem, std::vector<WorkItem>,
|
class Queue : public std::priority_queue<WorkItem, std::vector<WorkItem>, std::greater<WorkItem>>
|
||||||
std::greater<WorkItem>>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<WorkItem>& getContainer();
|
std::vector<WorkItem>& getContainer();
|
||||||
|
|||||||
@@ -50,4 +50,3 @@ bool is_zero(const timespec& ts)
|
|||||||
{
|
{
|
||||||
return !ts.tv_sec && !ts.tv_nsec;
|
return !ts.tv_sec && !ts.tv_nsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,49 +32,61 @@ enum SdpDirection
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
template<
|
template<class K, class V, class HashK = std::hash<K>, class EqK = std::equal_to<K>, class HashV = std::hash<V>,
|
||||||
class K, class V,
|
class EqV = std::equal_to<V>>
|
||||||
class HashK = std::hash<K>, class EqK = std::equal_to<K>,
|
class BiMap
|
||||||
class HashV = std::hash<V>, class EqV = std::equal_to<V>
|
{
|
||||||
>
|
|
||||||
class BiMap {
|
|
||||||
public:
|
public:
|
||||||
using key_type = K;
|
using key_type = K;
|
||||||
using mapped_type = V;
|
using mapped_type = V;
|
||||||
|
|
||||||
BiMap(const std::map<K,V>& initializers) {
|
BiMap(const std::map<K, V>& initializers)
|
||||||
for (const auto& item: initializers) {
|
{
|
||||||
|
for (const auto& item : initializers)
|
||||||
|
{
|
||||||
insert(item.first, item.second);
|
insert(item.first, item.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a new (key, value) pair. Returns false if either key or value already exists.
|
// Insert a new (key, value) pair. Returns false if either key or value already exists.
|
||||||
bool insert(const K& k, const V& v) {
|
bool insert(const K& k, const V& v)
|
||||||
if (contains_key(k) || contains_value(v)) return false;
|
{
|
||||||
|
if (contains_key(k) || contains_value(v))
|
||||||
|
return false;
|
||||||
auto ok = forward_.emplace(k, v);
|
auto ok = forward_.emplace(k, v);
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
auto ov = reverse_.emplace(v, k);
|
auto ov = reverse_.emplace(v, k);
|
||||||
if (!ov.second) { // shouldn't happen given the guard above
|
if (!ov.second)
|
||||||
|
{ // shouldn't happen given the guard above
|
||||||
forward_.erase(k);
|
forward_.erase(k);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (...) {
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
forward_.erase(k);
|
forward_.erase(k);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
return ok.second;
|
return ok.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(K&& k, V&& v) {
|
bool insert(K&& k, V&& v)
|
||||||
if (contains_key(k) || contains_value(v)) return false;
|
{
|
||||||
|
if (contains_key(k) || contains_value(v))
|
||||||
|
return false;
|
||||||
auto ok = forward_.emplace(std::move(k), std::move(v));
|
auto ok = forward_.emplace(std::move(k), std::move(v));
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
auto ov = reverse_.emplace(ok.first->second, ok.first->first); // use stored refs
|
auto ov = reverse_.emplace(ok.first->second, ok.first->first); // use stored refs
|
||||||
if (!ov.second) {
|
if (!ov.second)
|
||||||
|
{
|
||||||
forward_.erase(ok.first);
|
forward_.erase(ok.first);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (...) {
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
forward_.erase(ok.first);
|
forward_.erase(ok.first);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@@ -82,10 +94,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace value for existing key (and update reverse map). Returns false if value is already bound elsewhere.
|
// Replace value for existing key (and update reverse map). Returns false if value is already bound elsewhere.
|
||||||
bool replace_by_key(const K& k, const V& new_v) {
|
bool replace_by_key(const K& k, const V& new_v)
|
||||||
|
{
|
||||||
auto it = forward_.find(k);
|
auto it = forward_.find(k);
|
||||||
if (it == forward_.end()) return false;
|
if (it == forward_.end())
|
||||||
if (contains_value(new_v)) return false;
|
return false;
|
||||||
|
if (contains_value(new_v))
|
||||||
|
return false;
|
||||||
// remove old reverse, insert new reverse, then update forward
|
// remove old reverse, insert new reverse, then update forward
|
||||||
reverse_.erase(it->second);
|
reverse_.erase(it->second);
|
||||||
reverse_.emplace(new_v, k);
|
reverse_.emplace(new_v, k);
|
||||||
@@ -94,10 +109,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace key for existing value (and update forward map). Returns false if key is already bound elsewhere.
|
// Replace key for existing value (and update forward map). Returns false if key is already bound elsewhere.
|
||||||
bool replace_by_value(const V& v, const K& new_k) {
|
bool replace_by_value(const V& v, const K& new_k)
|
||||||
|
{
|
||||||
auto it = reverse_.find(v);
|
auto it = reverse_.find(v);
|
||||||
if (it == reverse_.end()) return false;
|
if (it == reverse_.end())
|
||||||
if (contains_key(new_k)) return false;
|
return false;
|
||||||
|
if (contains_key(new_k))
|
||||||
|
return false;
|
||||||
forward_.erase(it->second);
|
forward_.erase(it->second);
|
||||||
forward_.emplace(new_k, v);
|
forward_.emplace(new_k, v);
|
||||||
it->second = new_k;
|
it->second = new_k;
|
||||||
@@ -105,17 +123,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Erase by key/value. Return number erased (0 or 1).
|
// Erase by key/value. Return number erased (0 or 1).
|
||||||
size_t erase_key(const K& k) {
|
size_t erase_key(const K& k)
|
||||||
|
{
|
||||||
auto it = forward_.find(k);
|
auto it = forward_.find(k);
|
||||||
if (it == forward_.end()) return 0;
|
if (it == forward_.end())
|
||||||
|
return 0;
|
||||||
reverse_.erase(it->second);
|
reverse_.erase(it->second);
|
||||||
forward_.erase(it);
|
forward_.erase(it);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t erase_value(const V& v) {
|
size_t erase_value(const V& v)
|
||||||
|
{
|
||||||
auto it = reverse_.find(v);
|
auto it = reverse_.find(v);
|
||||||
if (it == reverse_.end()) return 0;
|
if (it == reverse_.end())
|
||||||
|
return 0;
|
||||||
forward_.erase(it->second);
|
forward_.erase(it->second);
|
||||||
reverse_.erase(it);
|
reverse_.erase(it);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -125,11 +147,13 @@ public:
|
|||||||
bool contains_key(const K& k) const { return forward_.find(k) != forward_.end(); }
|
bool contains_key(const K& k) const { return forward_.find(k) != forward_.end(); }
|
||||||
bool contains_value(const V& v) const { return reverse_.find(v) != reverse_.end(); }
|
bool contains_value(const V& v) const { return reverse_.find(v) != reverse_.end(); }
|
||||||
|
|
||||||
const V* find_by_key(const K& k) const {
|
const V* find_by_key(const K& k) const
|
||||||
|
{
|
||||||
auto it = forward_.find(k);
|
auto it = forward_.find(k);
|
||||||
return (it == forward_.end()) ? nullptr : &it->second;
|
return (it == forward_.end()) ? nullptr : &it->second;
|
||||||
}
|
}
|
||||||
const K* find_by_value(const V& v) const {
|
const K* find_by_value(const V& v) const
|
||||||
|
{
|
||||||
auto it = reverse_.find(v);
|
auto it = reverse_.find(v);
|
||||||
return (it == reverse_.end()) ? nullptr : &it->second;
|
return (it == reverse_.end()) ? nullptr : &it->second;
|
||||||
}
|
}
|
||||||
@@ -138,7 +162,8 @@ public:
|
|||||||
const V& at_key(const K& k) const { return forward_.at(k); }
|
const V& at_key(const K& k) const { return forward_.at(k); }
|
||||||
const K& at_value(const V& v) const { return reverse_.at(v); }
|
const K& at_value(const V& v) const { return reverse_.at(v); }
|
||||||
|
|
||||||
void clear() noexcept {
|
void clear() noexcept
|
||||||
|
{
|
||||||
forward_.clear();
|
forward_.clear();
|
||||||
reverse_.clear();
|
reverse_.clear();
|
||||||
}
|
}
|
||||||
@@ -147,7 +172,8 @@ public:
|
|||||||
size_t size() const noexcept { return forward_.size(); }
|
size_t size() const noexcept { return forward_.size(); }
|
||||||
|
|
||||||
// Reserve buckets for performance (optional)
|
// Reserve buckets for performance (optional)
|
||||||
void reserve(size_t n) {
|
void reserve(size_t n)
|
||||||
|
{
|
||||||
forward_.reserve(n);
|
forward_.reserve(n);
|
||||||
reverse_.reserve(n);
|
reverse_.reserve(n);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
#define ADR_WINDOW_CLASS_NAME L"HIDDEN_USB_CHANGE_DELEGATE_WINDOWCLASS_%u"
|
#define ADR_WINDOW_CLASS_NAME L"HIDDEN_USB_CHANGE_DELEGATE_WINDOWCLASS_%u"
|
||||||
#define ADR_WINDOW_NAME L"HIDDEN_USB_CHANGE_DELEGATE_WINDOW_%u"
|
#define ADR_WINDOW_NAME L"HIDDEN_USB_CHANGE_DELEGATE_WINDOW_%u"
|
||||||
|
|
||||||
UsbChangeListener::UsbChangeListener()
|
UsbChangeListener::UsbChangeListener() : mNotifyHandle(NULL), mHiddenWindow(NULL), mDelegate(NULL)
|
||||||
:mNotifyHandle(NULL), mHiddenWindow(NULL), mDelegate(NULL)
|
|
||||||
{
|
{
|
||||||
wsprintfW(mWindowClassName, ADR_WINDOW_CLASS_NAME, (unsigned int)rand());
|
wsprintfW(mWindowClassName, ADR_WINDOW_CLASS_NAME, (unsigned int)rand());
|
||||||
}
|
}
|
||||||
@@ -40,11 +39,8 @@ void UsbChangeListener::start()
|
|||||||
|
|
||||||
wchar_t windowname[128];
|
wchar_t windowname[128];
|
||||||
wsprintfW(windowname, ADR_WINDOW_NAME, rand());
|
wsprintfW(windowname, ADR_WINDOW_NAME, rand());
|
||||||
mHiddenWindow = CreateWindowW( mWindowClassName,
|
mHiddenWindow =
|
||||||
windowname,
|
CreateWindowW(mWindowClassName, windowname, WS_POPUP | WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
|
||||||
WS_POPUP | WS_DISABLED,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
NULL, NULL, NULL, NULL );
|
|
||||||
if (!mHiddenWindow)
|
if (!mHiddenWindow)
|
||||||
throw Exception(ERR_CREATEWINDOW, GetLastError());
|
throw Exception(ERR_CREATEWINDOW, GetLastError());
|
||||||
if (!SetWindowLongPtr(mHiddenWindow, GWLP_USERDATA, (LONG_PTR)this))
|
if (!SetWindowLongPtr(mHiddenWindow, GWLP_USERDATA, (LONG_PTR)this))
|
||||||
@@ -57,7 +53,8 @@ void UsbChangeListener::start()
|
|||||||
mNotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
mNotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||||
|
|
||||||
// Register notification
|
// Register notification
|
||||||
if (!RegisterDeviceNotification(mHiddenWindow, &mNotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES))
|
if (!RegisterDeviceNotification(mHiddenWindow, &mNotificationFilter,
|
||||||
|
DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES))
|
||||||
throw Exception(ERR_REGISTERNOTIFICATION, GetLastError());
|
throw Exception(ERR_REGISTERNOTIFICATION, GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,33 +25,19 @@ Variant::Variant()
|
|||||||
mPointer = nullptr;
|
mPointer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::~Variant()
|
Variant::~Variant() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Variant::Variant(bool value)
|
Variant::Variant(bool value) : mType(VTYPE_BOOL), mBool(value) {}
|
||||||
:mType(VTYPE_BOOL), mBool(value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Variant::Variant(int value)
|
Variant::Variant(int value) : mType(VTYPE_INT), mInt(value) {}
|
||||||
:mType(VTYPE_INT), mInt(value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Variant::Variant(int64_t value)
|
Variant::Variant(int64_t value) : mType(VTYPE_INT64), mInt64(value) {}
|
||||||
:mType(VTYPE_INT64), mInt64(value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Variant::Variant(float value)
|
Variant::Variant(float value) : mType(VTYPE_FLOAT), mFloat(value) {}
|
||||||
:mType(VTYPE_FLOAT), mFloat(value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Variant::Variant(double value)
|
Variant::Variant(double value) : mType(VTYPE_FLOAT), mFloat((float)value) {}
|
||||||
:mType(VTYPE_FLOAT), mFloat((float)value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Variant::Variant(const std::string& value)
|
Variant::Variant(const std::string& value) : mType(VTYPE_STRING), mString(value) {}
|
||||||
:mType(VTYPE_STRING), mString(value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Variant& Variant::operator=(bool value)
|
Variant& Variant::operator=(bool value)
|
||||||
{
|
{
|
||||||
@@ -122,10 +108,14 @@ Variant Variant::operator + (const Variant& rhs)
|
|||||||
switch (type())
|
switch (type())
|
||||||
{
|
{
|
||||||
case VTYPE_BOOL:
|
case VTYPE_BOOL:
|
||||||
case VTYPE_INT: return asInt() + rhs.asInt();
|
case VTYPE_INT:
|
||||||
case VTYPE_INT64: return asInt64() + rhs.asInt64();
|
return asInt() + rhs.asInt();
|
||||||
case VTYPE_FLOAT: return asFloat() + rhs.asFloat();
|
case VTYPE_INT64:
|
||||||
case VTYPE_STRING: return asStdString() + rhs.asStdString();
|
return asInt64() + rhs.asInt64();
|
||||||
|
case VTYPE_FLOAT:
|
||||||
|
return asFloat() + rhs.asFloat();
|
||||||
|
case VTYPE_STRING:
|
||||||
|
return asStdString() + rhs.asStdString();
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -137,9 +127,12 @@ Variant Variant::operator - (const Variant& rhs)
|
|||||||
{
|
{
|
||||||
case VTYPE_BOOL:
|
case VTYPE_BOOL:
|
||||||
case VTYPE_STRING:
|
case VTYPE_STRING:
|
||||||
case VTYPE_INT: return asInt() - rhs.asInt();
|
case VTYPE_INT:
|
||||||
case VTYPE_INT64: return asInt64() - rhs.asInt64();
|
return asInt() - rhs.asInt();
|
||||||
case VTYPE_FLOAT: return asFloat() - rhs.asFloat();
|
case VTYPE_INT64:
|
||||||
|
return asInt64() - rhs.asInt64();
|
||||||
|
case VTYPE_FLOAT:
|
||||||
|
return asFloat() - rhs.asFloat();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -152,9 +145,12 @@ Variant Variant::operator * (const Variant& rhs)
|
|||||||
{
|
{
|
||||||
case VTYPE_BOOL:
|
case VTYPE_BOOL:
|
||||||
case VTYPE_STRING:
|
case VTYPE_STRING:
|
||||||
case VTYPE_INT: return asInt() * rhs.asInt();
|
case VTYPE_INT:
|
||||||
case VTYPE_INT64: return asInt64() * rhs.asInt64();
|
return asInt() * rhs.asInt();
|
||||||
case VTYPE_FLOAT: return asFloat() * rhs.asFloat();
|
case VTYPE_INT64:
|
||||||
|
return asInt64() * rhs.asInt64();
|
||||||
|
case VTYPE_FLOAT:
|
||||||
|
return asFloat() * rhs.asFloat();
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -166,9 +162,12 @@ Variant Variant::operator / (const Variant& rhs)
|
|||||||
{
|
{
|
||||||
case VTYPE_BOOL:
|
case VTYPE_BOOL:
|
||||||
case VTYPE_STRING:
|
case VTYPE_STRING:
|
||||||
case VTYPE_INT: return asInt() / rhs.asInt();
|
case VTYPE_INT:
|
||||||
case VTYPE_INT64: return asInt64() / rhs.asInt64();
|
return asInt() / rhs.asInt();
|
||||||
case VTYPE_FLOAT: return asFloat() / rhs.asFloat();
|
case VTYPE_INT64:
|
||||||
|
return asInt64() / rhs.asInt64();
|
||||||
|
case VTYPE_FLOAT:
|
||||||
|
return asFloat() / rhs.asFloat();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -179,11 +178,15 @@ bool Variant::operator < (const Variant& rhs) const
|
|||||||
{
|
{
|
||||||
switch (type())
|
switch (type())
|
||||||
{
|
{
|
||||||
case VTYPE_STRING: return asStdString() < rhs.asStdString();
|
case VTYPE_STRING:
|
||||||
|
return asStdString() < rhs.asStdString();
|
||||||
case VTYPE_BOOL:
|
case VTYPE_BOOL:
|
||||||
case VTYPE_INT: return asInt() < rhs.asInt();
|
case VTYPE_INT:
|
||||||
case VTYPE_INT64: return asInt64() < rhs.asInt64();
|
return asInt() < rhs.asInt();
|
||||||
case VTYPE_FLOAT: return asFloat() < rhs.asFloat();
|
case VTYPE_INT64:
|
||||||
|
return asInt64() < rhs.asInt64();
|
||||||
|
case VTYPE_FLOAT:
|
||||||
|
return asFloat() < rhs.asFloat();
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -198,13 +201,21 @@ bool Variant::operator == (const Variant& rhs) const
|
|||||||
{
|
{
|
||||||
switch (type())
|
switch (type())
|
||||||
{
|
{
|
||||||
case VTYPE_STRING: return asStdString() == rhs.asStdString();
|
case VTYPE_STRING:
|
||||||
case VTYPE_BOOL: return asBool() == rhs.asBool();
|
return asStdString() == rhs.asStdString();
|
||||||
case VTYPE_INT: return asInt() == rhs.asInt();
|
case VTYPE_BOOL:
|
||||||
case VTYPE_INT64: return asInt64() == rhs.asInt64();
|
return asBool() == rhs.asBool();
|
||||||
case VTYPE_FLOAT: return asFloat() == rhs.asFloat();
|
case VTYPE_INT:
|
||||||
case VTYPE_POINTER: return asPointer() == rhs.asPointer();
|
return asInt() == rhs.asInt();
|
||||||
case VTYPE_VMAP: assert(0); break;
|
case VTYPE_INT64:
|
||||||
|
return asInt64() == rhs.asInt64();
|
||||||
|
case VTYPE_FLOAT:
|
||||||
|
return asFloat() == rhs.asFloat();
|
||||||
|
case VTYPE_POINTER:
|
||||||
|
return asPointer() == rhs.asPointer();
|
||||||
|
case VTYPE_VMAP:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -345,13 +356,9 @@ VariantType Variant::type() const
|
|||||||
return mType;
|
return mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantMap::VariantMap()
|
VariantMap::VariantMap() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantMap::~VariantMap()
|
VariantMap::~VariantMap() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VariantMap::empty() const
|
bool VariantMap::empty() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ public:
|
|||||||
|
|
||||||
Variant& operator[](int itemId);
|
Variant& operator[](int itemId);
|
||||||
Variant& at(int itemId);
|
Variant& at(int itemId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::map<int, Variant> mData;
|
std::map<int, Variant> mData;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,9 +21,8 @@
|
|||||||
std::string XcapHelper::buildBuddyList(const std::string& listName, const std::vector<std::string>& buddies)
|
std::string XcapHelper::buildBuddyList(const std::string& listName, const std::vector<std::string>& buddies)
|
||||||
{
|
{
|
||||||
std::ostringstream result;
|
std::ostringstream result;
|
||||||
result << XML_HEADER <<
|
result << XML_HEADER << "<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\">" << "<list name=\""
|
||||||
"<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\">" <<
|
<< listName.c_str() << "\">";
|
||||||
"<list name=\"" << listName.c_str() << "\">";
|
|
||||||
|
|
||||||
// to test CT only!
|
// to test CT only!
|
||||||
// result << "<entry uri=\"" << "sip:dbogovych1@10.11.1.25" << "\"/>";
|
// result << "<entry uri=\"" << "sip:dbogovych1@10.11.1.25" << "\"/>";
|
||||||
@@ -40,35 +39,20 @@ std::string XcapHelper::buildBuddyList(const std::string& listName, const std::v
|
|||||||
std::string XcapHelper::buildRules(const std::vector<std::string>& buddies)
|
std::string XcapHelper::buildRules(const std::vector<std::string>& buddies)
|
||||||
{
|
{
|
||||||
std::ostringstream result;
|
std::ostringstream result;
|
||||||
result << XML_HEADER <<
|
result << XML_HEADER << "<ruleset xmlns=\"urn:ietf:params:xml:ns:common-policy\">" << "<rule id=\"presence_allow\">"
|
||||||
"<ruleset xmlns=\"urn:ietf:params:xml:ns:common-policy\">" <<
|
<< "<conditions>";
|
||||||
"<rule id=\"presence_allow\">" <<
|
|
||||||
"<conditions>";
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < buddies.size(); i++)
|
for (unsigned i = 0; i < buddies.size(); i++)
|
||||||
{
|
{
|
||||||
result << "<identity><one id=\"" <<
|
result << "<identity><one id=\"" << normalizeSipUri(buddies[i]).c_str() << "\"/></identity>";
|
||||||
normalizeSipUri(buddies[i]).c_str() << "\"/></identity>";
|
|
||||||
}
|
}
|
||||||
result << "</conditions>" <<
|
result << "</conditions>" << "<actions>" << "<sub-handling xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" << "allow"
|
||||||
"<actions>" <<
|
<< "</sub-handling>" << "</actions>" << "<transformations>"
|
||||||
"<sub-handling xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" <<
|
<< "<provide-devices xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" << "<all-devices/>"
|
||||||
"allow" <<
|
<< "</provide-devices>" << "<provide-persons xmlns=\"urn:ietf:params:xml:ns:pres-rules\">"
|
||||||
"</sub-handling>" <<
|
<< "<all-persons/>" << "</provide-persons>"
|
||||||
"</actions>" <<
|
<< "<provide-services xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" << "<all-services/>"
|
||||||
"<transformations>" <<
|
<< "</provide-services>" << "</transformations>" << "</rule>" << "</ruleset>";
|
||||||
"<provide-devices xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" <<
|
|
||||||
"<all-devices/>" <<
|
|
||||||
"</provide-devices>" <<
|
|
||||||
"<provide-persons xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" <<
|
|
||||||
"<all-persons/>" <<
|
|
||||||
"</provide-persons>" <<
|
|
||||||
"<provide-services xmlns=\"urn:ietf:params:xml:ns:pres-rules\">" <<
|
|
||||||
"<all-services/>" <<
|
|
||||||
"</provide-services>" <<
|
|
||||||
"</transformations>" <<
|
|
||||||
"</rule>" <<
|
|
||||||
"</ruleset>";
|
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,17 +60,17 @@ std::string XcapHelper::buildServices(const std::string& serviceUri, const std::
|
|||||||
{
|
{
|
||||||
std::ostringstream result;
|
std::ostringstream result;
|
||||||
|
|
||||||
result << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl <<
|
result << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl
|
||||||
"<rls-services xmlns=\"urn:ietf:params:xml:ns:rls-services\"" << std::endl <<
|
<< "<rls-services xmlns=\"urn:ietf:params:xml:ns:rls-services\"" << std::endl
|
||||||
"xmlns:rl=\"urn:ietf:params:xml:ns:resource-lists\"" << std::endl <<
|
<< "xmlns:rl=\"urn:ietf:params:xml:ns:resource-lists\"" << std::endl
|
||||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" << std::endl <<
|
<< "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" << std::endl
|
||||||
"<service uri=\"" << normalizeSipUri(serviceUri).c_str() << "\">" << std::endl <<
|
<< "<service uri=\"" << normalizeSipUri(serviceUri).c_str() << "\">" << std::endl
|
||||||
"<resource-list>" << listRef.c_str() << "</resource-list>" << std::endl <<
|
<< "<resource-list>" << listRef.c_str() << "</resource-list>" << std::endl
|
||||||
"<packages>" << std::endl <<
|
<< "<packages>" << std::endl
|
||||||
"<package>presence</package>" << std::endl <<
|
<< "<package>presence</package>" << std::endl
|
||||||
"</packages>" << std::endl <<
|
<< "</packages>" << std::endl
|
||||||
"</service>" << std::endl <<
|
<< "</service>" << std::endl
|
||||||
"</rls-services>";
|
<< "</rls-services>";
|
||||||
|
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,18 +11,14 @@ using namespace MT;
|
|||||||
|
|
||||||
|
|
||||||
// Constant of AMR-NB frame lengths in bytes.
|
// Constant of AMR-NB frame lengths in bytes.
|
||||||
const uint8_t amrnb_framelen[9] =
|
const uint8_t amrnb_framelen[9] = {12, 13, 15, 17, 19, 20, 26, 31, 5};
|
||||||
{12, 13, 15, 17, 19, 20, 26, 31, 5};
|
|
||||||
|
|
||||||
const uint16_t amrnb_framelenbits[9] =
|
const uint16_t amrnb_framelenbits[9] = {95, 103, 118, 134, 148, 159, 204, 244, 39};
|
||||||
{95, 103, 118, 134, 148, 159, 204, 244, 39};
|
|
||||||
|
|
||||||
|
|
||||||
// Constant of AMR-WB frame lengths in bytes.
|
// Constant of AMR-WB frame lengths in bytes.
|
||||||
const uint8_t amrwb_framelen[10] =
|
const uint8_t amrwb_framelen[10] = {17, 23, 32, 37, 40, 46, 50, 58, 60, 5 /* SID packet */};
|
||||||
{17, 23, 32, 37, 40, 46, 50, 58, 60, 5 /* SID packet */};
|
const uint16_t amrwb_framelenbits[10] = {132, 177, 253, 285, 317, 365, 397, 461, 477, 40 /* SID packet */};
|
||||||
const uint16_t amrwb_framelenbits[10] =
|
|
||||||
{132, 177, 253, 285, 317, 365, 397, 461, 477, 40 /* SID packet */};
|
|
||||||
|
|
||||||
// Helper routines
|
// Helper routines
|
||||||
|
|
||||||
@@ -139,8 +135,7 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input, size_t& cngCounter)
|
|||||||
input.mCurrentTimestamp += input.mWideband ? 320 : 160;
|
input.mCurrentTimestamp += input.mWideband ? 320 : 160;
|
||||||
if (FT == SID_FT)
|
if (FT == SID_FT)
|
||||||
cngCounter++;
|
cngCounter++;
|
||||||
}
|
} while (F != 0);
|
||||||
while (F != 0);
|
|
||||||
|
|
||||||
for (size_t frameIndex = 0; frameIndex < result.mFrames.size() && !result.mDiscardPacket; frameIndex++)
|
for (size_t frameIndex = 0; frameIndex < result.mFrames.size() && !result.mDiscardPacket; frameIndex++)
|
||||||
{
|
{
|
||||||
@@ -150,7 +145,8 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input, size_t& cngCounter)
|
|||||||
// 10-13 for AMR-WB, the whole packet SHOULD be discarded. This is to
|
// 10-13 for AMR-WB, the whole packet SHOULD be discarded. This is to
|
||||||
// avoid the loss of data synchronization in the depacketization
|
// avoid the loss of data synchronization in the depacketization
|
||||||
// process, which can result in a huge degradation in speech quality.
|
// process, which can result in a huge degradation in speech quality.
|
||||||
bool discard = input.mWideband ? (f.mFrameType >= 10 && f.mFrameType <= 13) : (f.mFrameType >= 9 && f.mFrameType <= 14);
|
bool discard =
|
||||||
|
input.mWideband ? (f.mFrameType >= 10 && f.mFrameType <= 13) : (f.mFrameType >= 9 && f.mFrameType <= 14);
|
||||||
if (discard)
|
if (discard)
|
||||||
{
|
{
|
||||||
result.mDiscardPacket = true;
|
result.mDiscardPacket = true;
|
||||||
@@ -206,8 +202,9 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input, size_t& cngCounter)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ICELogError(<< "Problem parsing AMR header: octet-aligned is set, available " << int(input.mPayloadLength - byteOffset)
|
ICELogError(<< "Problem parsing AMR header: octet-aligned is set, available "
|
||||||
<< " bytes but requested " << (int)byteLength);
|
<< int(input.mPayloadLength - byteOffset) << " bytes but requested "
|
||||||
|
<< (int)byteLength);
|
||||||
result.mDiscardPacket = true;
|
result.mDiscardPacket = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -233,11 +230,7 @@ static AmrPayload parseAmrPayload(AmrPayloadInfo& input, size_t& cngCounter)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AmrNbCodec::CodecFactory::CodecFactory(const AmrCodecConfig& config)
|
AmrNbCodec::CodecFactory::CodecFactory(const AmrCodecConfig& config) : mConfig(config) {}
|
||||||
:mConfig(config)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* AmrNbCodec::CodecFactory::name()
|
const char* AmrNbCodec::CodecFactory::name()
|
||||||
{
|
{
|
||||||
@@ -255,10 +248,13 @@ int AmrNbCodec::CodecFactory::payloadType()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AmrNbCodec::CodecFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void AmrNbCodec::CodecFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
{}
|
SdpDirection direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int AmrNbCodec::CodecFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int AmrNbCodec::CodecFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -274,8 +270,7 @@ PCodec AmrNbCodec::CodecFactory::create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AmrNbCodec::AmrNbCodec(const AmrCodecConfig& config)
|
AmrNbCodec::AmrNbCodec(const AmrCodecConfig& config) : mConfig(config)
|
||||||
:mConfig(config)
|
|
||||||
{
|
{
|
||||||
// Contexts are created lazily (see ensureEncoder/ensureDecoder) - a codec
|
// Contexts are created lazily (see ensureEncoder/ensureDecoder) - a codec
|
||||||
// resolved only for network-MOS metadata never allocates them.
|
// resolved only for network-MOS metadata never allocates them.
|
||||||
@@ -310,14 +305,12 @@ AmrNbCodec::~AmrNbCodec()
|
|||||||
|
|
||||||
Codec::Info AmrNbCodec::info()
|
Codec::Info AmrNbCodec::info()
|
||||||
{
|
{
|
||||||
return {
|
return {.mName = MT_AMRNB_CODECNAME,
|
||||||
.mName = MT_AMRNB_CODECNAME,
|
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 20 * 16,
|
.mPcmLength = 20 * 16,
|
||||||
.mFrameTime = 20,
|
.mFrameTime = 20,
|
||||||
.mRtpLength = 0
|
.mRtpLength = 0};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult AmrNbCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult AmrNbCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -484,9 +477,7 @@ int AmrNbCodec::getCngCounter() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -------- AMR WB codec
|
// -------- AMR WB codec
|
||||||
AmrWbCodec::CodecFactory::CodecFactory(const AmrCodecConfig& config)
|
AmrWbCodec::CodecFactory::CodecFactory(const AmrCodecConfig& config) : mConfig(config) {}
|
||||||
:mConfig(config)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const char* AmrWbCodec::CodecFactory::name()
|
const char* AmrWbCodec::CodecFactory::name()
|
||||||
{
|
{
|
||||||
@@ -503,10 +494,13 @@ int AmrWbCodec::CodecFactory::payloadType()
|
|||||||
return mConfig.mPayloadType;
|
return mConfig.mPayloadType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmrWbCodec::CodecFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void AmrWbCodec::CodecFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
{}
|
SdpDirection direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int AmrWbCodec::CodecFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int AmrWbCodec::CodecFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -523,8 +517,7 @@ PCodec AmrWbCodec::CodecFactory::create()
|
|||||||
|
|
||||||
AmrWbStatistics MT::GAmrWbStatistics;
|
AmrWbStatistics MT::GAmrWbStatistics;
|
||||||
|
|
||||||
AmrWbCodec::AmrWbCodec(const AmrCodecConfig& config)
|
AmrWbCodec::AmrWbCodec(const AmrCodecConfig& config) : mConfig(config)
|
||||||
:mConfig(config)
|
|
||||||
{
|
{
|
||||||
// Decoder context is created lazily (see ensureDecoder) - a codec resolved
|
// Decoder context is created lazily (see ensureDecoder) - a codec resolved
|
||||||
// only for network-MOS metadata never allocates the AMR-WB decoder state.
|
// only for network-MOS metadata never allocates the AMR-WB decoder state.
|
||||||
@@ -551,14 +544,16 @@ AmrWbCodec::~AmrWbCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Info AmrWbCodec::info() {
|
Codec::Info AmrWbCodec::info()
|
||||||
|
{
|
||||||
return {
|
return {
|
||||||
.mName = MT_AMRWB_CODECNAME,
|
.mName = MT_AMRWB_CODECNAME,
|
||||||
.mSamplerate = 16000,
|
.mSamplerate = 16000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 20 * 16 * 2,
|
.mPcmLength = 20 * 16 * 2,
|
||||||
.mFrameTime = 20,
|
.mFrameTime = 20,
|
||||||
.mRtpLength = 0 /* There is complex structure inside AMR packet which may include multilple frames with various length. */
|
.mRtpLength =
|
||||||
|
0 /* There is complex structure inside AMR packet which may include multilple frames with various length. */
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,9 +704,7 @@ int AmrWbCodec::getCngCounter() const
|
|||||||
|
|
||||||
// ------------- GSM EFR -----------------
|
// ------------- GSM EFR -----------------
|
||||||
|
|
||||||
GsmEfrCodec::GsmEfrFactory::GsmEfrFactory(bool iuup, int ptype)
|
GsmEfrCodec::GsmEfrFactory::GsmEfrFactory(bool iuup, int ptype) : mIuUP(iuup), mPayloadType(ptype) {}
|
||||||
:mIuUP(iuup), mPayloadType(ptype)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const char* GsmEfrCodec::GsmEfrFactory::name()
|
const char* GsmEfrCodec::GsmEfrFactory::name()
|
||||||
{
|
{
|
||||||
@@ -728,10 +721,13 @@ int GsmEfrCodec::GsmEfrFactory::payloadType()
|
|||||||
return mPayloadType;
|
return mPayloadType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GsmEfrCodec::GsmEfrFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void GsmEfrCodec::GsmEfrFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
{}
|
SdpDirection direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int GsmEfrCodec::GsmEfrFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int GsmEfrCodec::GsmEfrFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -746,8 +742,7 @@ PCodec GsmEfrCodec::GsmEfrFactory::create()
|
|||||||
return PCodec(new GsmEfrCodec(mIuUP));
|
return PCodec(new GsmEfrCodec(mIuUP));
|
||||||
}
|
}
|
||||||
|
|
||||||
GsmEfrCodec::GsmEfrCodec(bool iuup)
|
GsmEfrCodec::GsmEfrCodec(bool iuup) : mIuUP(iuup)
|
||||||
:mIuUP(iuup)
|
|
||||||
{
|
{
|
||||||
mEncoderCtx = Encoder_Interface_init(1);
|
mEncoderCtx = Encoder_Interface_init(1);
|
||||||
mDecoderCtx = Decoder_Interface_init();
|
mDecoderCtx = Decoder_Interface_init();
|
||||||
@@ -770,14 +765,12 @@ GsmEfrCodec::~GsmEfrCodec()
|
|||||||
|
|
||||||
Codec::Info GsmEfrCodec::info()
|
Codec::Info GsmEfrCodec::info()
|
||||||
{
|
{
|
||||||
return {
|
return {.mName = MT_GSMEFR_CODECNAME,
|
||||||
.mName = MT_GSMEFR_CODECNAME,
|
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 20 * 16,
|
.mPcmLength = 20 * 16,
|
||||||
.mFrameTime = 20,
|
.mFrameTime = 20,
|
||||||
.mRtpLength = 0
|
.mRtpLength = 0};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult GsmEfrCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult GsmEfrCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -809,8 +802,7 @@ Codec::EncodeResult GsmEfrCodec::encode(std::span<const uint8_t> input, std::spa
|
|||||||
#define GSM_EFR_SAMPLES 160
|
#define GSM_EFR_SAMPLES 160
|
||||||
#define GSM_EFR_FRAME_LEN 31
|
#define GSM_EFR_FRAME_LEN 31
|
||||||
|
|
||||||
static void
|
static void msb_put_bit(uint8_t* buf, int bn, int bit)
|
||||||
msb_put_bit(uint8_t *buf, int bn, int bit)
|
|
||||||
{
|
{
|
||||||
int pos_byte = bn >> 3;
|
int pos_byte = bn >> 3;
|
||||||
int pos_bit = 7 - (bn & 7);
|
int pos_bit = 7 - (bn & 7);
|
||||||
@@ -821,8 +813,7 @@ msb_put_bit(uint8_t *buf, int bn, int bit)
|
|||||||
buf[pos_byte] &= ~(1 << pos_bit);
|
buf[pos_byte] &= ~(1 << pos_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int msb_get_bit(const uint8_t* buf, int bn)
|
||||||
msb_get_bit(const uint8_t *buf, int bn)
|
|
||||||
{
|
{
|
||||||
int pos_byte = bn >> 3;
|
int pos_byte = bn >> 3;
|
||||||
int pos_bit = 7 - (bn & 7);
|
int pos_bit = 7 - (bn & 7);
|
||||||
@@ -831,31 +822,17 @@ msb_get_bit(const uint8_t *buf, int bn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint16_t gsm690_12_2_bitorder[244] = {
|
const uint16_t gsm690_12_2_bitorder[244] = {
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 23, 15, 16, 17, 18, 19, 20, 21,
|
||||||
10, 11, 12, 13, 14, 23, 15, 16, 17, 18,
|
22, 24, 25, 26, 27, 28, 38, 141, 39, 142, 40, 143, 41, 144, 42, 145, 43, 146, 44, 147, 45, 148, 46,
|
||||||
19, 20, 21, 22, 24, 25, 26, 27, 28, 38,
|
149, 47, 97, 150, 200, 48, 98, 151, 201, 49, 99, 152, 202, 86, 136, 189, 239, 87, 137, 190, 240, 88, 138,
|
||||||
141, 39, 142, 40, 143, 41, 144, 42, 145, 43,
|
191, 241, 91, 194, 92, 195, 93, 196, 94, 197, 95, 198, 29, 30, 31, 32, 33, 34, 35, 50, 100, 153, 203,
|
||||||
146, 44, 147, 45, 148, 46, 149, 47, 97, 150,
|
89, 139, 192, 242, 51, 101, 154, 204, 55, 105, 158, 208, 90, 140, 193, 243, 59, 109, 162, 212, 63, 113, 166,
|
||||||
200, 48, 98, 151, 201, 49, 99, 152, 202, 86,
|
216, 67, 117, 170, 220, 36, 37, 54, 53, 52, 58, 57, 56, 62, 61, 60, 66, 65, 64, 70, 69, 68, 104,
|
||||||
136, 189, 239, 87, 137, 190, 240, 88, 138, 191,
|
103, 102, 108, 107, 106, 112, 111, 110, 116, 115, 114, 120, 119, 118, 157, 156, 155, 161, 160, 159, 165, 164, 163,
|
||||||
241, 91, 194, 92, 195, 93, 196, 94, 197, 95,
|
169, 168, 167, 173, 172, 171, 207, 206, 205, 211, 210, 209, 215, 214, 213, 219, 218, 217, 223, 222, 221, 73, 72,
|
||||||
198, 29, 30, 31, 32, 33, 34, 35, 50, 100,
|
71, 76, 75, 74, 79, 78, 77, 82, 81, 80, 85, 84, 83, 123, 122, 121, 126, 125, 124, 129, 128, 127, 132,
|
||||||
153, 203, 89, 139, 192, 242, 51, 101, 154, 204,
|
131, 130, 135, 134, 133, 176, 175, 174, 179, 178, 177, 182, 181, 180, 185, 184, 183, 188, 187, 186, 226, 225, 224,
|
||||||
55, 105, 158, 208, 90, 140, 193, 243, 59, 109,
|
229, 228, 227, 232, 231, 230, 235, 234, 233, 238, 237, 236, 96, 199,
|
||||||
162, 212, 63, 113, 166, 216, 67, 117, 170, 220,
|
|
||||||
36, 37, 54, 53, 52, 58, 57, 56, 62, 61,
|
|
||||||
60, 66, 65, 64, 70, 69, 68, 104, 103, 102,
|
|
||||||
108, 107, 106, 112, 111, 110, 116, 115, 114, 120,
|
|
||||||
119, 118, 157, 156, 155, 161, 160, 159, 165, 164,
|
|
||||||
163, 169, 168, 167, 173, 172, 171, 207, 206, 205,
|
|
||||||
211, 210, 209, 215, 214, 213, 219, 218, 217, 223,
|
|
||||||
222, 221, 73, 72, 71, 76, 75, 74, 79, 78,
|
|
||||||
77, 82, 81, 80, 85, 84, 83, 123, 122, 121,
|
|
||||||
126, 125, 124, 129, 128, 127, 132, 131, 130, 135,
|
|
||||||
134, 133, 176, 175, 174, 179, 178, 177, 182, 181,
|
|
||||||
180, 185, 184, 183, 188, 187, 186, 226, 225, 224,
|
|
||||||
229, 228, 227, 232, 231, 230, 235, 234, 233, 238,
|
|
||||||
237, 236, 96, 199,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Codec::DecodeResult GsmEfrCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::DecodeResult GsmEfrCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ protected:
|
|||||||
// this is ~a decoder state (several KB) saved per network-only stream.
|
// this is ~a decoder state (several KB) saved per network-only stream.
|
||||||
void ensureEncoder();
|
void ensureEncoder();
|
||||||
void ensureDecoder();
|
void ensureDecoder();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class CodecFactory : public Factory
|
class CodecFactory : public Factory
|
||||||
{
|
{
|
||||||
@@ -51,7 +52,8 @@ public:
|
|||||||
int payloadType() override;
|
int payloadType() override;
|
||||||
|
|
||||||
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction) override;
|
||||||
void create(CodecMap& codecs) override;
|
void create(CodecMap& codecs) override;
|
||||||
|
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
@@ -110,7 +112,8 @@ public:
|
|||||||
int payloadType() override;
|
int payloadType() override;
|
||||||
|
|
||||||
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction) override;
|
||||||
void create(CodecMap& codecs) override;
|
void create(CodecMap& codecs) override;
|
||||||
|
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
@@ -149,10 +152,12 @@ public:
|
|||||||
int payloadType() override;
|
int payloadType() override;
|
||||||
|
|
||||||
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction) override;
|
||||||
void create(CodecMap& codecs) override;
|
void create(CodecMap& codecs) override;
|
||||||
|
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool mIuUP;
|
bool mIuUP;
|
||||||
int mPayloadType;
|
int mPayloadType;
|
||||||
@@ -168,8 +173,7 @@ public:
|
|||||||
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of MT namespace
|
} // namespace MT
|
||||||
|
|
||||||
|
|
||||||
#endif // MT_AMRCODEC_H
|
#endif // MT_AMRCODEC_H
|
||||||
|
|
||||||
|
|||||||
+119
-120
@@ -57,10 +57,13 @@ int G729Codec::G729Factory::payloadType()
|
|||||||
return 18;
|
return 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G729Codec::G729Factory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void G729Codec::G729Factory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
{}
|
SdpDirection direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int G729Codec::G729Factory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int G729Codec::G729Factory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -70,10 +73,7 @@ PCodec G729Codec::G729Factory::create()
|
|||||||
return std::make_shared<G729Codec>();
|
return std::make_shared<G729Codec>();
|
||||||
}
|
}
|
||||||
|
|
||||||
G729Codec::G729Codec()
|
G729Codec::G729Codec() : mEncoder(nullptr), mDecoder(nullptr) {}
|
||||||
:mEncoder(nullptr), mDecoder(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
G729Codec::~G729Codec()
|
G729Codec::~G729Codec()
|
||||||
{
|
{
|
||||||
@@ -92,14 +92,12 @@ G729Codec::~G729Codec()
|
|||||||
|
|
||||||
Codec::Info G729Codec::info()
|
Codec::Info G729Codec::info()
|
||||||
{
|
{
|
||||||
return {
|
return {.mName = "G729",
|
||||||
.mName = "G729",
|
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 10 * 8 * 2,
|
.mPcmLength = 10 * 8 * 2,
|
||||||
.mFrameTime = 10,
|
.mFrameTime = 10,
|
||||||
.mRtpLength = 10
|
.mRtpLength = 10};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static const int SamplesPerFrame = 80;
|
// static const int SamplesPerFrame = 80;
|
||||||
@@ -119,7 +117,8 @@ Codec::EncodeResult G729Codec::encode(std::span<const uint8_t> input, std::span<
|
|||||||
Word16 parm[PRM_SIZE]; // ITU's service buffer
|
Word16 parm[PRM_SIZE]; // ITU's service buffer
|
||||||
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
||||||
{
|
{
|
||||||
Copy((int16_t*)input.data() + frameIndex * info().mPcmLength / 2, mEncoder->new_speech, info().mPcmLength / 2);
|
Copy((int16_t*)input.data() + frameIndex * info().mPcmLength / 2, mEncoder->new_speech,
|
||||||
|
info().mPcmLength / 2);
|
||||||
Pre_Process(mEncoder, mEncoder->new_speech, info().mPcmLength / 2);
|
Pre_Process(mEncoder, mEncoder->new_speech, info().mPcmLength / 2);
|
||||||
Coder_ld8a(mEncoder, parm);
|
Coder_ld8a(mEncoder, parm);
|
||||||
Store_Params(parm, output.data() + frameIndex * info().mRtpLength);
|
Store_Params(parm, output.data() + frameIndex * info().mRtpLength);
|
||||||
@@ -152,7 +151,8 @@ Codec::DecodeResult G729Codec::decode(std::span<const uint8_t> input, std::span<
|
|||||||
nrOfFrames = std::min(output.size_bytes() / info().mPcmLength, (size_t)nrOfFrames);
|
nrOfFrames = std::min(output.size_bytes() / info().mPcmLength, (size_t)nrOfFrames);
|
||||||
|
|
||||||
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
for (int frameIndex = 0; frameIndex < nrOfFrames; frameIndex++)
|
||||||
decodeFrame(input.data() + frameIndex * info().mRtpLength, (int16_t*)output.data() + frameIndex * info().mPcmLength);
|
decodeFrame(input.data() + frameIndex * info().mRtpLength,
|
||||||
|
(int16_t*)output.data() + frameIndex * info().mPcmLength);
|
||||||
|
|
||||||
result += nrOfFrames * info().mPcmLength;
|
result += nrOfFrames * info().mPcmLength;
|
||||||
|
|
||||||
@@ -194,7 +194,6 @@ void G729Codec::decodeFrame(const uint8_t* rtp, int16_t* pcm)
|
|||||||
|
|
||||||
for (i = 0; i < pcmLength() / 2; i++)
|
for (i = 0; i < pcmLength() / 2; i++)
|
||||||
pcm[i] = synth[i];
|
pcm[i] = synth[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -210,8 +209,7 @@ size_t G729Codec::plc(int lostFrames, std::span<uint8_t> output)
|
|||||||
#define OPUS_PACKET_LOSS 10
|
#define OPUS_PACKET_LOSS 10
|
||||||
#define OPUS_CODEC_COMPLEXITY 2
|
#define OPUS_CODEC_COMPLEXITY 2
|
||||||
|
|
||||||
OpusCodec::Params::Params()
|
OpusCodec::Params::Params() : mUseDtx(false), mUseInbandFec(true), mStereo(true), mPtime(20)
|
||||||
:mUseDtx(false), mUseInbandFec(true), mStereo(true), mPtime(20)
|
|
||||||
{
|
{
|
||||||
mExpectedPacketLoss = OPUS_PACKET_LOSS;
|
mExpectedPacketLoss = OPUS_PACKET_LOSS;
|
||||||
mTargetBitrate = OPUS_TARGET_BITRATE;
|
mTargetBitrate = OPUS_TARGET_BITRATE;
|
||||||
@@ -288,14 +286,11 @@ void OpusCodec::Params::parse(const resip::Data ¶ms)
|
|||||||
{
|
{
|
||||||
if (paramIter->mName == "usedtx")
|
if (paramIter->mName == "usedtx")
|
||||||
mUseDtx = paramIter->mValue == "1";
|
mUseDtx = paramIter->mValue == "1";
|
||||||
else
|
else if (paramIter->mName == "useinbandfec")
|
||||||
if (paramIter->mName == "useinbandfec")
|
|
||||||
mUseInbandFec = paramIter->mValue == "1";
|
mUseInbandFec = paramIter->mValue == "1";
|
||||||
else
|
else if (paramIter->mName == "stereo")
|
||||||
if (paramIter->mName == "stereo")
|
|
||||||
mStereo = paramIter->mValue == "1";
|
mStereo = paramIter->mValue == "1";
|
||||||
else
|
else if (paramIter->mName == "ptime")
|
||||||
if (paramIter->mName == "ptime")
|
|
||||||
mPtime = strx::toInt(paramIter->mValue.c_str(), 20);
|
mPtime = strx::toInt(paramIter->mValue.c_str(), 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,7 +322,8 @@ int OpusCodec::OpusFactory::payloadType()
|
|||||||
return mPType;
|
return mPType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpusCodec::OpusFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void OpusCodec::OpusFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
// Put opus codec record
|
// Put opus codec record
|
||||||
resip::Codec opus(name(), payloadType(), samplerate());
|
resip::Codec opus(name(), payloadType(), samplerate());
|
||||||
@@ -342,7 +338,8 @@ void OpusCodec::OpusFactory::updateSdp(resip::SdpContents::Session::Medium::Code
|
|||||||
#define stricmp strcasecmp
|
#define stricmp strcasecmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int OpusCodec::OpusFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int OpusCodec::OpusFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
resip::SdpContents::Session::Medium::CodecContainer::const_iterator codecIter;
|
resip::SdpContents::Session::Medium::CodecContainer::const_iterator codecIter;
|
||||||
for (codecIter = codecs.begin(); codecIter != codecs.end(); ++codecIter)
|
for (codecIter = codecs.begin(); codecIter != codecs.end(); ++codecIter)
|
||||||
@@ -357,7 +354,8 @@ int OpusCodec::OpusFactory::processSdp(const resip::SdpContents::Session::Medium
|
|||||||
mParams.mStereo |= codecIter->encodingParameters() == "2";
|
mParams.mStereo |= codecIter->encodingParameters() == "2";
|
||||||
|
|
||||||
// Here changes must be applied to instantiated codec
|
// Here changes must be applied to instantiated codec
|
||||||
for (CodecList::iterator instanceIter = mCodecList.begin(); instanceIter != mCodecList.end(); ++instanceIter)
|
for (CodecList::iterator instanceIter = mCodecList.begin(); instanceIter != mCodecList.end();
|
||||||
|
++instanceIter)
|
||||||
{
|
{
|
||||||
Codec& c = **instanceIter;
|
Codec& c = **instanceIter;
|
||||||
if ((c.channels() == (mParams.mStereo ? 2 : 1)) && resipCodec.getRate() == c.samplerate())
|
if ((c.channels() == (mParams.mStereo ? 2 : 1)) && resipCodec.getRate() == c.samplerate())
|
||||||
@@ -380,7 +378,8 @@ PCodec OpusCodec::OpusFactory::create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
OpusCodec::OpusCodec(Audio::Format fmt, int ptime)
|
OpusCodec::OpusCodec(Audio::Format fmt, int ptime)
|
||||||
:mEncoderCtx(nullptr), mDecoderCtx(nullptr), mChannels(fmt.channels()), mPTime(ptime), mSamplerate(fmt.rate()), mDecoderChannels(0)
|
: mEncoderCtx(nullptr), mDecoderCtx(nullptr), mChannels(fmt.channels()), mPTime(ptime), mSamplerate(fmt.rate()),
|
||||||
|
mDecoderChannels(0)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
mEncoderCtx = opus_encoder_create(mSamplerate, mChannels, OPUS_APPLICATION_VOIP, &status);
|
mEncoderCtx = opus_encoder_create(mSamplerate, mChannels, OPUS_APPLICATION_VOIP, &status);
|
||||||
@@ -398,7 +397,8 @@ void OpusCodec::applyParams(const Params ¶ms)
|
|||||||
if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_INBAND_FEC(params.mUseInbandFec ? 1 : 0))))
|
if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_INBAND_FEC(params.mUseInbandFec ? 1 : 0))))
|
||||||
ICELogError(<< "Failed to (un)set FEC mode in Opus encoder. Error " << opus_strerror(error));
|
ICELogError(<< "Failed to (un)set FEC mode in Opus encoder. Error " << opus_strerror(error));
|
||||||
|
|
||||||
if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_BITRATE(params.mTargetBitrate ? params.mTargetBitrate : OPUS_AUTO))))
|
if (OPUS_OK != (error = opus_encoder_ctl(
|
||||||
|
mEncoderCtx, OPUS_SET_BITRATE(params.mTargetBitrate ? params.mTargetBitrate : OPUS_AUTO))))
|
||||||
ICELogError(<< "Failed to (un)set target bandwidth. Error " << opus_strerror(error));
|
ICELogError(<< "Failed to (un)set target bandwidth. Error " << opus_strerror(error));
|
||||||
|
|
||||||
if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_PACKET_LOSS_PERC(params.mExpectedPacketLoss))))
|
if (OPUS_OK != (error = opus_encoder_ctl(mEncoderCtx, OPUS_SET_PACKET_LOSS_PERC(params.mExpectedPacketLoss))))
|
||||||
@@ -422,7 +422,8 @@ OpusCodec::~OpusCodec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Info OpusCodec::info() {
|
Codec::Info OpusCodec::info()
|
||||||
|
{
|
||||||
return {
|
return {
|
||||||
.mName = OPUS_CODEC_NAME,
|
.mName = OPUS_CODEC_NAME,
|
||||||
.mSamplerate = mSamplerate,
|
.mSamplerate = mSamplerate,
|
||||||
@@ -437,8 +438,8 @@ Codec::EncodeResult OpusCodec::encode(std::span<const uint8_t> input, std::span<
|
|||||||
{
|
{
|
||||||
// opus_encode() takes the frame size in samples per channel and the output
|
// opus_encode() takes the frame size in samples per channel and the output
|
||||||
// capacity in bytes.
|
// capacity in bytes.
|
||||||
int written = opus_encode(mEncoderCtx, (const opus_int16*)input.data(), input.size_bytes() / (sizeof(short) * channels()),
|
int written = opus_encode(mEncoderCtx, (const opus_int16*)input.data(),
|
||||||
output.data(), output.size_bytes());
|
input.size_bytes() / (sizeof(short) * channels()), output.data(), output.size_bytes());
|
||||||
if (written < 0)
|
if (written < 0)
|
||||||
return {.mEncoded = 0};
|
return {.mEncoded = 0};
|
||||||
else
|
else
|
||||||
@@ -485,8 +486,8 @@ Codec::DecodeResult OpusCodec::decode(std::span<const uint8_t> input, std::span<
|
|||||||
|
|
||||||
if (nr_of_channels == channels())
|
if (nr_of_channels == channels())
|
||||||
{
|
{
|
||||||
int decoded = opus_decode(mDecoderCtx, input.data(), input.size_bytes(),
|
int decoded =
|
||||||
(opus_int16*)output.data(), nr_of_frames, 0);
|
opus_decode(mDecoderCtx, input.data(), input.size_bytes(), (opus_int16*)output.data(), nr_of_frames, 0);
|
||||||
if (decoded < 0)
|
if (decoded < 0)
|
||||||
{
|
{
|
||||||
ICELogCritical(<< "opus_decode() returned " << decoded);
|
ICELogCritical(<< "opus_decode() returned " << decoded);
|
||||||
@@ -498,8 +499,7 @@ Codec::DecodeResult OpusCodec::decode(std::span<const uint8_t> input, std::span<
|
|||||||
// Channel count differs from the negotiated one - decode to a temporary
|
// Channel count differs from the negotiated one - decode to a temporary
|
||||||
// buffer and convert.
|
// buffer and convert.
|
||||||
std::vector<opus_int16> temp((size_t)nr_of_frames * nr_of_channels);
|
std::vector<opus_int16> temp((size_t)nr_of_frames * nr_of_channels);
|
||||||
int decoded = opus_decode(mDecoderCtx, input.data(), input.size_bytes(),
|
int decoded = opus_decode(mDecoderCtx, input.data(), input.size_bytes(), temp.data(), nr_of_frames, 0);
|
||||||
temp.data(), nr_of_frames, 0);
|
|
||||||
if (decoded < 0)
|
if (decoded < 0)
|
||||||
{
|
{
|
||||||
ICELogCritical(<< "opus_decode() returned " << decoded);
|
ICELogCritical(<< "opus_decode() returned " << decoded);
|
||||||
@@ -598,8 +598,8 @@ size_t OpusCodec::fec(std::span<const uint8_t> nextPacket, std::span<uint8_t> ou
|
|||||||
// decode_fec = 1: pull the redundant copy of the previous frame. If nextPacket
|
// decode_fec = 1: pull the redundant copy of the previous frame. If nextPacket
|
||||||
// carries no LBRR for it, Opus falls back to its own concealment internally,
|
// carries no LBRR for it, Opus falls back to its own concealment internally,
|
||||||
// so the result is never worse than plc().
|
// so the result is never worse than plc().
|
||||||
int decoded = opus_decode(mDecoderCtx, nextPacket.data(), nextPacket.size_bytes(),
|
int decoded = opus_decode(mDecoderCtx, nextPacket.data(), nextPacket.size_bytes(), (opus_int16*)output.data(),
|
||||||
(opus_int16*)output.data(), samples_per_channel, 1);
|
samples_per_channel, 1);
|
||||||
if (decoded <= 0)
|
if (decoded <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -615,8 +615,7 @@ size_t OpusCodec::getNumberOfSamples(std::span<const uint8_t> payload)
|
|||||||
// -------------- ILBC -------------------
|
// -------------- ILBC -------------------
|
||||||
#define ILBC_CODEC_NAME "ILBC"
|
#define ILBC_CODEC_NAME "ILBC"
|
||||||
|
|
||||||
IlbcCodec::IlbcCodec(int packetTime)
|
IlbcCodec::IlbcCodec(int packetTime) : mPacketTime(packetTime)
|
||||||
:mPacketTime(packetTime)
|
|
||||||
{
|
{
|
||||||
WebRtcIlbcfix_EncoderCreate(&mEncoderCtx);
|
WebRtcIlbcfix_EncoderCreate(&mEncoderCtx);
|
||||||
WebRtcIlbcfix_DecoderCreate(&mDecoderCtx);
|
WebRtcIlbcfix_DecoderCreate(&mDecoderCtx);
|
||||||
@@ -632,14 +631,12 @@ IlbcCodec::~IlbcCodec()
|
|||||||
|
|
||||||
Codec::Info IlbcCodec::info()
|
Codec::Info IlbcCodec::info()
|
||||||
{
|
{
|
||||||
return {
|
return {.mName = ILBC_CODEC_NAME,
|
||||||
.mName = ILBC_CODEC_NAME,
|
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = mPacketTime * 8 * (int)sizeof(short),
|
.mPcmLength = mPacketTime * 8 * (int)sizeof(short),
|
||||||
.mFrameTime = mPacketTime,
|
.mFrameTime = mPacketTime,
|
||||||
.mRtpLength = (mPacketTime == 20) ? 38 : 50
|
.mRtpLength = (mPacketTime == 20) ? 38 : 50};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult IlbcCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult IlbcCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -723,7 +720,8 @@ void IlbcCodec::IlbcFactory::create(CodecMap& codecs)
|
|||||||
codecs[mPType30ms] = PCodec(create());
|
codecs[mPType30ms] = PCodec(create());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IlbcCodec::IlbcFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
void IlbcCodec::IlbcFactory::updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
if (mPtime == 20 || direction == Sdp_Offer)
|
if (mPtime == 20 || direction == Sdp_Offer)
|
||||||
{
|
{
|
||||||
@@ -739,7 +737,8 @@ void IlbcCodec::IlbcFactory::updateSdp(resip::SdpContents::Session::Medium::Code
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IlbcCodec::IlbcFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction)
|
int IlbcCodec::IlbcFactory::processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction)
|
||||||
{
|
{
|
||||||
resip::SdpContents::Session::Medium::CodecContainer::const_iterator codecIter;
|
resip::SdpContents::Session::Medium::CodecContainer::const_iterator codecIter;
|
||||||
int pt = -1, ptime = 0;
|
int pt = -1, ptime = 0;
|
||||||
@@ -753,8 +752,7 @@ int IlbcCodec::IlbcFactory::processSdp(const resip::SdpContents::Session::Medium
|
|||||||
{
|
{
|
||||||
if (strstr(p.c_str(), "mode=") == p.c_str())
|
if (strstr(p.c_str(), "mode=") == p.c_str())
|
||||||
sscanf(p.c_str(), "mode=%d", &codecPtime);
|
sscanf(p.c_str(), "mode=%d", &codecPtime);
|
||||||
else
|
else if (strstr(p.c_str(), "ptime="))
|
||||||
if (strstr(p.c_str(), "ptime="))
|
|
||||||
sscanf(p.c_str(), "ptime=%d", &codecPtime);
|
sscanf(p.c_str(), "ptime=%d", &codecPtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,8 +761,7 @@ int IlbcCodec::IlbcFactory::processSdp(const resip::SdpContents::Session::Medium
|
|||||||
pt = codecIter->payloadType();
|
pt = codecIter->payloadType();
|
||||||
ptime = codecPtime;
|
ptime = codecPtime;
|
||||||
}
|
}
|
||||||
else
|
else if (!codecPtime)
|
||||||
if (!codecPtime)
|
|
||||||
{
|
{
|
||||||
// Suppose it is 30ms ilbc
|
// Suppose it is 30ms ilbc
|
||||||
pt = codecIter->payloadType();
|
pt = codecIter->payloadType();
|
||||||
@@ -781,8 +778,7 @@ int IlbcCodec::IlbcFactory::processSdp(const resip::SdpContents::Session::Medium
|
|||||||
// --- IsacCodec(s) ---
|
// --- IsacCodec(s) ---
|
||||||
#define ISAC_CODEC_NAME "ISAC"
|
#define ISAC_CODEC_NAME "ISAC"
|
||||||
|
|
||||||
IsacCodec::IsacCodec(int samplerate)
|
IsacCodec::IsacCodec(int samplerate) : mSamplerate(samplerate)
|
||||||
:mSamplerate(samplerate)
|
|
||||||
{
|
{
|
||||||
// This code initializes isac encoder to automatic mode - it will adjust its bitrate automatically.
|
// This code initializes isac encoder to automatic mode - it will adjust its bitrate automatically.
|
||||||
// Frame time is 60 ms
|
// Frame time is 60 ms
|
||||||
@@ -798,19 +794,20 @@ IsacCodec::IsacCodec(int samplerate)
|
|||||||
|
|
||||||
IsacCodec::~IsacCodec()
|
IsacCodec::~IsacCodec()
|
||||||
{
|
{
|
||||||
WebRtcIsacfix_Free(mEncoderCtx); mEncoderCtx = NULL;
|
WebRtcIsacfix_Free(mEncoderCtx);
|
||||||
WebRtcIsacfix_Free(mDecoderCtx); mDecoderCtx = NULL;
|
mEncoderCtx = NULL;
|
||||||
|
WebRtcIsacfix_Free(mDecoderCtx);
|
||||||
|
mDecoderCtx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Info IsacCodec::info() {
|
Codec::Info IsacCodec::info()
|
||||||
return {
|
{
|
||||||
.mName = "isac",
|
return {.mName = "isac",
|
||||||
.mSamplerate = mSamplerate,
|
.mSamplerate = mSamplerate,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 60 * mSamplerate / 1000 * 2,
|
.mPcmLength = 60 * mSamplerate / 1000 * 2,
|
||||||
.mFrameTime = 60,
|
.mFrameTime = 60,
|
||||||
.mRtpLength = 0
|
.mRtpLength = 0};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult IsacCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult IsacCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -834,7 +831,8 @@ Codec::EncodeResult IsacCodec::encode(std::span<const uint8_t> input, std::span<
|
|||||||
Codec::DecodeResult IsacCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::DecodeResult IsacCodec::decode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
WebRtc_Word16 speechType = 0;
|
WebRtc_Word16 speechType = 0;
|
||||||
unsigned produced = WebRtcIsacfix_Decode(mDecoderCtx, (const WebRtc_UWord16*)input.data(), input.size_bytes(), (WebRtc_Word16*)output.data(), &speechType);
|
unsigned produced = WebRtcIsacfix_Decode(mDecoderCtx, (const WebRtc_UWord16*)input.data(), input.size_bytes(),
|
||||||
|
(WebRtc_Word16*)output.data(), &speechType);
|
||||||
if (produced == (unsigned)-1)
|
if (produced == (unsigned)-1)
|
||||||
return {.mDecoded = 0};
|
return {.mDecoded = 0};
|
||||||
|
|
||||||
@@ -853,9 +851,7 @@ size_t IsacCodec::plc(int lostFrames, std::span<uint8_t> output)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- IsacFactory16K ---
|
// --- IsacFactory16K ---
|
||||||
IsacCodec::IsacFactory16K::IsacFactory16K(int ptype)
|
IsacCodec::IsacFactory16K::IsacFactory16K(int ptype) : mPType(ptype) {}
|
||||||
:mPType(ptype)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const char* IsacCodec::IsacFactory16K::name()
|
const char* IsacCodec::IsacFactory16K::name()
|
||||||
{
|
{
|
||||||
@@ -878,9 +874,7 @@ PCodec IsacCodec::IsacFactory16K::create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- IsacFactory32K ---
|
// --- IsacFactory32K ---
|
||||||
IsacCodec::IsacFactory32K::IsacFactory32K(int ptype)
|
IsacCodec::IsacFactory32K::IsacFactory32K(int ptype) : mPType(ptype) {}
|
||||||
:mPType(ptype)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
const char* IsacCodec::IsacFactory32K::name()
|
const char* IsacCodec::IsacFactory32K::name()
|
||||||
@@ -907,31 +901,29 @@ PCodec IsacCodec::IsacFactory32K::create()
|
|||||||
#define ULAW_CODEC_NAME "PCMU"
|
#define ULAW_CODEC_NAME "PCMU"
|
||||||
#define ALAW_CODEC_NAME "PCMA"
|
#define ALAW_CODEC_NAME "PCMA"
|
||||||
|
|
||||||
G711Codec::G711Codec(int type)
|
G711Codec::G711Codec(int type) : mType(type) {}
|
||||||
:mType(type)
|
|
||||||
{}
|
|
||||||
|
|
||||||
G711Codec::~G711Codec()
|
G711Codec::~G711Codec() {}
|
||||||
{}
|
|
||||||
|
|
||||||
Codec::Info G711Codec::info() {
|
Codec::Info G711Codec::info()
|
||||||
return {
|
{
|
||||||
.mName = mType == ALaw ? "PCMA" : "PCMU",
|
return {.mName = mType == ALaw ? "PCMA" : "PCMU",
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 10 * 16,
|
.mPcmLength = 10 * 16,
|
||||||
.mFrameTime = 10,
|
.mFrameTime = 10,
|
||||||
.mRtpLength = 10 * 8
|
.mRtpLength = 10 * 8};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult G711Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult G711Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
if (mType == ALaw)
|
if (mType == ALaw)
|
||||||
result = WebRtcG711_EncodeA(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes() / 2, (WebRtc_Word16*)output.data());
|
result = WebRtcG711_EncodeA(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes() / 2,
|
||||||
|
(WebRtc_Word16*)output.data());
|
||||||
else
|
else
|
||||||
result = WebRtcG711_EncodeU(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes() / 2, (WebRtc_Word16*)output.data());
|
result = WebRtcG711_EncodeU(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes() / 2,
|
||||||
|
(WebRtc_Word16*)output.data());
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return {.mEncoded = 0};
|
return {.mEncoded = 0};
|
||||||
@@ -947,9 +939,11 @@ Codec::DecodeResult G711Codec::decode(std::span<const uint8_t> input, std::span<
|
|||||||
WebRtc_Word16 speechType;
|
WebRtc_Word16 speechType;
|
||||||
|
|
||||||
if (mType == ALaw)
|
if (mType == ALaw)
|
||||||
result = WebRtcG711_DecodeA(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes(), (WebRtc_Word16*)output.data(), &speechType);
|
result = WebRtcG711_DecodeA(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes(),
|
||||||
|
(WebRtc_Word16*)output.data(), &speechType);
|
||||||
else
|
else
|
||||||
result = WebRtcG711_DecodeU(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes(), (WebRtc_Word16*)output.data(), &speechType);
|
result = WebRtcG711_DecodeU(nullptr, (WebRtc_Word16*)input.data(), input.size_bytes(),
|
||||||
|
(WebRtc_Word16*)output.data(), &speechType);
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return {.mDecoded = 0};
|
return {.mDecoded = 0};
|
||||||
@@ -1000,9 +994,7 @@ PCodec G711Codec::UlawFactory::create()
|
|||||||
|
|
||||||
// ---------- GsmCodec -------------
|
// ---------- GsmCodec -------------
|
||||||
|
|
||||||
GsmCodec::GsmFactory::GsmFactory(Type codecType, int pt)
|
GsmCodec::GsmFactory::GsmFactory(Type codecType, int pt) : mCodecType(codecType), mPayloadType(pt) {}
|
||||||
:mCodecType(codecType), mPayloadType(pt)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const char* GsmCodec::GsmFactory::name()
|
const char* GsmCodec::GsmFactory::name()
|
||||||
{
|
{
|
||||||
@@ -1024,8 +1016,7 @@ PCodec GsmCodec::GsmFactory::create()
|
|||||||
return PCodec(new GsmCodec(mCodecType));
|
return PCodec(new GsmCodec(mCodecType));
|
||||||
}
|
}
|
||||||
|
|
||||||
GsmCodec::GsmCodec(Type codecType)
|
GsmCodec::GsmCodec(Type codecType) : mCodecType(codecType)
|
||||||
:mCodecType(codecType)
|
|
||||||
{
|
{
|
||||||
mGSM = gsm_create();
|
mGSM = gsm_create();
|
||||||
if (codecType != Type::Bytes_33)
|
if (codecType != Type::Bytes_33)
|
||||||
@@ -1037,28 +1028,37 @@ GsmCodec::GsmCodec(Type codecType)
|
|||||||
|
|
||||||
GsmCodec::~GsmCodec()
|
GsmCodec::~GsmCodec()
|
||||||
{
|
{
|
||||||
gsm_destroy(mGSM); mGSM = nullptr;
|
gsm_destroy(mGSM);
|
||||||
|
mGSM = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Info GsmCodec::info() {
|
Codec::Info GsmCodec::info()
|
||||||
|
{
|
||||||
int rtpLength = 0;
|
int rtpLength = 0;
|
||||||
switch (mCodecType)
|
switch (mCodecType)
|
||||||
{
|
{
|
||||||
case Type::Bytes_31: rtpLength = GSM_RTPFRAME_SIZE_31; break;
|
case Type::Bytes_31:
|
||||||
case Type::Bytes_32: rtpLength = GSM_RTPFRAME_SIZE_32; break;
|
rtpLength = GSM_RTPFRAME_SIZE_31;
|
||||||
case Type::Bytes_33: rtpLength = GSM_RTPFRAME_SIZE_33; break;
|
break;
|
||||||
case Type::Bytes_65: rtpLength = GSM_RTPFRAME_SIZE_32 + GSM_RTPFRAME_SIZE_33; break;
|
case Type::Bytes_32:
|
||||||
default: rtpLength = GSM_RTPFRAME_SIZE_33;
|
rtpLength = GSM_RTPFRAME_SIZE_32;
|
||||||
|
break;
|
||||||
|
case Type::Bytes_33:
|
||||||
|
rtpLength = GSM_RTPFRAME_SIZE_33;
|
||||||
|
break;
|
||||||
|
case Type::Bytes_65:
|
||||||
|
rtpLength = GSM_RTPFRAME_SIZE_32 + GSM_RTPFRAME_SIZE_33;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rtpLength = GSM_RTPFRAME_SIZE_33;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {.mName = "GSM-06.10",
|
||||||
.mName = "GSM-06.10",
|
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = GSM_AUDIOFRAME_TIME * 16,
|
.mPcmLength = GSM_AUDIOFRAME_TIME * 16,
|
||||||
.mFrameTime = GSM_AUDIOFRAME_TIME,
|
.mFrameTime = GSM_AUDIOFRAME_TIME,
|
||||||
.mRtpLength = rtpLength
|
.mRtpLength = rtpLength};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult GsmCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult GsmCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -1120,25 +1120,25 @@ G722Codec::G722Codec()
|
|||||||
{
|
{
|
||||||
mEncoder = g722_encode_init(nullptr, 64000, 0);
|
mEncoder = g722_encode_init(nullptr, 64000, 0);
|
||||||
mDecoder = g722_decode_init(nullptr, 64000, 0);
|
mDecoder = g722_decode_init(nullptr, 64000, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G722Codec::~G722Codec()
|
G722Codec::~G722Codec()
|
||||||
{
|
{
|
||||||
g722_decode_release((g722_decode_state_t*)mDecoder); mDecoder = nullptr;
|
g722_decode_release((g722_decode_state_t*)mDecoder);
|
||||||
g722_encode_release((g722_encode_state_t*)mEncoder); mEncoder = nullptr;
|
mDecoder = nullptr;
|
||||||
|
g722_encode_release((g722_encode_state_t*)mEncoder);
|
||||||
|
mEncoder = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Info G722Codec::info() {
|
Codec::Info G722Codec::info()
|
||||||
|
{
|
||||||
// ToDo: double check the G722 calls - remember RFC has bug about samplerate
|
// ToDo: double check the G722 calls - remember RFC has bug about samplerate
|
||||||
return {
|
return {.mName = G722_MIME_NAME,
|
||||||
.mName = G722_MIME_NAME,
|
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 640,
|
.mPcmLength = 640,
|
||||||
.mFrameTime = 20,
|
.mFrameTime = 20,
|
||||||
.mRtpLength = 160
|
.mRtpLength = 160};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult G722Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult G722Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -1146,7 +1146,8 @@ Codec::EncodeResult G722Codec::encode(std::span<const uint8_t> input, std::span<
|
|||||||
if (output.size_bytes() < input.size_bytes() / 4)
|
if (output.size_bytes() < input.size_bytes() / 4)
|
||||||
return {.mEncoded = 0}; // Destination buffer not big enough
|
return {.mEncoded = 0}; // Destination buffer not big enough
|
||||||
|
|
||||||
int r = g722_encode((g722_encode_state_t *)mEncoder, (unsigned char*)output.data(), ( short*)input.data(), input.size_bytes() / 2);
|
int r = g722_encode((g722_encode_state_t*)mEncoder, (unsigned char*)output.data(), (short*)input.data(),
|
||||||
|
input.size_bytes() / 2);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return {.mEncoded = 0};
|
return {.mEncoded = 0};
|
||||||
|
|
||||||
@@ -1158,7 +1159,9 @@ Codec::DecodeResult G722Codec::decode(std::span<const uint8_t> input, std::span<
|
|||||||
if (output.size_bytes() < input.size_bytes() * 4)
|
if (output.size_bytes() < input.size_bytes() * 4)
|
||||||
return {.mDecoded = 0}; // Destination buffer not big enough
|
return {.mDecoded = 0}; // Destination buffer not big enough
|
||||||
|
|
||||||
int r = g722_decode((g722_decode_state_t *)mDecoder, (short*)output.data(), (unsigned char*)input.data(), input.size_bytes()) * 2;
|
int r = g722_decode((g722_decode_state_t*)mDecoder, (short*)output.data(), (unsigned char*)input.data(),
|
||||||
|
input.size_bytes()) *
|
||||||
|
2;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return {.mDecoded = 0};
|
return {.mDecoded = 0};
|
||||||
return {.mDecoded = (size_t)r};
|
return {.mDecoded = (size_t)r};
|
||||||
@@ -1174,8 +1177,7 @@ size_t G722Codec::plc(int lostFrames, std::span<uint8_t> output)
|
|||||||
return lostFrames * pcmLength();
|
return lostFrames * pcmLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
G722Codec::G722Factory::G722Factory()
|
G722Codec::G722Factory::G722Factory() {}
|
||||||
{}
|
|
||||||
|
|
||||||
const char* G722Codec::G722Factory::name()
|
const char* G722Codec::G722Factory::name()
|
||||||
{
|
{
|
||||||
@@ -1267,8 +1269,10 @@ static bool repackHalfRate(BitReader& br, uint16_t frame[22], bool& lastItem)
|
|||||||
frame[17] = br.readBits(5); // GSP0_4;
|
frame[17] = br.readBits(5); // GSP0_4;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame[18] = 0; frame[19] = 0;
|
frame[18] = 0;
|
||||||
frame[20] = 0; frame[21] = 0;
|
frame[19] = 0;
|
||||||
|
frame[20] = 0;
|
||||||
|
frame[21] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GSMHR_NODATA:
|
case GSMHR_NODATA:
|
||||||
@@ -1292,15 +1296,14 @@ GsmHrCodec::~GsmHrCodec()
|
|||||||
mDecoder = nullptr;
|
mDecoder = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Info GsmHrCodec::info() {
|
Codec::Info GsmHrCodec::info()
|
||||||
return {
|
{
|
||||||
.mName = "GSM-HR-08",
|
return {.mName = "GSM-HR-08",
|
||||||
.mSamplerate = 8000,
|
.mSamplerate = 8000,
|
||||||
.mChannels = 1,
|
.mChannels = 1,
|
||||||
.mPcmLength = 20 * 8 * 2,
|
.mPcmLength = 20 * 8 * 2,
|
||||||
.mFrameTime = 20,
|
.mFrameTime = 20,
|
||||||
.mRtpLength = 0
|
.mRtpLength = 0};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::EncodeResult GsmHrCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
Codec::EncodeResult GsmHrCodec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||||
@@ -1351,8 +1354,7 @@ static const int params_voiced[] = {
|
|||||||
5, /* gsp0_4 */
|
5, /* gsp0_4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int msb_get_bit(const uint8_t* buf, int bn)
|
||||||
msb_get_bit(const uint8_t *buf, int bn)
|
|
||||||
{
|
{
|
||||||
int pos_byte = bn >> 3;
|
int pos_byte = bn >> 3;
|
||||||
int pos_bit = 7 - (bn & 7);
|
int pos_bit = 7 - (bn & 7);
|
||||||
@@ -1360,8 +1362,7 @@ msb_get_bit(const uint8_t *buf, int bn)
|
|||||||
return (buf[pos_byte] >> pos_bit) & 1;
|
return (buf[pos_byte] >> pos_bit) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int hr_ref_from_canon(uint16_t* hr_ref, const uint8_t* canon)
|
||||||
hr_ref_from_canon(uint16_t *hr_ref, const uint8_t *canon)
|
|
||||||
{
|
{
|
||||||
int i, j, voiced;
|
int i, j, voiced;
|
||||||
const int* params;
|
const int* params;
|
||||||
@@ -1421,9 +1422,7 @@ size_t GsmHrCodec::plc(int lostFrames, std::span<uint8_t> output)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GsmHrCodec::GsmHrFactory::GsmHrFactory(int ptype)
|
GsmHrCodec::GsmHrFactory::GsmHrFactory(int ptype) : mPtype(ptype) {}
|
||||||
:mPtype(ptype)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const char* GsmHrCodec::GsmHrFactory::name()
|
const char* GsmHrCodec::GsmHrFactory::name()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ public:
|
|||||||
int payloadType() override;
|
int payloadType() override;
|
||||||
|
|
||||||
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction) override;
|
||||||
|
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
};
|
};
|
||||||
@@ -64,20 +65,14 @@ class OpusCodec: public Codec
|
|||||||
protected:
|
protected:
|
||||||
OpusEncoder* mEncoderCtx = nullptr;
|
OpusEncoder* mEncoderCtx = nullptr;
|
||||||
OpusDecoder* mDecoderCtx = nullptr;
|
OpusDecoder* mDecoderCtx = nullptr;
|
||||||
int mPTime = 0,
|
int mPTime = 0, mSamplerate = 0, mChannels = 0;
|
||||||
mSamplerate = 0,
|
|
||||||
mChannels = 0;
|
|
||||||
int mDecoderChannels = 0;
|
int mDecoderChannels = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Params
|
struct Params
|
||||||
{
|
{
|
||||||
bool mUseDtx = false,
|
bool mUseDtx = false, mUseInbandFec = false, mStereo = false;
|
||||||
mUseInbandFec = false,
|
int mPtime = 0, mTargetBitrate = 0, mExpectedPacketLoss = 0;
|
||||||
mStereo = false;
|
|
||||||
int mPtime = 0,
|
|
||||||
mTargetBitrate = 0,
|
|
||||||
mExpectedPacketLoss = 0;
|
|
||||||
|
|
||||||
Params();
|
Params();
|
||||||
resip::Data toString() const;
|
resip::Data toString() const;
|
||||||
@@ -100,7 +95,8 @@ public:
|
|||||||
int samplerate() override;
|
int samplerate() override;
|
||||||
int payloadType() override;
|
int payloadType() override;
|
||||||
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
void updateSdp(resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
||||||
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs, SdpDirection direction) override;
|
int processSdp(const resip::SdpContents::Session::Medium::CodecContainer& codecs,
|
||||||
|
SdpDirection direction) override;
|
||||||
PCodec create() override;
|
PCodec create() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +130,6 @@ public:
|
|||||||
int mPType20ms, mPType30ms;
|
int mPType20ms, mPType30ms;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IlbcFactory(int ptype20ms, int ptype30ms);
|
IlbcFactory(int ptype20ms, int ptype30ms);
|
||||||
const char* name();
|
const char* name();
|
||||||
int samplerate();
|
int samplerate();
|
||||||
@@ -200,6 +195,7 @@ protected:
|
|||||||
int mSamplerate = 0;
|
int mSamplerate = 0;
|
||||||
ISACFIX_MainStruct* mEncoderCtx = nullptr;
|
ISACFIX_MainStruct* mEncoderCtx = nullptr;
|
||||||
ISACFIX_MainStruct* mDecoderCtx = nullptr;
|
ISACFIX_MainStruct* mDecoderCtx = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class IsacFactory16K : public Factory
|
class IsacFactory16K : public Factory
|
||||||
{
|
{
|
||||||
@@ -239,7 +235,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// GSM MIME name
|
/// GSM MIME name
|
||||||
#define GSM_MIME_NAME "gsm"
|
#define GSM_MIME_NAME "gsm"
|
||||||
|
|
||||||
@@ -275,6 +270,7 @@ public:
|
|||||||
Bytes_31,
|
Bytes_31,
|
||||||
Bytes_65
|
Bytes_65
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct gsm_state* mGSM; /// Pointer to codec context
|
struct gsm_state* mGSM; /// Pointer to codec context
|
||||||
Type mCodecType;
|
Type mCodecType;
|
||||||
@@ -382,6 +378,6 @@ public:
|
|||||||
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
DecodeResult decode(std::span<const uint8_t> input, std::span<uint8_t> output) override;
|
||||||
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
size_t plc(int lostFrames, std::span<uint8_t> output) override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace MT
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && defined(USE_AMR_CODEC)
|
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && \
|
||||||
|
defined(USE_AMR_CODEC)
|
||||||
#include "MT_AmrCodec.h"
|
#include "MT_AmrCodec.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -27,9 +28,11 @@
|
|||||||
using namespace MT;
|
using namespace MT;
|
||||||
|
|
||||||
// ----------------- RtpBuffer::Packet --------------
|
// ----------------- RtpBuffer::Packet --------------
|
||||||
RtpBuffer::Packet::Packet(const std::shared_ptr<RTPPacket>& packet, std::chrono::milliseconds timelength, int samplerate)
|
RtpBuffer::Packet::Packet(const std::shared_ptr<RTPPacket>& packet, std::chrono::milliseconds timelength,
|
||||||
|
int samplerate)
|
||||||
: mRtp(packet), mTimelength(timelength), mSamplerate(samplerate)
|
: mRtp(packet), mTimelength(timelength), mSamplerate(samplerate)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const std::shared_ptr<RTPPacket>& RtpBuffer::Packet::rtp() const
|
const std::shared_ptr<RTPPacket>& RtpBuffer::Packet::rtp() const
|
||||||
{
|
{
|
||||||
@@ -57,15 +60,13 @@ std::vector<short>& RtpBuffer::Packet::pcm()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------ RtpBuffer ----------------
|
// ------------ RtpBuffer ----------------
|
||||||
RtpBuffer::RtpBuffer(Statistics& stat)
|
RtpBuffer::RtpBuffer(Statistics& stat) : mStat(stat) {}
|
||||||
:mStat(stat)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RtpBuffer::~RtpBuffer()
|
RtpBuffer::~RtpBuffer()
|
||||||
{
|
{
|
||||||
if (mAddCounter)
|
if (mAddCounter)
|
||||||
ICELogDebug(<< "Number of add packets: " << mAddCounter << ", number of retrieved packets " << mReturnedCounter);
|
ICELogDebug(<< "Number of add packets: " << mAddCounter << ", number of retrieved packets "
|
||||||
|
<< mReturnedCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpBuffer::setHigh(std::chrono::milliseconds t)
|
void RtpBuffer::setHigh(std::chrono::milliseconds t)
|
||||||
@@ -109,7 +110,8 @@ bool SequenceSort(const std::shared_ptr<RtpBuffer::Packet>& p1, const std::share
|
|||||||
return p1->rtp()->GetExtendedSequenceNumber() < p2->rtp()->GetExtendedSequenceNumber();
|
return p1->rtp()->GetExtendedSequenceNumber() < p2->rtp()->GetExtendedSequenceNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RtpBuffer::Packet> RtpBuffer::add(const std::shared_ptr<jrtplib::RTPPacket>& packet, std::chrono::milliseconds timelength, int rate)
|
std::shared_ptr<RtpBuffer::Packet> RtpBuffer::add(const std::shared_ptr<jrtplib::RTPPacket>& packet,
|
||||||
|
std::chrono::milliseconds timelength, int rate)
|
||||||
{
|
{
|
||||||
if (!packet)
|
if (!packet)
|
||||||
return std::shared_ptr<Packet>();
|
return std::shared_ptr<Packet>();
|
||||||
@@ -196,8 +198,7 @@ void RtpBuffer::trimToHighWater(size_t maxPackets)
|
|||||||
// high-water mark (mHigh, when set) or, if maxPackets != 0, the packet-count
|
// high-water mark (mHigh, when set) or, if maxPackets != 0, the packet-count
|
||||||
// cap. Always keep at least one packet so loss/gap accounting has a reference.
|
// cap. Always keep at least one packet so loss/gap accounting has a reference.
|
||||||
while (mPacketList.size() > 1 &&
|
while (mPacketList.size() > 1 &&
|
||||||
((0ms != mHigh && total > mHigh) ||
|
((0ms != mHigh && total > mHigh) || (maxPackets != 0 && mPacketList.size() > maxPackets)))
|
||||||
(maxPackets != 0 && mPacketList.size() > maxPackets)))
|
|
||||||
{
|
{
|
||||||
ICELogMedia(<< "Dropping RTP packets from jitter buffer");
|
ICELogMedia(<< "Dropping RTP packets from jitter buffer");
|
||||||
total -= mPacketList.front()->timelength();
|
total -= mPacketList.front()->timelength();
|
||||||
@@ -290,8 +291,9 @@ RtpBuffer::FetchResult RtpBuffer::fetch()
|
|||||||
.mTimestampEnd = gapEnd});
|
.mTimestampEnd = gapEnd});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: here we should decide smth - 2-packet gap shoud report Status::Gap two times at least; but current implementation gives only one.
|
// ToDo: here we should decide smth - 2-packet gap shoud report Status::Gap two times at least; but
|
||||||
// It is not big problem - as gap is detected when we have smth to return usually
|
// current implementation gives only one. It is not big problem - as gap is detected when we have
|
||||||
|
// smth to return usually
|
||||||
mLastSeqno = seqno;
|
mLastSeqno = seqno;
|
||||||
mLastReceiveTime = packet.rtp()->GetReceiveTime();
|
mLastReceiveTime = packet.rtp()->GetReceiveTime();
|
||||||
result = {FetchResult::Status::Gap};
|
result = {FetchResult::Status::Gap};
|
||||||
@@ -374,16 +376,14 @@ int RtpBuffer::getNumberOfAddPackets() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------- Receiver ---------------
|
//-------------- Receiver ---------------
|
||||||
Receiver::Receiver(Statistics& stat)
|
Receiver::Receiver(Statistics& stat) : mStat(stat) {}
|
||||||
:mStat(stat)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Receiver::~Receiver()
|
Receiver::~Receiver() {}
|
||||||
{}
|
|
||||||
|
|
||||||
//-------------- AudioReceiver ----------------
|
//-------------- AudioReceiver ----------------
|
||||||
AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics& stat)
|
AudioReceiver::AudioReceiver(const CodecList::Settings& settings, MT::Statistics& stat)
|
||||||
:Receiver(stat), mRtpBuffer(stat), mDtmfBuffer(stat), mCodecSettings(settings), mCodecList(settings), mDtmfReceiver(stat)
|
: Receiver(stat), mRtpBuffer(stat), mDtmfBuffer(stat), mCodecSettings(settings), mCodecList(settings),
|
||||||
|
mDtmfReceiver(stat)
|
||||||
{
|
{
|
||||||
// Init codecs
|
// Init codecs
|
||||||
mCodecList.setSettings(settings);
|
mCodecList.setSettings(settings);
|
||||||
@@ -449,7 +449,8 @@ void AudioReceiver::setCodecSettings(const CodecList::Settings& codecSettings)
|
|||||||
const bool lazy = mCodecSettings.mLazyCodecMap;
|
const bool lazy = mCodecSettings.mLazyCodecMap;
|
||||||
mCodecSettings = codecSettings;
|
mCodecSettings = codecSettings;
|
||||||
mCodecSettings.mLazyCodecMap = lazy;
|
mCodecSettings.mLazyCodecMap = lazy;
|
||||||
mCodecList.setSettings(mCodecSettings); // This builds factory list with proper payload types according to payload types in settings
|
mCodecList.setSettings(
|
||||||
|
mCodecSettings); // This builds factory list with proper payload types according to payload types in settings
|
||||||
|
|
||||||
// Rebuild codec map from factory list
|
// Rebuild codec map from factory list
|
||||||
mCodecList.fillCodecMap(mCodecMap);
|
mCodecList.fillCodecMap(mCodecMap);
|
||||||
@@ -485,10 +486,7 @@ Codec* AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p)
|
|||||||
Codec* codec = nullptr;
|
Codec* codec = nullptr;
|
||||||
|
|
||||||
// Estimate time length
|
// Estimate time length
|
||||||
int time_length = 0,
|
int time_length = 0, samplerate = 8000, payloadLength = p->GetPayloadLength(), ptype = p->GetPayloadType();
|
||||||
samplerate = 8000,
|
|
||||||
payloadLength = p->GetPayloadLength(),
|
|
||||||
ptype = p->GetPayloadType();
|
|
||||||
|
|
||||||
// ICELogMedia(<< "Adding packet No " << p->GetSequenceNumber());
|
// ICELogMedia(<< "Adding packet No " << p->GetSequenceNumber());
|
||||||
|
|
||||||
@@ -522,8 +520,7 @@ Codec* AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p)
|
|||||||
|
|
||||||
if (!codec)
|
if (!codec)
|
||||||
time_length = 10;
|
time_length = 10;
|
||||||
else
|
else if (!codec->rtpLength())
|
||||||
if (!codec->rtpLength())
|
|
||||||
time_length = codec->frameTime();
|
time_length = codec->frameTime();
|
||||||
else
|
else
|
||||||
time_length = lround(double(payloadLength) / codec->rtpLength() * codec->frameTime());
|
time_length = lround(double(payloadLength) / codec->rtpLength() * codec->frameTime());
|
||||||
@@ -618,7 +615,8 @@ void AudioReceiver::produceCNG(std::chrono::milliseconds length, Audio::DataWind
|
|||||||
if (options.mSkipDecode)
|
if (options.mSkipDecode)
|
||||||
mDecodedLength = 0;
|
mDecodedLength = 0;
|
||||||
else
|
else
|
||||||
mDecodedLength = cng().produce(mCodec->samplerate(), tail, reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
mDecodedLength =
|
||||||
|
cng().produce(mCodec->samplerate(), tail, reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
||||||
|
|
||||||
if (mDecodedLength)
|
if (mDecodedLength)
|
||||||
processDecoded(output, options);
|
processDecoded(output, options);
|
||||||
@@ -636,13 +634,13 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
|||||||
{
|
{
|
||||||
// Synthesize comfort noise. It will be done on AUDIO_SAMPLERATE rate directly to mResampledFrame buffer.
|
// Synthesize comfort noise. It will be done on AUDIO_SAMPLERATE rate directly to mResampledFrame buffer.
|
||||||
// Do not forget to send this noise to analysis
|
// Do not forget to send this noise to analysis
|
||||||
mDecodedLength = cng().produce(mCodec->samplerate(), mLastPacketTimeLength, reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
mDecodedLength = cng().produce(mCodec->samplerate(), mLastPacketTimeLength,
|
||||||
|
reinterpret_cast<short*>(mDecodedFrame.data()), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
decodePacketTo(output, options, mCngPacket);
|
decodePacketTo(output, options, mCngPacket);
|
||||||
}
|
}
|
||||||
else
|
else if (mCodec && mFrameCount && !mCodecSettings.mSkipDecode)
|
||||||
if (mCodec && mFrameCount && !mCodecSettings.mSkipDecode)
|
|
||||||
{
|
{
|
||||||
// Conceal the gap into mDecodedFrame/mDecodedLength.
|
// Conceal the gap into mDecodedFrame/mDecodedLength.
|
||||||
if (options.mSkipDecode)
|
if (options.mSkipDecode)
|
||||||
@@ -662,8 +660,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
|||||||
auto codecIter = mCodecMap.find(next->rtp()->GetPayloadType());
|
auto codecIter = mCodecMap.find(next->rtp()->GetPayloadType());
|
||||||
if (codecIter != mCodecMap.end() && codecIter->second == mCodec)
|
if (codecIter != mCodecMap.end() && codecIter->second == mCodec)
|
||||||
{
|
{
|
||||||
mDecodedLength = mCodec->fec({next->rtp()->GetPayloadData(), (size_t)next->rtp()->GetPayloadLength()},
|
mDecodedLength = mCodec->fec(
|
||||||
concealBuffer);
|
{next->rtp()->GetPayloadData(), (size_t)next->rtp()->GetPayloadLength()}, concealBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,8 +673,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
|||||||
if (!mDecodedLength)
|
if (!mDecodedLength)
|
||||||
{
|
{
|
||||||
// PLC unsupported or failed - substitute one frame of silence.
|
// PLC unsupported or failed - substitute one frame of silence.
|
||||||
size_t frameBytes = (size_t)mCodec->frameTime() * mCodec->samplerate() / 1000
|
size_t frameBytes = (size_t)mCodec->frameTime() * mCodec->samplerate() / 1000 * sizeof(short) *
|
||||||
* sizeof(short) * std::max(1, mCodec->channels());
|
std::max(1, mCodec->channels());
|
||||||
frameBytes = std::min(frameBytes, concealBuffer.size_bytes());
|
frameBytes = std::min(frameBytes, concealBuffer.size_bytes());
|
||||||
mDecodedLength = frameBytes;
|
mDecodedLength = frameBytes;
|
||||||
memset(mDecodedFrame.data(), 0, mDecodedLength);
|
memset(mDecodedFrame.data(), 0, mDecodedLength);
|
||||||
@@ -703,13 +701,15 @@ AudioReceiver::DecodeResult AudioReceiver::decodeGapTo(Audio::DataWindow& output
|
|||||||
if (mDecodedLength)
|
if (mDecodedLength)
|
||||||
{
|
{
|
||||||
processDecoded(output, options);
|
processDecoded(output, options);
|
||||||
return {.mStatus = DecodeResult::Status::Ok, .mSamplerate = mCodec->samplerate(), .mChannels = mCodec->channels()};
|
return {
|
||||||
|
.mStatus = DecodeResult::Status::Ok, .mSamplerate = mCodec->samplerate(), .mChannels = mCodec->channels()};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return {.mStatus = DecodeResult::Status::Skip};
|
return {.mStatus = DecodeResult::Status::Skip};
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& output, DecodeOptions options, const std::shared_ptr<RtpBuffer::Packet>& packet)
|
AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& output, DecodeOptions options,
|
||||||
|
const std::shared_ptr<RtpBuffer::Packet>& packet)
|
||||||
{
|
{
|
||||||
if (!packet || !packet->rtp())
|
if (!packet || !packet->rtp())
|
||||||
return {DecodeResult::Status::Skip};
|
return {DecodeResult::Status::Skip};
|
||||||
@@ -719,7 +719,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
|
|
||||||
mFailedCount = 0;
|
mFailedCount = 0;
|
||||||
|
|
||||||
// Check if we need to emit silence - it may happen in the case if next packet has RTP timestamp much beyond the previous one; maybe DTX was active.
|
// Check if we need to emit silence - it may happen in the case if next packet has RTP timestamp much beyond the
|
||||||
|
// previous one; maybe DTX was active.
|
||||||
if (mLastPacketTimestamp && mLastPacketTimeLength && mCodec)
|
if (mLastPacketTimestamp && mLastPacketTimeLength && mCodec)
|
||||||
{
|
{
|
||||||
int units = rtp.GetTimestamp() - *mLastPacketTimestamp;
|
int units = rtp.GetTimestamp() - *mLastPacketTimestamp;
|
||||||
@@ -756,7 +757,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
result.mSamplerate = mCodec->samplerate();
|
result.mSamplerate = mCodec->samplerate();
|
||||||
|
|
||||||
// Check if it is CNG packet
|
// Check if it is CNG packet
|
||||||
if (((ptype == 0 || ptype == 8) && rtp.GetPayloadLength() >= 1 && rtp.GetPayloadLength() <= 6) || rtp.GetPayloadType() == 13)
|
if (((ptype == 0 || ptype == 8) && rtp.GetPayloadLength() >= 1 && rtp.GetPayloadLength() <= 6) ||
|
||||||
|
rtp.GetPayloadType() == 13)
|
||||||
{
|
{
|
||||||
if (options.mSkipDecode)
|
if (options.mSkipDecode)
|
||||||
mDecodedLength = 0;
|
mDecodedLength = 0;
|
||||||
@@ -767,7 +769,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
cng().decode3389(rtp.GetPayloadData(), rtp.GetPayloadLength());
|
cng().decode3389(rtp.GetPayloadData(), rtp.GetPayloadLength());
|
||||||
|
|
||||||
// Emit CNG mLastPacketLength milliseconds
|
// Emit CNG mLastPacketLength milliseconds
|
||||||
mDecodedLength = cng().produce(mCodec->samplerate(), mLastPacketTimeLength, (short*)mDecodedFrame.data(), true);
|
mDecodedLength =
|
||||||
|
cng().produce(mCodec->samplerate(), mLastPacketTimeLength, (short*)mDecodedFrame.data(), true);
|
||||||
if (mDecodedLength)
|
if (mDecodedLength)
|
||||||
processDecoded(output, options);
|
processDecoded(output, options);
|
||||||
}
|
}
|
||||||
@@ -802,8 +805,10 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Decode frame by frame
|
// Decode frame by frame
|
||||||
auto codecInput = std::span{rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength};
|
auto codecInput =
|
||||||
auto codecOutput = std::span{(uint8_t*)mDecodedFrame.data(), mDecodedFrame.size() * sizeof(int16_t)};
|
std::span{rtp.GetPayloadData() + i * mCodec->rtpLength(), (size_t)frameLength};
|
||||||
|
auto codecOutput =
|
||||||
|
std::span{(uint8_t*)mDecodedFrame.data(), mDecodedFrame.size() * sizeof(int16_t)};
|
||||||
auto r = mCodec->decode(codecInput, codecOutput);
|
auto r = mCodec->decode(codecInput, codecOutput);
|
||||||
mDecodedLength = r.mDecoded;
|
mDecodedLength = r.mDecoded;
|
||||||
if (mDecodedLength > 0)
|
if (mDecodedLength > 0)
|
||||||
@@ -832,8 +837,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
|||||||
AudioReceiver::DecodeResult AudioReceiver::decodeEmptyTo(Audio::DataWindow& output, DecodeOptions options)
|
AudioReceiver::DecodeResult AudioReceiver::decodeEmptyTo(Audio::DataWindow& output, DecodeOptions options)
|
||||||
{
|
{
|
||||||
// There are two cases
|
// There are two cases
|
||||||
// First is we have no ready time estimated how much audio should be emitted i.e. audio is decoded right after the next packet arrives.
|
// First is we have no ready time estimated how much audio should be emitted i.e. audio is decoded right after the
|
||||||
// In this case we just skip the analysis - we should not be called in this situation
|
// next packet arrives. In this case we just skip the analysis - we should not be called in this situation
|
||||||
if (options.mElapsed == 0ms || !mCodec)
|
if (options.mElapsed == 0ms || !mCodec)
|
||||||
return {.mStatus = DecodeResult::Status::Skip};
|
return {.mStatus = DecodeResult::Status::Skip};
|
||||||
|
|
||||||
@@ -851,7 +856,8 @@ AudioReceiver::DecodeResult AudioReceiver::decodeEmptyTo(Audio::DataWindow& outp
|
|||||||
// the CNG decoder writes straight into its buffer.
|
// the CNG decoder writes straight into its buffer.
|
||||||
size_t bytesPerMs = (size_t)fmt.rate() / 1000 * sizeof(short) * fmt.channels();
|
size_t bytesPerMs = (size_t)fmt.rate() / 1000 * sizeof(short) * fmt.channels();
|
||||||
size_t room = output.capacity() - output.filled();
|
size_t room = output.capacity() - output.filled();
|
||||||
int ms = bytesPerMs ? (int)std::min<int64_t>(options.mElapsed.count(), (int64_t)(room / bytesPerMs)) : 0;
|
int ms =
|
||||||
|
bytesPerMs ? (int)std::min<int64_t>(options.mElapsed.count(), (int64_t)(room / bytesPerMs)) : 0;
|
||||||
if (ms <= 0)
|
if (ms <= 0)
|
||||||
return {.mStatus = DecodeResult::Status::Skip};
|
return {.mStatus = DecodeResult::Status::Skip};
|
||||||
auto produced = cng().produce(fmt.rate(), ms, (short*)(output.mutableData() + output.filled()), false);
|
auto produced = cng().produce(fmt.rate(), ms, (short*)(output.mutableData() + output.filled()), false);
|
||||||
@@ -918,11 +924,8 @@ void MT::AudioReceiver::logReceiveHeartbeat()
|
|||||||
size_t dropDelta = mStat.mPacketDropped - mStatDropLast;
|
size_t dropDelta = mStat.mPacketDropped - mStatDropLast;
|
||||||
|
|
||||||
ICELogInfo(<< "[rx-heartbeat] buffered=" << mRtpBuffer.bufferedTime().count() << "ms"
|
ICELogInfo(<< "[rx-heartbeat] buffered=" << mRtpBuffer.bufferedTime().count() << "ms"
|
||||||
<< " packets=" << mRtpBuffer.getCount()
|
<< " packets=" << mRtpBuffer.getCount() << " underruns/5s=" << mUnderrunCount << " gaps/5s=" << mGapCount
|
||||||
<< " underruns/5s=" << mUnderrunCount
|
<< " loss/5s=" << lossDelta << " dropped/5s=" << dropDelta);
|
||||||
<< " gaps/5s=" << mGapCount
|
|
||||||
<< " loss/5s=" << lossDelta
|
|
||||||
<< " dropped/5s=" << dropDelta);
|
|
||||||
|
|
||||||
mStatLogLast = t;
|
mStatLogLast = t;
|
||||||
mUnderrunCount = 0;
|
mUnderrunCount = 0;
|
||||||
@@ -938,7 +941,8 @@ void MT::AudioReceiver::updateDecodingTimeStatistics()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto t = std::chrono::steady_clock::now();
|
auto t = std::chrono::steady_clock::now();
|
||||||
mStat.mDecodingInterval.process(std::chrono::duration_cast<std::chrono::milliseconds>(t - *mDecodeTimestamp).count());
|
mStat.mDecodingInterval.process(
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(t - *mDecodeTimestamp).count());
|
||||||
mDecodeTimestamp = t;
|
mDecodeTimestamp = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -993,9 +997,17 @@ AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output,
|
|||||||
// Decode to mAvailable buffer
|
// Decode to mAvailable buffer
|
||||||
switch (fr.mStatus)
|
switch (fr.mStatus)
|
||||||
{
|
{
|
||||||
case RtpBuffer::FetchResult::Status::Gap: mGapCount++; result = decodeGapTo(mAvailable, options.decreaseElapsedBy(produced)); break;
|
case RtpBuffer::FetchResult::Status::Gap:
|
||||||
case RtpBuffer::FetchResult::Status::NoPacket: result = decodeEmptyTo(mAvailable, options.decreaseElapsedBy(produced)); break;
|
mGapCount++;
|
||||||
case RtpBuffer::FetchResult::Status::RegularPacket: result = decodePacketTo(mAvailable, options.decreaseElapsedBy(produced), fr.mPacket); updateDecodeIntervalStatistics(); break;
|
result = decodeGapTo(mAvailable, options.decreaseElapsedBy(produced));
|
||||||
|
break;
|
||||||
|
case RtpBuffer::FetchResult::Status::NoPacket:
|
||||||
|
result = decodeEmptyTo(mAvailable, options.decreaseElapsedBy(produced));
|
||||||
|
break;
|
||||||
|
case RtpBuffer::FetchResult::Status::RegularPacket:
|
||||||
|
result = decodePacketTo(mAvailable, options.decreaseElapsedBy(produced), fr.mPacket);
|
||||||
|
updateDecodeIntervalStatistics();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@@ -1026,7 +1038,8 @@ AudioReceiver::DecodeResult AudioReceiver::getAudioTo(Audio::DataWindow& output,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mProducedAudio += produced;
|
mProducedAudio += produced;
|
||||||
// ICELogDebug(<< "Requested " << options.mElapsed << ", produced " << produced << ", remains " << mAvailable.getTimeLength(fmt) << ", packets " << getRtpBuffer().getCount());
|
// ICELogDebug(<< "Requested " << options.mElapsed << ", produced " << produced << ", remains " <<
|
||||||
|
// mAvailable.getTimeLength(fmt) << ", packets " << getRtpBuffer().getCount());
|
||||||
|
|
||||||
logReceiveHeartbeat();
|
logReceiveHeartbeat();
|
||||||
return result;
|
return result;
|
||||||
@@ -1059,9 +1072,11 @@ void AudioReceiver::makeMonoAndResample(int rate, int channels)
|
|||||||
if (channels != AUDIO_CHANNELS)
|
if (channels != AUDIO_CHANNELS)
|
||||||
{
|
{
|
||||||
if (channels == 1)
|
if (channels == 1)
|
||||||
mConvertedLength = Audio::ChannelConverter::monoToStereo(mDecodedFrame.data(), mDecodedLength, mConvertedFrame.data(), mDecodedLength * 2);
|
mConvertedLength = Audio::ChannelConverter::monoToStereo(mDecodedFrame.data(), mDecodedLength,
|
||||||
|
mConvertedFrame.data(), mDecodedLength * 2);
|
||||||
else
|
else
|
||||||
mDecodedLength = Audio::ChannelConverter::stereoToMono(mDecodedFrame.data(), mDecodedLength, mDecodedFrame.data(), mDecodedLength / 2);
|
mDecodedLength = Audio::ChannelConverter::stereoToMono(mDecodedFrame.data(), mDecodedLength,
|
||||||
|
mDecodedFrame.data(), mDecodedLength / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* frames = mConvertedLength ? (void*)mConvertedFrame.data() : (void*)mDecodedFrame.data();
|
void* frames = mConvertedLength ? (void*)mConvertedFrame.data() : (void*)mDecodedFrame.data();
|
||||||
@@ -1070,10 +1085,18 @@ void AudioReceiver::makeMonoAndResample(int rate, int channels)
|
|||||||
Audio::Resampler* r = nullptr;
|
Audio::Resampler* r = nullptr;
|
||||||
switch (rate)
|
switch (rate)
|
||||||
{
|
{
|
||||||
case 8000: r = &mResampler8; break;
|
case 8000:
|
||||||
case 16000: r = &mResampler16; break;
|
r = &mResampler8;
|
||||||
case 32000: r = &mResampler32; break;
|
break;
|
||||||
case 48000: r = &mResampler48; break;
|
case 16000:
|
||||||
|
r = &mResampler16;
|
||||||
|
break;
|
||||||
|
case 32000:
|
||||||
|
r = &mResampler32;
|
||||||
|
break;
|
||||||
|
case 48000:
|
||||||
|
r = &mResampler48;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
memcpy(mResampledFrame.data(), frames, length);
|
memcpy(mResampledFrame.data(), frames, length);
|
||||||
mResampledLength = length;
|
mResampledLength = length;
|
||||||
@@ -1081,7 +1104,8 @@ void AudioReceiver::makeMonoAndResample(int rate, int channels)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t processedInput = 0;
|
size_t processedInput = 0;
|
||||||
mResampledLength = r->processBuffer(frames, length, processedInput, mResampledFrame.data(), r->getDestLength(length));
|
mResampledLength =
|
||||||
|
r->processBuffer(frames, length, processedInput, mResampledFrame.data(), r->getDestLength(length));
|
||||||
// processedInput result value is ignored - it is always equal to length as internal sample rate is 8/16/32/48K
|
// processedInput result value is ignored - it is always equal to length as internal sample rate is 8/16/32/48K
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1093,7 +1117,8 @@ Codec* AudioReceiver::findCodec(int payloadType)
|
|||||||
|
|
||||||
void AudioReceiver::updateAmrCodecStats(Codec* c)
|
void AudioReceiver::updateAmrCodecStats(Codec* c)
|
||||||
{
|
{
|
||||||
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && defined(USE_AMR_CODEC)
|
#if !defined(TARGET_ANDROID) && !defined(TARGET_OPENWRT) && !defined(TARGET_WIN) && !defined(TARGET_RPI) && \
|
||||||
|
defined(USE_AMR_CODEC)
|
||||||
AmrNbCodec* nb = dynamic_cast<AmrNbCodec*>(c);
|
AmrNbCodec* nb = dynamic_cast<AmrNbCodec*>(c);
|
||||||
AmrWbCodec* wb = dynamic_cast<AmrWbCodec*>(c);
|
AmrWbCodec* wb = dynamic_cast<AmrWbCodec*>(c);
|
||||||
|
|
||||||
@@ -1102,8 +1127,7 @@ void AudioReceiver::updateAmrCodecStats(Codec* c)
|
|||||||
mStat.mBitrateSwitchCounter = nb->getSwitchCounter();
|
mStat.mBitrateSwitchCounter = nb->getSwitchCounter();
|
||||||
mStat.mCng = nb->getCngCounter();
|
mStat.mCng = nb->getCngCounter();
|
||||||
}
|
}
|
||||||
else
|
else if (wb != nullptr)
|
||||||
if (wb != nullptr)
|
|
||||||
{
|
{
|
||||||
mStat.mBitrateSwitchCounter = wb->getSwitchCounter();
|
mStat.mBitrateSwitchCounter = wb->getSwitchCounter();
|
||||||
mStat.mCng = wb->getCngCounter();
|
mStat.mCng = wb->getCngCounter();
|
||||||
@@ -1114,7 +1138,8 @@ void AudioReceiver::updateAmrCodecStats(Codec* c)
|
|||||||
int AudioReceiver::getSize() const
|
int AudioReceiver::getSize() const
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
result += sizeof(*this) + mResampler8.getSize() + mResampler16.getSize() + mResampler32.getSize() + mResampler48.getSize();
|
result += sizeof(*this) + mResampler8.getSize() + mResampler16.getSize() + mResampler32.getSize() +
|
||||||
|
mResampler48.getSize();
|
||||||
|
|
||||||
if (mCodec)
|
if (mCodec)
|
||||||
; // ToDo: need the way to calculate size of codec instances
|
; // ToDo: need the way to calculate size of codec instances
|
||||||
@@ -1138,8 +1163,7 @@ AudioReceiver::MediaInfo AudioReceiver::infoFor(jrtplib::RTPPacket& p)
|
|||||||
|
|
||||||
packetTime = std::chrono::milliseconds(frameCount * codec->frameTime());
|
packetTime = std::chrono::milliseconds(frameCount * codec->frameTime());
|
||||||
}
|
}
|
||||||
else
|
else if (typeid(*codec) == typeid(OpusCodec))
|
||||||
if (typeid(*codec) == typeid(OpusCodec))
|
|
||||||
{
|
{
|
||||||
OpusCodec* oc = dynamic_cast<OpusCodec*>(codec);
|
OpusCodec* oc = dynamic_cast<OpusCodec*>(codec);
|
||||||
assert(oc);
|
assert(oc);
|
||||||
@@ -1167,12 +1191,9 @@ void AudioReceiver::updateDecodeIntervalStatistics()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------- DtmfReceiver -------------------
|
// ----------------------- DtmfReceiver -------------------
|
||||||
DtmfReceiver::DtmfReceiver(Statistics& stat)
|
DtmfReceiver::DtmfReceiver(Statistics& stat) : Receiver(stat) {}
|
||||||
:Receiver(stat)
|
|
||||||
{}
|
|
||||||
|
|
||||||
DtmfReceiver::~DtmfReceiver()
|
DtmfReceiver::~DtmfReceiver() {}
|
||||||
{}
|
|
||||||
|
|
||||||
void DtmfReceiver::add(const std::shared_ptr<RTPPacket>& p)
|
void DtmfReceiver::add(const std::shared_ptr<RTPPacket>& p)
|
||||||
{
|
{
|
||||||
@@ -1192,8 +1213,8 @@ void DtmfReceiver::add(const std::shared_ptr<RTPPacket>& p)
|
|||||||
mCallback(ev.mTone);
|
mCallback(ev.mTone);
|
||||||
|
|
||||||
// Queue statistics item
|
// Queue statistics item
|
||||||
mStat.mDtmf2833Timeline.emplace_back(Dtmf2833Event{.mTone = ev.mTone,
|
mStat.mDtmf2833Timeline.emplace_back(
|
||||||
.mTimestamp = RtpHelper::toMicroseconds(p->GetReceiveTime())});
|
Dtmf2833Event{.mTone = ev.mTone, .mTimestamp = RtpHelper::toMicroseconds(p->GetReceiveTime())});
|
||||||
}
|
}
|
||||||
|
|
||||||
mEvent = ev.mTone;
|
mEvent = ev.mTone;
|
||||||
|
|||||||
@@ -70,9 +70,12 @@ public:
|
|||||||
{
|
{
|
||||||
switch (mStatus)
|
switch (mStatus)
|
||||||
{
|
{
|
||||||
case Status::RegularPacket: return "packet";
|
case Status::RegularPacket:
|
||||||
case Status::Gap: return "gap";
|
return "packet";
|
||||||
case Status::NoPacket: return "empty";
|
case Status::Gap:
|
||||||
|
return "gap";
|
||||||
|
case Status::NoPacket:
|
||||||
|
return "empty";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -99,7 +102,8 @@ public:
|
|||||||
int getCount() const;
|
int getCount() const;
|
||||||
|
|
||||||
// Returns false if packet was not add - maybe too old or too new or duplicate
|
// Returns false if packet was not add - maybe too old or too new or duplicate
|
||||||
std::shared_ptr<Packet> add(const std::shared_ptr<RTPPacket>& packet, std::chrono::milliseconds timelength, int rate);
|
std::shared_ptr<Packet> add(const std::shared_ptr<RTPPacket>& packet, std::chrono::milliseconds timelength,
|
||||||
|
int rate);
|
||||||
|
|
||||||
typedef std::vector<std::shared_ptr<Packet>> ResultList;
|
typedef std::vector<std::shared_ptr<Packet>> ResultList;
|
||||||
typedef std::shared_ptr<ResultList> PResultList;
|
typedef std::shared_ptr<ResultList> PResultList;
|
||||||
@@ -134,8 +138,7 @@ protected:
|
|||||||
std::chrono::milliseconds mHigh = std::chrono::milliseconds(RTP_BUFFER_HIGH),
|
std::chrono::milliseconds mHigh = std::chrono::milliseconds(RTP_BUFFER_HIGH),
|
||||||
mLow = std::chrono::milliseconds(RTP_BUFFER_LOW),
|
mLow = std::chrono::milliseconds(RTP_BUFFER_LOW),
|
||||||
mPrebuffer = std::chrono::milliseconds(RTP_BUFFER_PREBUFFER);
|
mPrebuffer = std::chrono::milliseconds(RTP_BUFFER_PREBUFFER);
|
||||||
int mReturnedCounter = 0,
|
int mReturnedCounter = 0, mAddCounter = 0;
|
||||||
mAddCounter = 0;
|
|
||||||
|
|
||||||
mutable Mutex mGuard;
|
mutable Mutex mGuard;
|
||||||
typedef std::vector<std::shared_ptr<Packet>> PacketList;
|
typedef std::vector<std::shared_ptr<Packet>> PacketList;
|
||||||
@@ -189,8 +192,8 @@ public:
|
|||||||
void setCodecSettings(const CodecList::Settings& codecSettings);
|
void setCodecSettings(const CodecList::Settings& codecSettings);
|
||||||
CodecList::Settings& getCodecSettings();
|
CodecList::Settings& getCodecSettings();
|
||||||
|
|
||||||
// Returns false when packet is rejected as illegal. codec parameter will show codec which will be used for decoding.
|
// Returns false when packet is rejected as illegal. codec parameter will show codec which will be used for
|
||||||
// Lifetime of pointer to codec is limited by lifetime of AudioReceiver (it is container).
|
// decoding. Lifetime of pointer to codec is limited by lifetime of AudioReceiver (it is container).
|
||||||
Codec* add(const std::shared_ptr<jrtplib::RTPPacket>& p);
|
Codec* add(const std::shared_ptr<jrtplib::RTPPacket>& p);
|
||||||
|
|
||||||
struct DecodeOptions
|
struct DecodeOptions
|
||||||
@@ -199,17 +202,15 @@ public:
|
|||||||
bool mResampleToMainRate = true; // Resample all decoded audio to AUDIO_SAMPLERATE
|
bool mResampleToMainRate = true; // Resample all decoded audio to AUDIO_SAMPLERATE
|
||||||
bool mFillGapByCNG = false; // Use CNG information if available
|
bool mFillGapByCNG = false; // Use CNG information if available
|
||||||
bool mSkipDecode = false; // Don't do decode, just dry run - fetch packets, remove them from the jitter buffer
|
bool mSkipDecode = false; // Don't do decode, just dry run - fetch packets, remove them from the jitter buffer
|
||||||
std::chrono::milliseconds mElapsed = 0ms; // How much milliseconds should be decoded; zero value means "decode just next packet from the buffer"
|
std::chrono::milliseconds mElapsed =
|
||||||
|
0ms; // How much milliseconds should be decoded; zero value means "decode just next packet from the buffer"
|
||||||
DecodeOptions decreaseElapsedBy(std::chrono::milliseconds delta)
|
DecodeOptions decreaseElapsedBy(std::chrono::milliseconds delta)
|
||||||
{
|
{
|
||||||
return
|
return {.mRealtimeProcessing = mRealtimeProcessing,
|
||||||
{
|
|
||||||
.mRealtimeProcessing = mRealtimeProcessing,
|
|
||||||
.mResampleToMainRate = mResampleToMainRate,
|
.mResampleToMainRate = mResampleToMainRate,
|
||||||
.mFillGapByCNG = mFillGapByCNG,
|
.mFillGapByCNG = mFillGapByCNG,
|
||||||
.mSkipDecode = mSkipDecode,
|
.mSkipDecode = mSkipDecode,
|
||||||
.mElapsed = std::max(mElapsed - delta, 0ms)
|
.mElapsed = std::max(mElapsed - delta, 0ms)};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -256,7 +257,8 @@ protected:
|
|||||||
CngDecoder& cng();
|
CngDecoder& cng();
|
||||||
|
|
||||||
RtpBuffer mRtpBuffer; // RTP jitter buffer itself; here are audio packets
|
RtpBuffer mRtpBuffer; // RTP jitter buffer itself; here are audio packets
|
||||||
RtpBuffer mDtmfBuffer; // These two (mDtmfBuffer / mDtmfReceiver) are for our analyzer stack only; in normal softphone logic DTMF packets goes via SingleAudioStream::mDtmfReceiver
|
RtpBuffer mDtmfBuffer; // These two (mDtmfBuffer / mDtmfReceiver) are for our analyzer stack only; in normal
|
||||||
|
// softphone logic DTMF packets goes via SingleAudioStream::mDtmfReceiver
|
||||||
DtmfReceiver mDtmfReceiver;
|
DtmfReceiver mDtmfReceiver;
|
||||||
|
|
||||||
CodecMap mCodecMap;
|
CodecMap mCodecMap;
|
||||||
@@ -269,9 +271,11 @@ protected:
|
|||||||
// Lazily created on first CNG use (getAudioTo); its ctor calls WebRtcCng_CreateDec,
|
// Lazily created on first CNG use (getAudioTo); its ctor calls WebRtcCng_CreateDec,
|
||||||
// which is wasted for the many streams that never decode comfort noise. Access via cng().
|
// which is wasted for the many streams that never decode comfort noise. Access via cng().
|
||||||
std::unique_ptr<CngDecoder> mCngDecoder;
|
std::unique_ptr<CngDecoder> mCngDecoder;
|
||||||
size_t mDTXSamplesToEmit = 0; // How much silence (or CNG) should be emited before next RTP packet gets into the action
|
size_t mDTXSamplesToEmit =
|
||||||
|
0; // How much silence (or CNG) should be emited before next RTP packet gets into the action
|
||||||
|
|
||||||
// Already decoded data that can be retrieved without actual decoding - it may happen because of getAudioTo() may be limited by time interval
|
// Already decoded data that can be retrieved without actual decoding - it may happen because of getAudioTo() may be
|
||||||
|
// limited by time interval
|
||||||
Audio::DataWindow mAvailable;
|
Audio::DataWindow mAvailable;
|
||||||
|
|
||||||
// Decode/convert/resample scratch buffers. These were inline arrays
|
// Decode/convert/resample scratch buffers. These were inline arrays
|
||||||
@@ -297,10 +301,7 @@ protected:
|
|||||||
std::optional<uint32_t> mLastPacketTimestamp;
|
std::optional<uint32_t> mLastPacketTimestamp;
|
||||||
|
|
||||||
int mFailedCount = 0;
|
int mFailedCount = 0;
|
||||||
Audio::Resampler mResampler8,
|
Audio::Resampler mResampler8, mResampler16, mResampler32, mResampler48;
|
||||||
mResampler16,
|
|
||||||
mResampler32,
|
|
||||||
mResampler48;
|
|
||||||
|
|
||||||
Audio::PWavFileWriter mDecodedDump;
|
Audio::PWavFileWriter mDecodedDump;
|
||||||
|
|
||||||
@@ -330,7 +331,8 @@ protected:
|
|||||||
void updateAmrCodecStats(Codec* c);
|
void updateAmrCodecStats(Codec* c);
|
||||||
|
|
||||||
DecodeResult decodeGapTo(Audio::DataWindow& output, DecodeOptions options);
|
DecodeResult decodeGapTo(Audio::DataWindow& output, DecodeOptions options);
|
||||||
DecodeResult decodePacketTo(Audio::DataWindow& output, DecodeOptions options, const std::shared_ptr<RtpBuffer::Packet>& p);
|
DecodeResult decodePacketTo(Audio::DataWindow& output, DecodeOptions options,
|
||||||
|
const std::shared_ptr<RtpBuffer::Packet>& p);
|
||||||
DecodeResult decodeEmptyTo(Audio::DataWindow& output, DecodeOptions options);
|
DecodeResult decodeEmptyTo(Audio::DataWindow& output, DecodeOptions options);
|
||||||
|
|
||||||
std::optional<std::chrono::steady_clock::time_point> mLastDecodeTimestamp;
|
std::optional<std::chrono::steady_clock::time_point> mLastDecodeTimestamp;
|
||||||
@@ -347,9 +349,8 @@ protected:
|
|||||||
size_t mStatLossLast = 0; // mStat.mPacketLoss at last heartbeat
|
size_t mStatLossLast = 0; // mStat.mPacketLoss at last heartbeat
|
||||||
size_t mStatDropLast = 0; // mStat.mPacketDropped at last heartbeat
|
size_t mStatDropLast = 0; // mStat.mPacketDropped at last heartbeat
|
||||||
void logReceiveHeartbeat();
|
void logReceiveHeartbeat();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace MT
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user