From 7d5c2e63da51ec40dbe3df637b814ff8d40e7f30 Mon Sep 17 00:00:00 2001 From: Eloi BAIL <eloi.bail@savoirfairelinux.com> Date: Wed, 18 Feb 2015 20:34:09 -0500 Subject: [PATCH] media: codec layer refactoring * Implement a centralized system media codec information view * Implement media codec container to manage audio/video codecs * Instantiate set of codecs per account * Provide D-Bus API to retrives codecs information from client side * Provide a SIP account (any) access to AV codecs Important notes: * IAX account usability is disabled until we provide a new implementation (see redmine Refs #66805) * Some unittest are disabled until we provide a correct implementation * Some part of code are disabled until SDP refactoring patchset is merged (Gerrit #1185) * Some cleanup are also included Refs #66619 Change-Id: I233889e47860b9362281d9ab3cdb506ce86ec997 Signed-off-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> --- .../dbus/configurationmanager-introspec.xml | 6 +- daemon/bin/dbus/dbusconfigurationmanager.cpp | 4 +- daemon/bin/dbus/dbusconfigurationmanager.h | 6 +- daemon/bin/dbus/dbusvideomanager.cpp | 16 +- daemon/bin/dbus/dbusvideomanager.h | 6 +- daemon/bin/dbus/videomanager-introspec.xml | 29 +- daemon/src/account.cpp | 322 ++++++++++++------ daemon/src/account.h | 53 +-- daemon/src/client/configurationmanager.cpp | 20 +- daemon/src/client/videomanager.cpp | 23 +- daemon/src/client/videomanager.h | 1 - .../dring/configurationmanager_interface.h | 6 +- daemon/src/dring/videomanager_interface.h | 5 +- daemon/src/iax/iaxcall.cpp | 15 +- daemon/src/iax/iaxcall.h | 2 +- daemon/src/iax/iaxvoiplink.cpp | 47 ++- daemon/src/managerimpl.cpp | 2 +- daemon/src/managerimpl.h | 3 - daemon/src/media/Makefile.am | 18 +- .../media/audio/codecs/audiocodecfactory.cpp | 3 + .../media/audio/codecs/audiocodecfactory.h | 3 + daemon/src/media/libav_utils.cpp | 81 ----- daemon/src/media/libav_utils.h | 8 - daemon/src/media/media_codec.cpp | 167 +++++++++ daemon/src/media/media_codec.h | 178 ++++++++++ daemon/src/media/system_codec_container.cpp | 174 ++++++++++ daemon/src/media/system_codec_container.h | 79 +++++ daemon/src/media/video/test/Makefile.am | 7 +- .../media/video/test/test_video_endpoint.cpp | 58 ---- .../media/video/test/test_video_endpoint.h | 46 --- .../src/media/video/test/test_video_rtp.cpp | 11 +- daemon/src/ringdht/ringaccount.cpp | 7 +- daemon/src/sip/sdp.cpp | 202 ++++++----- daemon/src/sip/sdp.h | 29 +- daemon/src/sip/sipaccount.cpp | 7 +- daemon/src/sip/sipaccountbase.cpp | 8 + daemon/src/sip/sipcall.cpp | 32 +- daemon/src/sip/sipvoiplink.cpp | 6 +- daemon/test/audiocodectest.cpp | 11 + daemon/test/audiocodectest.h | 9 +- daemon/test/sdptest.cpp | 7 + daemon/test/sdptest.h | 7 + daemon/test/siptest.cpp | 8 + daemon/test/tlstest.cpp | 8 + gnome/src/config/videoconf.c | 71 ++-- .../dbus/configurationmanager-introspec.xml | 6 +- gnome/src/dbus/dbus.c | 22 +- gnome/src/dbus/dbus.h | 6 +- gnome/src/dbus/videomanager-introspec.xml | 28 +- 49 files changed, 1282 insertions(+), 591 deletions(-) create mode 100644 daemon/src/media/media_codec.cpp create mode 100644 daemon/src/media/media_codec.h create mode 100644 daemon/src/media/system_codec_container.cpp create mode 100644 daemon/src/media/system_codec_container.h delete mode 100644 daemon/src/media/video/test/test_video_endpoint.cpp delete mode 100644 daemon/src/media/video/test/test_video_endpoint.h diff --git a/daemon/bin/dbus/configurationmanager-introspec.xml b/daemon/bin/dbus/configurationmanager-introspec.xml index f898eea96d..90cadcd6cc 100644 --- a/daemon/bin/dbus/configurationmanager-introspec.xml +++ b/daemon/bin/dbus/configurationmanager-introspec.xml @@ -370,12 +370,12 @@ <method name="getAudioCodecList" tp:name-for-bindings="getAudioCodecList"> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorInt"/> - <arg type="ai" name="list" direction="out"> + <arg type="au" name="list" direction="out"> </arg> </method> <method name="getAudioCodecDetails" tp:name-for-bindings="getAudioCodecDetails"> - <arg type="i" name="payload" direction="in"> + <arg type="u" name="codecId" direction="in"> </arg> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="as" name="details" direction="out"> @@ -386,7 +386,7 @@ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorInt"/> <arg type="s" name="accountID" direction="in"> </arg> - <arg type="ai" name="list" direction="out"> + <arg type="au" name="list" direction="out"> </arg> </method> diff --git a/daemon/bin/dbus/dbusconfigurationmanager.cpp b/daemon/bin/dbus/dbusconfigurationmanager.cpp index 9e755763ed..d658d83672 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.cpp +++ b/daemon/bin/dbus/dbusconfigurationmanager.cpp @@ -116,9 +116,9 @@ DBusConfigurationManager::getSupportedCiphers(const std::string& accountID) -> d } auto -DBusConfigurationManager::getAudioCodecDetails(const int32_t& payload) -> decltype(DRing::getAudioCodecDetails(payload)) +DBusConfigurationManager::getAudioCodecDetails(const unsigned& codecId) -> decltype(DRing::getAudioCodecDetails(codecId)) { - return DRing::getAudioCodecDetails(payload); + return DRing::getAudioCodecDetails(codecId); } auto diff --git a/daemon/bin/dbus/dbusconfigurationmanager.h b/daemon/bin/dbus/dbusconfigurationmanager.h index 940e685796..2672c803c8 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.h +++ b/daemon/bin/dbus/dbusconfigurationmanager.h @@ -76,10 +76,10 @@ class DBusConfigurationManager : void registerAllAccounts(void); std::map<std::string, std::string> getTlsDefaultSettings(); std::vector<std::string> getSupportedCiphers(const std::string& accountID); - std::vector<int32_t> getAudioCodecList(); + std::vector<unsigned> getAudioCodecList(); std::vector<std::string> getSupportedTlsMethod(); - std::vector<std::string> getAudioCodecDetails(const int32_t& payload); - std::vector<int32_t> getActiveAudioCodecList(const std::string& accountID); + std::vector<std::string> getAudioCodecDetails(const unsigned& codecId); + std::vector<unsigned> getActiveAudioCodecList(const std::string& accountID); void setActiveAudioCodecList(const std::vector<std::string>& list, const std::string& accountID); std::vector<std::string> getAudioPluginList(); void setAudioPlugin(const std::string& audioPlugin); diff --git a/daemon/bin/dbus/dbusvideomanager.cpp b/daemon/bin/dbus/dbusvideomanager.cpp index e69e1e4a15..3aa48e1e31 100644 --- a/daemon/bin/dbus/dbusvideomanager.cpp +++ b/daemon/bin/dbus/dbusvideomanager.cpp @@ -29,8 +29,6 @@ */ #include "dbusvideomanager.h" -#include "managerimpl.h" -#include "manager.h" #include "client/videomanager.h" DBusVideoManager::DBusVideoManager(DBus::Connection& connection) @@ -38,15 +36,21 @@ DBusVideoManager::DBusVideoManager(DBus::Connection& connection) {} auto -DBusVideoManager::getCodecs(const std::string& accountID) -> decltype(DRing::getCodecs(accountID)) +DBusVideoManager::getVideoCodecList(const std::string& accountID) -> decltype(DRing::getVideoCodecList(accountID)) { - return DRing::getCodecs(accountID); + return DRing::getVideoCodecList(accountID); +} + +auto +DBusVideoManager::getVideoCodecDetails(const unsigned& codecId) -> decltype(DRing::getVideoCodecDetails(codecId)) +{ + return DRing::getVideoCodecDetails(codecId); } void -DBusVideoManager::setCodecs(const std::string& accountID, const std::vector<std::map<std::string, std::string>>& details) +DBusVideoManager::setVideoCodecList(const std::string& accountID, const std::vector<unsigned> &list) { - DRing::setCodecs(accountID, details); + DRing::setVideoCodecList(accountID, list); } auto diff --git a/daemon/bin/dbus/dbusvideomanager.h b/daemon/bin/dbus/dbusvideomanager.h index 7d2d279804..33e2def9f8 100644 --- a/daemon/bin/dbus/dbusvideomanager.h +++ b/daemon/bin/dbus/dbusvideomanager.h @@ -57,13 +57,13 @@ class DBusVideoManager : public DBus::IntrospectableAdaptor, public DBus::ObjectAdaptor { - public: DBusVideoManager(DBus::Connection& connection); // Methods - std::vector<std::map<std::string, std::string>> getCodecs(const std::string& accountID); - void setCodecs(const std::string& accountID, const std::vector<std::map<std::string, std::string>>& details); + std::vector<unsigned > getVideoCodecList(const std::string& accountID); + std::vector<std::string> getVideoCodecDetails(const unsigned& codecId); + void setVideoCodecList(const std::string& accountID, const std::vector<unsigned>& list); std::vector<std::string> getDeviceList(); std::map<std::string, std::map<std::string, std::vector<std::string>>> getCapabilities(const std::string& name); std::map<std::string, std::string> getSettings(const std::string& name); diff --git a/daemon/bin/dbus/videomanager-introspec.xml b/daemon/bin/dbus/videomanager-introspec.xml index de9761b9fb..d78e281643 100644 --- a/daemon/bin/dbus/videomanager-introspec.xml +++ b/daemon/bin/dbus/videomanager-introspec.xml @@ -49,24 +49,31 @@ <!-- Video Codec related methods --> - <method name="getCodecs" tp:name-for-bindings="getCodecs"> - <tp:docstring>Gets the hashtable describing all the codecs and their parameters for a given account</tp:docstring> + <method name="getVideoCodecList" tp:name-for-bindings="getVideoCodecList"> <arg type="s" name="accountID" direction="in"> </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> - <arg type="aa{ss}" name="details" direction="out"> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorInt"/> + <arg type="au" name="list" direction="out"> </arg> </method> - <method name="setCodecs" tp:name-for-bindings="setCodecs"> - <tp:docstring>Sets a vector of hashtables describing codecs and their parameters for a given account, one hashtable per codec</tp:docstring> - <arg type="s" name="accountID" direction="in"> - </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorMapStringString"/> - <arg type="aa{ss}" name="details" direction="in"> - </arg> + <method name="getVideoCodecDetails" tp:name-for-bindings="getVideoCodecDetails"> + <arg type="u" name="codecid" direction="in"> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="details" direction="out"> + </arg> </method> + <method name="setVideoCodecList" tp:name-for-bindings="setVideoCodecList"> + <tp:docstring>Sets a vector of hashtables describing codecs and their parameters for a given account, one hashtable per codec</tp:docstring> + <arg type="s" name="accountID" direction="in"> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorInt"/> + <arg type="au" name="list" direction="in"> + </arg> + </method> + <method name="startCamera" tp:name-for-bindings="startCamera"> <tp:docstring> Starts the video camera, which renders the active v4l2 device's video to shared memory. Useful for testing/debugging camera settings</tp:docstring> </method> diff --git a/daemon/src/account.cpp b/daemon/src/account.cpp index 28c9cdfb26..c0bd05f3a3 100644 --- a/daemon/src/account.cpp +++ b/daemon/src/account.cpp @@ -51,11 +51,13 @@ #include "account_schema.h" #include "string_utils.h" #include "config/yamlparser.h" +#include "system_codec_container.h" #include <yaml-cpp/yaml.h> #include "upnp/upnp_control.h" #include "ip_utils.h" +#include "intrin.h" namespace ring { @@ -85,12 +87,7 @@ const char * const Account::HAS_CUSTOM_USER_AGENT_KEY = "hasCustomUserAgent"; const char * const Account::PRESENCE_MODULE_ENABLED_KEY = "presenceModuleEnabled"; const char * const Account::UPNP_ENABLED_KEY = "upnpEnabled"; -using std::map; -using std::string; -using std::vector; - - -Account::Account(const string &accountID) +Account::Account(const std::string &accountID) : accountID_(accountID) , username_() , hostname_() @@ -98,9 +95,10 @@ Account::Account(const string &accountID) , enabled_(true) , autoAnswerEnabled_(false) , registrationState_(RegistrationState::UNREGISTERED) - , audioCodecList_() - , videoCodecList_() + , systemCodecContainer_(getSystemCodecContainer()) + , accountCodecInfoList_() , audioCodecStr_() + , videoCodecStr_() , ringtonePath_("") , ringtoneEnabled_(true) , displayName_("") @@ -126,13 +124,13 @@ Account::~Account() {} void -Account::attachCall(const string& id) +Account::attachCall(const std::string& id) { callIDSet_.insert(id); } void -Account::detachCall(const string& id) +Account::detachCall(const std::string& id) { callIDSet_.erase(id); } @@ -145,7 +143,8 @@ Account::freeAccount() doUnregister(); } -void Account::setRegistrationState(RegistrationState state) +void +Account::setRegistrationState(RegistrationState state) { if (state != registrationState_) { registrationState_ = state; @@ -158,31 +157,41 @@ void Account::setRegistrationState(RegistrationState state) } } -void Account::loadDefaultCodecs() +void +Account::loadDefaultCodecs() { - // TODO - // CodecMap codecMap = Manager::instance ().getCodecDescriptorMap ().getCodecsMap(); - - // Initialize codec - vector<string> result; - result.push_back("0"); - result.push_back("3"); - result.push_back("8"); - result.push_back("9"); - result.push_back("104"); - result.push_back("110"); - result.push_back("111"); - result.push_back("112"); + // default codec are system codecs + auto systemCodecList = systemCodecContainer_->getSystemCodecInfoList(); + + for (const auto& systemCodec: systemCodecList) { + // only take encoders and or decoders + if (systemCodec->codecType & CODEC_UNDEFINED) + continue; + + if (systemCodec->mediaType & MEDIA_AUDIO) { + // we are sure of our downcast type : use static_pointer_cast + auto audioCodec = std::static_pointer_cast<SystemAudioCodecInfo>(systemCodec); + // instantiate AccountAudioCodecInfo initialized with our system codec + auto codec = std::make_shared <AccountAudioCodecInfo>(*audioCodec); + accountCodecInfoList_.push_back(codec); + RING_DBG("[%s] loading audio codec = %s", accountID_.c_str(), + codec->systemCodecInfo.name.c_str()); + } - setActiveAudioCodecs(result); -#ifdef RING_VIDEO - // we don't need to validate via setVideoCodecs, since these are defaults - videoCodecList_ = libav_utils::getDefaultVideoCodecs(); -#endif + if (systemCodec->mediaType & MEDIA_VIDEO) { + // we are sure of our downcast type : use static_pointer_cast + auto videoCodec = std::static_pointer_cast<SystemVideoCodecInfo>(systemCodec); + // instantiate AccountVideoCodecInfo initialized with our system codec + auto codec = std::make_shared<AccountVideoCodecInfo>(*videoCodec); + accountCodecInfoList_.push_back(codec); + RING_DBG("[%s] loading video codec = %s", accountID_.c_str(), + codec->systemCodecInfo.name.c_str()); + } + } } - -void Account::serialize(YAML::Emitter &out) +void +Account::serialize(YAML::Emitter &out) { out << YAML::Key << ID_KEY << YAML::Value << accountID_; out << YAML::Key << ALIAS_KEY << YAML::Value << alias_; @@ -201,7 +210,8 @@ void Account::serialize(YAML::Emitter &out) out << YAML::Key << UPNP_ENABLED_KEY << YAML::Value << upnpEnabled_; } -void Account::unserialize(const YAML::Node &node) +void +Account::unserialize(const YAML::Node &node) { using yaml_utils::parseValue; @@ -229,7 +239,8 @@ void Account::unserialize(const YAML::Node &node) upnpEnabled_.store(enabled); } -void Account::setAccountDetails(const std::map<std::string, std::string> &details) +void +Account::setAccountDetails(const std::map<std::string, std::string> &details) { // Account setting common to SIP and IAX parseString(details, Conf::CONFIG_ACCOUNT_ALIAS, alias_); @@ -251,7 +262,8 @@ void Account::setAccountDetails(const std::map<std::string, std::string> &detail upnpEnabled_.store(enabled); } -std::map<std::string, std::string> Account::getAccountDetails() const +std::map<std::string, std::string> +Account::getAccountDetails() const { std::map<std::string, std::string> a; @@ -277,7 +289,8 @@ std::map<std::string, std::string> Account::getAccountDetails() const return a; } -std::map<std::string, std::string> Account::getVolatileAccountDetails() const +std::map<std::string, std::string> +Account::getVolatileAccountDetails() const { std::map<std::string, std::string> a; @@ -286,33 +299,40 @@ std::map<std::string, std::string> Account::getVolatileAccountDetails() const } #ifdef RING_VIDEO +/* +* TODO ebail : * +* video codec information format changed (merged with audio mechanism) +* we need thus to adapt serialization / unserialization to it +* +*/ +#if 0 static bool -isPositiveInteger(const string &s) +isPositiveInteger(const std::string& s) { - string::const_iterator it = s.begin(); + std::string::const_iterator it = s.begin(); while (it != s.end() and std::isdigit(*it)) ++it; return not s.empty() and it == s.end(); } static bool -isBoolean(const string &s) +isBoolean(const std::string& s) { return s == "true" or s == "false"; } template <typename Predicate> static bool -isFieldValid(const map<string, string> &codec, const char *field, Predicate p) +isFieldValid(const std::map<std::string, std::string>& codec, const char* field, Predicate p) { - map<string, string>::const_iterator key(codec.find(field)); + std::map<std::string, std::string>::const_iterator key(codec.find(field)); return key != codec.end() and p(key->second); } static bool -isCodecValid(const map<string, string> &codec, const vector<map<string, string> > &defaults) +isCodecValid(const std::map<std::string, std::string>& codec, const std::vector<std::map<std::string, std::string>>& defaults) { - const map<string, string>::const_iterator name(codec.find(Account::VIDEO_CODEC_NAME)); + const std::map<std::string, std::string>::const_iterator name(codec.find(Account::VIDEO_CODEC_NAME)); if (name == codec.end()) { RING_ERR("Field \"name\" missing in codec specification"); return false; @@ -329,10 +349,20 @@ isCodecValid(const map<string, string> &codec, const vector<map<string, string> RING_ERR("Codec %s not supported", name->second.c_str()); return false; } +#endif // ebail static bool -isCodecListValid(const vector<map<string, string> > &list) +isCodecListValid(const std::vector<unsigned>& list UNUSED) { +/* +* TODO ebail : * +* video codec information format changed (merged with audio mechanism) +* we need thus to adapt serialization / unserialization to it +* +*/ +#if 1 /* ebail : for the moment always return true */ + return true; +#else const auto defaults(libav_utils::getDefaultVideoCodecs()); if (list.size() != defaults.size()) { RING_ERR("New codec list has a different length than the list of supported codecs"); @@ -345,10 +375,12 @@ isCodecListValid(const vector<map<string, string> > &list) return false; } return true; +#endif // ebail } -#endif +#endif // RING_VIDEO -void Account::setVideoCodecs(const vector<map<string, string> > &list) +void +Account::setVideoCodecs(const std::vector<unsigned> &list) { #ifdef RING_VIDEO if (isCodecListValid(list)) @@ -362,30 +394,55 @@ void Account::setVideoCodecs(const vector<map<string, string> > &list) // Required format: payloads separated by slashes. // @return std::string The serializable string static std::string -join_string(const std::vector<std::string> &v) +join_string(const std::vector<unsigned> &v) { std::ostringstream os; - std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(os, "/")); + std::copy(v.begin(), v.end(), std::ostream_iterator<unsigned>(os, "/")); return os.str(); } -void Account::setActiveAudioCodecs(const vector<string> &list) +std::vector<unsigned> +Account::getActiveAudioCodecs() const +{ + return getActiveAccountCodecInfoIdList(MEDIA_AUDIO); +} + +void +Account::setActiveAudioCodecs(const std::vector<std::string>& list) { // first clear the previously stored codecs - audioCodecList_.clear(); + // TODO: mutex to protect isActive + desactivateAllMedia(MEDIA_AUDIO); // list contains the ordered payload of active codecs picked by the user for this account // we used the codec vector to save the order. - for (const auto &item : list) { - int payload = std::atoi(item.c_str()); - audioCodecList_.push_back(payload); + uint16_t order = 1; + for (const auto& item : list) { + auto codecId = std::atoi(item.c_str()); + if (auto accCodec = searchCodecById(codecId, MEDIA_AUDIO)) { + accCodec->isActive = true; + accCodec->order = order; + ++order; + } } - // update the codec string according to new codec selection - audioCodecStr_ = join_string(list); + std::sort(std::begin(accountCodecInfoList_), + std::end (accountCodecInfoList_), + [](std::shared_ptr<AccountCodecInfo> a, + std::shared_ptr<AccountCodecInfo> b) { + return a->order < b->order; + }); + + audioCodecStr_ = join_string(getActiveAccountCodecInfoIdList(MEDIA_AUDIO)); + + for (const auto& item : accountCodecInfoList_) + RING_DBG("[%s] order:%d, isActive=%s, codec=%s", accountID_.c_str(), + item->order, (item->isActive ? "true" : "false"), + item->systemCodecInfo.to_string().c_str()); } -string Account::mapStateNumberToString(RegistrationState state) +std::string +Account::mapStateNumberToString(RegistrationState state) { #define CASE_STATE(X) case RegistrationState::X: \ return #X @@ -408,63 +465,44 @@ string Account::mapStateNumberToString(RegistrationState state) #undef CASE_STATE } -vector<map<string, string> > -Account::getAllVideoCodecs() const +std::vector<unsigned> +Account::getAllVideoCodecsId() const { - return videoCodecList_; + return getAccountCodecInfoIdList(MEDIA_VIDEO); } -static bool -is_inactive(const map<string, string> &codec) -{ - map<string, string>::const_iterator iter = codec.find(Account::VIDEO_CODEC_ENABLED); - return iter == codec.end() or iter->second != "true"; -} - -vector<int> +std::vector<unsigned> Account::getDefaultAudioCodecs() { - vector<int> result; - result.push_back(0); - result.push_back(3); - result.push_back(8); - result.push_back(9); - result.push_back(104); - result.push_back(110); - result.push_back(111); - result.push_back(112); - - return result; + return getSystemCodecContainer()->getSystemCodecInfoIdList(MEDIA_AUDIO); } -vector<map<string, string> > +std::vector<unsigned> Account::getActiveVideoCodecs() const { - if (not videoEnabled_) - return vector<map<string, string>>(); - - // FIXME: validate video codec details first - vector<map<string, string> > result(videoCodecList_); - result.erase(std::remove_if(result.begin(), result.end(), is_inactive), result.end()); - return result; + if (videoEnabled_) + return getActiveAccountCodecInfoIdList(MEDIA_VIDEO); + return {}; } -#define find_iter() \ - const auto iter = details.find(key); \ - if (iter == details.end()) { \ - RING_ERR("Couldn't find key \"%s\"", key); \ - return; \ - } +#define find_iter() \ + const auto& iter = details.find(key); \ + if (iter == details.end()) { \ + RING_ERR("Couldn't find key \"%s\"", key); \ + return; \ + } void -Account::parseString(const std::map<std::string, std::string> &details, const char *key, std::string &s) +Account::parseString(const std::map<std::string, std::string>& details, + const char* key, std::string& s) { find_iter(); s = iter->second; } void -Account::parseBool(const std::map<std::string, std::string> &details, const char *key, bool &b) +Account::parseBool(const std::map<std::string, std::string>& details, + const char* key, bool &b) { find_iter(); b = iter->second == TRUE_STR; @@ -477,12 +515,12 @@ Account::parseBool(const std::map<std::string, std::string> &details, const char * If use UPnP is set to false, the address will be empty. */ IpAddr -Account::getUPnPIpAddress() const { +Account::getUPnPIpAddress() const +{ std::lock_guard<std::mutex> lk(upnp_mtx); - if (not upnpEnabled_) - return {}; - - return upnp_->getExternalIP(); + if (upnpEnabled_) + return upnp_->getExternalIP(); + return {}; } /** @@ -493,10 +531,90 @@ bool Account::getUPnPActive() const { std::lock_guard<std::mutex> lk(upnp_mtx); - if (not upnpEnabled_) - return false; + if (upnpEnabled_) + return upnp_->hasValidIGD(); + return false; +} + +/* + * private account codec searching functions + * + * */ +std::shared_ptr<AccountCodecInfo> +Account::searchCodecById(unsigned codecId, MediaType mediaType) +{ + for (auto& codecIt: accountCodecInfoList_) { + if ((codecIt->systemCodecInfo.id == codecId) && + (codecIt->systemCodecInfo.mediaType & mediaType )) + return codecIt; + } + return {}; +} + +std::shared_ptr<AccountCodecInfo> +Account::searchCodecByName(std::string name, MediaType mediaType) +{ + for (auto& codecIt: accountCodecInfoList_) { + if ((codecIt->systemCodecInfo.name.compare(name) == 0) && + (codecIt->systemCodecInfo.mediaType & mediaType )) + return codecIt; + } + return {}; +} + +std::shared_ptr<AccountCodecInfo> +Account::searchCodecByPayload(unsigned payload, MediaType mediaType) +{ + for (auto& codecIt: accountCodecInfoList_) { + if ((codecIt->payloadType == payload ) && + (codecIt->systemCodecInfo.mediaType & mediaType )) + return codecIt; + } + return {}; +} - return upnp_->hasValidIGD(); +std::vector<unsigned> +Account::getActiveAccountCodecInfoIdList(MediaType mediaType) const +{ + std::vector<unsigned> idList; + for (auto& codecIt: accountCodecInfoList_) { + if ((codecIt->systemCodecInfo.mediaType & mediaType) && + (codecIt->isActive)) + idList.push_back(codecIt->systemCodecInfo.id); + } + return idList; +} + +std::vector<unsigned> +Account::getAccountCodecInfoIdList(MediaType mediaType) const +{ + std::vector<unsigned> idList; + for (auto& codecIt: accountCodecInfoList_) { + if (codecIt->systemCodecInfo.mediaType & mediaType) + idList.push_back(codecIt->systemCodecInfo.id); + } + return idList; +} + +void +Account::desactivateAllMedia(MediaType mediaType) +{ + for (auto& codecIt: accountCodecInfoList_) { + if (codecIt->systemCodecInfo.mediaType & mediaType) + codecIt->isActive = false; + } +} + +std::vector<std::shared_ptr<AccountCodecInfo>> +Account::getActiveAccountCodecInfoList(MediaType mediaType) +{ + std::vector<std::shared_ptr<AccountCodecInfo>> accountCodecList; + for (auto& codecIt: accountCodecInfoList_) { + if ((codecIt->systemCodecInfo.mediaType & mediaType) && + (codecIt->isActive)) + accountCodecList.push_back(codecIt); + } + return accountCodecList; } } // namespace ring diff --git a/daemon/src/account.h b/daemon/src/account.h index 9da2304fca..3fbbac8a1d 100644 --- a/daemon/src/account.h +++ b/daemon/src/account.h @@ -41,6 +41,7 @@ #include "config/serializable.h" #include "registration_states.h" #include "ip_utils.h" +#include "media_codec.h" #include <functional> #include <string> @@ -55,18 +56,20 @@ namespace ring { namespace upnp { class Controller; -}} +}} // namespace ring::upnp namespace YAML { class Emitter; class Node; -} +} // namespace YAML namespace ring { class Call; +class SystemCodecContainer; -class VoipLinkException : public std::runtime_error { +class VoipLinkException : public std::runtime_error +{ public: VoipLinkException(const std::string &str = "") : std::runtime_error("VoipLinkException occured: " + str) {} @@ -79,8 +82,8 @@ class VoipLinkException : public std::runtime_error { * It contains account, configuration, VoIP Link and Calls (inside the VoIPLink) */ -class Account : public Serializable, public std::enable_shared_from_this<Account> { - +class Account : public Serializable, public std::enable_shared_from_this<Account> +{ public: constexpr static const char *TRUE_STR = "true"; constexpr static const char *FALSE_STR = "false"; @@ -153,7 +156,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account * This is why no newIncomingCall() method exist here. */ - std::vector<std::shared_ptr<Call> > getCalls(); + std::vector<std::shared_ptr<Call>> getCalls(); /** * Tell if the account is enable or not. @@ -194,31 +197,27 @@ class Account : public Serializable, public std::enable_shared_from_this<Account alias_ = alias; } - std::vector<std::map<std::string, std::string> > - getAllVideoCodecs() const; - - std::vector<std::map<std::string, std::string> > - getActiveVideoCodecs() const; + std::vector<unsigned> getAllVideoCodecsId() const; + std::vector<unsigned> getActiveVideoCodecs() const; - static std::vector<int> getDefaultAudioCodecs(); + static std::vector<unsigned> getDefaultAudioCodecs(); /* Accessor to data structures * @return The list that reflects the user's choice */ - std::vector<int> getActiveAudioCodecs() const { - return audioCodecList_; - } + std::vector<unsigned> getActiveAudioCodecs() const; /** * Update both the codec order structure and the codec string used for * SDP offer and configuration respectively */ void setActiveAudioCodecs(const std::vector<std::string>& list); - void setVideoCodecs(const std::vector<std::map<std::string, std::string> > &codecs); + void setVideoCodecs(const std::vector<unsigned> &codecs); std::string getRingtonePath() const { return ringtonePath_; } + void setRingtonePath(const std::string &path) { ringtonePath_ = path; } @@ -246,7 +245,6 @@ class Account : public Serializable, public std::enable_shared_from_this<Account } void attachCall(const std::string& id); - void detachCall(const std::string& id); static const char * const VIDEO_CODEC_ENABLED; @@ -277,13 +275,14 @@ class Account : public Serializable, public std::enable_shared_from_this<Account /** * Set of call's ID attached to the account. */ - std::set<std::string> callIDSet_ = {{}}; + std::set<std::string> callIDSet_; protected: static void parseString(const std::map<std::string, std::string> &details, const char *key, std::string &s); static void parseBool(const std::map<std::string, std::string> &details, const char *key, bool &b); friend class ConfigurationTest; + // General configuration keys for accounts static const char * const AUDIO_CODECS_KEY; static const char * const VIDEO_CODECS_KEY; @@ -348,18 +347,21 @@ class Account : public Serializable, public std::enable_shared_from_this<Account /** * Vector containing the order of the codecs */ - std::vector<int> audioCodecList_; + std::shared_ptr<SystemCodecContainer> systemCodecContainer_; + std::vector<unsigned> audioCodecList_; + std::vector<std::shared_ptr<AccountCodecInfo>> accountCodecInfoList_; /** * Vector containing the video codecs in order */ - std::vector<std::map<std::string, std::string> > videoCodecList_; + std::vector<unsigned> videoCodecList_; /** * List of audio codecs obtained when parsing configuration and used * to generate codec order list */ std::string audioCodecStr_; + std::string videoCodecStr_; /** * Ringtone .au file used for this account @@ -410,6 +412,17 @@ class Account : public Serializable, public std::enable_shared_from_this<Account * flag which determines if this account is set to use UPnP. */ std::atomic_bool upnpEnabled_ {false}; + + /** + * private account codec searching functions + */ + std::shared_ptr<AccountCodecInfo> searchCodecById(unsigned codecId, MediaType mediaType); + std::shared_ptr<AccountCodecInfo> searchCodecByName(std::string name, MediaType mediaType); + std::shared_ptr<AccountCodecInfo> searchCodecByPayload(unsigned payload, MediaType mediaType); + std::vector<unsigned> getAccountCodecInfoIdList(MediaType mediaType) const; + std::vector<unsigned> getActiveAccountCodecInfoIdList(MediaType mediaType) const; + void desactivateAllMedia(MediaType mediaType); + std::vector<std::shared_ptr<AccountCodecInfo>> getActiveAccountCodecInfoList(MediaType mediaType); }; } // namespace ring diff --git a/daemon/src/client/configurationmanager.cpp b/daemon/src/client/configurationmanager.cpp index 410a8f6c37..c5ba4976b5 100644 --- a/daemon/src/client/configurationmanager.cpp +++ b/daemon/src/client/configurationmanager.cpp @@ -47,6 +47,7 @@ #include "sip/sipaccount.h" #include "security_const.h" #include "audio/audiolayer.h" +#include "system_codec_container.h" #include "client/signal.h" #include <dirent.h> @@ -91,14 +92,12 @@ getIp2IpDetails() return std::map<std::string, std::string>(); } - std::map<std::string, std::string> getAccountDetails(const std::string& accountID) { return ring::Manager::instance().getAccountDetails(accountID); } - std::map<std::string, std::string> getVolatileAccountDetails(const std::string& accountID) { @@ -231,10 +230,10 @@ getAccountList() * Send the list of all codecs loaded to the client through DBus. * Can stay global, as only the active codecs will be set per accounts */ -std::vector<int32_t> +std::vector<unsigned> getAudioCodecList() { - std::vector<int32_t> list {ring::Manager::instance().audioCodecFactory.getCodecList()}; + std::vector<unsigned> list {ring::getSystemCodecContainer()->getSystemCodecInfoIdList(ring::MEDIA_AUDIO)}; if (list.empty()) ring::emitSignal<ConfigurationSignal::Error>(CODECS_NOT_LOADED); return list; @@ -258,15 +257,16 @@ getSupportedCiphers(const std::string& accountID) } std::vector<std::string> -getAudioCodecDetails(int32_t payload) +getAudioCodecDetails(unsigned codecId) { - std::vector<std::string> result {ring::Manager::instance().audioCodecFactory.getCodecSpecifications(payload)}; - if (result.empty()) - ring::emitSignal<ConfigurationSignal::Error>(CODECS_NOT_LOADED); - return result; + auto codec = ring::getSystemCodecContainer()->searchCodecById(codecId, ring::MEDIA_AUDIO); + if (auto foundCodec = std::static_pointer_cast<ring::SystemAudioCodecInfo>(codec)) + return foundCodec->getCodecSpecifications(); + ring::emitSignal<ConfigurationSignal::Error>(CODECS_NOT_LOADED); + return {}; } -std::vector<int32_t> +std::vector<unsigned> getActiveAudioCodecList(const std::string& accountID) { if (auto acc = ring::Manager::instance().getAccount(accountID)) diff --git a/daemon/src/client/videomanager.cpp b/daemon/src/client/videomanager.cpp index 5ec3995271..cf880e0f30 100644 --- a/daemon/src/client/videomanager.cpp +++ b/daemon/src/client/videomanager.cpp @@ -38,6 +38,7 @@ #include "account.h" #include "logger.h" #include "manager.h" +#include "system_codec_container.h" #include "client/signal.h" namespace DRing { @@ -60,21 +61,29 @@ registerVideoHandlers(const std::map<std::string, } } - -std::vector<std::map<std::string, std::string>> -getCodecs(const std::string& accountID) +std::vector<unsigned> +getVideoCodecList(const std::string& accountID) { if (auto acc = ring::Manager::instance().getAccount(accountID)) - return acc->getAllVideoCodecs(); + return acc->getAllVideoCodecsId(); + return {}; +} + +std::vector<std::string> +getVideoCodecDetails(unsigned codecId) +{ + auto codec = ring::getSystemCodecContainer()->searchCodecById(codecId, ring::MEDIA_VIDEO); + if (auto foundCodec = std::static_pointer_cast<ring::SystemVideoCodecInfo>(codec)) + return foundCodec->getCodecSpecifications(); return {}; } void -setCodecs(const std::string& accountID, - const std::vector<std::map<std::string, std::string>>& details) +setVideoCodecList(const std::string& accountID, + const std::vector<unsigned>& list) { if (auto acc = ring::Manager::instance().getAccount(accountID)) { - acc->setVideoCodecs(details); + acc->setVideoCodecs(list); ring::Manager::instance().saveConfig(); } } diff --git a/daemon/src/client/videomanager.h b/daemon/src/client/videomanager.h index c7772faa62..6124c639e0 100644 --- a/daemon/src/client/videomanager.h +++ b/daemon/src/client/videomanager.h @@ -43,7 +43,6 @@ #include "video/video_base.h" #include "video/video_input.h" - namespace ring { struct VideoManager diff --git a/daemon/src/dring/configurationmanager_interface.h b/daemon/src/dring/configurationmanager_interface.h index e5847313f8..e4afb165a6 100644 --- a/daemon/src/dring/configurationmanager_interface.h +++ b/daemon/src/dring/configurationmanager_interface.h @@ -100,11 +100,11 @@ void registerAllAccounts(void); std::map<std::string, std::string> getTlsDefaultSettings(); -std::vector<int32_t> getAudioCodecList(); +std::vector<unsigned> getAudioCodecList(); std::vector<std::string> getSupportedTlsMethod(); std::vector<std::string> getSupportedCiphers(const std::string& accountID); -std::vector<std::string> getAudioCodecDetails(int32_t payload); -std::vector<int32_t> getActiveAudioCodecList(const std::string& accountID); +std::vector<std::string> getAudioCodecDetails(unsigned codecId); +std::vector<unsigned> getActiveAudioCodecList(const std::string& accountID); void setActiveAudioCodecList(const std::vector<std::string>& list, const std::string& accountID); diff --git a/daemon/src/dring/videomanager_interface.h b/daemon/src/dring/videomanager_interface.h index 5f683e9f58..acb66d89c9 100644 --- a/daemon/src/dring/videomanager_interface.h +++ b/daemon/src/dring/videomanager_interface.h @@ -64,8 +64,9 @@ struct VideoSignal { void registerVideoHandlers(const std::map<std::string, std::shared_ptr<CallbackWrapperBase>>&); -std::vector<std::map<std::string, std::string>> getCodecs(const std::string& accountID); -void setCodecs(const std::string& accountID, const std::vector<std::map<std::string, std::string>>& details); +std::vector<unsigned> getVideoCodecList(const std::string& accountID); +std::vector<std::string> getVideoCodecDetails(unsigned codecId); +void setVideoCodecList(const std::string& accountID, const std::vector<unsigned>& list); std::vector<std::string> getDeviceList(); VideoCapabilities getCapabilities(const std::string& name); std::map<std::string, std::string> getSettings(const std::string& name); diff --git a/daemon/src/iax/iaxcall.cpp b/daemon/src/iax/iaxcall.cpp index 3f7710ad7d..4e976aa1bd 100644 --- a/daemon/src/iax/iaxcall.cpp +++ b/daemon/src/iax/iaxcall.cpp @@ -81,15 +81,15 @@ IAXCall::IAXCall(IAXAccount& account, const std::string& id, Call::CallType type ringbuffer_ = Manager::instance().getRingBufferPool().createRingBuffer(getCallId()); } -int IAXCall::getSupportedFormat(const std::string &accountID) const +int +IAXCall::getSupportedFormat(const std::string &accountID) const { - using std::vector; const auto account = Manager::instance().getAccount(accountID); int format_mask = 0; if (account) { - vector<int> codecs(account->getActiveAudioCodecs()); + std::vector<unsigned> codecs{account->getActiveAudioCodecs()}; for (const auto &i : codecs) format_mask |= codecToASTFormat(i); @@ -99,13 +99,13 @@ int IAXCall::getSupportedFormat(const std::string &accountID) const return format_mask; } -int IAXCall::getFirstMatchingFormat(int needles, const std::string &accountID) const +int +IAXCall::getFirstMatchingFormat(int needles, const std::string &accountID) const { - using std::vector; const auto account = Manager::instance().getAccount(accountID); if (account != NULL) { - vector<int> codecs(account->getActiveAudioCodecs()); + std::vector<unsigned> codecs{account->getActiveAudioCodecs()}; for (const auto &i : codecs) { int format_mask = codecToASTFormat(i); @@ -120,7 +120,8 @@ int IAXCall::getFirstMatchingFormat(int needles, const std::string &accountID) c return 0; } -int IAXCall::getAudioCodec() const +int +IAXCall::getAudioCodecPayload() const { switch (format) { case AST_FORMAT_ULAW: diff --git a/daemon/src/iax/iaxcall.h b/daemon/src/iax/iaxcall.h index 3545d635a6..54bb031d9b 100644 --- a/daemon/src/iax/iaxcall.h +++ b/daemon/src/iax/iaxcall.h @@ -86,7 +86,7 @@ class IAXCall : public Call */ int getFirstMatchingFormat(int needles, const std::string &accountID) const; - int getAudioCodec() const; + int getAudioCodecPayload() const; int format; iax_session* session; diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index 5b4daf3298..86ec4fe683 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -47,6 +47,8 @@ #include "map_utils.h" #include "call_factory.h" #include "ring_types.h" +#include "system_codec_container.h" +#include "intrin.h" // for UNUSED namespace ring { @@ -152,13 +154,13 @@ IAXVoIPLink::sendAudioFromMic() if (currentCall->getState() != Call::ACTIVE) continue; - int codecType = currentCall->getAudioCodec(); - auto audioCodec = Manager::instance().audioCodecFactory.getCodec(codecType).get(); - + int codecType = currentCall->getAudioCodecPayload(); + auto codec = getSystemCodecContainer()->searchCodecByPayload(codecType, MEDIA_AUDIO); + auto audioCodec = std::static_pointer_cast<SystemAudioCodecInfo>(codec); if (!audioCodec) continue; - Manager::instance().getRingBufferPool().setInternalSamplingRate(audioCodec->getClockRate()); + Manager::instance().getRingBufferPool().setInternalSamplingRate(audioCodec->sampleRate); unsigned int mainBufferSampleRate = Manager::instance().getRingBufferPool().getInternalSamplingRate(); @@ -173,10 +175,10 @@ IAXVoIPLink::sendAudioFromMic() rawBuffer_.resize(samples); samples = Manager::instance().getRingBufferPool().getData(rawBuffer_, currentCall->getCallId()); - int compSize; - unsigned int audioRate = audioCodec->getClockRate(); + int compSize = 0; + unsigned int audioRate = audioCodec->sampleRate; int outSamples; - AudioBuffer *in; + UNUSED AudioBuffer *in; if (audioRate != mainBufferSampleRate) { rawBuffer_.setSampleRate(audioRate); @@ -189,12 +191,21 @@ IAXVoIPLink::sendAudioFromMic() in = &rawBuffer_; } + /* + * TODO ebail : * + * IAX use old codec API (based on audiocodec wrapper) + * It does not use libav API + * We disable it for the moment + */ +#if 0 compSize = audioCodec->encode(in->getData(), encodedData_, RAW_BUFFER_SIZE); +#endif if (currentCall->session and samples > 0) { std::lock_guard<std::mutex> lock(mutexIAX); - if (iax_send_voice(currentCall->session, currentCall->format, encodedData_, compSize, outSamples) == -1) + if (iax_send_voice(currentCall->session, currentCall->format, + encodedData_, compSize, outSamples) == -1) RING_ERR("IAX: Error sending voice data."); } } @@ -329,27 +340,35 @@ IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall& call) if (!event->datalen) return; - auto audioCodec = Manager::instance().audioCodecFactory.getCodec(call.getAudioCodec()).get(); + auto codec = getSystemCodecContainer()->searchCodecByPayload(call.getAudioCodecPayload(), MEDIA_AUDIO); + auto audioCodec = std::dynamic_pointer_cast<SystemAudioCodecInfo>(codec); if (!audioCodec) return; - Manager::instance().getRingBufferPool().setInternalSamplingRate(audioCodec->getClockRate()); + Manager::instance().getRingBufferPool().setInternalSamplingRate(audioCodec->sampleRate); unsigned int mainBufferSampleRate = Manager::instance().getRingBufferPool().getInternalSamplingRate(); if (event->subclass) call.format = event->subclass; - unsigned char *data = (unsigned char*) event->data; unsigned int size = event->datalen; - - unsigned int max = audioCodec->getClockRate() * 20 / 1000; + unsigned int max = audioCodec->sampleRate * 20 / 1000; if (size > max) size = max; + /* + * TODO ebail : * + * IAX use old codec API (based on audiocodec wrapper) + * It does not use libav API + * We disable it for the moment + */ +#if 0 + unsigned char *data = (unsigned char*) event->data; audioCodec->decode(rawBuffer_.getData(), data , size); +#endif AudioBuffer *out = &rawBuffer_; - unsigned int audioRate = audioCodec->getClockRate(); + unsigned int audioRate = audioCodec->sampleRate; if (audioRate != mainBufferSampleRate) { rawBuffer_.setSampleRate(mainBufferSampleRate); diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index cb709ce9ac..a803e75e6b 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -157,7 +157,7 @@ ManagerImpl::ManagerImpl() : pluginManager_(new PluginManager) , preferences(), voipPreferences(), hookPreference(), audioPreference(), shortcutPreferences(), - hasTriedToRegister_(false), audioCodecFactory(*pluginManager_), + hasTriedToRegister_(false), currentCallMutex_(), dtmfKey_(), dtmfBuf_(0, AudioFormat::MONO()), toneMutex_(), telephoneTone_(), audiofile_(), audioLayerMutex_(), waitingCalls_(), waitingCallsMutex_(), path_() diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index ec943c945b..ed14a7fcf6 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -56,7 +56,6 @@ #include "audio/audiolayer.h" #include "audio/sound/tone.h" // for Tone::TONEID declaration -#include "audio/codecs/audiocodecfactory.h" #include "preferences.h" #include "history/history.h" @@ -743,8 +742,6 @@ class ManagerImpl { */ std::vector<std::string> loadAccountOrder() const; - // map of codec (for configlist request) - const AudioCodecFactory audioCodecFactory; private: void removeAccounts(); diff --git a/daemon/src/media/Makefile.am b/daemon/src/media/Makefile.am index 3e587e4ef1..d865e4b6ca 100644 --- a/daemon/src/media/Makefile.am +++ b/daemon/src/media/Makefile.am @@ -10,18 +10,22 @@ endif libmedia_la_SOURCES = \ libav_utils.cpp \ - socket_pair.cpp \ - media_decoder.cpp \ - media_encoder.cpp \ - media_io_handle.cpp + socket_pair.cpp \ + media_decoder.cpp \ + media_encoder.cpp \ + media_io_handle.cpp \ + media_codec.cpp \ + system_codec_container.cpp noinst_HEADERS = \ libav_utils.h \ libav_deps.h \ socket_pair.h \ - media_decoder.h \ - media_encoder.h \ - media_io_handle.h + media_decoder.h \ + media_encoder.h \ + media_io_handle.h \ + media_codec.h \ + system_codec_container.h libmedia_la_LIBADD = \ ./audio/libaudio.la diff --git a/daemon/src/media/audio/codecs/audiocodecfactory.cpp b/daemon/src/media/audio/codecs/audiocodecfactory.cpp index 68c5b57faf..b60cfb0000 100644 --- a/daemon/src/media/audio/codecs/audiocodecfactory.cpp +++ b/daemon/src/media/audio/codecs/audiocodecfactory.cpp @@ -51,6 +51,7 @@ #include <stdexcept> #include <sstream> +#if 0 namespace ring { AudioCodecFactory::AudioCodecFactory(PluginManager& pluginManager) @@ -336,3 +337,5 @@ AudioCodecFactory::getCodecSpecifications(const int32_t& payload) const } } // namespace ring + +#endif diff --git a/daemon/src/media/audio/codecs/audiocodecfactory.h b/daemon/src/media/audio/codecs/audiocodecfactory.h index e2da6ae48d..dcbdaef14a 100644 --- a/daemon/src/media/audio/codecs/audiocodecfactory.h +++ b/daemon/src/media/audio/codecs/audiocodecfactory.h @@ -38,6 +38,7 @@ #include <map> #include <vector> +#if 0 namespace ring { class PluginManager; @@ -173,4 +174,6 @@ class AudioCodecFactory { } // namespace ring +#endif + #endif // __CODEC_DESCRIPTOR_H__ diff --git a/daemon/src/media/libav_utils.cpp b/daemon/src/media/libav_utils.cpp index 164a33cda8..eb9abf4478 100644 --- a/daemon/src/media/libav_utils.cpp +++ b/daemon/src/media/libav_utils.cpp @@ -45,36 +45,6 @@ namespace ring { namespace libav_utils { -std::map<std::string, std::string> encoders_; - -#ifdef RING_VIDEO -std::vector<std::string> installed_video_codecs_; - -static void -findInstalledVideoCodecs() -{ - std::vector<std::string> libav_codecs; - AVCodec *p = NULL; - while ((p = av_codec_next(p))) - if (p->type == AVMEDIA_TYPE_VIDEO) - libav_codecs.push_back(p->name); - - for (const auto &it : encoders_) { - if (std::find(libav_codecs.begin(), libav_codecs.end(), it.second) != libav_codecs.end()) - installed_video_codecs_.push_back(it.first); - else - RING_ERR("Didn't find \"%s\" encoder", it.second.c_str()); - } -} - -std::vector<std::string> getVideoCodecList() -{ - if (installed_video_codecs_.empty()) - findInstalledVideoCodecs(); - return installed_video_codecs_; -} -#endif // RING_VIDEO - // protect libav/ffmpeg access static int avcodecManageMutex(void **data, enum AVLockOp op) @@ -109,10 +79,6 @@ avcodecManageMutex(void **data, enum AVLockOp op) return AVERROR(ret); } -std::map<std::string, std::string> encodersMap() -{ - return encoders_; -} static void init_once() { @@ -126,32 +92,6 @@ static void init_once() if (getDebugMode()) av_log_set_level(AV_LOG_VERBOSE); - - /* list of codecs tested and confirmed to work */ - encoders_["H264"] = "libx264"; - encoders_["H263-2000"] = "h263p"; - encoders_["VP8"] = "libvpx"; - encoders_["MP4V-ES"] = "mpeg4"; - - encoders_["PCMA"] = "pcm_alaw"; - encoders_["PCMU"] = "pcm_mulaw"; - encoders_["opus"] = "libopus"; - encoders_["G722"] = "g722"; - encoders_["speex"] = "libspeex"; - - //FFmpeg needs to be modified to allow us to send configuration - //inline, with CODEC_FLAG_GLOBAL_HEADER - //encoders["THEORA"] = "libtheora"; - - // ffmpeg hardcodes RTP output format to H263-2000 - // but it can receive H263-1998 - // encoders["H263-1998"] = "h263p"; - - // ffmpeg doesn't know RTP format for H263 (payload type = 34) - //encoders["H263"] = "h263"; -#ifdef RING_VIDEO - findInstalledVideoCodecs(); -#endif // RING_VIDEO } static std::once_flag already_called; @@ -161,27 +101,6 @@ void sfl_avcodec_init() std::call_once(already_called, init_once); } -#ifdef RING_VIDEO -std::vector<std::map<std::string, std::string> > -getDefaultVideoCodecs() -{ - const char * const DEFAULT_BITRATE = "400"; - sfl_avcodec_init(); - std::vector<std::map<std::string, std::string> > result; - for (const auto &item : installed_video_codecs_) { - std::map<std::string, std::string> codec; - // FIXME: get these keys from proper place - codec["name"] = item; - codec["bitrate"] = DEFAULT_BITRATE; - codec["enabled"] = "true"; - // FIXME: make a nicer version of this - if (item == "H264") - codec["parameters"] = DEFAULT_H264_PROFILE_LEVEL_ID; - result.push_back(codec); - } - return result; -} -#endif // RING_VIDEO int libav_pixel_format(int fmt) { diff --git a/daemon/src/media/libav_utils.h b/daemon/src/media/libav_utils.h index 47e171f211..46bb441c3b 100644 --- a/daemon/src/media/libav_utils.h +++ b/daemon/src/media/libav_utils.h @@ -42,14 +42,6 @@ namespace ring { namespace libav_utils { int libav_pixel_format(int fmt); int sfl_pixel_format(int fmt); - std::map<std::string, std::string> encodersMap(); - - std::vector<std::string> getVideoCodecList(); - -#ifdef RING_VIDEO - std::vector<std::map <std::string, std::string> > getDefaultVideoCodecs(); -#endif // RING_VIDEO - const char *const DEFAULT_H264_PROFILE_LEVEL_ID = "profile-level-id=428014"; const char *const MAX_H264_PROFILE_LEVEL_ID = "profile-level-id=640034"; diff --git a/daemon/src/media/media_codec.cpp b/daemon/src/media/media_codec.cpp new file mode 100644 index 0000000000..b55118dbdf --- /dev/null +++ b/daemon/src/media/media_codec.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2015 Savoir-Faire Linux Inc. + * Author: Eloi BAIL <eloi.bail@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include "libav_deps.h" +#include "media_codec.h" + +#include <string.h> +#include <sstream> + +namespace ring { + +static unsigned& +generateId() +{ + static unsigned id = 0; + return ++id; +} + +/* + * SystemCodecInfo + */ +SystemCodecInfo::SystemCodecInfo(unsigned avcodecId, const std::string name, + std::string libName, + MediaType mediaType, CodecType codecType, + unsigned bitrate, unsigned payloadType) + : id(generateId()) + , avcodecId(avcodecId) + , name(name) + , libName(libName) + , codecType(codecType) + , mediaType(mediaType) + , payloadType(payloadType) + , bitrate(bitrate) +{} + +SystemCodecInfo::~SystemCodecInfo() +{} + +std::string +SystemCodecInfo::to_string() const +{ + std::ostringstream out; + out << " type:" << (unsigned)codecType + << " , avcodecID:" << avcodecId + << " ,name:" << name + << " ,PT:" << payloadType + << " ,libName:" << libName + << " ,bitrate:" << bitrate; + + return out.str(); +} + +/* + * SystemAudioCodecInfo + */ +SystemAudioCodecInfo::SystemAudioCodecInfo(unsigned m_avcodecId, + const std::string m_name, + std::string m_libName, + CodecType m_type, unsigned m_bitrate, + unsigned m_sampleRate, + unsigned m_nbChannels, + unsigned m_payloadType) + : SystemCodecInfo(m_avcodecId, m_name, m_libName, MEDIA_AUDIO, m_type, m_bitrate, m_payloadType) + , sampleRate(m_sampleRate), nbChannels(m_nbChannels) +{} + +SystemAudioCodecInfo::~SystemAudioCodecInfo() +{} + +bool +SystemAudioCodecInfo::isPCMG722() const +{ + return avcodecId == AV_CODEC_ID_ADPCM_G722; +} + + +std::vector<std::string> +SystemAudioCodecInfo::getCodecSpecifications() +{ + return {name, // name of the codec + std::to_string(sampleRate), // sample rate + std::to_string(bitrate), // bit rate + std::to_string(nbChannels) // channel number + }; +} + +/* + * SystemVideoCodecInfo + */ +SystemVideoCodecInfo::SystemVideoCodecInfo(unsigned m_avcodecId, + const std::string m_name, + std::string m_libName, + CodecType m_type, + unsigned m_payloadType) + : SystemCodecInfo(m_avcodecId, m_name, m_libName, MEDIA_VIDEO, m_type, m_payloadType) +{} + +SystemVideoCodecInfo::~SystemVideoCodecInfo() +{} + +std::vector<std::string> +SystemVideoCodecInfo::getCodecSpecifications() +{ + return {name, // name of the codec + std::to_string(bitrate), // bit rate + parameters // parameters + }; +} + +AccountCodecInfo::AccountCodecInfo(const SystemCodecInfo& sysCodecInfo) + : systemCodecInfo(sysCodecInfo) + , order(0) + , isActive(true) + , payloadType(sysCodecInfo.payloadType) + , bitrate(sysCodecInfo.bitrate) +{} + +AccountCodecInfo::~AccountCodecInfo() +{} + +AccountAudioCodecInfo::AccountAudioCodecInfo(const SystemAudioCodecInfo& sysCodecInfo) + : AccountCodecInfo(sysCodecInfo) + , sampleRate(sysCodecInfo.sampleRate) + , nbChannels(sysCodecInfo.nbChannels) +{} + +AccountAudioCodecInfo::~AccountAudioCodecInfo() +{} + +AccountVideoCodecInfo::AccountVideoCodecInfo(const SystemVideoCodecInfo& sysCodecInfo) + : AccountCodecInfo(sysCodecInfo) + , frameRate(sysCodecInfo.frameRate) + , profileId(sysCodecInfo.profileId) +{} + +AccountVideoCodecInfo::~AccountVideoCodecInfo() +{} + +} // namespace ring diff --git a/daemon/src/media/media_codec.h b/daemon/src/media/media_codec.h new file mode 100644 index 0000000000..d2bed09540 --- /dev/null +++ b/daemon/src/media/media_codec.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2015 Savoir-Faire Linux Inc. + * Author: Eloi BAIL <eloi.bail@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef __MEDIA_CODEC_H__ +#define __MEDIA_CODEC_H__ + +#include "audio/audiobuffer.h" // for AudioFormat +#include "sip/sdes_negotiator.h" +#include "ip_utils.h" + +#include <string> +#include <vector> +#include <iostream> +#include <unistd.h> + +namespace ring { + +enum CodecType : unsigned { + CODEC_UNDEFINED = 0, + CODEC_ENCODER = 1, + CODEC_DECODER = 2, + CODEC_ENCODER_DECODER = CODEC_ENCODER | CODEC_DECODER +}; + +enum MediaType : unsigned { + MEDIA_UNDEFINED = 0, + MEDIA_AUDIO = 1, + MEDIA_VIDEO = 2, + MEDIA_ALL = MEDIA_AUDIO | MEDIA_VIDEO +}; + +/* + * SystemCodecInfo + * represent information of a codec available on the system (using libav) + * store default codec values + */ +struct SystemCodecInfo +{ + SystemCodecInfo(unsigned avcodecId, const std::string name, + std::string libName, MediaType mediaType, + CodecType codecType = CODEC_UNDEFINED, unsigned bitrate = 0, + unsigned payloadType = 0); + + virtual ~SystemCodecInfo(); + + /* generic codec information */ + unsigned id; /* id of the codec used with dbus */ + unsigned avcodecId; /* read as AVCodecID libav codec identifier */ + std::string name; + std::string libName; + CodecType codecType; + MediaType mediaType; + + /* default codec values */ + unsigned payloadType; + unsigned bitrate; + + std::string to_string() const; +}; + +/* + * SystemAudioCodecInfo + * represent information of a audio codec available on the system (using libav) + * store default codec values + */ +struct SystemAudioCodecInfo : SystemCodecInfo +{ + SystemAudioCodecInfo(unsigned avcodecId, const std::string name, + std::string libName, CodecType type, + unsigned bitrate = 0, + unsigned sampleRate = 0, unsigned nbChannels = 0, + unsigned payloadType = 0); + + ~SystemAudioCodecInfo(); + + std::vector<std::string> getCodecSpecifications(); + bool isPCMG722() const; + + unsigned sampleRate; + unsigned nbChannels; +}; + +/* + * SystemVideoCodecInfo + * represent information of a video codec available on the system (using libav) + * store default codec values + */ +struct SystemVideoCodecInfo : SystemCodecInfo +{ + SystemVideoCodecInfo(unsigned avcodecId, const std::string name, + std::string libName, CodecType type = CODEC_UNDEFINED, + unsigned payloadType = 0); + + ~SystemVideoCodecInfo(); + + std::vector<std::string> getCodecSpecifications(); + + unsigned frameRate; + unsigned profileId; + std::string parameters; +}; + +/* + * AccountCodecInfo + * represent information of a codec on a account + * store account codec values + */ +struct AccountCodecInfo +{ + AccountCodecInfo(const SystemCodecInfo& sysCodecInfo); + ~AccountCodecInfo(); + + const SystemCodecInfo& systemCodecInfo; + unsigned order; /*used to define prefered codec list order in UI*/ + bool isActive; + /* account custom values */ + unsigned payloadType; + unsigned bitrate; +}; + +struct AccountAudioCodecInfo : AccountCodecInfo +{ + AccountAudioCodecInfo(const SystemAudioCodecInfo& sysCodecInfo); + ~AccountAudioCodecInfo(); + + std::vector<std::string> getCodecSpecifications(); + + /* account custom values */ + unsigned sampleRate; + unsigned nbChannels; +}; + +struct AccountVideoCodecInfo : AccountCodecInfo +{ + AccountVideoCodecInfo(const SystemVideoCodecInfo& sysCodecInfo); + ~AccountVideoCodecInfo(); + + std::vector<std::string> getCodecSpecifications(); + + /* account custom values */ + unsigned frameRate; + unsigned profileId; + std::string parameters; +}; + +bool operator== (SystemCodecInfo codec1, SystemCodecInfo codec2); + +} // namespace ring + +#endif // __MEDIA_CODEC_H__ diff --git a/daemon/src/media/system_codec_container.cpp b/daemon/src/media/system_codec_container.cpp new file mode 100644 index 0000000000..b2c1596f8e --- /dev/null +++ b/daemon/src/media/system_codec_container.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2013 Savoir-Faire Linux Inc. + * Author: Eloi BAIL <eloi.bail@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include "libav_deps.h" +#include "logger.h" +#include "system_codec_container.h" + +namespace ring { + +decltype(getGlobalInstance<SystemCodecContainer>)& getSystemCodecContainer = getGlobalInstance<SystemCodecContainer>; + +SystemCodecContainer::SystemCodecContainer() +{ + initCodecConfig(); +} + +SystemCodecContainer::~SystemCodecContainer() +{ + //TODO +} + +void +SystemCodecContainer::initCodecConfig() +{ + availableCodecList_ = { + /* Define supported video codec*/ + std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_H264, + "H264", "libx264", + CODEC_ENCODER_DECODER), + + std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_H263P, + "H263-2000", "h263p", + CODEC_ENCODER_DECODER), + + // TODO : add last video codecs with correct params + + /* Define supported audio codec*/ + std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_PCM_ALAW, + "PCMA","pcm_alaw", + CODEC_ENCODER_DECODER, + 64, 8000, 1, 8), + + std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_OPUS, + "opus","libopus", + CODEC_ENCODER_DECODER, + 0, 48000, 2, 104), + + //TODO : add last audio codecs with correct params + }; + + checkInstalledCodecs(); +} + +void +SystemCodecContainer::checkInstalledCodecs() +{ + AVCodecID codecId; + std::string codecName; + CodecType codecType; + + for (const auto& codecIt: availableCodecList_) { + codecId = (AVCodecID)codecIt->avcodecId; + codecName = codecIt->name; + codecType = codecIt->codecType; + + RING_INFO("Checking codec %s", codecName.c_str()); + + if (codecType & CODEC_ENCODER) { + if (avcodec_find_encoder(codecId) != nullptr) { + RING_INFO("### Found encoder %s", codecIt->to_string().c_str()); + } else { + RING_ERR("Can not find encoder for codec %s", codecName.c_str()); + codecIt->codecType = (CodecType)((unsigned)codecType & ~CODEC_ENCODER); + } + } + + if (codecType & CODEC_DECODER) { + if (avcodec_find_decoder(codecId) != nullptr) { + RING_INFO("### Found decoder %s", codecIt->to_string().c_str()); + } else { + RING_ERR("Can not find decoder for codec %s", codecName.c_str()); + codecIt->codecType = (CodecType)((unsigned)codecType & ~CODEC_DECODER); + } + } + } +} + +std::vector<std::shared_ptr<SystemCodecInfo>> +SystemCodecContainer::getSystemCodecInfoList(MediaType mediaType) +{ + if (mediaType & MEDIA_ALL) + return availableCodecList_; + + //otherwise we have to instantiate a new list containing filtered objects + // must be destroyed by the caller... + std::vector<std::shared_ptr<SystemCodecInfo>> systemCodecList; + for (const auto& codecIt: availableCodecList_) { + if (codecIt->mediaType & mediaType) + systemCodecList.push_back(codecIt); + } + return systemCodecList; +} + +std::vector<unsigned> +SystemCodecContainer::getSystemCodecInfoIdList(MediaType mediaType) +{ + std::vector<unsigned> idList; + for (const auto& codecIt: availableCodecList_) { + if (codecIt->mediaType & mediaType) + idList.push_back(codecIt->id); + } + return idList; +} + +std::shared_ptr<SystemCodecInfo> +SystemCodecContainer::searchCodecById(unsigned codecId, MediaType mediaType) +{ + for (const auto& codecIt: availableCodecList_) { + if ((codecIt->id == codecId) && + (codecIt->mediaType & mediaType )) + return codecIt; + } + return {}; +} +std::shared_ptr<SystemCodecInfo> +SystemCodecContainer::searchCodecByName(std::string name, MediaType mediaType) +{ + for (const auto& codecIt: availableCodecList_) { + if ((codecIt->name.compare(name) == 0) && + (codecIt->mediaType & mediaType )) + return codecIt; + } + return {}; +} +std::shared_ptr<SystemCodecInfo> +SystemCodecContainer::searchCodecByPayload(unsigned payload, MediaType mediaType) +{ + for (const auto& codecIt: availableCodecList_) { + if ((codecIt->payloadType == payload ) && + (codecIt->mediaType & mediaType)) + return codecIt; + } + return {}; +} + +} // namespace ring diff --git a/daemon/src/media/system_codec_container.h b/daemon/src/media/system_codec_container.h new file mode 100644 index 0000000000..c3d7477dd6 --- /dev/null +++ b/daemon/src/media/system_codec_container.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 Savoir-Faire Linux Inc. + * Author: Eloi BAIL <eloi.bail@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef __SYSTEM_CODEC_CONTAINER_H__ +#define __SYSTEM_CODEC_CONTAINER_H__ + +#include "media_codec.h" +#include "ring_types.h" + +#include <string> +#include <vector> +#include <memory> + +namespace ring { + +class SystemCodecContainer; + +extern decltype(getGlobalInstance<SystemCodecContainer>)& getSystemCodecContainer; + +class SystemCodecContainer +{ + public: + SystemCodecContainer(); + ~SystemCodecContainer(); + + std::vector<std::shared_ptr<SystemCodecInfo>> + getSystemCodecInfoList(MediaType mediaType = MEDIA_ALL); + + std::vector<unsigned> + getSystemCodecInfoIdList(MediaType type = MEDIA_ALL); + + std::shared_ptr<SystemCodecInfo> + searchCodecById(unsigned codecId, MediaType type = MEDIA_ALL); + + std::shared_ptr<SystemCodecInfo> + searchCodecByName(std::string name, MediaType type = MEDIA_ALL); + + std::shared_ptr<SystemCodecInfo> + searchCodecByPayload(unsigned payload, MediaType type = MEDIA_ALL); + + private: + /* available audio & video codec */ + std::vector<std::shared_ptr<SystemCodecInfo>> availableCodecList_; + + void initCodecConfig(); + void checkInstalledCodecs(); +}; + +} // namespace ring + +#endif //SYSTEM_CODEC_CONTAINER diff --git a/daemon/src/media/video/test/Makefile.am b/daemon/src/media/video/test/Makefile.am index 9f454aaf68..75bb112f47 100644 --- a/daemon/src/media/video/test/Makefile.am +++ b/daemon/src/media/video/test/Makefile.am @@ -1,10 +1,7 @@ include $(top_srcdir)/globals.mak -TESTS=test_video_endpoint test_shm test_video_input test_video_rtp -check_PROGRAMS=test_video_endpoint test_video_rtp test_video_input test_shm - -test_video_endpoint_SOURCES=test_video_endpoint.cpp test_video_endpoint.h -test_video_endpoint_LDADD=$(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS) +TESTS=test_shm test_video_input test_video_rtp +check_PROGRAMS=test_video_rtp test_video_input test_shm test_video_rtp_SOURCES=test_video_rtp.cpp test_video_rtp_LDADD=$(top_builddir)/src/libring.la $(top_builddir)/src/media/video/libvideo.la $(YAML_LIBS) diff --git a/daemon/src/media/video/test/test_video_endpoint.cpp b/daemon/src/media/video/test/test_video_endpoint.cpp deleted file mode 100644 index 62b3b6d297..0000000000 --- a/daemon/src/media/video/test/test_video_endpoint.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011-2013 Savoir-Faire Linux Inc. - * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#include "test_video_endpoint.h" -#include <cstdlib> -#include <memory> -#include <iostream> -#include <cassert> -#include "libav_utils.h" - -namespace ring { namespace video { namespace test { - -void VideoEndpointTest::testListInstalledCodecs() -{ - /* This would list codecs */ - std::cout << "Installed codecs:" << std::endl; - std::vector<std::string> codecs(libav_utils::getVideoCodecList()); - std::vector<std::string>::iterator it; - for (it = codecs.begin(); it != codecs.end(); ++it) - std::cout << '\t' << *it << std::endl; -} - -}}} // namespace ring::video::test - -int main () -{ - ring::libav_utils::sfl_avcodec_init(); - ring::video::test::VideoEndpointTest test; - test.testListInstalledCodecs(); - return 0; -} diff --git a/daemon/src/media/video/test/test_video_endpoint.h b/daemon/src/media/video/test/test_video_endpoint.h deleted file mode 100644 index 090abfd54c..0000000000 --- a/daemon/src/media/video/test/test_video_endpoint.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011-2013 Savoir-Faire Linux Inc. - * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#ifndef _VIDEO_ENDPOINT_TEST_ -#define _VIDEO_ENDPOINT_TEST_ - -namespace ring { namespace video { namespace test { - -class VideoEndpointTest { -public: - void testListInstalledCodecs(); - void testCodecMap(); - void testIsSupportedCodec(); - void testRTPSession(); -}; - -}}} // namespace ring::video::test - -#endif // _VIDEO_ENDPOINT_TEST_ diff --git a/daemon/src/media/video/test/test_video_rtp.cpp b/daemon/src/media/video/test/test_video_rtp.cpp index 6718f7e47e..5db9f1ab56 100644 --- a/daemon/src/media/video/test/test_video_rtp.cpp +++ b/daemon/src/media/video/test/test_video_rtp.cpp @@ -28,19 +28,18 @@ * as that of the covered work. */ +#include "video_rtp_session.h" +#include "video_device_monitor.h" + #include <iostream> -#include <cassert> -#include <unistd.h> // for sleep #include <map> #include <string> -#include "video_rtp_session.h" -#include "video_device_monitor.h" +#include <unistd.h> // for sleep int main () { ring::video::VideoDeviceMonitor monitor; - ring::video::VideoRtpSession session("test", - monitor.getSettings(monitor.getDefaultDevice())); + ring::video::VideoRtpSession session("test", {}); session.start(12345); sleep(5); session.stop(); diff --git a/daemon/src/ringdht/ringaccount.cpp b/daemon/src/ringdht/ringaccount.cpp index 277e7b20c9..6ed82104a2 100644 --- a/daemon/src/ringdht/ringaccount.cpp +++ b/daemon/src/ringdht/ringaccount.cpp @@ -62,6 +62,7 @@ #include <yaml-cpp/yaml.h> #include "upnp/upnp_control.h" +#include "system_codec_container.h" #include <algorithm> #include <array> @@ -256,13 +257,9 @@ RingAccount::createOutgoingCall(const std::shared_ptr<SIPCall>& call, const std: // Initialize the session using ULAW as default codec in case of early media // The session should be ready to receive media once the first INVITE is sent, before // the session initialization is completed - AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); - if (!ac) + if (!getSystemCodecContainer()->searchCodecByName("PCMA", ring::MEDIA_AUDIO)) throw VoipLinkException("Could not instantiate codec for early media"); - std::vector<AudioCodec *> audioCodecs; - audioCodecs.push_back(ac); - // Building the local SDP offer auto& sdp = call->getSDP(); diff --git a/daemon/src/sip/sdp.cpp b/daemon/src/sip/sdp.cpp index 4a22128082..6ef71a6452 100644 --- a/daemon/src/sip/sdp.cpp +++ b/daemon/src/sip/sdp.cpp @@ -42,6 +42,10 @@ #include "logger.h" #include "libav_utils.h" +#include "media_codec.h" +#include "system_codec_container.h" +#include "intrin.h" // for UNUSED + #include <algorithm> #include <cassert> @@ -96,12 +100,12 @@ Sdp::~Sdp() } static bool -hasPayload(const std::vector<AudioCodec*> &codecs, int pt) +hasPayload(const std::vector<std::shared_ptr<SystemAudioCodecInfo>>& codecs, + int pt) { - for (const auto &i : codecs) - if (i and i->getPayloadType() == pt) - return true; - return false; + return std::any_of(std::begin(codecs), std::end(codecs), + [pt](const std::shared_ptr<SystemAudioCodecInfo>& c) + { return c and c->payloadType == (unsigned)pt; }); } static bool @@ -122,50 +126,59 @@ rtpmapToString(pjmedia_sdp_rtpmap *rtpmap) return os.str(); } -static AudioCodec * +std::shared_ptr<SystemCodecInfo> findCodecByName(const std::string &codec) { // try finding by name - return Manager::instance().audioCodecFactory.getCodec(codec).get(); + return getSystemCodecContainer()->searchCodecByName(codec); } -void Sdp::setActiveLocalSdpSession(const pjmedia_sdp_session *sdp) +void +Sdp::setActiveLocalSdpSession(const pjmedia_sdp_session* sdp) { activeLocalSession_ = (pjmedia_sdp_session*) sdp; sessionAudioMediaLocal_.clear(); for (unsigned i = 0; i < activeLocalSession_->media_count; ++i) { - pjmedia_sdp_media *current = activeLocalSession_->media[i]; + auto current = activeLocalSession_->media[i]; for (unsigned fmt = 0; fmt < current->desc.fmt_count; ++fmt) { static const pj_str_t STR_RTPMAP = { (char*) "rtpmap", 6 }; - pjmedia_sdp_attr *rtpMapAttribute = pjmedia_sdp_media_find_attr(current, &STR_RTPMAP, ¤t->desc.fmt[fmt]); + auto rtpMapAttribute = pjmedia_sdp_media_find_attr(current, &STR_RTPMAP, ¤t->desc.fmt[fmt]); if (!rtpMapAttribute) { RING_ERR("Could not find rtpmap attribute"); break; } - pjmedia_sdp_rtpmap *rtpmap; + pjmedia_sdp_rtpmap* rtpmap; // pool managed pjmedia_sdp_attr_to_rtpmap(memPool_.get(), rtpMapAttribute, &rtpmap); if (!pj_stricmp2(¤t->desc.media, "audio")) { - const unsigned long pt = pj_strtoul(¤t->desc.fmt[fmt]); - if (pt != telephoneEventPayload_ and not hasPayload(sessionAudioMediaLocal_, pt)) { - auto codec = Manager::instance().audioCodecFactory.getCodec(pt).get(); - if (codec) - sessionAudioMediaLocal_.push_back(codec); - else { - codec = findCodecByName(rtpmapToString(rtpmap)); - if (codec) - sessionAudioMediaLocal_.push_back(codec); - else - RING_ERR("Could not get codec for name %.*s", rtpmap->enc_name.slen, rtpmap->enc_name.ptr); - } + // Add audio codec + + // Check if payloadType is not TelephoneEvent and not added yet + const auto pt = pj_strtoul(¤t->desc.fmt[fmt]); + if (pt == telephoneEventPayload_ + or hasPayload(sessionAudioMediaLocal_, pt)) + continue; + + if (auto syscodec = getSystemCodecContainer()->searchCodecByPayload(pt, MEDIA_AUDIO)) { + auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(syscodec); + sessionAudioMediaLocal_.push_back(codec); + } else if (auto syscodec = findCodecByName(rtpmapToString(rtpmap))) { + auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(syscodec); + sessionAudioMediaLocal_.push_back(codec); + } else { + RING_ERR("Could not find codec matching name %.*s", + rtpmap->enc_name.slen, rtpmap->enc_name.ptr); } + } else if (!pj_stricmp2(¤t->desc.media, "video")) { - const string codec(rtpmap->enc_name.ptr, rtpmap->enc_name.slen); + // Add video codec + + const std::string codec(rtpmap->enc_name.ptr, rtpmap->enc_name.slen); if (not hasCodec(sessionVideoMedia_, codec)) sessionVideoMedia_.push_back(codec); } @@ -173,8 +186,8 @@ void Sdp::setActiveLocalSdpSession(const pjmedia_sdp_session *sdp) } } - -void Sdp::setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp) +void +Sdp::setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp) { if (!sdp) { RING_ERR("Remote sdp is NULL"); @@ -192,7 +205,7 @@ void Sdp::setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp) if (not parsedTelelphoneEvent) { static const pj_str_t STR_TELEPHONE_EVENT = { (char*) "telephone-event", 15}; - pjmedia_sdp_attr *telephoneEvent = pjmedia_sdp_attr_find(r_media->attr_count, r_media->attr, &STR_TELEPHONE_EVENT, NULL); + auto telephoneEvent = pjmedia_sdp_attr_find(r_media->attr_count, r_media->attr, &STR_TELEPHONE_EVENT, NULL); if (telephoneEvent != NULL) { pjmedia_sdp_rtpmap *rtpmap; @@ -205,37 +218,40 @@ void Sdp::setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp) // add audio codecs from remote as needed for (unsigned fmt = 0; fmt < r_media->desc.fmt_count; ++fmt) { static const pj_str_t STR_RTPMAP = { (char*) "rtpmap", 6 }; - pjmedia_sdp_attr *rtpMapAttribute = pjmedia_sdp_media_find_attr(r_media, &STR_RTPMAP, &r_media->desc.fmt[fmt]); + auto rtpMapAttribute = pjmedia_sdp_media_find_attr(r_media, &STR_RTPMAP, &r_media->desc.fmt[fmt]); if (!rtpMapAttribute) { RING_ERR("Could not find rtpmap attribute"); break; } - pjmedia_sdp_rtpmap *rtpmap; + pjmedia_sdp_rtpmap* rtpmap; pjmedia_sdp_attr_to_rtpmap(memPool_.get(), rtpMapAttribute, &rtpmap); - const unsigned long pt = pj_strtoul(&r_media->desc.fmt[fmt]); + const auto pt = pj_strtoul(&r_media->desc.fmt[fmt]); if (pt != telephoneEventPayload_ and not hasPayload(sessionAudioMediaRemote_, pt)) { - auto codec = Manager::instance().audioCodecFactory.getCodec(pt).get(); + auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(getSystemCodecContainer()->searchCodecByPayload(pt)); if (codec) { RING_DBG("Adding codec with new payload type %d", pt); sessionAudioMediaRemote_.push_back(codec); } else { // Search by codec name, clock rate and param (channel count) - codec = findCodecByName(rtpmapToString(rtpmap)); + codec = std::static_pointer_cast<SystemAudioCodecInfo> (findCodecByName(rtpmapToString(rtpmap))); if (codec) sessionAudioMediaRemote_.push_back(codec); else RING_ERR("Could not get codec for name %.*s", rtpmap->enc_name.slen, rtpmap->enc_name.ptr); } + } else { + RING_ERR("Can not find codec matching payload %d", pt); } } } } } -string Sdp::getSessionVideoCodec() const +std::string +Sdp::getSessionVideoCodec() const { if (sessionVideoMedia_.empty()) { RING_DBG("Session video media is empty"); @@ -244,10 +260,10 @@ string Sdp::getSessionVideoCodec() const return sessionVideoMedia_[0]; } -std::vector<AudioCodec*> +std::vector<std::shared_ptr<SystemAudioCodecInfo>> Sdp::getSessionAudioMedia() const { - vector<AudioCodec*> codecs; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> codecs; // Common codecs first for (auto c : sessionAudioMediaLocal_) { @@ -261,18 +277,19 @@ Sdp::getSessionAudioMedia() const if (std::find(codecs.begin(), codecs.end(), c) == codecs.end()) codecs.push_back(c); } + // Finally, the remote codecs so we can decode them for (auto c : sessionAudioMediaRemote_) { if (std::find(codecs.begin(), codecs.end(), c) == codecs.end()) codecs.push_back(c); } - RING_DBG("Ready to decode %u audio codecs", codecs.size()); + RING_DBG("Ready to decode %u audio codecs", codecs.size()); return codecs; } -pjmedia_sdp_media * +pjmedia_sdp_media* Sdp::setMediaDescriptorLines(bool audio) { pjmedia_sdp_media *med = PJ_POOL_ZALLOC_T(memPool_.get(), pjmedia_sdp_media); @@ -286,26 +303,28 @@ Sdp::setMediaDescriptorLines(bool audio) int dynamic_payload = 96; med->desc.fmt_count = audio ? audio_codec_list_.size() : video_codec_list_.size(); - for (unsigned i = 0; i < med->desc.fmt_count; ++i) { unsigned clock_rate; string enc_name; int payload; - const char *channels = ""; + std::string channels; + unsigned channels_int; if (audio) { - AudioCodec *codec = audio_codec_list_[i]; - payload = codec->getPayloadType(); - enc_name = codec->getMimeSubtype(); - clock_rate = codec->getSDPClockRate(); - channels = codec->getSDPChannels(); + auto codec = audio_codec_list_[i]; + payload = codec->payloadType; + enc_name = codec->name; + channels_int = codec->nbChannels; + channels = std::to_string(channels_int).c_str(); // G722 requires G722/8000 media description even though it's @ 16000 Hz // See http://tools.ietf.org/html/rfc3551#section-4.5.2 - if (codec->getPayloadType () == 9) + if (codec->isPCMG722()) clock_rate = 8000; + else + clock_rate = codec->sampleRate; } else { // FIXME: get this key from header - enc_name = video_codec_list_[i]["name"]; + enc_name = video_codec_list_[i]->name; clock_rate = 90000; payload = dynamic_payload; } @@ -323,8 +342,8 @@ Sdp::setMediaDescriptorLines(bool audio) rtpmap.pt = med->desc.fmt[i]; rtpmap.enc_name = pj_str((char*) enc_name.c_str()); rtpmap.clock_rate = clock_rate; - rtpmap.param.ptr = (char *) channels; - rtpmap.param.slen = strlen(channels); // don't include NULL terminator + rtpmap.param.ptr = (char *) channels.c_str(); + rtpmap.param.slen = strlen(channels.c_str()); // don't include NULL terminator pjmedia_sdp_attr *attr; pjmedia_sdp_rtpmap_to_attr(memPool_.get(), &rtpmap, &attr); @@ -336,7 +355,7 @@ Sdp::setMediaDescriptorLines(bool audio) std::ostringstream os; // FIXME: this should not be hardcoded, it will determine what profile and level // our peer will send us - std::string profileLevelID(video_codec_list_[i]["parameters"]); + std::string profileLevelID(video_codec_list_[i]->parameters); if (profileLevelID.empty()) profileLevelID = libav_utils::MAX_H264_PROFILE_LEVEL_ID; os << "fmtp:" << dynamic_payload << " " << profileLevelID; @@ -441,27 +460,31 @@ void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med) med->attr[med->attr_count++] = attr_fmtp; } -void Sdp::setLocalMediaVideoCapabilities(const vector<map<string, string> > &codecs) +void Sdp::setLocalMediaVideoCapabilities(const vector<unsigned> &selectedCodecs) { video_codec_list_.clear(); #ifdef RING_VIDEO - if (codecs.empty()) - RING_WARN("No selected video codec while building local SDP offer"); - else - video_codec_list_ = codecs; + for (const auto &i : selectedCodecs) { + auto codec = std::static_pointer_cast<SystemVideoCodecInfo>(getSystemCodecContainer()->searchCodecById(i)); + + if (codec) + video_codec_list_.push_back(codec); + else + RING_WARN("Couldn't find video codec"); + } #else - (void) codecs; + (void) selectedCodecs; #endif } -void Sdp::setLocalMediaAudioCapabilities(const vector<int> &selectedCodecs) +void Sdp::setLocalMediaAudioCapabilities(const vector<unsigned> &selectedCodecs) { if (selectedCodecs.empty()) RING_WARN("No selected codec while building local SDP offer"); audio_codec_list_.clear(); for (const auto &i : selectedCodecs) { - auto codec = Manager::instance().audioCodecFactory.getCodec(i).get(); + auto codec = std::static_pointer_cast<SystemAudioCodecInfo>(getSystemCodecContainer()->searchCodecById(i)); if (codec) audio_codec_list_.push_back(codec); @@ -479,7 +502,7 @@ printSession(const pjmedia_sdp_session *session) RING_DBG("%s", sessionStr.c_str()); } -int Sdp::createLocalSession(const vector<int> &selectedAudioCodecs, const vector<map<string, string> > &selectedVideoCodecs) +int Sdp::createLocalSession(const vector<unsigned> &selectedAudioCodecs, const vector<unsigned> &selectedVideoCodecs) { setLocalMediaAudioCapabilities(selectedAudioCodecs); setLocalMediaVideoCapabilities(selectedVideoCodecs); @@ -533,10 +556,10 @@ int Sdp::createLocalSession(const vector<int> &selectedAudioCodecs, const vector } bool -Sdp::createOffer(const vector<int> &selectedCodecs, - const vector<map<string, string> > &videoCodecs) +Sdp::createOffer(const vector<unsigned>& selectedAudioCodecs, + const vector<unsigned>& selectedVideoCodecs) { - if (createLocalSession(selectedCodecs, videoCodecs) != PJ_SUCCESS) { + if (createLocalSession(selectedAudioCodecs, selectedVideoCodecs) != PJ_SUCCESS) { RING_ERR("Failed to create initial offer"); return false; } @@ -545,12 +568,14 @@ Sdp::createOffer(const vector<int> &selectedCodecs, RING_ERR("Failed to create an initial SDP negotiator"); return false; } + return true; } -void Sdp::receiveOffer(const pjmedia_sdp_session* remote, - const vector<int> &selectedCodecs, - const vector<map<string, string> > &videoCodecs) +void +Sdp::receiveOffer(const pjmedia_sdp_session* remote, + const vector<unsigned>& selectedAudioCodecs, + const vector<unsigned>& selectedVideoCodecs) { if (!remote) { RING_ERR("Remote session is NULL"); @@ -560,7 +585,7 @@ void Sdp::receiveOffer(const pjmedia_sdp_session* remote, RING_DBG("Remote SDP Session:"); printSession(remote); - if (!localSession_ and createLocalSession(selectedCodecs, videoCodecs) != PJ_SUCCESS) { + if (!localSession_ and createLocalSession(selectedAudioCodecs, selectedVideoCodecs) != PJ_SUCCESS) { RING_ERR("Failed to create initial offer"); return; } @@ -847,28 +872,6 @@ std::string Sdp::getOutgoingAudioChannels() const } } -static vector<map<string, string> >::const_iterator -findCodecInList(const vector<map<string, string> > &codecs, const string &codec) -{ - for (vector<map<string, string> >::const_iterator i = codecs.begin(); i != codecs.end(); ++i) { - map<string, string>::const_iterator name = i->find("name"); - if (name != i->end() and (codec == name->second)) - return i; - } - return codecs.end(); -} - -std::string -Sdp::getOutgoingVideoField(const std::string &codec, const char *key) const -{ - const vector<map<string, string> >::const_iterator i = findCodecInList(video_codec_list_, codec); - if (i != video_codec_list_.end()) { - map<string, string>::const_iterator field = i->find(key); - if (field != i->end()) - return field->second; - } - return ""; -} int Sdp::getOutgoingVideoPayload() const @@ -1110,8 +1113,15 @@ void Sdp::getRemoteSdpCryptoFromOffer(const pjmedia_sdp_session* remote_sdp, Cry } } -bool Sdp::getOutgoingVideoSettings(map<string, string> &args) const +bool Sdp::getOutgoingVideoSettings(UNUSED std::map<std::string, std::string>& args) const { + /* + * TODO ebail : * + * This function use old codec information API + * We disable it and thus video for the moment + * patch set "SDP refactoring" should fix it + * */ +#if 0 #ifdef RING_VIDEO string codec(getOutgoingVideoCodec()); if (not codec.empty()) { @@ -1121,7 +1131,8 @@ bool Sdp::getOutgoingVideoSettings(map<string, string> &args) const return false; } else { args["codec"] = encoder; - args["bitrate"] = getOutgoingVideoField(codec, "bitrate"); + //ebail will be change by adrian SDP refactoring + //args["bitrate"] = getOutgoingVideoField(codec, "bitrate"); const int payload = getOutgoingVideoPayload(); std::ostringstream os; os << payload; @@ -1133,6 +1144,7 @@ bool Sdp::getOutgoingVideoSettings(map<string, string> &args) const } #else (void) args; +#endif #endif return false; } @@ -1141,13 +1153,15 @@ bool Sdp::getOutgoingAudioSettings(map<string, string> &args) const { string codec(getOutgoingAudioCodec()); if (not codec.empty()) { - const string encoder(libav_utils::encodersMap()[codec]); - if (encoder.empty()) { - RING_DBG("Couldn't find audio encoder for \"%s\"\n", codec.c_str()); + auto audioCodec = std::static_pointer_cast<SystemAudioCodecInfo>( + getSystemCodecContainer()->searchCodecByName(codec,MEDIA_AUDIO)); + if (!audioCodec ) { + RING_DBG("Couldn't find encoder for \"%s\"\n", codec.c_str()); return false; } else { - args["codec"] = encoder; - const int payload = getOutgoingAudioPayload(); + RING_DBG("CANDIDATE: %s",audioCodec->to_string().c_str()); + args["codec"] = audioCodec->libName; + const int payload = audioCodec->payloadType; std::ostringstream os; os << payload; args["payload_type"] = os.str(); diff --git a/daemon/src/sip/sdp.h b/daemon/src/sip/sdp.h index 170c54bff5..983059ced3 100644 --- a/daemon/src/sip/sdp.h +++ b/daemon/src/sip/sdp.h @@ -35,6 +35,7 @@ #include "noncopyable.h" #include "ip_utils.h" #include "ice_transport.h" +#include "media_codec.h" #include <pjmedia/sdp.h> #include <pjmedia/sdp_neg.h> @@ -135,9 +136,8 @@ class Sdp { * SDP negotiator instance with it. * @returns true if offer was created, false otherwise */ - bool - createOffer(const std::vector<int> &selectedCodecs, - const std::vector<std::map<std::string, std::string> > &videoCodecs); + bool createOffer(const std::vector<unsigned>& selectedAudioCodecs, + const std::vector<unsigned>& selectedVideoCodecs); /* * On receiving an invite outside a dialog, build the local offer and create the @@ -146,8 +146,8 @@ class Sdp { * @param remote The remote offer */ void receiveOffer(const pjmedia_sdp_session* remote, - const std::vector<int> &selectedCodecs, - const std::vector<std::map<std::string, std::string> > &videoCodecs); + const std::vector<unsigned>& selectedAudioCodecs, + const std::vector<unsigned>& selectedVideoCodecs); /** * Start the sdp negotiation. @@ -288,7 +288,7 @@ class Sdp { void setMediaTransportInfoFromRemoteSdp(); std::string getSessionVideoCodec() const; - std::vector<AudioCodec*> getSessionAudioMedia() const; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> getSessionAudioMedia() const; // Sets @param settings with appropriate values and returns true if // we are sending video, false otherwise bool getOutgoingVideoSettings(std::map<std::string, std::string> &settings) const; @@ -353,14 +353,14 @@ class Sdp { /** * Codec Map used for offer */ - std::vector<AudioCodec *> audio_codec_list_; - std::vector<std::map<std::string, std::string> > video_codec_list_; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> audio_codec_list_; + std::vector<std::shared_ptr<SystemVideoCodecInfo>> video_codec_list_; /** * The codecs that will be used by the session (after the SDP negotiation) */ - std::vector<AudioCodec *> sessionAudioMediaLocal_; - std::vector<AudioCodec *> sessionAudioMediaRemote_; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> sessionAudioMediaLocal_; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> sessionAudioMediaRemote_; std::vector<std::string> sessionVideoMedia_; std::string publishedIpAddr_; @@ -396,13 +396,14 @@ class Sdp { * Build the local media capabilities for this session * @param List of codec in preference order */ - void setLocalMediaAudioCapabilities(const std::vector<int> &selected); - void setLocalMediaVideoCapabilities(const std::vector<std::map<std::string, std::string> > &codecs); + void setLocalMediaAudioCapabilities(const std::vector<unsigned>& selected); + void setLocalMediaVideoCapabilities(const std::vector<unsigned>& codecs); + /* * Build the local SDP offer */ - int createLocalSession(const std::vector<int> &selectedAudio, - const std::vector<std::map<std::string, std::string> > &selectedVideo); + int createLocalSession(const std::vector<unsigned>& selectedAudio, + const std::vector<unsigned>& selectedVideo); /* * Adds a sdes attribute to the given media section. * diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index cfdcc9f3d4..dd5a5d29a6 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -61,6 +61,8 @@ #include "libav_utils.h" #endif +#include "system_codec_container.h" + #include <unistd.h> #include <pwd.h> @@ -246,11 +248,12 @@ SIPAccount::newOutgoingCall(const std::string& id, const std::string& toUrl) // Initialize the session using ULAW as default codec in case of early media // The session should be ready to receive media once the first INVITE is sent, before // the session initialization is completed - AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); + auto ac = std::static_pointer_cast<SystemAudioCodecInfo> + (getSystemCodecContainer()->searchCodecByName("PCMA", MEDIA_AUDIO)); if (!ac) throw VoipLinkException("Could not instantiate codec for early media"); - std::vector<AudioCodec *> audioCodecs; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> audioCodecs; audioCodecs.push_back(ac); // Building the local SDP offer diff --git a/daemon/src/sip/sipaccountbase.cpp b/daemon/src/sip/sipaccountbase.cpp index 880b105007..d283c70eb2 100644 --- a/daemon/src/sip/sipaccountbase.cpp +++ b/daemon/src/sip/sipaccountbase.cpp @@ -131,6 +131,12 @@ void SIPAccountBase::unserialize(const YAML::Node &node) Account::unserialize(node); parseValue(node, VIDEO_ENABLED_KEY, videoEnabled_); + /* + * TODO ebail : * + * video codec information format changed (merged with audio mechanism) + * we need thus to adapt serialization / unserialization to it + */ +#if 0 const auto &vCodecNode = node[VIDEO_CODECS_KEY]; auto tmp = parseVectorMap(vCodecNode, {VIDEO_CODEC_BITRATE, VIDEO_CODEC_ENABLED, VIDEO_CODEC_NAME, VIDEO_CODEC_PARAMETERS}); #ifdef RING_VIDEO @@ -142,6 +148,8 @@ void SIPAccountBase::unserialize(const YAML::Node &node) #endif // validate it setVideoCodecs(tmp); +#endif + setVideoCodecs(getAllVideoCodecsId()); parseValue(node, Conf::INTERFACE_KEY, interface_); int port = DEFAULT_SIP_PORT; diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp index b43eee0c48..05df0371fc 100644 --- a/daemon/src/sip/sipcall.cpp +++ b/daemon/src/sip/sipcall.cpp @@ -46,6 +46,8 @@ #include "audio/audiortp/avformat_rtp_session.h" +#include "system_codec_container.h" + #if HAVE_INSTANT_MESSAGING #include "im/instant_messaging.h" #endif @@ -582,17 +584,24 @@ SIPCall::offhold() void SIPCall::internalOffHold(const std::function<void()>& /*SDPUpdateFunc*/) { + /* + * TODO ebail : * + * Hold off use old codec API (based on audiocodec wrapper) + * It does not use libav API + * patch set "SDP refactoring" should fix it + */ +#if 0 if (not setState(Call::ACTIVE)) return; - std::vector<AudioCodec*> sessionMedia(sdp_->getSessionAudioMedia()); + std::vector<SystemAudioCodecInfo*> sessionMedia(sdp_->getSessionAudioMedia()); if (sessionMedia.empty()) { RING_WARN("Session media is empty"); return; } - std::vector<AudioCodec*> audioCodecs; + std::vector<SystemAudioCodecInfo*> audioCodecs; for (auto & i : sessionMedia) { @@ -600,7 +609,7 @@ SIPCall::internalOffHold(const std::function<void()>& /*SDPUpdateFunc*/) continue; // Create a new instance for this codec - AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(i->getPayloadType()); + SystemAudioCodecInfo* ac = Manager::instance().audioCodecFactory.instantiateCodec(i->getPayloadType()); if (ac == NULL) { RING_ERR("Could not instantiate codec %d", i->getPayloadType()); @@ -629,6 +638,7 @@ SIPCall::internalOffHold(const std::function<void()>& /*SDPUpdateFunc*/) RING_WARN("Reinvite failed, resuming hold"); onhold(); } +#endif } void @@ -801,7 +811,7 @@ SIPCall::startAllMedia() CryptoOffer crypto_offer; getSDP().getRemoteSdpCryptoFromOffer(sdp_->getActiveRemoteSdpSession(), crypto_offer); - std::vector<AudioCodec*> sessionMedia(sdp_->getSessionAudioMedia()); + std::vector<std::shared_ptr<SystemAudioCodecInfo>> sessionMedia(sdp_->getSessionAudioMedia()); if (sessionMedia.empty()) { RING_WARN("Session media is empty"); @@ -811,25 +821,23 @@ SIPCall::startAllMedia() try { Manager::instance().startAudioDriverStream(); - std::vector<AudioCodec*> audioCodecs; - - for (const auto & i : sessionMedia) { + std::vector<std::shared_ptr<SystemAudioCodecInfo>> audioCodecs; + for (const auto& i : sessionMedia) { if (!i) continue; - const int pl = i->getPayloadType(); - - AudioCodec *ac = Manager::instance().audioCodecFactory.instantiateCodec(pl); + const int pl = i->payloadType; + auto ac = std::static_pointer_cast<SystemAudioCodecInfo>(getSystemCodecContainer()->searchCodecByPayload(pl)); if (!ac) { RING_ERR("Could not instantiate codec %d", pl); } else { audioCodecs.push_back(ac); } } - } catch (const SdpException &e) { + } catch (const SdpException& e) { RING_ERR("%s", e.what()); - } catch (const std::exception &rtpException) { + } catch (const std::exception& rtpException) { RING_ERR("%s", rtpException.what()); } } diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 7ec1d6c702..187451c2e7 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -55,6 +55,7 @@ #include "im/instant_messaging.h" #endif +#include "system_codec_container.h" #include "audio/audiortp/avformat_rtp_session.h" #ifdef RING_VIDEO @@ -349,14 +350,15 @@ transaction_request_cb(pjsip_rx_data *rdata) call->setupLocalSDPFromIce(); - AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); + auto ac = std::static_pointer_cast<SystemAudioCodecInfo> + (getSystemCodecContainer()->searchCodecByName("PCMA", MEDIA_AUDIO)); if (!ac) { RING_ERR("Could not instantiate codec"); return PJ_FALSE; } - std::vector<AudioCodec *> audioCodecs; + std::vector<std::shared_ptr<SystemAudioCodecInfo>> audioCodecs; audioCodecs.push_back(ac); pjsip_dialog *dialog = 0; diff --git a/daemon/test/audiocodectest.cpp b/daemon/test/audiocodectest.cpp index 2473d3fbd0..82ab0ab751 100644 --- a/daemon/test/audiocodectest.cpp +++ b/daemon/test/audiocodectest.cpp @@ -28,6 +28,15 @@ * as that of the covered work. */ +/* + * ebail - 2015/02/18 + * testCodecs unit test is based on audiocodecfactory + * we are not using it anymore + * we should make this unit test work with libav + * this test is disabled for the moment + * */ +#if 0 + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -44,6 +53,7 @@ namespace ring { namespace test { + /* * Detect the power of a signal for a given frequency. * Adapted from: @@ -119,3 +129,4 @@ void AudioCodecTest::testCodecs() } }} // namespace ring::test +#endif diff --git a/daemon/test/audiocodectest.h b/daemon/test/audiocodectest.h index 6151c9bdeb..7bc7677cfc 100644 --- a/daemon/test/audiocodectest.h +++ b/daemon/test/audiocodectest.h @@ -52,7 +52,14 @@ class AudioCodecTest: public CppUnit::TestFixture { * Use cppunit library macros to add unit test the factory */ CPPUNIT_TEST_SUITE(AudioCodecTest); - CPPUNIT_TEST(testCodecs); + /* + * ebail - 2015/02/18 + * testCodecs unit test is based on audiocodecfactory + * we are not using it anymore + * we should make this unit test work with libav + * this test is disabled for the moment + * */ + //CPPUNIT_TEST(testCodecs); CPPUNIT_TEST_SUITE_END(); static const short frequency_ = 440; diff --git a/daemon/test/sdptest.cpp b/daemon/test/sdptest.cpp index 52ab131b89..5ef2a2cac5 100644 --- a/daemon/test/sdptest.cpp +++ b/daemon/test/sdptest.cpp @@ -28,6 +28,12 @@ * as that of the covered work. */ +/* + * ebail - 2015/02/18 + * unit test is based on old SDP manager code + * this test is disabled for the moment + * */ +#if 0 #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -298,3 +304,4 @@ void SDPTest::testReinvite() } }} // namespace ring::test +#endif diff --git a/daemon/test/sdptest.h b/daemon/test/sdptest.h index b0c69d07ef..c977a2b9b6 100644 --- a/daemon/test/sdptest.h +++ b/daemon/test/sdptest.h @@ -60,6 +60,12 @@ #include "noncopyable.h" namespace ring { namespace test { +/* + * ebail - 2015/02/18 + * unit test is based on old SDP manager code + * this test is disabled for the moment + * */ +#if 0 class SdpSessionException : public std::exception { public: @@ -129,3 +135,4 @@ CPPUNIT_TEST_SUITE_REGISTRATION(SDPTest); }} // namespace ring::test #endif +#endif //_SDP_TEST_ diff --git a/daemon/test/siptest.cpp b/daemon/test/siptest.cpp index 8b113394d6..09df660ae6 100644 --- a/daemon/test/siptest.cpp +++ b/daemon/test/siptest.cpp @@ -28,6 +28,13 @@ * as that of the covered work. */ +/* + * ebail - 2015/02/18 + * unit test is deprecated + * this test is disabled for the moment + * */ +#if 0 + #include <unistd.h> #include <cstdlib> #include <cstdio> @@ -431,3 +438,4 @@ void SIPTest::testIncomingIpCallSdp() } }} // namespace ring::test +#endif diff --git a/daemon/test/tlstest.cpp b/daemon/test/tlstest.cpp index a06e9c77b4..dbbbadf434 100644 --- a/daemon/test/tlstest.cpp +++ b/daemon/test/tlstest.cpp @@ -28,6 +28,13 @@ * as that of the covered work. */ +/* + * ebail - 2015/02/18 + * unit test is based on old SDP manager code + * this test is disabled for the moment + * */ +#if 0 + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -82,3 +89,4 @@ void TlsTest::testCertificate() } }} // namespace ring::test +#endif diff --git a/gnome/src/config/videoconf.c b/gnome/src/config/videoconf.c index 7479806c1f..86943701ed 100644 --- a/gnome/src/config/videoconf.c +++ b/gnome/src/config/videoconf.c @@ -167,29 +167,25 @@ preferences_dialog_fill_codec_list(account_t *acc) GtkListStore *codecStore = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(codecTreeView))); gtk_list_store_clear(codecStore); - GPtrArray *vcodecs = dbus_get_video_codecs(acc->accountID); + GArray *vcodecs = dbus_get_video_codec_list(acc->accountID); if (!vcodecs) return; - // Add the codecs in the list - for (size_t i = 0; i < vcodecs->len; ++i) { - GHashTable *c = g_ptr_array_index(vcodecs, i); - - if (c) { - GtkTreeIter iter; - gtk_list_store_append(codecStore, &iter); - const gchar *bitrate = g_hash_table_lookup(c, "bitrate"); - const gchar *parameters = g_hash_table_lookup(c, "parameters"); - const gboolean is_active = !g_strcmp0(g_hash_table_lookup(c, "enabled"), "true"); - const gchar *name = g_hash_table_lookup(c, "name"); - - gtk_list_store_set(codecStore, &iter, COLUMN_CODEC_ACTIVE, - is_active, COLUMN_CODEC_NAME, name, - COLUMN_CODEC_BITRATE, bitrate, - COLUMN_CODEC_PARAMETERS, parameters, -1); - } + GtkTreeIter iter; + // Get details for each codec + for (guint i = 0; i < vcodecs->len; i++) { + gtk_list_store_append(codecStore, &iter); + gchar **specs = dbus_get_video_codec_details(g_array_index(vcodecs, gint, i)); + const gchar *name = g_strdup(specs[0]); + const gchar *bitrate = g_strdup(specs[1]); + const gchar *parameters = g_strdup(specs[2]); + //FIXME : take from the list + const gboolean is_active = TRUE; + gtk_list_store_set(codecStore, &iter, COLUMN_CODEC_ACTIVE, + is_active, COLUMN_CODEC_NAME, name, + COLUMN_CODEC_BITRATE, bitrate, + COLUMN_CODEC_PARAMETERS, parameters, -1); } - g_ptr_array_free(vcodecs, TRUE); } /** @@ -200,35 +196,46 @@ preferences_dialog_fill_codec_list(account_t *acc) static gboolean video_codec_has_name(GHashTable *codec, const gchar *name) { + return TRUE; + /* ebail : disable for the moment - we do not use GHashTable anymore return g_strcmp0(g_hash_table_lookup(codec, "name"), name) == 0; + */ } static void video_codec_set_active(GHashTable *codec, gboolean active) { + /* ebail : disable for the moment - we do not use GHashTable anymore g_hash_table_replace(codec, g_strdup("enabled"), active ? g_strdup("true") : g_strdup("false")); + */ } static void video_codec_set_bitrate(GHashTable *codec, const gchar *bitrate) { + /* ebail : disable for the moment - we do not use GHashTable anymore g_hash_table_replace(codec, g_strdup("bitrate"), g_strdup(bitrate)); + */ } static void video_codec_set_parameters(GHashTable *codec, const gchar *parameters) { + /* ebail : disable for the moment - we do not use GHashTable anymore g_hash_table_replace(codec, g_strdup("parameters"), g_strdup(parameters)); + */ } static GHashTable * video_codec_list_get_by_name(GPtrArray *vcodecs, const gchar *name) { + /* ebail : disable for the moment - we do not use GHashTable anymore for (guint i = 0; i < vcodecs->len; ++i) { GHashTable *codec = g_ptr_array_index(vcodecs, i); if (video_codec_has_name(codec, name)) return codec; } + */ return NULL; } @@ -257,7 +264,7 @@ codec_active_toggled(G_GNUC_UNUSED GtkCellRendererToggle *renderer, gchar *path, COLUMN_CODEC_NAME, &name, -1); g_debug("%s", name); - GPtrArray *vcodecs = dbus_get_video_codecs(acc->accountID); + GArray *vcodecs = dbus_get_video_codec_list(acc->accountID); if (!vcodecs) return; @@ -270,22 +277,25 @@ codec_active_toggled(G_GNUC_UNUSED GtkCellRendererToggle *renderer, gchar *path, gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_CODEC_ACTIVE, active, -1); + /* ebail : disable for the moment - we do not use GHashTable anymore GHashTable *codec = video_codec_list_get_by_name(vcodecs, name); if (codec) { video_codec_set_active(codec, active); - dbus_set_video_codecs(acc->accountID, vcodecs); + dbus_set_video_codec_list(acc->accountID, vcodecs); } + */ } static GPtrArray * swap_pointers(GPtrArray *array, guint old_pos, guint new_pos) { + /* ebail : disable for the moment - we do not use GHashTable anymore GHashTable *src = g_ptr_array_index(array, old_pos); GHashTable *dst = g_ptr_array_index(array, new_pos); GPtrArray *new_array = g_ptr_array_new(); - for (guint i = 0; i < array->len; ++i) { + for (guint i = 0; i < array->length; ++i) { if (i == new_pos) g_ptr_array_add(new_array, src); else if (i == old_pos) @@ -296,6 +306,7 @@ swap_pointers(GPtrArray *array, guint old_pos, guint new_pos) g_ptr_array_free(array, TRUE); return new_array; + */ } /** @@ -337,13 +348,15 @@ codec_move(gboolean move_up, gpointer data) if (dest_pos >= 0 && dest_pos < gtk_tree_model_iter_n_children(model, NULL)) { account_t *acc = (account_t *) data; - GPtrArray *vcodecs = dbus_get_video_codecs(acc->accountID); + GArray *vcodecs = dbus_get_video_codec_list(acc->accountID); if (vcodecs) { // Perpetuate changes in daemon + /* ebail : disable for the moment - we do not use GHashTable anymore vcodecs = swap_pointers(vcodecs, pos, dest_pos); // FIXME: only do this AFTER apply is clicked, not every time we move codecs! - dbus_set_video_codecs(acc->accountID, vcodecs); + dbus_set_video_codec_list(acc->accountID, vcodecs); g_ptr_array_free(vcodecs, TRUE); + */ } } } @@ -405,13 +418,13 @@ bitrate_edited_cb(G_GNUC_UNUSED GtkCellRenderer *renderer, gchar *path, gchar *n gchar *name = NULL; gtk_tree_model_get(model, &iter, COLUMN_CODEC_NAME, &name, -1); - GPtrArray *vcodecs = dbus_get_video_codecs(acc->accountID); + GArray *vcodecs = dbus_get_video_codec_list(acc->accountID); if (!vcodecs) return; gchar *bitrate = g_strdup_printf("%llu", val); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_CODEC_BITRATE, bitrate, -1); - + /* ebail : disable for the moment - we do not use GHashTable anymore GHashTable *codec = video_codec_list_get_by_name(vcodecs, name); if (codec) { g_debug("Setting new bitrate %s for %s", bitrate, name); @@ -420,6 +433,7 @@ bitrate_edited_cb(G_GNUC_UNUSED GtkCellRenderer *renderer, gchar *path, gchar *n } else { g_warning("Could not find codec %s", name); } + */ g_free(bitrate); g_ptr_array_free(vcodecs, TRUE); } @@ -448,10 +462,10 @@ parameters_edited_cb(G_GNUC_UNUSED GtkCellRenderer *renderer, gchar *path, gchar gchar *name = NULL; gtk_tree_model_get(model, &iter, COLUMN_CODEC_NAME, &name, -1); - GPtrArray *vcodecs = dbus_get_video_codecs(acc->accountID); + GArray *vcodecs = dbus_get_video_codec_list(acc->accountID); if (!vcodecs) return; - + /* ebail : disable for the moment - we do not use GHashTable anymore gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_CODEC_PARAMETERS, new_text, -1); GHashTable *codec = video_codec_list_get_by_name(vcodecs, name); @@ -463,6 +477,7 @@ parameters_edited_cb(G_GNUC_UNUSED GtkCellRenderer *renderer, gchar *path, gchar g_warning("Could not find codec %s", name); } g_ptr_array_free(vcodecs, TRUE); + */ } diff --git a/gnome/src/dbus/configurationmanager-introspec.xml b/gnome/src/dbus/configurationmanager-introspec.xml index 72dda85e27..8c328ab7e8 100644 --- a/gnome/src/dbus/configurationmanager-introspec.xml +++ b/gnome/src/dbus/configurationmanager-introspec.xml @@ -351,12 +351,12 @@ <method name="getAudioCodecList" tp:name-for-bindings="getAudioCodecList"> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorInt"/> - <arg type="ai" name="list" direction="out"> + <arg type="aui" name="list" direction="out"> </arg> </method> <method name="getAudioCodecDetails" tp:name-for-bindings="getAudioCodecDetails"> - <arg type="i" name="payload" direction="in"> + <arg type="ui" name="codecid" direction="in"> </arg> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> <arg type="as" name="details" direction="out"> @@ -367,7 +367,7 @@ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorInt"/> <arg type="s" name="accountID" direction="in"> </arg> - <arg type="ai" name="list" direction="out"> + <arg type="aui" name="list" direction="out"> </arg> </method> diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c index 342c580598..eb1050c907 100644 --- a/gnome/src/dbus/dbus.c +++ b/gnome/src/dbus/dbus.c @@ -1424,21 +1424,31 @@ dbus_audio_codec_list() } #ifdef SFL_VIDEO -GPtrArray * -dbus_get_video_codecs(const gchar *accountID) +GArray * +dbus_get_video_codec_list(const gchar *accountID) +{ + GError *error = NULL; + GArray *array = NULL; + cx_ring_Ring_VideoManager_get_video_codec_list(video_proxy, accountID, &array, &error); + check_error(error); + return array; +} + +gchar ** +dbus_get_video_codec_details(int id) { GError *error = NULL; - GPtrArray *array = NULL; - cx_ring_Ring_VideoManager_get_codecs(video_proxy, accountID, &array, &error); + gchar **array; + cx_ring_Ring_VideoManager_get_video_codec_details(video_proxy, id, &array, &error); check_error(error); return array; } void -dbus_set_video_codecs(const gchar *accountID, const GPtrArray *list) +dbus_set_video_codec_list(const gchar *accountID, const GArray *list) { GError *error = NULL; - cx_ring_Ring_VideoManager_set_codecs(video_proxy, accountID, list, &error); + cx_ring_Ring_VideoManager_set_video_codec_list(video_proxy, accountID, list, &error); check_error(error); } diff --git a/gnome/src/dbus/dbus.h b/gnome/src/dbus/dbus.h index ce584d409f..8f03a1a727 100644 --- a/gnome/src/dbus/dbus.h +++ b/gnome/src/dbus/dbus.h @@ -214,14 +214,14 @@ GArray *dbus_audio_codec_list(); * @param payload The payload of the audio codec * @return gchar** The audio codec details */ -gchar **dbus_audio_codec_details(int payload); +gchar **dbus_audio_codec_details(int codecId); /** * ConfigurationManager - Get the video codec details * @param codec The name of the video codec * @return gchar** The video codec details */ -GHashTable *dbus_video_codec_details(const gchar *codec); +gchar **dbus_video_codec_details(int codecId); /** * ConfigurationManager - Get the default audio codec list @@ -255,7 +255,7 @@ dbus_get_video_codecs(const gchar *accountID); * @param list The list of codecs */ void -dbus_set_video_codecs(const gchar *id, const GPtrArray *list); +dbus_set_video_codec_list(const gchar *id, const GArray *list); /** * ConfigurationManager - Switch the video input diff --git a/gnome/src/dbus/videomanager-introspec.xml b/gnome/src/dbus/videomanager-introspec.xml index de9761b9fb..4ad97178fd 100644 --- a/gnome/src/dbus/videomanager-introspec.xml +++ b/gnome/src/dbus/videomanager-introspec.xml @@ -48,22 +48,28 @@ </method> <!-- Video Codec related methods --> + <method name="getVideoCodecList" tp:name-for-bindings="getVideoCodecList"> + <arg type="s" name="accountID" direction="in"> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorInt"/> + <arg type="aui" name="list" direction="out"> + </arg> + </method> - <method name="getCodecs" tp:name-for-bindings="getCodecs"> - <tp:docstring>Gets the hashtable describing all the codecs and their parameters for a given account</tp:docstring> - <arg type="s" name="accountID" direction="in"> - </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> - <arg type="aa{ss}" name="details" direction="out"> - </arg> - </method> + <method name="getVideoCodecDetails" tp:name-for-bindings="getVideoCodecDetails"> + <arg type="ui" name="codecid" direction="in"> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="details" direction="out"> + </arg> + </method> - <method name="setCodecs" tp:name-for-bindings="setCodecs"> + <method name="setVideoCodecList" tp:name-for-bindings="setVideoCodecList"> <tp:docstring>Sets a vector of hashtables describing codecs and their parameters for a given account, one hashtable per codec</tp:docstring> <arg type="s" name="accountID" direction="in"> </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorMapStringString"/> - <arg type="aa{ss}" name="details" direction="in"> + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorInt"/> + <arg type="aui" name="list" direction="in"> </arg> </method> -- GitLab