5G-MAG Reference Tools - MBMS Middleware
Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
MBMS_RT::ServiceAnnouncement Class Reference

#include <ServiceAnnouncement.h>

Collaboration diagram for MBMS_RT::ServiceAnnouncement:
Collaboration graph

Classes

struct  Item
 

Public Types

typedef std::function< std::shared_ptr< Service >const std::string &service_id)> get_service_callback_t
 
typedef std::function< void(const std::string &service_id, std::shared_ptr< Service >)> set_service_callback_t
 

Public Member Functions

 ServiceAnnouncement (const libconfig::Config &cfg, std::string tmgi, const std::string &mcast, unsigned long long tsi, std::string iface, boost::asio::io_service &io_service, CacheManagement &cache, bool seamless_switching, get_service_callback_t get_service, set_service_callback_t set_service)
 
virtual ~ServiceAnnouncement ()
 
const std::vector< Item > & items () const
 
const std::string & content () const
 
uint32_t toi () const
 
void parse_bootstrap (const std::string &str)
 Parse the service announcement/bootstrap file. More...
 
void start_flute_receiver (const std::string &mcast_address)
 Starts the FLUTE receiver at the specified multicast address. More...
 

Private Member Functions

void _addServiceAnnouncementItems (const std::string &str)
 Iterates through the service announcement file and adds the different sections/items to the the list of _items. More...
 
void _handleMbmsEnvelope (const Item &item)
 Parses the MBMS envelope. More...
 
void _handleMbmbsUserServiceDescriptionBundle (const Item &item, const std::string &bootstrap_format)
 Parses the MBMS USD. More...
 
std::tuple< std::shared_ptr< MBMS_RT::Service >, bool > _registerService (tinyxml2::XMLElement *usd, const std::string &service_id)
 Creates a new service or finds an existing service for the specified service id. More...
 
void _handleAppService (tinyxml2::XMLElement *app_service, const std::shared_ptr< Service > &service)
 Parse the appService element Spec: Presence of the r12:appService child element of userServiceDescription indicates that the associated MBMS User Service is an application service explicitly linked to the r12:broadcastAppService and r12:unicastAppService elements under deliveryMethod. More...
 
bool _setupBroadcastDelivery (tinyxml2::XMLElement *usd, std::string base, std::shared_ptr< ContentStream > cs)
 
void _setupByAlternativeContentElement (tinyxml2::XMLElement *app_service, const std::shared_ptr< MBMS_RT::Service > &service, tinyxml2::XMLElement *usd)
 Setup according to original SA format with an alternativeContentElement required to indicate that the stream is available via BC and UC. More...
 
void _setupBy5GMagConfig (tinyxml2::XMLElement *app_service, const std::shared_ptr< MBMS_RT::Service > &service, tinyxml2::XMLElement *usd)
 
void _setupBy5GMagLegacyFormat (tinyxml2::XMLElement *app_service, const std::shared_ptr< MBMS_RT::Service > &service, tinyxml2::XMLElement *usd)
 Setup according to the format that was used for the first 5G-MAG sample recordings. More...
 

Private Attributes

get_service_callback_t _get_service
 
set_service_callback_t _set_service
 
bool _seamless = false
 
std::vector< Item_items
 
const libconfig::Config & _cfg
 
bool _bootstrapped = false
 
uint32_t _toi = {}
 
std::string _raw_content
 
std::string _iface
 
std::string _tmgi
 
std::string _mcast_addr
 
std::string _mcast_port
 
std::string _base_path
 
unsigned long long _tsi = 0
 
std::thread _flute_thread
 
std::unique_ptr< LibFlute::Receiver > _flute_receiver
 
boost::asio::io_service & _io_service
 
CacheManagement_cache
 

Detailed Description

Definition at line 32 of file ServiceAnnouncement.h.

Member Typedef Documentation

◆ get_service_callback_t

typedef std::function<std::shared_ptr<Service>const std::string &service_id)> MBMS_RT::ServiceAnnouncement::get_service_callback_t

Definition at line 34 of file ServiceAnnouncement.h.

◆ set_service_callback_t

typedef std::function<void(const std::string &service_id, std::shared_ptr<Service>)> MBMS_RT::ServiceAnnouncement::set_service_callback_t

Definition at line 35 of file ServiceAnnouncement.h.

Constructor & Destructor Documentation

◆ ServiceAnnouncement()

MBMS_RT::ServiceAnnouncement::ServiceAnnouncement ( const libconfig::Config &  cfg,
std::string  tmgi,
const std::string &  mcast,
unsigned long long  tsi,
std::string  iface,
boost::asio::io_service &  io_service,
CacheManagement cache,
bool  seamless_switching,
get_service_callback_t  get_service,
set_service_callback_t  set_service 
)

Definition at line 36 of file ServiceAnnouncement.cpp.

43  : _cfg(cfg), _tmgi(std::move(tmgi)), _tsi(tsi), _iface(std::move(iface)), _io_service(io_service), _cache(cache),
44  _flute_thread{}, _seamless(seamless_switching), _get_service(std::move(get_service)),
45  _set_service(std::move(set_service)) {
46 }
get_service_callback_t _get_service
boost::asio::io_service & _io_service
set_service_callback_t _set_service
const libconfig::Config & _cfg
static Config cfg
Global configuration object.
Definition: main.cpp:111

◆ ~ServiceAnnouncement()

MBMS_RT::ServiceAnnouncement::~ServiceAnnouncement ( )
virtual

Definition at line 48 of file ServiceAnnouncement.cpp.

48  {
49  spdlog::info("Closing service announcement session with TMGI {}", _tmgi);
50  _flute_receiver.reset();
51  if (_flute_thread.joinable()) {
52  _flute_thread.join();
53  }
54 }
std::unique_ptr< LibFlute::Receiver > _flute_receiver

Member Function Documentation

◆ _addServiceAnnouncementItems()

void MBMS_RT::ServiceAnnouncement::_addServiceAnnouncementItems ( const std::string &  str)
private

Iterates through the service announcement file and adds the different sections/items to the the list of _items.

Parameters
{std::string}str

Definition at line 121 of file ServiceAnnouncement.cpp.

121  {
122  g_mime_init();
123  auto stream = g_mime_stream_mem_new_with_buffer(str.c_str(), str.length());
124  auto parser = g_mime_parser_new_with_stream(stream);
125  g_object_unref(stream);
126 
127  auto mpart = g_mime_parser_construct_part(parser, nullptr);
128  g_object_unref(parser);
129 
130  auto iter = g_mime_part_iter_new(mpart);
131  do {
132  GMimeObject *current = g_mime_part_iter_get_current(iter);
133  GMimeObject *parent = g_mime_part_iter_get_parent(iter);
134 
135  if (GMIME_IS_PART (current)) {
136  auto type = std::string(g_mime_content_type_get_mime_type(g_mime_object_get_content_type(current)));
137  std::string location = "";
138  if (g_mime_object_get_header(current, "Content-Location")) {
139  location = std::string(g_mime_object_get_header(current, "Content-Location"));
140  }
141  auto options = g_mime_format_options_new();
142  g_mime_format_options_add_hidden_header(options, "Content-Type");
143  g_mime_format_options_add_hidden_header(options, "Content-Transfer-Encoding");
144  g_mime_format_options_add_hidden_header(options, "Content-Location");
145  std::string content = g_mime_object_to_string(current, options);
146  boost::algorithm::trim_left(content);
147 
148  if (location != "") {
149  _items.emplace_back(Item{
150  type,
151  location,
152  0, 0, 0,
153  content
154  });
155  }
156  }
157  } while (g_mime_part_iter_next(iter));
158 
159 }
const std::string & content() const
static struct argp_option options[]
Definition: main.cpp:58

◆ _handleAppService()

void MBMS_RT::ServiceAnnouncement::_handleAppService ( tinyxml2::XMLElement *  app_service,
const std::shared_ptr< Service > &  service 
)
private

Parse the appService element Spec: Presence of the r12:appService child element of userServiceDescription indicates that the associated MBMS User Service is an application service explicitly linked to the r12:broadcastAppService and r12:unicastAppService elements under deliveryMethod.

Parameters
usd
app_service
service

Definition at line 272 of file ServiceAnnouncement.cpp.

273  {
274 
275  service->set_delivery_protocol_from_mime_type(app_service->Attribute(ServiceAnnouncementXmlElements::MIME_TYPE));
276 
277  // Now search for the content that corresponds to appServiceDescriptionURI. For instance appServiceDescriptionURI="http://localhost/watchfolder/manifest.m3u8"
278  // The attribute appServiceDescriptionURI of r12:appService references an Application Service Description which may be a Media Presentation Description fragment corresponding to a unified MPD.
279  for (const auto &item: _items) {
280  // item.uri is derived from the Content-Location of each entry in the bootstrap file. For HLS we are looking for the content of the master manifest in the bootstrap file:
281  if (item.uri == app_service->Attribute(ServiceAnnouncementXmlElements::APP_SERVICE_DESCRIPTION_URI)) {
282  web::uri uri(item.uri);
283 
284  // remove file, leave only dir
285  const std::string &path = uri.path();
286  size_t spos = path.rfind('/');
287  auto base_path = path.substr(0, spos + 1);
288 
289  // make relative path: remove leading /
290  if (base_path[0] == '/') {
291  base_path.erase(0, 1);
292  }
293  service->read_master_manifest(item.content, base_path);
294  _base_path = base_path;
295  }
296  }
297 }
const char *const APP_SERVICE_DESCRIPTION_URI
Definition: Constants.h:53
const char *const MIME_TYPE
Definition: Constants.h:52

◆ _handleMbmbsUserServiceDescriptionBundle()

void MBMS_RT::ServiceAnnouncement::_handleMbmbsUserServiceDescriptionBundle ( const Item item,
const std::string &  bootstrap_format 
)
private

Parses the MBMS USD.

Parameters
{MBMS_RT::ServiceAnnouncement::Item}item

Definition at line 197 of file ServiceAnnouncement.cpp.

198  {
199  try {
200  tinyxml2::XMLDocument doc;
201  doc.Parse(item.content.c_str());
202 
203  auto bundle = doc.FirstChildElement(ServiceAnnouncementXmlElements::BUNDLE_DESCRIPTION);
204  for (auto *usd = bundle->FirstChildElement(ServiceAnnouncementXmlElements::USER_SERVICE_DESCRIPTION);
205  usd != nullptr;
206  usd = usd->NextSiblingElement(ServiceAnnouncementXmlElements::USER_SERVICE_DESCRIPTION)) {
207 
208  // Create a new service
209  auto service_id = usd->Attribute(ServiceAnnouncementXmlElements::SERVICE_ID);
210  auto[service, is_new_service] = _registerService(usd, service_id);
211 
212  // Handle the app service element. Will read the master manifest as provided in the SA
213  auto app_service = usd->FirstChildElement(ServiceAnnouncementXmlElements::APP_SERVICE);
214  _handleAppService(app_service, service);
215 
216  // For the default format we need an alternativeContent attribute to setup the service
217  if (bootstrap_format == ServiceAnnouncementFormatConstants::FIVEG_MAG_BC_UC) {
218  _setupBy5GMagConfig(app_service, service, usd);
219  } else if (bootstrap_format == ServiceAnnouncementFormatConstants::FIVEG_MAG_LEGACY) {
220  _setupBy5GMagLegacyFormat(app_service, service, usd);
221  } else {
222  _setupByAlternativeContentElement(app_service, service, usd);
223  }
224 
225  if (is_new_service && service->content_streams().size() > 0) {
226  _set_service(service_id, service);
227  }
228  }
229  } catch (std::exception e) {
230  spdlog::warn("MBMS user service desription parsing failed: {}", e.what());
231  }
232 }
void _handleAppService(tinyxml2::XMLElement *app_service, const std::shared_ptr< Service > &service)
Parse the appService element Spec: Presence of the r12:appService child element of userServiceDescrip...
void _setupBy5GMagConfig(tinyxml2::XMLElement *app_service, const std::shared_ptr< MBMS_RT::Service > &service, tinyxml2::XMLElement *usd)
void _setupBy5GMagLegacyFormat(tinyxml2::XMLElement *app_service, const std::shared_ptr< MBMS_RT::Service > &service, tinyxml2::XMLElement *usd)
Setup according to the format that was used for the first 5G-MAG sample recordings.
std::tuple< std::shared_ptr< MBMS_RT::Service >, bool > _registerService(tinyxml2::XMLElement *usd, const std::string &service_id)
Creates a new service or finds an existing service for the specified service id.
void _setupByAlternativeContentElement(tinyxml2::XMLElement *app_service, const std::shared_ptr< MBMS_RT::Service > &service, tinyxml2::XMLElement *usd)
Setup according to original SA format with an alternativeContentElement required to indicate that the...
static char doc[]
Definition: main.cpp:56
const std::string FIVEG_MAG_BC_UC
Definition: Constants.h:33
const std::string FIVEG_MAG_LEGACY
Definition: Constants.h:34
const char *const SERVICE_ID
Definition: Constants.h:43
const char *const USER_SERVICE_DESCRIPTION
Definition: Constants.h:42
const char *const APP_SERVICE
Definition: Constants.h:44
const char *const BUNDLE_DESCRIPTION
Definition: Constants.h:39

◆ _handleMbmsEnvelope()

void MBMS_RT::ServiceAnnouncement::_handleMbmsEnvelope ( const Item item)
private

Parses the MBMS envelope.

Parameters
{MBMS_RT::ServiceAnnouncement::Item}item

Definition at line 165 of file ServiceAnnouncement.cpp.

165  {
166  try {
167  tinyxml2::XMLDocument doc;
168  doc.Parse(item.content.c_str());
169  auto envelope = doc.FirstChildElement(ServiceAnnouncementXmlElements::METADATA_ENVELOPE);
170  for (auto *i = envelope->FirstChildElement(ServiceAnnouncementXmlElements::ITEM);
171  i != nullptr; i = i->NextSiblingElement(ServiceAnnouncementXmlElements::ITEM)) {
172  spdlog::debug("uri: {}", i->Attribute(ServiceAnnouncementXmlElements::METADATA_URI));
173  for (auto &ir: _items) {
174  if (ir.uri == i->Attribute(ServiceAnnouncementXmlElements::METADATA_URI)) {
175  std::stringstream ss_from(i->Attribute(ServiceAnnouncementXmlElements::VALID_FROM));
176  struct std::tm from;
177  ss_from >> std::get_time(&from, "%Y-%m-%dT%H:%M:%S.%fZ");
178  ir.valid_from = mktime(&from);
179  std::stringstream ss_until(i->Attribute(ServiceAnnouncementXmlElements::VALID_UNTIL));
180  struct std::tm until;
181  ss_until >> std::get_time(&until, "%Y-%m-%dT%H:%M:%S.%fZ");
182  ir.valid_until = mktime(&until);
183  ir.version = atoi(i->Attribute(ServiceAnnouncementXmlElements::VERSION));
184  }
185  }
186  }
187  } catch (std::exception e) {
188  spdlog::warn("MBMS envelope parsing failed: {}", e.what());
189  }
190 }
const char *const ITEM
Definition: Constants.h:56
const char *const METADATA_ENVELOPE
Definition: Constants.h:54
const char *const VERSION
Definition: Constants.h:57
const char *const VALID_UNTIL
Definition: Constants.h:59
const char *const VALID_FROM
Definition: Constants.h:58
const char *const METADATA_URI
Definition: Constants.h:55

◆ _registerService()

auto MBMS_RT::ServiceAnnouncement::_registerService ( tinyxml2::XMLElement *  usd,
const std::string &  service_id 
)
private

Creates a new service or finds an existing service for the specified service id.

Parameters
usd
service_id
Returns

Definition at line 241 of file ServiceAnnouncement.cpp.

241  {
242  // Register a new service if we have not seen this service id before
243 
244  bool is_new_service = false;
245  auto service = _get_service(service_id);
246  if (service == nullptr) {
247  service = std::make_shared<Service>(_cache);
248  is_new_service = true;
249  }
250 
251  // read the names
252  for (auto *name = usd->FirstChildElement(ServiceAnnouncementXmlElements::NAME);
253  name != nullptr; name = name->NextSiblingElement(ServiceAnnouncementXmlElements::NAME)) {
254  auto lang = name->Attribute(ServiceAnnouncementXmlElements::LANG);
255  auto namestr = name->GetText();
256  if (lang && namestr) {
257  service->add_name(namestr, lang);
258  }
259  }
260 
261  return {service, is_new_service};
262 }
const char *const LANG
Definition: Constants.h:41
const char *const NAME
Definition: Constants.h:40

◆ _setupBroadcastDelivery()

bool MBMS_RT::ServiceAnnouncement::_setupBroadcastDelivery ( tinyxml2::XMLElement *  usd,
std::string  base,
std::shared_ptr< ContentStream cs 
)
private

◆ _setupBy5GMagConfig()

void MBMS_RT::ServiceAnnouncement::_setupBy5GMagConfig ( tinyxml2::XMLElement *  app_service,
const std::shared_ptr< MBMS_RT::Service > &  service,
tinyxml2::XMLElement *  usd 
)
private

Definition at line 299 of file ServiceAnnouncement.cpp.

301  {
302 
303  std::vector<std::shared_ptr<ContentStream>> broadcastContentStreams;
304  std::vector<std::shared_ptr<SeamlessContentStream>> unicastContentStreams;
305 // Create content stream objects for each broadcastAppService::basePattern element.
306  for (auto *delivery_method = usd->FirstChildElement(ServiceAnnouncementXmlElements::DELIVERY_METHOD);
307  delivery_method != nullptr;
308  delivery_method = delivery_method->NextSiblingElement(ServiceAnnouncementXmlElements::DELIVERY_METHOD)) {
309  auto sdp_uri = delivery_method->Attribute(ServiceAnnouncementXmlElements::SESSION_DESCRIPTION_URI);
310  // We assume that the master manifest is signaled in the SA and that we can simply replace the .sdp ending with .m3u8 to find the element with the right Content-Location
311  auto manifest_url = std::regex_replace(sdp_uri, std::regex(".sdp"), ".m3u8");
312  auto broadcast_app_service = delivery_method->FirstChildElement(
314 
315  if (broadcast_app_service != nullptr) {
316  for (auto *base_pattern = broadcast_app_service->FirstChildElement(ServiceAnnouncementXmlElements::BASE_PATTERN);
317  base_pattern != nullptr;
318  base_pattern = base_pattern->NextSiblingElement(ServiceAnnouncementXmlElements::BASE_PATTERN)) {
319 
320  std::string broadcast_url = base_pattern->GetText();
321 
322  // create a content stream
323  std::shared_ptr<ContentStream> cs;
324  if (_seamless) {
325  cs = std::make_shared<SeamlessContentStream>(broadcast_url, _iface, _io_service, _cache,
326  service->delivery_protocol(), _cfg);
327  } else {
328  cs = std::make_shared<ContentStream>(broadcast_url, _iface, _io_service, _cache, service->delivery_protocol(),
329  _cfg);
330  }
331 
332  for (const auto &item: _items) {
333  if (item.uri == manifest_url) {
334  cs->read_master_manifest(item.content);
335  }
336  if (item.content_type == ContentTypeConstants::SDP &&
337  item.uri == sdp_uri) {
338  cs->configure_5gbc_delivery_from_sdp(item.content);
339  }
340  }
341 
342  broadcastContentStreams.push_back(cs);
343  }
344  }
345 
346  if (_seamless) {
347  // Iterate through unicastAppService elements. If we find a match in identical content we add the CDN information to the existing broadcast content stream
348  // If not we create a new content stream object pointing to the CDN url
349  auto unicast_app_service = delivery_method->FirstChildElement(
351  if (unicast_app_service != nullptr) {
352  for (auto *base_pattern = unicast_app_service->FirstChildElement(
354  base_pattern != nullptr;
355  base_pattern = base_pattern->NextSiblingElement(ServiceAnnouncementXmlElements::BASE_PATTERN)) {
356  // For HLS streams base_pattern now holds the url to the media manifest
357  std::string unicast_url = base_pattern->GetText();
358  // Check for identical content entries that contain this base pattern.
359  for (auto *identical_content = app_service->FirstChildElement(
361  identical_content != nullptr;
362  identical_content = identical_content->NextSiblingElement(
364  std::shared_ptr<SeamlessContentStream> broadcast_content_stream;
365  bool found_identical_element = false;
366  for (auto *base_pattern_ic = identical_content->FirstChildElement(
368  base_pattern_ic != nullptr;
369  base_pattern_ic = base_pattern_ic->NextSiblingElement(ServiceAnnouncementXmlElements::BASE_PATTERN)) {
370  // For HLS streams base_pattern_ic now holds either an url that points to a BC media playlist or to a UC playlist
371  std::string identical_content_url = base_pattern_ic->GetText();
372  // Check if we have a match of our current unicast url with the url in the identical content element
373  // Otherwise check if the current identical content url points to an existing BC element
374  if (unicast_url == identical_content_url) {
375  found_identical_element = true;
376  } else {
377  for (auto &element: broadcastContentStreams) {
378  if (element->base() == identical_content_url) {
379  broadcast_content_stream = std::dynamic_pointer_cast<SeamlessContentStream>(element);
380  }
381  }
382  }
383  }
384  // If we found a matching broadcast stream we add the CDN url to this one. Otherwise, we create a new SeamlessContentStream element
385  if (broadcast_content_stream != nullptr && found_identical_element) {
386  broadcast_content_stream->set_cdn_endpoint(unicast_url);
387  } else {
388  std::shared_ptr<SeamlessContentStream> cs = std::make_shared<SeamlessContentStream>(manifest_url, _iface,
390  service->delivery_protocol(),
391  _cfg);
392  cs->set_cdn_endpoint(unicast_url);
393  unicastContentStreams.push_back(cs);
394  }
395  }
396  }
397  }
398  }
399 
400  for (auto &element: unicastContentStreams) {
401  service->add_and_start_content_stream(element);
402  }
403 
404  for (auto &element: broadcastContentStreams) {
405  service->add_and_start_content_stream(element);
406  }
407 
408  spdlog::info("Finished SA setup with 5G-MAG Format");
409  }
410 
411 }
const std::string SDP
Definition: Constants.h:26
const char *const BASE_PATTERN
Definition: Constants.h:47
const char *const DELIVERY_METHOD
Definition: Constants.h:45
const char *const IDENTICAL_CONTENT
Definition: Constants.h:51
const char *const UNICAST_APP_SERVICE
Definition: Constants.h:49
const char *const BROADCAST_APP_SERVICE
Definition: Constants.h:48
const char *const SESSION_DESCRIPTION_URI
Definition: Constants.h:46

◆ _setupBy5GMagLegacyFormat()

void MBMS_RT::ServiceAnnouncement::_setupBy5GMagLegacyFormat ( tinyxml2::XMLElement *  app_service,
const std::shared_ptr< MBMS_RT::Service > &  service,
tinyxml2::XMLElement *  usd 
)
private

Setup according to the format that was used for the first 5G-MAG sample recordings.

Parameters
app_service
service
usd

Definition at line 419 of file ServiceAnnouncement.cpp.

421  {
422 
423  std::vector<std::shared_ptr<ContentStream>> broadcastContentStreams;
424 // Create content stream objects for each broadcastAppService::basePattern element.
425  for (auto *delivery_method = usd->FirstChildElement(ServiceAnnouncementXmlElements::DELIVERY_METHOD);
426  delivery_method != nullptr;
427  delivery_method = delivery_method->NextSiblingElement(ServiceAnnouncementXmlElements::DELIVERY_METHOD)) {
428  auto sdp_uri = delivery_method->Attribute(ServiceAnnouncementXmlElements::SESSION_DESCRIPTION_URI);
429  // We assume that the master manifest is signaled in the SA and that we can simply replace the .sdp ending with .m3u8 or .mpd to find the element with the right Content-Location
430  std::string manifest_type = service->delivery_protocol() == DeliveryProtocol::HLS ? ContentTypeConstants::HLS_MANIFEST : ContentTypeConstants::DASH_MANIFEST;
431  auto manifest_url = std::regex_replace(sdp_uri, std::regex(".sdp"), "." + manifest_type);
432  auto broadcast_app_service = delivery_method->FirstChildElement(
434 
435  if (broadcast_app_service != nullptr) {
436  for (auto *base_pattern = broadcast_app_service->FirstChildElement(ServiceAnnouncementXmlElements::BASE_PATTERN);
437  base_pattern != nullptr;
438  base_pattern = base_pattern->NextSiblingElement(ServiceAnnouncementXmlElements::BASE_PATTERN)) {
439 
440  std::string broadcast_url = base_pattern->GetText();
441 
442  // create a content stream if this is not a base pattern that points to file://
443  if (service->delivery_protocol() == DeliveryProtocol::DASH || (service->delivery_protocol() == DeliveryProtocol::HLS && broadcast_url.find("file://") == std::string::npos)) {
444 
445  std::shared_ptr<ContentStream> cs;
446  cs = std::make_shared<ContentStream>(broadcast_url, _iface, _io_service, _cache, service->delivery_protocol(),
447  _cfg);
448 
449  cs->set_base_path(_base_path);
450  for (const auto &item: _items) {
451  if (item.uri == manifest_url && service->delivery_protocol() == DeliveryProtocol::HLS) {
452  cs->read_master_manifest(item.content);
453  }
454  if (item.content_type == ContentTypeConstants::SDP &&
455  item.uri == sdp_uri) {
456  cs->configure_5gbc_delivery_from_sdp(item.content);
457  }
458  }
459 
460  broadcastContentStreams.push_back(cs);
461  }
462  }
463  }
464 
465  for (auto &element: broadcastContentStreams) {
466  service->add_and_start_content_stream(element);
467  }
468 
469  spdlog::info("Finished SA setup with 5G-MAG Legacy Format");
470 
471  }
472 }
const std::string DASH_MANIFEST
Definition: Constants.h:28
const std::string HLS_MANIFEST
Definition: Constants.h:27

◆ _setupByAlternativeContentElement()

void MBMS_RT::ServiceAnnouncement::_setupByAlternativeContentElement ( tinyxml2::XMLElement *  app_service,
const std::shared_ptr< MBMS_RT::Service > &  service,
tinyxml2::XMLElement *  usd 
)
private

Setup according to original SA format with an alternativeContentElement required to indicate that the stream is available via BC and UC.

Parameters
app_service
service
usd

Definition at line 481 of file ServiceAnnouncement.cpp.

483  {
484  auto alternative_content = app_service->FirstChildElement(ServiceAnnouncementXmlElements::ALTERNATIVE_CONTENT);
485  if (alternative_content != nullptr) {
486  for (auto *base_pattern = alternative_content->FirstChildElement(ServiceAnnouncementXmlElements::BASE_PATTERN);
487  base_pattern != nullptr;
488  base_pattern = base_pattern->NextSiblingElement(ServiceAnnouncementXmlElements::BASE_PATTERN)) {
489  std::string base = base_pattern->GetText();
490 
491  // create a content stream
492  std::shared_ptr<ContentStream> cs;
493  if (_seamless) {
494  cs = std::make_shared<SeamlessContentStream>(base, _iface, _io_service, _cache,
495  service->delivery_protocol(), _cfg);
496  } else {
497  cs = std::make_shared<ContentStream>(base, _iface, _io_service, _cache, service->delivery_protocol(),
498  _cfg);
499  }
500 
501 
502  // Check for 5GBC delivery method elements
503  bool broadcast_delivery_available = false;
504  for (auto *delivery_method = usd->FirstChildElement(ServiceAnnouncementXmlElements::DELIVERY_METHOD);
505  delivery_method != nullptr;
506  delivery_method = delivery_method->NextSiblingElement(ServiceAnnouncementXmlElements::DELIVERY_METHOD)) {
507  auto sdp_uri = delivery_method->Attribute(ServiceAnnouncementXmlElements::SESSION_DESCRIPTION_URI);
508  auto broadcast_app_service = delivery_method->FirstChildElement(
510  std::string broadcast_base_pattern = broadcast_app_service->FirstChildElement(
512 
513  if (broadcast_base_pattern == base) {
514  for (const auto &item: _items) {
515  if (item.uri == broadcast_base_pattern) {
516  cs->read_master_manifest(item.content);
517  }
518  if (item.content_type == ContentTypeConstants::SDP &&
519  item.uri == sdp_uri) {
520  broadcast_delivery_available = cs->configure_5gbc_delivery_from_sdp(item.content);
521  }
522  }
523  }
524  }
525  bool unicast_delivery_available = false;
526 
527  // When seamless switching is enabled we check for unicast endpoints as well
528  if (_seamless) {
529  if (!broadcast_delivery_available) {
530  // No 5G broadcast available. Assume the base pattern is a CDN endpoint.
531  std::dynamic_pointer_cast<SeamlessContentStream>(cs)->set_cdn_endpoint(base);
532  unicast_delivery_available = true;
533  } else {
534  // Check for identical content entries to find a CDN base pattern
535  for (auto *identical_content = app_service->FirstChildElement(
537  identical_content != nullptr;
538  identical_content = identical_content->NextSiblingElement(
540 
541  bool base_matched = false;
542  std::string found_identical_base;
543  for (auto *base_pattern = identical_content->FirstChildElement(
545  base_pattern != nullptr;
546  base_pattern = base_pattern->NextSiblingElement(ServiceAnnouncementXmlElements::BASE_PATTERN)) {
547  std::string identical_base = base_pattern->GetText();
548  if (base == identical_base) {
549  base_matched = true;
550  } else {
551  found_identical_base = identical_base;
552  }
553  }
554 
555  if (base_matched && found_identical_base.length()) {
556  std::dynamic_pointer_cast<SeamlessContentStream>(cs)->set_cdn_endpoint(found_identical_base);
557  }
558  }
559  }
560  }
561 
562  if (unicast_delivery_available || broadcast_delivery_available) {
563  service->add_and_start_content_stream(cs);
564  }
565  }
566  }
567 }
const char *const ALTERNATIVE_CONTENT
Definition: Constants.h:50

◆ content()

const std::string& MBMS_RT::ServiceAnnouncement::content ( ) const
inline

Definition at line 56 of file ServiceAnnouncement.h.

56 { return _raw_content; };

◆ items()

const std::vector<Item>& MBMS_RT::ServiceAnnouncement::items ( ) const
inline

Definition at line 54 of file ServiceAnnouncement.h.

54 { return _items; };

◆ parse_bootstrap()

auto MBMS_RT::ServiceAnnouncement::parse_bootstrap ( const std::string &  str)

Parse the service announcement/bootstrap file.

Parameters
str

Definition at line 95 of file ServiceAnnouncement.cpp.

95  {
96  std::string bootstrap_format = ServiceAnnouncementFormatConstants::DEFAULT;
97  _cfg.lookupValue("mw.bootstrap_format", bootstrap_format);
98 
99  // Add all the SA items including their content to _items
101 
102  // Parse MBMS envelope: <metadataEnvelope>
103  for (const auto &item: _items) {
104  if (item.content_type == ContentTypeConstants::MBMS_ENVELOPE) {
105  _handleMbmsEnvelope(item);
106  }
107  }
108 
109  // Parse MBMS user service description bundle
110  for (const auto &item: _items) {
111  if (item.content_type == ContentTypeConstants::MBMS_USER_SERVICE_DESCRIPTION) {
112  _handleMbmbsUserServiceDescriptionBundle(item, bootstrap_format);
113  }
114  }
115 }
void _handleMbmsEnvelope(const Item &item)
Parses the MBMS envelope.
void _addServiceAnnouncementItems(const std::string &str)
Iterates through the service announcement file and adds the different sections/items to the the list ...
void _handleMbmbsUserServiceDescriptionBundle(const Item &item, const std::string &bootstrap_format)
Parses the MBMS USD.
const std::string MBMS_ENVELOPE
Definition: Constants.h:22
const std::string MBMS_USER_SERVICE_DESCRIPTION
Definition: Constants.h:23

◆ start_flute_receiver()

auto MBMS_RT::ServiceAnnouncement::start_flute_receiver ( const std::string &  mcast_address)

Starts the FLUTE receiver at the specified multicast address.

Includes a callback function that is called once a file has been received via multicast Used for receiving a service announcement file via multicast

Parameters
mcast_address

Definition at line 61 of file ServiceAnnouncement.cpp.

61  {
62  size_t delim = mcast_address.find(':');
63  if (delim == std::string::npos) {
64  spdlog::error("Invalid multicast address {}", mcast_address);
65  return;
66  }
67  _mcast_addr = mcast_address.substr(0, delim);
68  _mcast_port = mcast_address.substr(delim + 1);
69  spdlog::info("Starting FLUTE receiver on {}:{} for TSI {}", _mcast_addr, _mcast_port, _tsi);
70  _flute_thread = std::thread{[&]() {
71  _flute_receiver = std::make_unique<LibFlute::Receiver>(_iface, _mcast_addr, atoi(_mcast_port.c_str()), _tsi,
72  _io_service);
73  _flute_receiver->register_completion_callback(
74  [&](std::shared_ptr<LibFlute::File> file) { //NOLINT
75  spdlog::info("{} (TOI {}) has been received",
76  file->meta().content_location, file->meta().toi);
77  if (!_bootstrapped || _toi != file->meta().toi) {
78  _toi = file->meta().toi;
79  if (file->meta().content_type == "application/x-gzip") {
80  _raw_content = gzip::decompress(file->buffer(), file->length());
81  } else {
82  _raw_content = std::string(file->buffer());
83  }
84  parse_bootstrap(file->buffer());
85  }
86  });
87  }};
88 }
void parse_bootstrap(const std::string &str)
Parse the service announcement/bootstrap file.

◆ toi()

uint32_t MBMS_RT::ServiceAnnouncement::toi ( ) const
inline

Definition at line 58 of file ServiceAnnouncement.h.

58 { return _toi; };

Member Data Documentation

◆ _base_path

std::string MBMS_RT::ServiceAnnouncement::_base_path
private

Definition at line 83 of file ServiceAnnouncement.h.

◆ _bootstrapped

bool MBMS_RT::ServiceAnnouncement::_bootstrapped = false
private

Definition at line 75 of file ServiceAnnouncement.h.

◆ _cache

CacheManagement& MBMS_RT::ServiceAnnouncement::_cache
private

Definition at line 89 of file ServiceAnnouncement.h.

◆ _cfg

const libconfig::Config& MBMS_RT::ServiceAnnouncement::_cfg
private

Definition at line 73 of file ServiceAnnouncement.h.

◆ _flute_receiver

std::unique_ptr<LibFlute::Receiver> MBMS_RT::ServiceAnnouncement::_flute_receiver
private

Definition at line 86 of file ServiceAnnouncement.h.

◆ _flute_thread

std::thread MBMS_RT::ServiceAnnouncement::_flute_thread
private

Definition at line 85 of file ServiceAnnouncement.h.

◆ _get_service

get_service_callback_t MBMS_RT::ServiceAnnouncement::_get_service
private

Definition at line 66 of file ServiceAnnouncement.h.

◆ _iface

std::string MBMS_RT::ServiceAnnouncement::_iface
private

Definition at line 79 of file ServiceAnnouncement.h.

◆ _io_service

boost::asio::io_service& MBMS_RT::ServiceAnnouncement::_io_service
private

Definition at line 88 of file ServiceAnnouncement.h.

◆ _items

std::vector<Item> MBMS_RT::ServiceAnnouncement::_items
private

Definition at line 71 of file ServiceAnnouncement.h.

◆ _mcast_addr

std::string MBMS_RT::ServiceAnnouncement::_mcast_addr
private

Definition at line 81 of file ServiceAnnouncement.h.

◆ _mcast_port

std::string MBMS_RT::ServiceAnnouncement::_mcast_port
private

Definition at line 82 of file ServiceAnnouncement.h.

◆ _raw_content

std::string MBMS_RT::ServiceAnnouncement::_raw_content
private

Definition at line 78 of file ServiceAnnouncement.h.

◆ _seamless

bool MBMS_RT::ServiceAnnouncement::_seamless = false
private

Definition at line 69 of file ServiceAnnouncement.h.

◆ _set_service

set_service_callback_t MBMS_RT::ServiceAnnouncement::_set_service
private

Definition at line 67 of file ServiceAnnouncement.h.

◆ _tmgi

std::string MBMS_RT::ServiceAnnouncement::_tmgi
private

Definition at line 80 of file ServiceAnnouncement.h.

◆ _toi

uint32_t MBMS_RT::ServiceAnnouncement::_toi = {}
private

Definition at line 77 of file ServiceAnnouncement.h.

◆ _tsi

unsigned long long MBMS_RT::ServiceAnnouncement::_tsi = 0
private

Definition at line 84 of file ServiceAnnouncement.h.


The documentation for this class was generated from the following files: