[DASH] Support custom Accessibility and Role elements
Add dash_accessibilities stream descriptor, which is a semi-colon separated list of accessibility_scheme_id_uri=value. It is optional. Add dash_roles stream descriptor, which is a semi-colon separated list of strings. It is optional. Closes #565. Change-Id: Idb1c20bb410fdd016db07e11fe507c102a3dd8ea
This commit is contained in:
parent
0a2b43939c
commit
796974d2a1
|
@ -0,0 +1,16 @@
|
|||
DASH specific stream descriptor fields
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:dash_accessibilities (accessibilities):
|
||||
|
||||
Optional semicolon separated list of values for DASH Accessibility element.
|
||||
The value should be in the format: scheme_id_uri=value, which propagates
|
||||
to the Accessibility element in the result DASH manifest. See DASH
|
||||
(ISO/IEC 23009-1) specification for details.
|
||||
|
||||
:dash_roles (roles):
|
||||
|
||||
Optional semicolon separated list of values for DASH Role element. The
|
||||
value should be one of: **caption**, **subtitle**, **main**, **alternate**,
|
||||
**supplementary**, **commentary** and **dub**. See DASH (ISO/IEC 23009-1)
|
||||
specification for details.
|
|
@ -82,5 +82,6 @@ which describes the streams.
|
|||
Configuration options
|
||||
---------------------
|
||||
|
||||
.. include:: /options/dash_stream_descriptors.rst
|
||||
.. include:: /options/dash_options.rst
|
||||
.. include:: /options/segment_template_formatting.rst
|
||||
|
|
|
@ -104,7 +104,14 @@ const char kUsage[] =
|
|||
" unspecified, no I-Frames only playlist is created.\n"
|
||||
" - hls_characteristics (charcs): Optional colon/semicolon separated\n"
|
||||
" list of values for the CHARACTERISTICS attribute for EXT-X-MEDIA.\n"
|
||||
" See CHARACTERISTICS attribute in http://bit.ly/2OOUkdB for details.\n";
|
||||
" See CHARACTERISTICS attribute in http://bit.ly/2OOUkdB for details.\n"
|
||||
" - dash_accessibilities (accessibilities): Optional semicolon separated\n"
|
||||
" list of values for DASH Accessibility elements. The value should be\n"
|
||||
" in the format: scheme_id_uri=value.\n"
|
||||
" - dash_roles (roles): Optional semicolon separated list of values for\n"
|
||||
" DASH Role elements. The value should be one of: caption, subtitle,\n"
|
||||
" main, alternate, supplementary, commentary and dub. See DASH\n"
|
||||
" (ISO/IEC 23009-1) specification for details.\n";
|
||||
|
||||
// Labels for parameters in RawKey key info.
|
||||
const char kDrmLabelLabel[] = "label";
|
||||
|
|
|
@ -31,6 +31,8 @@ enum FieldType {
|
|||
kSkipEncryptionField,
|
||||
kDrmStreamLabelField,
|
||||
kHlsCharacteristicsField,
|
||||
kDashAccessiblitiesField,
|
||||
kDashRolesField,
|
||||
};
|
||||
|
||||
struct FieldNameToTypeMapping {
|
||||
|
@ -67,6 +69,14 @@ const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
|
|||
{"hls_characteristics", kHlsCharacteristicsField},
|
||||
{"characteristics", kHlsCharacteristicsField},
|
||||
{"charcs", kHlsCharacteristicsField},
|
||||
{"dash_accessibilities", kDashAccessiblitiesField},
|
||||
{"dash_accessibility", kDashAccessiblitiesField},
|
||||
{"accessibilities", kDashAccessiblitiesField},
|
||||
{"accessibility", kDashAccessiblitiesField},
|
||||
{"dash_roles", kDashRolesField},
|
||||
{"dash_role", kDashRolesField},
|
||||
{"roles", kDashRolesField},
|
||||
{"role", kDashRolesField},
|
||||
};
|
||||
|
||||
FieldType GetFieldType(const std::string& field_name) {
|
||||
|
@ -176,6 +186,26 @@ base::Optional<StreamDescriptor> ParseStreamDescriptor(
|
|||
base::SplitString(iter->second, ";:", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
break;
|
||||
case kDashAccessiblitiesField:
|
||||
descriptor.dash_accessiblities =
|
||||
base::SplitString(iter->second, ";", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
for (const std::string& accessibility :
|
||||
descriptor.dash_accessiblities) {
|
||||
size_t pos = accessibility.find('=');
|
||||
if (pos == std::string::npos) {
|
||||
LOG(ERROR)
|
||||
<< "Accessibility should be in scheme=value format, but seeing "
|
||||
<< accessibility;
|
||||
return base::nullopt;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kDashRolesField:
|
||||
descriptor.dash_roles =
|
||||
base::SplitString(iter->second, ";", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first
|
||||
<< "\").";
|
||||
|
|
|
@ -275,6 +275,8 @@ class PackagerAppTest(unittest.TestCase):
|
|||
using_time_specifier=False,
|
||||
hls=False,
|
||||
hls_characteristics=None,
|
||||
dash_accessibilities=None,
|
||||
dash_roles=None,
|
||||
trick_play_factor=None,
|
||||
drm_label=None,
|
||||
skip_encryption=None,
|
||||
|
@ -301,6 +303,8 @@ class PackagerAppTest(unittest.TestCase):
|
|||
$Number$. This flag is only relevant if segmented is True.
|
||||
hls: Should the output be for an HLS manifest.
|
||||
hls_characteristics: CHARACTERISTICS attribute for the HLS stream.
|
||||
dash_accessibilities: Accessibility element for the DASH stream.
|
||||
dash_roles: Role element for the DASH stream.
|
||||
trick_play_factor: Signals the stream is to be used for a trick play
|
||||
stream and which key frames to use. A trick play factor of 0 is the
|
||||
same as not specifying a trick play factor.
|
||||
|
@ -356,6 +360,11 @@ class PackagerAppTest(unittest.TestCase):
|
|||
if hls_characteristics:
|
||||
stream.Append('hls_characteristics', hls_characteristics)
|
||||
|
||||
if dash_accessibilities:
|
||||
stream.Append('dash_accessibilities', dash_accessibilities)
|
||||
if dash_roles:
|
||||
stream.Append('dash_roles', dash_roles)
|
||||
|
||||
requires_init_segment = segmented and base_ext not in [
|
||||
'aac', 'ac3', 'ec3', 'ts', 'vtt'
|
||||
]
|
||||
|
@ -638,6 +647,18 @@ class PackagerFunctionalTest(PackagerAppTest):
|
|||
self._GetStreams(['audio', 'video']), self._GetFlags(output_dash=True))
|
||||
self._CheckTestResults('audio-video')
|
||||
|
||||
def testAudioVideoWithAccessibilitiesAndRoles(self):
|
||||
streams = [
|
||||
self._GetStream(
|
||||
'audio',
|
||||
dash_accessibilities='urn:tva:metadata:cs:AudioPurposeCS:2007=1',
|
||||
dash_roles='alternate'),
|
||||
self._GetStream('video'),
|
||||
]
|
||||
|
||||
self.assertPackageSuccess(streams, self._GetFlags(output_dash=True))
|
||||
self._CheckTestResults('audio-video-with-accessibilities-and-roles')
|
||||
|
||||
def testAudioVideoWithTrickPlay(self):
|
||||
streams = [
|
||||
self._GetStream('audio'),
|
||||
|
|
BIN
packager/app/test/testdata/audio-video-with-accessibilities-and-roles/bear-640x360-audio.mp4
vendored
Normal file
BIN
packager/app/test/testdata/audio-video-with-accessibilities-and-roles/bear-640x360-audio.mp4
vendored
Normal file
Binary file not shown.
BIN
packager/app/test/testdata/audio-video-with-accessibilities-and-roles/bear-640x360-video.mp4
vendored
Normal file
BIN
packager/app/test/testdata/audio-video-with-accessibilities-and-roles/bear-640x360-video.mp4
vendored
Normal file
Binary file not shown.
25
packager/app/test/testdata/audio-video-with-accessibilities-and-roles/output.mpd
vendored
Normal file
25
packager/app/test/testdata/audio-video-with-accessibilities-and-roles/output.mpd
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Generated with https://github.com/google/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" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.7360665798187256S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
<BaseURL>bear-640x360-video.mp4</BaseURL>
|
||||
<SegmentBase indexRange="859-926" timescale="30000">
|
||||
<Initialization range="0-858"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
||||
<Accessibility schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007" value="1"/>
|
||||
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="alternate"/>
|
||||
<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="793-860" timescale="44100">
|
||||
<Initialization range="0-792"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
|
@ -71,6 +71,10 @@ void MpdNotifyMuxerListener::OnMediaStart(
|
|||
LOG(ERROR) << "Failed to generate MediaInfo from input.";
|
||||
return;
|
||||
}
|
||||
for (const std::string& accessibility : accessibilities_)
|
||||
media_info->add_dash_accessibilities(accessibility);
|
||||
for (const std::string& role : roles_)
|
||||
media_info->add_dash_roles(role);
|
||||
|
||||
if (is_encrypted_) {
|
||||
internal::SetContentProtectionFields(protection_scheme_, default_key_id_,
|
||||
|
|
|
@ -55,6 +55,12 @@ class MpdNotifyMuxerListener : public MuxerListener {
|
|||
void OnCueEvent(int64_t timestamp, const std::string& cue_data) override;
|
||||
/// @}
|
||||
|
||||
void set_accessibilities(const std::vector<std::string>& accessiblities) {
|
||||
accessibilities_ = accessiblities;
|
||||
}
|
||||
|
||||
void set_roles(const std::vector<std::string>& roles) { roles_ = roles; }
|
||||
|
||||
private:
|
||||
MpdNotifyMuxerListener(const MpdNotifyMuxerListener&) = delete;
|
||||
MpdNotifyMuxerListener& operator=(const MpdNotifyMuxerListener&) = delete;
|
||||
|
@ -65,6 +71,9 @@ class MpdNotifyMuxerListener : public MuxerListener {
|
|||
base::Optional<uint32_t> notification_id_;
|
||||
std::unique_ptr<MediaInfo> media_info_;
|
||||
|
||||
std::vector<std::string> accessibilities_;
|
||||
std::vector<std::string> roles_;
|
||||
|
||||
bool is_encrypted_ = false;
|
||||
// Storage for values passed to OnEncryptionInfoReady().
|
||||
FourCC protection_scheme_ = FOURCC_NULL;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "packager/media/event/muxer_listener_factory.h"
|
||||
|
||||
#include "packager/base/memory/ptr_util.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include "packager/hls/base/hls_notifier.h"
|
||||
#include "packager/media/event/combined_muxer_listener.h"
|
||||
|
@ -30,10 +31,13 @@ std::unique_ptr<MuxerListener> CreateMediaInfoDumpListenerInternal(
|
|||
}
|
||||
|
||||
std::unique_ptr<MuxerListener> CreateMpdListenerInternal(
|
||||
const MuxerListenerFactory::StreamData& stream,
|
||||
MpdNotifier* notifier) {
|
||||
DCHECK(notifier);
|
||||
|
||||
std::unique_ptr<MuxerListener> listener(new MpdNotifyMuxerListener(notifier));
|
||||
auto listener = base::MakeUnique<MpdNotifyMuxerListener>(notifier);
|
||||
listener->set_accessibilities(stream.dash_accessiblities);
|
||||
listener->set_roles(stream.dash_roles);
|
||||
return listener;
|
||||
}
|
||||
|
||||
|
@ -91,7 +95,8 @@ std::unique_ptr<MuxerListener> MuxerListenerFactory::CreateListener(
|
|||
CreateMediaInfoDumpListenerInternal(stream.media_info_output));
|
||||
}
|
||||
if (mpd_notifier_) {
|
||||
combined_listener->AddListener(CreateMpdListenerInternal(mpd_notifier_));
|
||||
combined_listener->AddListener(
|
||||
CreateMpdListenerInternal(stream, mpd_notifier_));
|
||||
}
|
||||
if (hls_notifier_) {
|
||||
for (auto& listener :
|
||||
|
|
|
@ -46,6 +46,11 @@ class MuxerListenerFactory {
|
|||
std::string hls_playlist_name;
|
||||
std::string hls_iframe_playlist_name;
|
||||
std::vector<std::string> hls_characteristics;
|
||||
|
||||
// DASH specific values needed to write DASH mpd. Will only be used if an
|
||||
// MpdNotifier is given to the factory.
|
||||
std::vector<std::string> dash_accessiblities;
|
||||
std::vector<std::string> dash_roles;
|
||||
};
|
||||
|
||||
/// Create a new muxer listener.
|
||||
|
|
|
@ -55,11 +55,8 @@ std::string RoleToText(AdaptationSet::Role role) {
|
|||
case AdaptationSet::kRoleDub:
|
||||
return "dub";
|
||||
default:
|
||||
break;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return "";
|
||||
}
|
||||
|
||||
// Returns the picture aspect ratio string e.g. "16:9", "4:3".
|
||||
|
@ -225,6 +222,11 @@ void AdaptationSet::UpdateContentProtectionPssh(const std::string& drm_uuid,
|
|||
&content_protection_elements_);
|
||||
}
|
||||
|
||||
void AdaptationSet::AddAccessibility(const std::string& scheme,
|
||||
const std::string& value) {
|
||||
accessibilities_.push_back(Accessibility{scheme, value});
|
||||
}
|
||||
|
||||
void AdaptationSet::AddRole(Role role) {
|
||||
roles_.insert(role);
|
||||
}
|
||||
|
@ -318,6 +320,11 @@ xml::scoped_xml_ptr<xmlNode> AdaptationSet::GetXml() {
|
|||
"urn:mpeg:dash:adaptation-set-switching:2016", switching_ids);
|
||||
}
|
||||
|
||||
for (const AdaptationSet::Accessibility& accessibility : accessibilities_) {
|
||||
adaptation_set.AddAccessibilityElement(accessibility.scheme,
|
||||
accessibility.value);
|
||||
}
|
||||
|
||||
for (AdaptationSet::Role role : roles_)
|
||||
adaptation_set.AddRoleElement("urn:mpeg:dash:role:2011", RoleToText(role));
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ class AdaptationSet {
|
|||
// element to the AdaptationSet with schemeIdUri=urn:mpeg:dash:role:2011.
|
||||
// See ISO/IEC 23009-1:2012 section 5.8.5.5.
|
||||
enum Role {
|
||||
kRoleUnknown,
|
||||
kRoleCaption,
|
||||
kRoleSubtitle,
|
||||
kRoleMain,
|
||||
|
@ -94,6 +95,13 @@ class AdaptationSet {
|
|||
virtual void UpdateContentProtectionPssh(const std::string& drm_uuid,
|
||||
const std::string& pssh);
|
||||
|
||||
/// Set the Accessibility element for this AdaptationSet.
|
||||
/// See ISO/IEC 23009-1:2012 section 5.8.4.3.
|
||||
/// @param scheme is the schemeIdUri of the accessibility element.
|
||||
/// @param value is the value of the accessibility element.
|
||||
virtual void AddAccessibility(const std::string& scheme,
|
||||
const std::string& value);
|
||||
|
||||
/// Set the Role element for this AdaptationSet.
|
||||
/// The Role element's is schemeIdUri='urn:mpeg:dash:role:2011'.
|
||||
/// See ISO/IEC 23009-1:2012 section 5.8.5.5.
|
||||
|
@ -271,6 +279,13 @@ class AdaptationSet {
|
|||
// in this set.
|
||||
std::set<std::string> picture_aspect_ratio_;
|
||||
|
||||
// accessibilities of this AdaptationSet.
|
||||
struct Accessibility {
|
||||
std::string scheme;
|
||||
std::string value;
|
||||
};
|
||||
std::vector<Accessibility> accessibilities_;
|
||||
|
||||
// The roles of this AdaptationSet.
|
||||
std::set<Role> roles_;
|
||||
|
||||
|
|
|
@ -163,6 +163,22 @@ TEST_F(AdaptationSetTest, CheckAdaptationSetId) {
|
|||
AttributeEqual("id", std::to_string(kAdaptationSetId)));
|
||||
}
|
||||
|
||||
// Verify AdaptationSet::AddAccessibilityElement() works.
|
||||
TEST_F(AdaptationSetTest, AddAccessibilityElement) {
|
||||
auto adaptation_set = CreateAdaptationSet(kNoLanguage);
|
||||
adaptation_set->AddAccessibility("urn:tva:metadata:cs:AudioPurposeCS:2007",
|
||||
"2");
|
||||
|
||||
// The empty contentType is sort of a side effect of being able to generate an
|
||||
// MPD without adding any Representations.
|
||||
const char kExpectedOutput[] =
|
||||
"<AdaptationSet contentType=\"\">\n"
|
||||
" <Accessibility schemeIdUri=\"urn:tva:metadata:cs:AudioPurposeCS:2007\""
|
||||
" value=\"2\"/>\n"
|
||||
"</AdaptationSet>";
|
||||
EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput));
|
||||
}
|
||||
|
||||
// Verify AdaptationSet::AddRole() works for "main" role.
|
||||
TEST_F(AdaptationSetTest, AdaptationAddRoleElementMain) {
|
||||
auto adaptation_set = CreateAdaptationSet(kNoLanguage);
|
||||
|
|
|
@ -164,4 +164,12 @@ message MediaInfo {
|
|||
|
||||
// HLS only. Defines CHARACTERISTICS attribute of the stream.
|
||||
repeated string hls_characteristics = 20;
|
||||
|
||||
// DASH only. Defines Accessibility elements of the stream. It should be in
|
||||
// the format: scheme_id_uri=value.
|
||||
repeated string dash_accessibilities = 21;
|
||||
// DASH only. Defines Role elements of the stream. The value can be a valid
|
||||
// Role value defined in "urn:mpeg:dash:role:2011" scheme or in the format:
|
||||
// scheme_id_uri=value (to be implemented).
|
||||
repeated string dash_roles = 22;
|
||||
}
|
||||
|
|
|
@ -168,6 +168,18 @@ std::string GetAdaptationSetKey(const MediaInfo& media_info) {
|
|||
key.append(":trick_play");
|
||||
}
|
||||
|
||||
if (!media_info.dash_accessibilities().empty()) {
|
||||
key.append(":accessibility_");
|
||||
for (const std::string& accessibility : media_info.dash_accessibilities())
|
||||
key.append(accessibility);
|
||||
}
|
||||
|
||||
if (!media_info.dash_roles().empty()) {
|
||||
key.append(":roles_");
|
||||
for (const std::string& role : media_info.dash_roles())
|
||||
key.append(role);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,24 @@ const std::string& GetDefaultTextLanguage(const MpdOptions& mpd_options) {
|
|||
: mpd_options.mpd_params.default_text_language;
|
||||
}
|
||||
|
||||
AdaptationSet::Role RoleFromString(const std::string& role_str) {
|
||||
if (role_str == "caption")
|
||||
return AdaptationSet::Role::kRoleCaption;
|
||||
if (role_str == "subtitle")
|
||||
return AdaptationSet::Role::kRoleSubtitle;
|
||||
if (role_str == "main")
|
||||
return AdaptationSet::Role::kRoleMain;
|
||||
if (role_str == "alternate")
|
||||
return AdaptationSet::Role::kRoleAlternate;
|
||||
if (role_str == "supplementary")
|
||||
return AdaptationSet::Role::kRoleSupplementary;
|
||||
if (role_str == "commentary")
|
||||
return AdaptationSet::Role::kRoleCommentary;
|
||||
if (role_str == "dub")
|
||||
return AdaptationSet::Role::kRoleDub;
|
||||
return AdaptationSet::Role::kRoleUnknown;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Period::Period(uint32_t period_id,
|
||||
|
@ -159,7 +177,16 @@ bool Period::SetNewAdaptationSetAttributes(
|
|||
const MediaInfo& media_info,
|
||||
const std::list<AdaptationSet*>& adaptation_sets,
|
||||
AdaptationSet* new_adaptation_set) {
|
||||
if (!language.empty()) {
|
||||
if (!media_info.dash_roles().empty()) {
|
||||
for (const std::string& role_str : media_info.dash_roles()) {
|
||||
AdaptationSet::Role role = RoleFromString(role_str);
|
||||
if (role == AdaptationSet::kRoleUnknown) {
|
||||
LOG(ERROR) << "Unrecognized role '" << role_str << "'.";
|
||||
return false;
|
||||
}
|
||||
new_adaptation_set->AddRole(role);
|
||||
}
|
||||
} else if (!language.empty()) {
|
||||
const bool is_main_role =
|
||||
language == (media_info.has_audio_info()
|
||||
? GetDefaultAudioLanguage(mpd_options_)
|
||||
|
@ -167,6 +194,17 @@ bool Period::SetNewAdaptationSetAttributes(
|
|||
if (is_main_role)
|
||||
new_adaptation_set->AddRole(AdaptationSet::kRoleMain);
|
||||
}
|
||||
for (const std::string& accessibility : media_info.dash_accessibilities()) {
|
||||
size_t pos = accessibility.find('=');
|
||||
if (pos == std::string::npos) {
|
||||
LOG(ERROR)
|
||||
<< "Accessibility should be in scheme=value format, but seeing "
|
||||
<< accessibility;
|
||||
return false;
|
||||
}
|
||||
new_adaptation_set->AddAccessibility(accessibility.substr(0, pos),
|
||||
accessibility.substr(pos + 1));
|
||||
}
|
||||
|
||||
if (media_info.has_video_info()) {
|
||||
// Because 'language' is ignored for videos, |adaptation_sets| must have
|
||||
|
|
|
@ -286,6 +286,16 @@ AdaptationSetXmlNode::AdaptationSetXmlNode()
|
|||
: RepresentationBaseXmlNode("AdaptationSet") {}
|
||||
AdaptationSetXmlNode::~AdaptationSetXmlNode() {}
|
||||
|
||||
void AdaptationSetXmlNode::AddAccessibilityElement(
|
||||
const std::string& scheme_id_uri,
|
||||
const std::string& value) {
|
||||
XmlNode accessibility("Accessibility");
|
||||
accessibility.SetStringAttribute("schemeIdUri", scheme_id_uri);
|
||||
if (!value.empty())
|
||||
accessibility.SetStringAttribute("value", value);
|
||||
AddChild(accessibility.PassScopedPtr());
|
||||
}
|
||||
|
||||
void AdaptationSetXmlNode::AddRoleElement(const std::string& scheme_id_uri,
|
||||
const std::string& value) {
|
||||
XmlNode role("Role");
|
||||
|
|
|
@ -130,6 +130,11 @@ class AdaptationSetXmlNode : public RepresentationBaseXmlNode {
|
|||
AdaptationSetXmlNode();
|
||||
~AdaptationSetXmlNode() override;
|
||||
|
||||
/// @param scheme_id_uri is content of the schemeIdUri attribute.
|
||||
/// @param value is the content of value attribute.
|
||||
void AddAccessibilityElement(const std::string& scheme_id_uri,
|
||||
const std::string& value);
|
||||
|
||||
/// @param scheme_id_uri is content of the schemeIdUri attribute.
|
||||
/// @param value is the content of value attribute.
|
||||
void AddRoleElement(const std::string& scheme_id_uri,
|
||||
|
|
|
@ -87,11 +87,15 @@ MuxerListenerFactory::StreamData ToMuxerListenerData(
|
|||
const StreamDescriptor& stream) {
|
||||
MuxerListenerFactory::StreamData data;
|
||||
data.media_info_output = stream.output;
|
||||
|
||||
data.hls_group_id = stream.hls_group_id;
|
||||
data.hls_name = stream.hls_name;
|
||||
data.hls_playlist_name = stream.hls_playlist_name;
|
||||
data.hls_iframe_playlist_name = stream.hls_iframe_playlist_name;
|
||||
data.hls_characteristics = stream.hls_characteristics;
|
||||
|
||||
data.dash_accessiblities = stream.dash_accessiblities;
|
||||
data.dash_roles = stream.dash_roles;
|
||||
return data;
|
||||
};
|
||||
|
||||
|
|
|
@ -123,6 +123,11 @@ struct StreamDescriptor {
|
|||
/// Optional for HLS output. It defines the CHARACTERISTICS attribute of the
|
||||
/// stream.
|
||||
std::vector<std::string> hls_characteristics;
|
||||
|
||||
/// Optional for DASH output. It defines Accessibility elements of the stream.
|
||||
std::vector<std::string> dash_accessiblities;
|
||||
/// Optional for DASH output. It defines Role elements of the stream.
|
||||
std::vector<std::string> dash_roles;
|
||||
};
|
||||
|
||||
class SHAKA_EXPORT Packager {
|
||||
|
|
Loading…
Reference in New Issue