Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for adding Session Based Descriptor Document Essential Property for DASH #856

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/packager/mpd_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ struct MpdParams {
/// and is greatly influnced by the player.
/// This parameter is required by DASH-IF Low Latency standards.
double target_latency_seconds = 1;

/// Session Based Description Document flags.
struct SBD {
std::string url_;
std::string template_;
std::vector<std::pair<std::string, std::string>> sbd_keys_;
};
std::vector<SBD> sbd_adaptation_set_video;
std::vector<SBD> sbd_adaptation_set_audio;
std::vector<SBD> sbd_adaptation_set_text;
std::vector<SBD> sbd_adaptation_set_all;
};

} // namespace shaka
Expand Down
47 changes: 47 additions & 0 deletions packager/app/mpd_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,50 @@ ABSL_FLAG(
"https://shaka-project.github.io/shaka-packager/html/tutorials/low_latency.html "
// clang-format on
"for more information.");
ABSL_FLAG(std::string,
sbd_url_all,
"",
"Comma separated URLs of sbd document.Add to all adaptation sets.");
ABSL_FLAG(std::string,
sbd_template_all,
"",
"Comma separated template used to create URL query.");
ABSL_FLAG(std::string,
sbd_key_all,
"",
"Comma separated SBD keys to fetch from sbd client.");
ABSL_FLAG(
std::string,
sbd_url_video,
"",
"Comma separated URL of sbd document. Add to all video adaptation sets");
ABSL_FLAG(std::string,
sbd_template_video,
"",
"Comma separated template used to create URL query.");
ABSL_FLAG(std::string, sbd_key_video, "", "SBD keys to fetch from sbd client.");
ABSL_FLAG(std::string,
sbd_url_audio,
"",
"Comma separated URL of sbd document.Add to all adaptation sets.");
ABSL_FLAG(std::string,
sbd_template_audio,
"",
"Comma separated Template used to create URL query.");
ABSL_FLAG(std::string,
sbd_key_audio,
"",
"Comma separated SBD keys to fetch from sbd client.");
ABSL_FLAG(
std::string,
sbd_url_text,
"",
"Comma separated URL of sbd document. Add to all text adapatation sets.");
ABSL_FLAG(std::string,
sbd_template_text,
"",
"Comma separated Template used to create URL query.");
ABSL_FLAG(std::string,
sbd_key_text,
"",
"Comma separated SBD key-value pairs.");
17 changes: 17 additions & 0 deletions packager/app/mpd_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,21 @@ ABSL_DECLARE_FLAG(bool, include_mspr_pro_for_playready);
ABSL_DECLARE_FLAG(bool, dash_force_segment_list);
ABSL_DECLARE_FLAG(bool, low_latency_dash_mode);

// Session based urls
ABSL_DECLARE_FLAG(std::string, sbd_url_all);
ABSL_DECLARE_FLAG(std::string, sbd_template_all);
ABSL_DECLARE_FLAG(std::string, sbd_key_all);

ABSL_DECLARE_FLAG(std::string, sbd_url_video);
ABSL_DECLARE_FLAG(std::string, sbd_template_video);
ABSL_DECLARE_FLAG(std::string, sbd_key_video);

ABSL_DECLARE_FLAG(std::string, sbd_url_audio);
ABSL_DECLARE_FLAG(std::string, sbd_template_audio);
ABSL_DECLARE_FLAG(std::string, sbd_key_audio);
ABSL_DECLARE_FLAG(std::string, sbd_url_text);

ABSL_DECLARE_FLAG(std::string, sbd_template_text);
ABSL_DECLARE_FLAG(std::string, sbd_key_text);

#endif // APP_MPD_FLAGS_H_
63 changes: 63 additions & 0 deletions packager/app/packager_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,50 @@ bool ParseProtectionSystems(const std::string& protection_systems_str,
return true;
}

void addSBDParams(const std::string& sbd_url,
const std::string& sbd_template,
const std::string& sbd_key,
const std::string content_type,
MpdParams& mpd_params) {
// Get comma separted urls
std::vector<std::string> sbd_urls = absl::StrSplit(sbd_url, ",");
std::vector<std::string> sbd_templates = absl::StrSplit(sbd_template, ",");

std::vector<std::vector<std::pair<std::string, std::string>>> sbd_keys_all;

if (!sbd_key.empty()) {
std::vector<std::string> sbd_keys = absl::StrSplit(sbd_key, ":");
for (std::string key : sbd_keys) {
std::vector<KVPair> pairs = SplitStringIntoKeyValuePairs(key, '=', ',');
if (pairs.empty()) {
LOG(ERROR) << "Invalid --sbd_key keyname/defaultvalue pairs.";
}

std::vector<std::pair<std::string, std::string>> v;
for (const auto& string_pair : pairs) {
v.push_back(std::make_pair(string_pair.first, string_pair.second));
}
sbd_keys_all.push_back(v);
}
}

// store sbd details in mpd params.
for (int i = 0; i < (int)sbd_urls.size(); i++) {
if (content_type == "all")
mpd_params.sbd_adaptation_set_all.push_back(
{sbd_urls[i], sbd_templates[i], sbd_keys_all[i]});
if (content_type == "video")
mpd_params.sbd_adaptation_set_video.push_back(
{sbd_urls[i], sbd_templates[i], sbd_keys_all[i]});
if (content_type == "audio")
mpd_params.sbd_adaptation_set_audio.push_back(
{sbd_urls[i], sbd_templates[i], sbd_keys_all[i]});
if (content_type == "text")
mpd_params.sbd_adaptation_set_text.push_back(
{sbd_urls[i], sbd_templates[i], sbd_keys_all[i]});
}
}

std::optional<PackagingParams> GetPackagingParams() {
PackagingParams packaging_params;

Expand Down Expand Up @@ -523,6 +567,25 @@ std::optional<PackagingParams> GetPackagingParams() {
absl::GetFlag(FLAGS_include_mspr_pro_for_playready);
mpd_params.low_latency_dash_mode = absl::GetFlag(FLAGS_low_latency_dash_mode);

if (!absl::GetFlag(FLAGS_sbd_url_all).empty())
addSBDParams(absl::GetFlag(FLAGS_sbd_url_all),
absl::GetFlag(FLAGS_sbd_template_all),
absl::GetFlag(FLAGS_sbd_key_all), "all", mpd_params);

if (!absl::GetFlag(FLAGS_sbd_url_video).empty()) {
addSBDParams(absl::GetFlag(FLAGS_sbd_url_video),
absl::GetFlag(FLAGS_sbd_template_video),
absl::GetFlag(FLAGS_sbd_key_video), "video", mpd_params);
}
if (!absl::GetFlag(FLAGS_sbd_url_audio).empty())
addSBDParams(absl::GetFlag(FLAGS_sbd_url_audio),
absl::GetFlag(FLAGS_sbd_template_audio),
absl::GetFlag(FLAGS_sbd_key_audio), "audio", mpd_params);
if (!absl::GetFlag(FLAGS_sbd_url_text).empty())
addSBDParams(absl::GetFlag(FLAGS_sbd_url_text),
absl::GetFlag(FLAGS_sbd_template_text),
absl::GetFlag(FLAGS_sbd_key_text), "text", mpd_params);

HlsParams& hls_params = packaging_params.hls_params;
if (!GetHlsPlaylistType(absl::GetFlag(FLAGS_hls_playlist_type),
&hls_params.playlist_type)) {
Expand Down
61 changes: 60 additions & 1 deletion packager/app/test/packager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,19 @@ def _GetFlags(self,
use_fake_clock=True,
allow_codec_switching=False,
dash_force_segment_list=False,
force_cl_index=None):
force_cl_index=False,
sbd_url_all=None,
sbd_template_all=None,
sbd_key_all=None,
sbd_url_video=None,
sbd_template_video=None,
sbd_key_video=None,
sbd_url_audio=None,
sbd_template_audio=None,
sbd_key_audio=None,
sbd_url_text=None,
sbd_template_text=None,
sbd_key_text=None):

flags = ['--single_threaded']

Expand Down Expand Up @@ -564,6 +576,34 @@ def _GetFlags(self,
if utc_timings:
flags += ['--utc_timings', utc_timings]

if sbd_url_all:
flags += ['--sbd_url_all', sbd_url_all]
if sbd_template_all:
flags += ['--sbd_template_all', sbd_template_all]
if sbd_key_all:
flags += ['--sbd_key_all', sbd_key_all]

if sbd_url_video:
flags += ['--sbd_url_video', sbd_url_video]
if sbd_template_video:
flags += ['--sbd_template_video', sbd_template_video]
if sbd_key_video:
flags += ['--sbd_key_video', sbd_key_video]

if sbd_url_audio:
flags += ['--sbd_url_audio', sbd_url_audio]
if sbd_template_audio:
flags += ['--sbd_template_audio', sbd_template_audio]
if sbd_key_audio:
flags += ['--sbd_key_audio', sbd_key_audio]

if sbd_url_text:
flags += ['--sbd_url_text', sbd_url_text]
if sbd_template_text:
flags += ['--sbd_template_text', sbd_template_text]
if sbd_key_text:
flags += ['--sbd_key_text', sbd_key_text]

if generate_static_live_mpd:
flags += ['--generate_static_live_mpd']

Expand Down Expand Up @@ -808,6 +848,25 @@ def testDashLabel(self):
self.assertPackageSuccess(streams, self._GetFlags(output_dash=True))
self._CheckTestResults('dash-label')

def testSBD(self):
streams = [
self._GetStream('video'),
self._GetStream('audio'),
]
self.assertPackageSuccess(
streams,
self._GetFlags(output_dash=True,
sbd_url_all='all_adaptation_sets',
sbd_template_all='t1',
sbd_key_all='k1=v1,k2=v2',
sbd_url_video='video1,video2',
sbd_template_video='t2,t3',
sbd_key_video='k3=v3:k4=v4' ,
sbd_url_audio='audio1,audio2' ,
sbd_template_audio='t4,t5',
sbd_key_audio='k5=v5:k6=v6'))
self._CheckTestResults('sbd_test')

def testForcedSubtitle(self):
streams = [
self._GetStream('audio', hls=True),
Expand Down
Binary file not shown.
Binary file not shown.
43 changes: 43 additions & 0 deletions packager/app/test/testdata/sbd_test/output.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:sbd="urn:mpeg:dash:sbd:2020" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.736067S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<EssentialProperty schemeIdUri="urn:mpeg:dash:sbd:2020" value="video1" sbd:template="t2">
<sbd:Key name="k3" defaultValue="v3"/>
</EssentialProperty>
<EssentialProperty schemeIdUri="urn:mpeg:dash:sbd:2020" value="video2" sbd:template="t3">
<sbd:Key name="k4" defaultValue="v4"/>
</EssentialProperty>
<EssentialProperty schemeIdUri="urn:mpeg:dash:sbd:2020" value="all_adaptation_sets" sbd:template="t1">
<sbd:Key name="k1" defaultValue="v1"/>
<sbd:Key name="k2" defaultValue="v2"/>
</EssentialProperty>
<Representation id="0" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="870-937" timescale="30000">
<Initialization range="0-869"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
<EssentialProperty schemeIdUri="urn:mpeg:dash:sbd:2020" value="audio1" sbd:template="t4">
<sbd:Key name="k5" defaultValue="v5"/>
</EssentialProperty>
<EssentialProperty schemeIdUri="urn:mpeg:dash:sbd:2020" value="audio2" sbd:template="t5">
<sbd:Key name="k6" defaultValue="v6"/>
</EssentialProperty>
<EssentialProperty schemeIdUri="urn:mpeg:dash:sbd:2020" value="all_adaptation_sets" sbd:template="t1">
<sbd:Key name="k1" defaultValue="v1"/>
<sbd:Key name="k2" defaultValue="v2"/>
</EssentialProperty>
<Representation id="1" bandwidth="133334" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>bear-640x360-audio.mp4</BaseURL>
<SegmentBase indexRange="804-871" timescale="44100">
<Initialization range="0-803"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
37 changes: 36 additions & 1 deletion packager/mpd/base/adaptation_set.cc
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,47 @@ std::optional<xml::XmlNode> AdaptationSet::GetXml() {
? tp_adaptation_set->index_.value()
: tp_adaptation_set->id());
}

if (!trick_play_reference_ids.empty() &&
!adaptation_set.AddEssentialProperty(
"http://dashif.org/guidelines/trickmode", trick_play_reference_ids)) {
"http://dashif.org/guidelines/trickmode", trick_play_reference_ids,
mpd_options_)) {
return std::nullopt;
}

// Add sbd essential property here
// video
if (!mpd_options_.mpd_params.sbd_adaptation_set_video.empty() &&
content_type_ == "video") {
if (!adaptation_set.AddEssentialProperty("urn:mpeg:dash:sbd:2020", "video",
mpd_options_)) {
return std::nullopt;
}
}
// audio
if (!mpd_options_.mpd_params.sbd_adaptation_set_audio.empty() &&
content_type_ == "audio") {
if (!adaptation_set.AddEssentialProperty("urn:mpeg:dash:sbd:2020", "audio",
mpd_options_)) {
return std::nullopt;
}
}
// text
if (!mpd_options_.mpd_params.sbd_adaptation_set_text.empty() &&
content_type_ == "text") {
if (!adaptation_set.AddEssentialProperty("urn:mpeg:dash:sbd:2020", "text",
mpd_options_)) {
return std::nullopt;
}
}
// all
if (!mpd_options_.mpd_params.sbd_adaptation_set_all.empty()) {
if (!adaptation_set.AddEssentialProperty("urn:mpeg:dash:sbd:2020", "all",
mpd_options_)) {
return std::nullopt;
}
}

std::string switching_ids;
for (const AdaptationSet* s_adaptation_set : switchable_adaptation_sets_) {
// Should be a comma-separated list, see DASH-IOP 3.8.
Expand Down
8 changes: 4 additions & 4 deletions packager/mpd/base/mpd_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ bool AddMpdNameSpaceInfo(XmlNode* mpd) {
"urn:marlin:mas:1-0:services:schemas:mpd";
static const char kXmlNamespaceXlink[] = "http://www.w3.org/1999/xlink";
static const char kMsprNamespace[] = "urn:microsoft:playready";
static const char kSbdNamespace[] = "urn:mpeg:dash:sbd:2020";

const std::map<std::string, std::string> uris = {
{"cenc", kCencNamespace},
{"mas", kMarlinNamespace},
{"xlink", kXmlNamespaceXlink},
{"mspr", kMsprNamespace},
{"cenc", kCencNamespace}, {"mas", kMarlinNamespace},
{"xlink", kXmlNamespaceXlink}, {"mspr", kMsprNamespace},
{"sbd", kSbdNamespace},
};

for (const std::string& namespace_name : namespaces) {
Expand Down
Loading
Loading