Remote source origin is parsed and extracted from SDP when the source is discovered or updated.
This way we avoid parsing the SDP multiple times.
This commit is contained in:
parent
02ccef73c4
commit
6ed3a9ef54
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include "utils.hpp"
|
|
||||||
#include "browser.hpp"
|
#include "browser.hpp"
|
||||||
|
|
||||||
using namespace boost::algorithm;
|
using namespace boost::algorithm;
|
||||||
@ -85,6 +84,7 @@ bool Browser::worker() {
|
|||||||
ip::address_v4(ntohl(addr)).to_string(),
|
ip::address_v4(ntohl(addr)).to_string(),
|
||||||
sdp_get_subject(sdp),
|
sdp_get_subject(sdp),
|
||||||
{},
|
{},
|
||||||
|
sdp_get_origin(sdp),
|
||||||
sdp,
|
sdp,
|
||||||
static_cast<uint32_t>(
|
static_cast<uint32_t>(
|
||||||
duration_cast<second_t>(steady_clock::now() - startup_)
|
duration_cast<second_t>(steady_clock::now() - startup_)
|
||||||
@ -163,8 +163,9 @@ void Browser::on_change_rtsp_source(const std::string& name,
|
|||||||
<< " name " << name << " domain " << domain;
|
<< " name " << name << " domain " << domain;
|
||||||
auto upd_source{*it};
|
auto upd_source{*it};
|
||||||
upd_source.id = s.id;
|
upd_source.id = s.id;
|
||||||
upd_source.sdp = s.sdp;
|
|
||||||
upd_source.address = s.address;
|
upd_source.address = s.address;
|
||||||
|
upd_source.origin = sdp_get_origin(s.sdp);
|
||||||
|
upd_source.sdp = s.sdp;
|
||||||
upd_source.last_seen = last_seen;
|
upd_source.last_seen = last_seen;
|
||||||
sources_.get<name_tag>().replace(it, upd_source);
|
sources_.get<name_tag>().replace(it, upd_source);
|
||||||
return;
|
return;
|
||||||
@ -174,8 +175,8 @@ void Browser::on_change_rtsp_source(const std::string& name,
|
|||||||
/* entry not found -> add */
|
/* entry not found -> add */
|
||||||
BOOST_LOG_TRIVIAL(info) << "browser:: adding RTSP source " << s.id << " name "
|
BOOST_LOG_TRIVIAL(info) << "browser:: adding RTSP source " << s.id << " name "
|
||||||
<< name << " domain " << domain;
|
<< name << " domain " << domain;
|
||||||
sources_.insert(
|
sources_.insert({s.id, s.source, s.address, name, domain,
|
||||||
{s.id, s.source, s.address, name, domain, s.sdp, last_seen, 0});
|
sdp_get_origin(s.sdp), s.sdp, last_seen, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::on_remove_rtsp_source(const std::string& name,
|
void Browser::on_remove_rtsp_source(const std::string& name,
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "igmp.hpp"
|
#include "igmp.hpp"
|
||||||
#include "mdns_client.hpp"
|
#include "mdns_client.hpp"
|
||||||
#include "sap.hpp"
|
#include "sap.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
using namespace boost::multi_index;
|
using namespace boost::multi_index;
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ struct RemoteSource {
|
|||||||
std::string address;
|
std::string address;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string domain; /* mDNS only */
|
std::string domain; /* mDNS only */
|
||||||
|
SDPOrigin origin;
|
||||||
std::string sdp;
|
std::string sdp;
|
||||||
uint32_t last_seen{0}; /* seconds from daemon startup */
|
uint32_t last_seen{0}; /* seconds from daemon startup */
|
||||||
uint32_t announce_period{0}; /* period between annoucements */
|
uint32_t announce_period{0}; /* period between annoucements */
|
||||||
|
@ -607,44 +607,6 @@ std::string SessionManager::get_removed_source_sdp_(
|
|||||||
return sdp;
|
return sdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SessionManager::parse_sdp_origin(const std::string sdp,
|
|
||||||
SDPOrigin& origin) const {
|
|
||||||
try {
|
|
||||||
std::stringstream sdp_string_stream(sdp);
|
|
||||||
std::string line;
|
|
||||||
while (getline(sdp_string_stream, line, '\n')) {
|
|
||||||
boost::trim(line);
|
|
||||||
if (line[1] != '=') {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid SDP file";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::string val = line.substr(2);
|
|
||||||
switch (line[0]) {
|
|
||||||
case 'o':
|
|
||||||
std::vector<std::string> fields;
|
|
||||||
boost::split(fields, val, [line](char c) { return c == ' '; });
|
|
||||||
if (fields.size() < 6) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid origin";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
origin.username = fields[0];
|
|
||||||
origin.session_id = fields[1];
|
|
||||||
origin.session_version = std::stoull(fields[2]);
|
|
||||||
origin.network_type = fields[3];
|
|
||||||
origin.address_type = fields[4];
|
|
||||||
origin.unicast_address = fields[5];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
BOOST_LOG_TRIVIAL(fatal) << "session_manager:: invalid SDP"
|
|
||||||
<< ", cannot extract SDP identifier";
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SessionManager::get_source_sdp_(uint32_t id,
|
std::string SessionManager::get_source_sdp_(uint32_t id,
|
||||||
const StreamInfo& info) const {
|
const StreamInfo& info) const {
|
||||||
std::shared_lock ptp_lock(ptp_mutex_);
|
std::shared_lock ptp_lock(ptp_mutex_);
|
||||||
@ -1068,23 +1030,21 @@ std::list<StreamSink> SessionManager::get_updated_sinks(
|
|||||||
uint64_t newVersion{0};
|
uint64_t newVersion{0};
|
||||||
StreamSink sink{get_sink_(id, info)};
|
StreamSink sink{get_sink_(id, info)};
|
||||||
for (auto& source : sources_list) {
|
for (auto& source : sources_list) {
|
||||||
SDPOrigin source_sdp_origin;
|
// if no remote source origin specified, skip
|
||||||
if (!parse_sdp_origin(source.sdp, source_sdp_origin))
|
if (source.origin.session_id == "")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sinks_[sink.id].origin == source_sdp_origin &&
|
// search for the largest corresponding remote source version
|
||||||
sink.sdp != source.sdp &&
|
if (sinks_[sink.id].origin == source.origin && sink.sdp != source.sdp &&
|
||||||
sinks_[sink.id].origin.session_version <
|
sinks_[sink.id].origin.session_version <
|
||||||
source_sdp_origin.session_version &&
|
source.origin.session_version &&
|
||||||
newVersion < source_sdp_origin.session_version) {
|
newVersion < source.origin.session_version) {
|
||||||
newVersion = source_sdp_origin.session_version;
|
newVersion = source.origin.session_version;
|
||||||
sink.sdp = source.sdp;
|
sink.sdp = source.sdp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newVersion) {
|
if (newVersion) {
|
||||||
// Re-add sink with new SDP, since the sink.id is the same there will be
|
|
||||||
// an update
|
|
||||||
BOOST_LOG_TRIVIAL(info)
|
BOOST_LOG_TRIVIAL(info)
|
||||||
<< "session_manager:: sink " << std::to_string(sink.id)
|
<< "session_manager:: sink " << std::to_string(sink.id)
|
||||||
<< " SDP change detected version " << newVersion << " updating";
|
<< " SDP change detected version " << newVersion << " updating";
|
||||||
@ -1097,6 +1057,8 @@ std::list<StreamSink> SessionManager::get_updated_sinks(
|
|||||||
void SessionManager::update_sinks(const std::list<RemoteSource>& sources_list) {
|
void SessionManager::update_sinks(const std::list<RemoteSource>& sources_list) {
|
||||||
auto sinks_list = get_updated_sinks(sources_list);
|
auto sinks_list = get_updated_sinks(sources_list);
|
||||||
for (auto& sink : sinks_list) {
|
for (auto& sink : sinks_list) {
|
||||||
|
// Re-add sink with new SDP, since the sink.id is the same there will be
|
||||||
|
// an update
|
||||||
add_sink(sink);
|
add_sink(sink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,23 +32,6 @@
|
|||||||
#include "igmp.hpp"
|
#include "igmp.hpp"
|
||||||
#include "sap.hpp"
|
#include "sap.hpp"
|
||||||
|
|
||||||
struct SDPOrigin {
|
|
||||||
std::string username;
|
|
||||||
std::string session_id;
|
|
||||||
uint64_t session_version{0};
|
|
||||||
std::string network_type;
|
|
||||||
std::string address_type;
|
|
||||||
std::string unicast_address;
|
|
||||||
|
|
||||||
bool operator==(const SDPOrigin& rhs) const {
|
|
||||||
// session_version is not part of comparison, see RFC 4566
|
|
||||||
return username == rhs.username && session_id == rhs.session_id &&
|
|
||||||
network_type == rhs.network_type &&
|
|
||||||
address_type == rhs.address_type &&
|
|
||||||
unicast_address == rhs.unicast_address;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StreamSource {
|
struct StreamSource {
|
||||||
uint8_t id{0};
|
uint8_t id{0};
|
||||||
bool enabled{false};
|
bool enabled{false};
|
||||||
@ -211,7 +194,6 @@ class SessionManager {
|
|||||||
const std::list<RemoteSource> sources_list) const;
|
const std::list<RemoteSource> sources_list) const;
|
||||||
|
|
||||||
bool parse_sdp(const std::string sdp, StreamInfo& info) const;
|
bool parse_sdp(const std::string sdp, StreamInfo& info) const;
|
||||||
bool parse_sdp_origin(const std::string sdp, SDPOrigin& origin) const;
|
|
||||||
bool worker();
|
bool worker();
|
||||||
// singleton, use create() to build
|
// singleton, use create() to build
|
||||||
SessionManager(std::shared_ptr<DriverManager> driver,
|
SessionManager(std::shared_ptr<DriverManager> driver,
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
#include "log.hpp"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
@ -86,9 +87,9 @@ std::string get_host_node_id(uint32_t ip_addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string sdp_get_subject(const std::string& sdp) {
|
std::string sdp_get_subject(const std::string& sdp) {
|
||||||
std::stringstream ssstrem(sdp);
|
std::stringstream sstrem(sdp);
|
||||||
std::string line;
|
std::string line;
|
||||||
while (getline(ssstrem, line, '\n')) {
|
while (getline(sstrem, line, '\n')) {
|
||||||
if (line.substr(0, 2) == "s=") {
|
if (line.substr(0, 2) == "s=") {
|
||||||
auto subject = line.substr(2);
|
auto subject = line.substr(2);
|
||||||
boost::trim(subject);
|
boost::trim(subject);
|
||||||
@ -97,3 +98,40 @@ std::string sdp_get_subject(const std::string& sdp) {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDPOrigin sdp_get_origin(const std::string sdp) {
|
||||||
|
SDPOrigin origin;
|
||||||
|
try {
|
||||||
|
std::stringstream sstream(sdp);
|
||||||
|
std::string line;
|
||||||
|
while (getline(sstream, line, '\n')) {
|
||||||
|
boost::trim(line);
|
||||||
|
if (line[1] != '=') {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid SDP file";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::string val = line.substr(2);
|
||||||
|
if (line[0] == 'o') {
|
||||||
|
std::vector<std::string> fields;
|
||||||
|
boost::split(fields, val, [line](char c) { return c == ' '; });
|
||||||
|
if (fields.size() < 6) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "session_manager:: invalid origin";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin.username = fields[0];
|
||||||
|
origin.session_id = fields[1];
|
||||||
|
origin.session_version = std::stoull(fields[2]);
|
||||||
|
origin.network_type = fields[3];
|
||||||
|
origin.address_type = fields[4];
|
||||||
|
origin.unicast_address = fields[5];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
BOOST_LOG_TRIVIAL(fatal) << "session_manager:: invalid SDP"
|
||||||
|
<< ", cannot extract SDP identifier";
|
||||||
|
}
|
||||||
|
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
@ -38,4 +38,23 @@ std::string get_host_node_id(uint32_t ip_addr);
|
|||||||
|
|
||||||
std::string sdp_get_subject(const std::string& sdp);
|
std::string sdp_get_subject(const std::string& sdp);
|
||||||
|
|
||||||
|
struct SDPOrigin {
|
||||||
|
std::string username;
|
||||||
|
std::string session_id;
|
||||||
|
uint64_t session_version{0};
|
||||||
|
std::string network_type;
|
||||||
|
std::string address_type;
|
||||||
|
std::string unicast_address;
|
||||||
|
|
||||||
|
bool operator==(const SDPOrigin& rhs) const {
|
||||||
|
// session_version is not part of comparison, see RFC 4566
|
||||||
|
return username == rhs.username && session_id == rhs.session_id &&
|
||||||
|
network_type == rhs.network_type &&
|
||||||
|
address_type == rhs.address_type &&
|
||||||
|
unicast_address == rhs.unicast_address;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SDPOrigin sdp_get_origin(const std::string sdp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user