Part one of supporting live profile with static mpd
- Added two new fields in MpdOptions: dash_profile and mpd_type - Updated MpdBuilder to support LiveProfile with static mpd - Command line arguments will be updated in the next CL Issue #142 Change-Id: Ibd35e5c9e1b1ef98043392e3f04a0af4700135c1
This commit is contained in:
parent
ce23fbacc4
commit
5aaae303e8
|
@ -460,16 +460,14 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
|||
|
||||
std::unique_ptr<MpdNotifier> mpd_notifier;
|
||||
if (!FLAGS_mpd_output.empty()) {
|
||||
DashProfile profile =
|
||||
FLAGS_single_segment ? kOnDemandProfile : kLiveProfile;
|
||||
std::vector<std::string> base_urls = base::SplitString(
|
||||
FLAGS_base_urls, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
if (FLAGS_generate_dash_if_iop_compliant_mpd) {
|
||||
mpd_notifier.reset(new DashIopMpdNotifier(profile, mpd_options, base_urls,
|
||||
FLAGS_mpd_output));
|
||||
mpd_notifier.reset(
|
||||
new DashIopMpdNotifier(mpd_options, base_urls, FLAGS_mpd_output));
|
||||
} else {
|
||||
mpd_notifier.reset(new SimpleMpdNotifier(profile, mpd_options, base_urls,
|
||||
FLAGS_mpd_output));
|
||||
mpd_notifier.reset(
|
||||
new SimpleMpdNotifier(mpd_options, base_urls, FLAGS_mpd_output));
|
||||
}
|
||||
if (!mpd_notifier->Init()) {
|
||||
LOG(ERROR) << "MpdNotifier failed to initialize.";
|
||||
|
|
|
@ -171,6 +171,12 @@ bool GetMuxerOptions(MuxerOptions* muxer_options) {
|
|||
bool GetMpdOptions(MpdOptions* mpd_options) {
|
||||
DCHECK(mpd_options);
|
||||
|
||||
mpd_options->dash_profile =
|
||||
FLAGS_single_segment ? DashProfile::kOnDemand : DashProfile::kLive;
|
||||
// Single segment does not always mean static mpd.
|
||||
// TODO(kqyang): Add a new flag for mpd type and update the code.
|
||||
mpd_options->mpd_type =
|
||||
FLAGS_single_segment ? MpdType::kStatic : MpdType::kDynamic;
|
||||
mpd_options->availability_time_offset = FLAGS_availability_time_offset;
|
||||
mpd_options->minimum_update_period = FLAGS_minimum_update_period;
|
||||
mpd_options->min_buffer_time = FLAGS_min_buffer_time;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.781S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.781S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="audio" subsegmentAlignment="true">
|
||||
<Representation id="0" bandwidth="81545" codecs="opus" mimeType="audio/mp4" audioSamplingRate="48000">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.768S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.768S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="audio">
|
||||
<Representation id="0" bandwidth="69362" codecs="vorbis" mimeType="audio/webm" audioSamplingRate="44100">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.781S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.781S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="audio">
|
||||
<Representation id="0" bandwidth="76531" codecs="opus" mimeType="audio/webm" audioSamplingRate="48000">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="885567" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="884377" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="885567" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="885567" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="882040" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="dynamic" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<Period id="0" start="PT0S">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="875620" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="dynamic" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<Period id="0" start="PT0S">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="dynamic" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<Period id="0" start="PT0S">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="876506" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="dynamic" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<Period id="0" start="PT0S">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="00000000-0000-0000-0000-000000000000"/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" type="dynamic" publishTime="some_publish_time" availabilityStartTime="some_availability_start_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
|
||||
<Period id="0" start="PT0S">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="872999" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.76317S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="text">
|
||||
<Representation id="0" bandwidth="256" mimeType="text/vtt">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.8028S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.8028S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="264870" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.73607S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.73607S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="882040" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.736S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.736S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="342199" codecs="vp08.00.00.08.01.01.00.00" mimeType="video/mp4" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.736S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.736S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" par="16:9">
|
||||
<Representation id="0" bandwidth="337062" codecs="vp8" mimeType="video/webm" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.736S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.736S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" par="16:9">
|
||||
<Representation id="0" bandwidth="335457" codecs="vp8" mimeType="video/webm" sar="1:1">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?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" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT0S">
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT0S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="text">
|
||||
<Representation id="0" bandwidth="256" mimeType="text/vtt">
|
||||
|
|
|
@ -22,8 +22,8 @@ namespace media {
|
|||
MpdNotifyMuxerListener::MpdNotifyMuxerListener(MpdNotifier* mpd_notifier)
|
||||
: mpd_notifier_(mpd_notifier), notification_id_(0), is_encrypted_(false) {
|
||||
DCHECK(mpd_notifier);
|
||||
DCHECK(mpd_notifier->dash_profile() == kOnDemandProfile ||
|
||||
mpd_notifier->dash_profile() == kLiveProfile);
|
||||
DCHECK(mpd_notifier->dash_profile() == DashProfile::kOnDemand ||
|
||||
mpd_notifier->dash_profile() == DashProfile::kLive);
|
||||
}
|
||||
|
||||
MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {}
|
||||
|
@ -76,7 +76,7 @@ void MpdNotifyMuxerListener::OnMediaStart(
|
|||
key_system_info_, media_info.get());
|
||||
}
|
||||
|
||||
if (mpd_notifier_->dash_profile() == kLiveProfile) {
|
||||
if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
|
||||
// TODO(kqyang): Check return result.
|
||||
mpd_notifier_->NotifyNewContainer(*media_info, ¬ification_id_);
|
||||
} else {
|
||||
|
@ -88,7 +88,7 @@ void MpdNotifyMuxerListener::OnMediaStart(
|
|||
// the information is in the media info.
|
||||
void MpdNotifyMuxerListener::OnSampleDurationReady(
|
||||
uint32_t sample_duration) {
|
||||
if (mpd_notifier_->dash_profile() == kLiveProfile) {
|
||||
if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
|
||||
mpd_notifier_->NotifySampleDuration(notification_id_, sample_duration);
|
||||
return;
|
||||
}
|
||||
|
@ -117,8 +117,10 @@ void MpdNotifyMuxerListener::OnMediaEnd(bool has_init_range,
|
|||
uint64_t index_range_end,
|
||||
float duration_seconds,
|
||||
uint64_t file_size) {
|
||||
if (mpd_notifier_->dash_profile() == kLiveProfile) {
|
||||
if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
|
||||
DCHECK(subsegments_.empty());
|
||||
if (mpd_notifier_->mpd_type() == MpdType::kStatic)
|
||||
mpd_notifier_->Flush();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -152,10 +154,11 @@ void MpdNotifyMuxerListener::OnNewSegment(const std::string& file_name,
|
|||
uint64_t start_time,
|
||||
uint64_t duration,
|
||||
uint64_t segment_file_size) {
|
||||
if (mpd_notifier_->dash_profile() == kLiveProfile) {
|
||||
if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
|
||||
// TODO(kqyang): Check return result.
|
||||
mpd_notifier_->NotifyNewSegment(
|
||||
notification_id_, start_time, duration, segment_file_size);
|
||||
if (mpd_notifier_->mpd_type() == MpdType::kDynamic)
|
||||
mpd_notifier_->Flush();
|
||||
} else {
|
||||
SubsegmentInfo subsegment = {start_time, duration, segment_file_size};
|
||||
|
|
|
@ -64,17 +64,25 @@ const uint8_t kBogusIv[] = {
|
|||
|
||||
namespace media {
|
||||
|
||||
class MpdNotifyMuxerListenerTest : public ::testing::Test {
|
||||
class MpdNotifyMuxerListenerTest : public ::testing::TestWithParam<MpdType> {
|
||||
public:
|
||||
|
||||
void SetupForVod() {
|
||||
notifier_.reset(new MockMpdNotifier(kOnDemandProfile));
|
||||
MpdOptions mpd_options;
|
||||
mpd_options.dash_profile = DashProfile::kOnDemand;
|
||||
// On-demand profile should be static.
|
||||
mpd_options.mpd_type = MpdType::kStatic;
|
||||
notifier_.reset(new MockMpdNotifier(mpd_options));
|
||||
listener_.reset(
|
||||
new MpdNotifyMuxerListener(notifier_.get()));
|
||||
}
|
||||
|
||||
void SetupForLive() {
|
||||
notifier_.reset(new MockMpdNotifier(kLiveProfile));
|
||||
MpdOptions mpd_options;
|
||||
mpd_options.dash_profile = DashProfile::kLive;
|
||||
// Live profile can be static or dynamic.
|
||||
mpd_options.mpd_type = GetParam();
|
||||
notifier_.reset(new MockMpdNotifier(mpd_options));
|
||||
listener_.reset(new MpdNotifyMuxerListener(notifier_.get()));
|
||||
}
|
||||
|
||||
|
@ -271,7 +279,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodOnNewSegment) {
|
|||
|
||||
// Live without key rotation. Note that OnEncryptionInfoReady() is called before
|
||||
// OnMediaStart() but no more calls.
|
||||
TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
|
||||
TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
|
||||
SetupForLive();
|
||||
MuxerOptions muxer_options;
|
||||
SetDefaultLiveMuxerOptionsValues(&muxer_options);
|
||||
|
@ -317,9 +325,12 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
|
|||
.Times(1);
|
||||
EXPECT_CALL(*notifier_,
|
||||
NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
|
||||
// Flush should only be called once in OnMediaEnd.
|
||||
if (GetParam() == MpdType::kDynamic)
|
||||
EXPECT_CALL(*notifier_, Flush());
|
||||
EXPECT_CALL(*notifier_,
|
||||
NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
|
||||
if (GetParam() == MpdType::kDynamic)
|
||||
EXPECT_CALL(*notifier_, Flush());
|
||||
|
||||
std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
|
||||
|
@ -333,13 +344,14 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
|
|||
listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
|
||||
::testing::Mock::VerifyAndClearExpectations(notifier_.get());
|
||||
|
||||
EXPECT_CALL(*notifier_, Flush()).Times(0);
|
||||
EXPECT_CALL(*notifier_, Flush())
|
||||
.Times(GetParam() == MpdType::kDynamic ? 0 : 1);
|
||||
FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
|
||||
}
|
||||
|
||||
// Live with key rotation. Note that OnEncryptionInfoReady() is called before
|
||||
// and after OnMediaStart().
|
||||
TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
|
||||
TEST_P(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
|
||||
SetupForLive();
|
||||
MuxerOptions muxer_options;
|
||||
SetDefaultLiveMuxerOptionsValues(&muxer_options);
|
||||
|
@ -382,9 +394,12 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
|
|||
EXPECT_CALL(*notifier_, NotifyEncryptionUpdate(_, _, _, _)).Times(1);
|
||||
EXPECT_CALL(*notifier_,
|
||||
NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
|
||||
// Flush should only be called once in OnMediaEnd.
|
||||
if (GetParam() == MpdType::kDynamic)
|
||||
EXPECT_CALL(*notifier_, Flush());
|
||||
EXPECT_CALL(*notifier_,
|
||||
NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
|
||||
if (GetParam() == MpdType::kDynamic)
|
||||
EXPECT_CALL(*notifier_, Flush());
|
||||
|
||||
std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
|
||||
|
@ -401,9 +416,14 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
|
|||
listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
|
||||
::testing::Mock::VerifyAndClearExpectations(notifier_.get());
|
||||
|
||||
EXPECT_CALL(*notifier_, Flush()).Times(0);
|
||||
EXPECT_CALL(*notifier_, Flush())
|
||||
.Times(GetParam() == MpdType::kDynamic ? 0 : 1);
|
||||
FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
|
||||
MpdNotifyMuxerListenerTest,
|
||||
::testing::Values(MpdType::kStatic, MpdType::kDynamic));
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
||||
|
|
|
@ -39,17 +39,12 @@ std::set<std::string> GetUUIDs(
|
|||
} // namespace
|
||||
|
||||
DashIopMpdNotifier::DashIopMpdNotifier(
|
||||
DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path)
|
||||
: MpdNotifier(dash_profile),
|
||||
: MpdNotifier(mpd_options),
|
||||
output_path_(output_path),
|
||||
mpd_builder_(new MpdBuilder(dash_profile == kLiveProfile
|
||||
? MpdBuilder::kDynamic
|
||||
: MpdBuilder::kStatic,
|
||||
mpd_options)) {
|
||||
DCHECK(dash_profile == kLiveProfile || dash_profile == kOnDemandProfile);
|
||||
mpd_builder_(new MpdBuilder(mpd_options)) {
|
||||
for (size_t i = 0; i < base_urls.size(); ++i)
|
||||
mpd_builder_->AddBaseUrl(base_urls[i]);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,7 @@ namespace shaka {
|
|||
/// All video Adaptation Sets have Role set to "main".
|
||||
class DashIopMpdNotifier : public MpdNotifier {
|
||||
public:
|
||||
DashIopMpdNotifier(DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
DashIopMpdNotifier(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path);
|
||||
~DashIopMpdNotifier() override;
|
||||
|
|
|
@ -91,8 +91,7 @@ MATCHER_P(ContentProtectionElementEq, expected, "") {
|
|||
// (https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests);
|
||||
// also because SimpleMpdNotifier and DashIopMpdNotifier have common behavior
|
||||
// for most of the public functions.
|
||||
class DashIopMpdNotifierTest
|
||||
: public ::testing::TestWithParam<MpdBuilder::MpdType> {
|
||||
class DashIopMpdNotifierTest : public ::testing::Test {
|
||||
protected:
|
||||
DashIopMpdNotifierTest()
|
||||
: default_mock_adaptation_set_(
|
||||
|
@ -109,23 +108,11 @@ class DashIopMpdNotifierTest
|
|||
base::DeleteFile(temp_file_path_, false /* non recursive, just 1 file */);
|
||||
}
|
||||
|
||||
MpdBuilder::MpdType GetMpdBuilderType(const DashIopMpdNotifier& notifier) {
|
||||
return notifier.MpdBuilderForTesting()->type();
|
||||
}
|
||||
|
||||
void SetMpdBuilder(DashIopMpdNotifier* notifier,
|
||||
std::unique_ptr<MpdBuilder> mpd_builder) {
|
||||
notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
|
||||
}
|
||||
|
||||
MpdBuilder::MpdType mpd_type() {
|
||||
return GetParam();
|
||||
}
|
||||
|
||||
DashProfile dash_profile() {
|
||||
return mpd_type() == MpdBuilder::kStatic ? kOnDemandProfile : kLiveProfile;
|
||||
}
|
||||
|
||||
// Use output_path_ for specifying the MPD output path so that
|
||||
// WriteMpdToFile() doesn't crash.
|
||||
std::string output_path_;
|
||||
|
@ -142,27 +129,13 @@ class DashIopMpdNotifierTest
|
|||
base::FilePath temp_file_path_;
|
||||
};
|
||||
|
||||
// Verify that it creates the correct MpdBuilder type using DashProfile passed
|
||||
// to the constructor.
|
||||
TEST_F(DashIopMpdNotifierTest, CreateCorrectMpdBuilderType) {
|
||||
DashIopMpdNotifier on_demand_notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
EXPECT_TRUE(on_demand_notifier.Init());
|
||||
EXPECT_EQ(MpdBuilder::kStatic, GetMpdBuilderType(on_demand_notifier));
|
||||
DashIopMpdNotifier live_notifier(kLiveProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
EXPECT_TRUE(live_notifier.Init());
|
||||
EXPECT_EQ(MpdBuilder::kDynamic, GetMpdBuilderType(live_notifier));
|
||||
}
|
||||
|
||||
// Verify that basic VOD NotifyNewContainer() operation works.
|
||||
// No encrypted contents.
|
||||
TEST_P(DashIopMpdNotifierTest, NotifyNewContainer) {
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) {
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
|
||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||
|
@ -183,18 +156,17 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainer) {
|
|||
|
||||
// Verify that if the MediaInfo contains text information, then
|
||||
// MpdBuilder::ForceSetSegmentAlignment() is called.
|
||||
TEST_P(DashIopMpdNotifierTest, NotifyNewTextContainer) {
|
||||
TEST_F(DashIopMpdNotifierTest, NotifyNewTextContainer) {
|
||||
const char kTextMediaInfo[] =
|
||||
"text_info {\n"
|
||||
" format: 'ttml'\n"
|
||||
" language: 'en'\n"
|
||||
"}\n"
|
||||
"container_type: CONTAINER_TEXT\n";
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(StrEq("en")))
|
||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||
|
@ -218,12 +190,11 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewTextContainer) {
|
|||
// MediaInfo::ProtectedContent.
|
||||
// Two AdaptationSets should be created.
|
||||
// AdaptationSets with different DRM won't be switchable.
|
||||
TEST_P(DashIopMpdNotifierTest,
|
||||
TEST_F(DashIopMpdNotifierTest,
|
||||
NotifyNewContainersWithDifferentProtectedContent) {
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
// Note they both have different (bogus) pssh, like real use case.
|
||||
// default Key ID = _default_key_id_
|
||||
|
@ -338,11 +309,10 @@ TEST_P(DashIopMpdNotifierTest,
|
|||
// Verify VOD NotifyNewContainer() operation works with same
|
||||
// MediaInfo::ProtectedContent. Only one AdaptationSet should be
|
||||
// created.
|
||||
TEST_P(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
// These have the same default key ID and PSSH.
|
||||
const char kSdProtectedContent[] =
|
||||
|
@ -441,12 +411,11 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
|
|||
}
|
||||
|
||||
// AddContentProtection() should not work and should always return false.
|
||||
TEST_P(DashIopMpdNotifierTest, AddContentProtection) {
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
TEST_F(DashIopMpdNotifierTest, AddContentProtection) {
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
|
||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||
|
@ -473,11 +442,10 @@ TEST_P(DashIopMpdNotifierTest, AddContentProtection) {
|
|||
// should be switchable.
|
||||
// 3. Add a 4k protected content. This should also make a new AdaptationSet.
|
||||
// It should be switchable with SD/HD AdaptationSet.
|
||||
TEST_P(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
// These have the same default key ID and PSSH.
|
||||
const char kSdProtectedContent[] =
|
||||
|
@ -610,12 +578,11 @@ TEST_P(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
|
|||
|
||||
// Even if the UUIDs match, video and audio AdaptationSets should not be
|
||||
// switchable.
|
||||
TEST_P(DashIopMpdNotifierTest,
|
||||
TEST_F(DashIopMpdNotifierTest,
|
||||
DoNotSetAdaptationSetSwitchingIfContentTypesDifferent) {
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
// These have the same default key ID and PSSH.
|
||||
const char kVideoContent[] =
|
||||
|
@ -699,7 +666,7 @@ TEST_P(DashIopMpdNotifierTest,
|
|||
ElementsAre());
|
||||
}
|
||||
|
||||
TEST_P(DashIopMpdNotifierTest, UpdateEncryption) {
|
||||
TEST_F(DashIopMpdNotifierTest, UpdateEncryption) {
|
||||
const char kProtectedContent[] =
|
||||
"video_info {\n"
|
||||
" codec: 'avc1'\n"
|
||||
|
@ -720,11 +687,10 @@ TEST_P(DashIopMpdNotifierTest, UpdateEncryption) {
|
|||
"}\n"
|
||||
"container_type: 1\n";
|
||||
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
|
||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||
|
@ -761,8 +727,8 @@ TEST_P(DashIopMpdNotifierTest, UpdateEncryption) {
|
|||
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
||||
// threads causes a deadlock. This tests with DashIopMpdNotifier.
|
||||
TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
||||
DashIopMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
uint32_t container_id;
|
||||
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
||||
&container_id));
|
||||
|
@ -772,7 +738,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
|||
}
|
||||
|
||||
// Don't put different audio languages or codecs in the same AdaptationSet.
|
||||
TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
||||
TEST_F(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
||||
// MP4, English
|
||||
const char kAudioContent1[] =
|
||||
"audio_info {\n"
|
||||
|
@ -825,10 +791,9 @@ TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
|||
"container_type: CONTAINER_WEBM\n"
|
||||
"media_duration_seconds: 10.5\n";
|
||||
|
||||
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type()));
|
||||
DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
||||
std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
|
||||
|
@ -871,10 +836,4 @@ TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
|||
ConvertToMediaInfo(kAudioContent4), &unused_container_id));
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
|
||||
DashIopMpdNotifierTest,
|
||||
::testing::Values(MpdBuilder::kStatic,
|
||||
MpdBuilder::kDynamic));
|
||||
|
||||
} // namespace shaka
|
||||
|
|
|
@ -6,20 +6,17 @@ namespace shaka {
|
|||
namespace {
|
||||
const char kEmptyLang[] = "";
|
||||
const MpdOptions kDefaultMpdOptions;
|
||||
const MpdBuilder::MpdType kDefaultMpdType = MpdBuilder::kStatic;
|
||||
} // namespace
|
||||
|
||||
// Doesn't matter what values get passed to the super class' constructor.
|
||||
// All methods used for testing should be mocked.
|
||||
MockMpdBuilder::MockMpdBuilder(MpdType type)
|
||||
: MpdBuilder(type, kDefaultMpdOptions) {}
|
||||
MockMpdBuilder::MockMpdBuilder() : MpdBuilder(kDefaultMpdOptions) {}
|
||||
MockMpdBuilder::~MockMpdBuilder() {}
|
||||
|
||||
MockAdaptationSet::MockAdaptationSet(uint32_t adaptation_set_id)
|
||||
: AdaptationSet(adaptation_set_id,
|
||||
kEmptyLang,
|
||||
kDefaultMpdOptions,
|
||||
kDefaultMpdType,
|
||||
&sequence_counter_) {}
|
||||
MockAdaptationSet::~MockAdaptationSet() {}
|
||||
|
||||
|
|
|
@ -18,9 +18,7 @@ namespace shaka {
|
|||
|
||||
class MockMpdBuilder : public MpdBuilder {
|
||||
public:
|
||||
// |type| indicates whether the MPD should be for VOD or live content (kStatic
|
||||
// for VOD profile, or kDynamic for live profile).
|
||||
explicit MockMpdBuilder(MpdType type);
|
||||
MockMpdBuilder();
|
||||
~MockMpdBuilder() override;
|
||||
|
||||
MOCK_METHOD1(AddAdaptationSet, AdaptationSet*(const std::string& lang));
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace shaka {
|
||||
|
||||
MockMpdNotifier::MockMpdNotifier(DashProfile profile) : MpdNotifier(profile) {}
|
||||
MockMpdNotifier::MockMpdNotifier(const MpdOptions& mpd_options)
|
||||
: MpdNotifier(mpd_options) {}
|
||||
MockMpdNotifier::~MockMpdNotifier() {}
|
||||
|
||||
} // namespace shaka
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace shaka {
|
|||
|
||||
class MockMpdNotifier : public MpdNotifier {
|
||||
public:
|
||||
MockMpdNotifier(DashProfile profile);
|
||||
explicit MockMpdNotifier(const MpdOptions& mpd_options);
|
||||
virtual ~MockMpdNotifier();
|
||||
|
||||
MOCK_METHOD0(Init, bool());
|
||||
|
|
|
@ -396,10 +396,8 @@ class RepresentationStateChangeListenerImpl
|
|||
|
||||
} // namespace
|
||||
|
||||
MpdBuilder::MpdBuilder(MpdType type, const MpdOptions& mpd_options)
|
||||
: type_(type),
|
||||
mpd_options_(mpd_options),
|
||||
clock_(new base::DefaultClock()) {}
|
||||
MpdBuilder::MpdBuilder(const MpdOptions& mpd_options)
|
||||
: mpd_options_(mpd_options), clock_(new base::DefaultClock()) {}
|
||||
|
||||
MpdBuilder::~MpdBuilder() {}
|
||||
|
||||
|
@ -410,7 +408,7 @@ void MpdBuilder::AddBaseUrl(const std::string& base_url) {
|
|||
AdaptationSet* MpdBuilder::AddAdaptationSet(const std::string& lang) {
|
||||
std::unique_ptr<AdaptationSet> adaptation_set(
|
||||
new AdaptationSet(adaptation_set_counter_.GetNext(), lang, mpd_options_,
|
||||
type_, &representation_counter_));
|
||||
&representation_counter_));
|
||||
DCHECK(adaptation_set);
|
||||
|
||||
if (!lang.empty() && lang == mpd_options_.default_language) {
|
||||
|
@ -482,7 +480,8 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (type_ == kDynamic) {
|
||||
// TODO(kqyang): Should we set @start unconditionally to 0?
|
||||
if (mpd_options_.mpd_type == MpdType::kDynamic) {
|
||||
// This is the only Period and it is a regular period.
|
||||
period.SetStringAttribute("start", "PT0S");
|
||||
}
|
||||
|
@ -491,16 +490,35 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
|
|||
return NULL;
|
||||
|
||||
AddMpdNameSpaceInfo(&mpd);
|
||||
|
||||
static const char kOnDemandProfile[] =
|
||||
"urn:mpeg:dash:profile:isoff-on-demand:2011";
|
||||
static const char kLiveProfile[] =
|
||||
"urn:mpeg:dash:profile:isoff-live:2011";
|
||||
switch (mpd_options_.dash_profile) {
|
||||
case DashProfile::kOnDemand:
|
||||
mpd.SetStringAttribute("profiles", kOnDemandProfile);
|
||||
break;
|
||||
case DashProfile::kLive:
|
||||
mpd.SetStringAttribute("profiles", kLiveProfile);
|
||||
break;
|
||||
default:
|
||||
NOTREACHED() << "Unknown DASH profile: "
|
||||
<< static_cast<int>(mpd_options_.dash_profile);
|
||||
break;
|
||||
}
|
||||
|
||||
AddCommonMpdInfo(&mpd);
|
||||
switch (type_) {
|
||||
case kStatic:
|
||||
switch (mpd_options_.mpd_type) {
|
||||
case MpdType::kStatic:
|
||||
AddStaticMpdInfo(&mpd);
|
||||
break;
|
||||
case kDynamic:
|
||||
case MpdType::kDynamic:
|
||||
AddDynamicMpdInfo(&mpd);
|
||||
break;
|
||||
default:
|
||||
NOTREACHED() << "Unknown MPD type: " << type_;
|
||||
NOTREACHED() << "Unknown MPD type: "
|
||||
<< static_cast<int>(mpd_options_.mpd_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -532,13 +550,10 @@ void MpdBuilder::AddCommonMpdInfo(XmlNode* mpd_node) {
|
|||
|
||||
void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) {
|
||||
DCHECK(mpd_node);
|
||||
DCHECK_EQ(MpdBuilder::kStatic, type_);
|
||||
DCHECK_EQ(MpdType::kStatic, mpd_options_.mpd_type);
|
||||
|
||||
static const char kStaticMpdType[] = "static";
|
||||
static const char kStaticMpdProfile[] =
|
||||
"urn:mpeg:dash:profile:isoff-on-demand:2011";
|
||||
mpd_node->SetStringAttribute("type", kStaticMpdType);
|
||||
mpd_node->SetStringAttribute("profiles", kStaticMpdProfile);
|
||||
mpd_node->SetStringAttribute(
|
||||
"mediaPresentationDuration",
|
||||
SecondsToXmlDuration(GetStaticMpdDuration(mpd_node)));
|
||||
|
@ -546,13 +561,10 @@ void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) {
|
|||
|
||||
void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
||||
DCHECK(mpd_node);
|
||||
DCHECK_EQ(MpdBuilder::kDynamic, type_);
|
||||
DCHECK_EQ(MpdType::kDynamic, mpd_options_.mpd_type);
|
||||
|
||||
static const char kDynamicMpdType[] = "dynamic";
|
||||
static const char kDynamicMpdProfile[] =
|
||||
"urn:mpeg:dash:profile:isoff-live:2011";
|
||||
mpd_node->SetStringAttribute("type", kDynamicMpdType);
|
||||
mpd_node->SetStringAttribute("profiles", kDynamicMpdProfile);
|
||||
|
||||
// No offset from NOW.
|
||||
mpd_node->SetStringAttribute("publishTime",
|
||||
|
@ -594,12 +606,13 @@ void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
|
|||
|
||||
float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
|
||||
DCHECK(mpd_node);
|
||||
DCHECK_EQ(MpdBuilder::kStatic, type_);
|
||||
DCHECK_EQ(MpdType::kStatic, mpd_options_.mpd_type);
|
||||
|
||||
xmlNodePtr period_node = FindPeriodNode(mpd_node);
|
||||
DCHECK(period_node) << "Period element must be a child of mpd_node.";
|
||||
DCHECK(IsPeriodNode(period_node));
|
||||
|
||||
// TODO(kqyang): Verify if this works for static + live profile.
|
||||
// Attribute mediaPresentationDuration must be present for 'static' MPD. So
|
||||
// setting "PT0S" is required even if none of the representaions have duration
|
||||
// attribute.
|
||||
|
@ -673,13 +686,11 @@ void MpdBuilder::MakePathsRelativeToMpd(const std::string& mpd_path,
|
|||
AdaptationSet::AdaptationSet(uint32_t adaptation_set_id,
|
||||
const std::string& lang,
|
||||
const MpdOptions& mpd_options,
|
||||
MpdBuilder::MpdType mpd_type,
|
||||
base::AtomicSequenceNumber* counter)
|
||||
: representation_counter_(counter),
|
||||
id_(adaptation_set_id),
|
||||
lang_(lang),
|
||||
mpd_options_(mpd_options),
|
||||
mpd_type_(mpd_type),
|
||||
segments_aligned_(kSegmentAlignmentUnknown),
|
||||
force_set_segment_alignment_(false) {
|
||||
DCHECK(counter);
|
||||
|
@ -791,12 +802,13 @@ xml::scoped_xml_ptr<xmlNode> AdaptationSet::GetXml() {
|
|||
|
||||
// Note: must be checked before checking segments_aligned_ (below). So that
|
||||
// segments_aligned_ is set before checking below.
|
||||
if (mpd_type_ == MpdBuilder::kStatic) {
|
||||
if (mpd_options_.dash_profile == DashProfile::kOnDemand) {
|
||||
CheckVodSegmentAlignment();
|
||||
}
|
||||
|
||||
if (segments_aligned_ == kSegmentAlignmentTrue) {
|
||||
adaptation_set.SetStringAttribute(mpd_type_ == MpdBuilder::kStatic
|
||||
adaptation_set.SetStringAttribute(
|
||||
mpd_options_.dash_profile == DashProfile::kOnDemand
|
||||
? "subsegmentAlignment"
|
||||
: "segmentAlignment",
|
||||
"true");
|
||||
|
@ -860,7 +872,7 @@ void AdaptationSet::AddAdaptationSetSwitching(uint32_t adaptation_set_id) {
|
|||
void AdaptationSet::OnNewSegmentForRepresentation(uint32_t representation_id,
|
||||
uint64_t start_time,
|
||||
uint64_t duration) {
|
||||
if (mpd_type_ == MpdBuilder::kDynamic) {
|
||||
if (mpd_options_.dash_profile == DashProfile::kLive) {
|
||||
CheckLiveSegmentAlignment(representation_id, start_time, duration);
|
||||
} else {
|
||||
representation_segment_start_times_[representation_id].push_back(
|
||||
|
|
|
@ -56,15 +56,9 @@ class RepresentationXmlNode;
|
|||
/// This class generates DASH MPDs (Media Presentation Descriptions).
|
||||
class MpdBuilder {
|
||||
public:
|
||||
enum MpdType {
|
||||
kStatic = 0,
|
||||
kDynamic
|
||||
};
|
||||
|
||||
/// Constructs MpdBuilder.
|
||||
/// @param type indicates whether the MPD should be for VOD or live content
|
||||
/// (kStatic for VOD profile, or kDynamic for live profile).
|
||||
MpdBuilder(MpdType type, const MpdOptions& mpd_options);
|
||||
/// @param mpd_options contains options on how this MPD should be built.
|
||||
explicit MpdBuilder(const MpdOptions& mpd_options);
|
||||
virtual ~MpdBuilder();
|
||||
|
||||
/// Add <BaseURL> entry to the MPD.
|
||||
|
@ -88,9 +82,6 @@ class MpdBuilder {
|
|||
/// @return true on success, false otherwise.
|
||||
virtual bool ToString(std::string* output);
|
||||
|
||||
/// @return The mpd type.
|
||||
MpdType type() const { return type_; }
|
||||
|
||||
/// Adjusts the fields of MediaInfo so that paths are relative to the
|
||||
/// specified MPD path.
|
||||
/// @param mpd_path is the file path of the MPD file.
|
||||
|
@ -106,9 +97,11 @@ class MpdBuilder {
|
|||
}
|
||||
|
||||
private:
|
||||
// DynamicMpdBuilderTest needs to set availabilityStartTime so that the test
|
||||
// LiveMpdBuilderTest needs to set availabilityStartTime so that the test
|
||||
// doesn't need to depend on current time.
|
||||
friend class DynamicMpdBuilderTest;
|
||||
friend class LiveMpdBuilderTest;
|
||||
template <DashProfile profile>
|
||||
friend class MpdBuilderTest;
|
||||
|
||||
bool ToStringImpl(std::string* output);
|
||||
|
||||
|
@ -143,7 +136,6 @@ class MpdBuilder {
|
|||
// successful, false otherwise.
|
||||
bool GetEarliestTimestamp(double* timestamp_seconds);
|
||||
|
||||
MpdType type_;
|
||||
MpdOptions mpd_options_;
|
||||
std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_;
|
||||
|
||||
|
@ -286,12 +278,11 @@ class AdaptationSet {
|
|||
AdaptationSet(uint32_t adaptation_set_id,
|
||||
const std::string& lang,
|
||||
const MpdOptions& mpd_options,
|
||||
MpdBuilder::MpdType mpd_type,
|
||||
base::AtomicSequenceNumber* representation_counter);
|
||||
|
||||
private:
|
||||
friend class MpdBuilder;
|
||||
template <MpdBuilder::MpdType type>
|
||||
template <DashProfile profile>
|
||||
friend class MpdBuilderTest;
|
||||
|
||||
// kSegmentAlignmentUnknown means that it is uncertain if the
|
||||
|
@ -345,7 +336,6 @@ class AdaptationSet {
|
|||
const uint32_t id_;
|
||||
const std::string lang_;
|
||||
const MpdOptions& mpd_options_;
|
||||
const MpdBuilder::MpdType mpd_type_;
|
||||
|
||||
// The ids of the adaptation sets this adaptation set can switch to.
|
||||
std::vector<uint32_t> adaptation_set_switching_ids_;
|
||||
|
@ -513,7 +503,7 @@ class Representation {
|
|||
|
||||
private:
|
||||
friend class AdaptationSet;
|
||||
template <MpdBuilder::MpdType type>
|
||||
template <DashProfile profile>
|
||||
friend class MpdBuilderTest;
|
||||
|
||||
bool AddLiveInfo(xml::RepresentationXmlNode* representation);
|
||||
|
|
|
@ -104,12 +104,16 @@ class MockRepresentationStateChangeListener
|
|||
};
|
||||
} // namespace
|
||||
|
||||
template <MpdBuilder::MpdType type>
|
||||
template <DashProfile profile>
|
||||
class MpdBuilderTest : public ::testing::Test {
|
||||
public:
|
||||
MpdBuilderTest() : mpd_(type, MpdOptions()), representation_() {}
|
||||
MpdBuilderTest() : mpd_(MpdOptions()), representation_() {
|
||||
mpd_.mpd_options_.dash_profile = profile;
|
||||
}
|
||||
~MpdBuilderTest() override {}
|
||||
|
||||
MpdOptions* mutable_mpd_options() { return &mpd_.mpd_options_; }
|
||||
|
||||
void CheckMpd(const std::string& expected_output_file) {
|
||||
std::string mpd_doc;
|
||||
ASSERT_TRUE(mpd_.ToString(&mpd_doc));
|
||||
|
@ -138,24 +142,20 @@ class MpdBuilderTest : public ::testing::Test {
|
|||
// constructor signatures.
|
||||
std::unique_ptr<Representation> CreateRepresentation(
|
||||
const MediaInfo& media_info,
|
||||
const MpdOptions& mpd_options,
|
||||
uint32_t representation_id,
|
||||
std::unique_ptr<RepresentationStateChangeListener>
|
||||
state_change_listener) {
|
||||
return std::unique_ptr<Representation>(
|
||||
new Representation(media_info, mpd_options, representation_id,
|
||||
new Representation(media_info, mpd_options_, representation_id,
|
||||
std::move(state_change_listener)));
|
||||
}
|
||||
|
||||
std::unique_ptr<AdaptationSet> CreateAdaptationSet(
|
||||
uint32_t adaptation_set_id,
|
||||
const std::string& lang,
|
||||
const MpdOptions& mpd_options,
|
||||
MpdBuilder::MpdType mpd_type,
|
||||
base::AtomicSequenceNumber* representation_counter) {
|
||||
return std::unique_ptr<AdaptationSet>(
|
||||
new AdaptationSet(adaptation_set_id, lang, mpd_options, mpd_type,
|
||||
representation_counter));
|
||||
return std::unique_ptr<AdaptationSet>(new AdaptationSet(
|
||||
adaptation_set_id, lang, mpd_options_, representation_counter));
|
||||
}
|
||||
|
||||
// Helper function to return an empty listener for tests that don't need
|
||||
|
@ -170,29 +170,30 @@ class MpdBuilderTest : public ::testing::Test {
|
|||
Representation* representation_; // Owned by |mpd_|.
|
||||
|
||||
private:
|
||||
MpdOptions mpd_options_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MpdBuilderTest);
|
||||
};
|
||||
|
||||
class StaticMpdBuilderTest : public MpdBuilderTest<MpdBuilder::kStatic> {};
|
||||
class OnDemandMpdBuilderTest : public MpdBuilderTest<DashProfile::kOnDemand> {};
|
||||
|
||||
// Use this test name for things that are common to both static an dynamic
|
||||
// mpd builder tests.
|
||||
typedef StaticMpdBuilderTest CommonMpdBuilderTest;
|
||||
typedef OnDemandMpdBuilderTest CommonMpdBuilderTest;
|
||||
|
||||
class DynamicMpdBuilderTest : public MpdBuilderTest<MpdBuilder::kDynamic> {
|
||||
class LiveMpdBuilderTest : public MpdBuilderTest<DashProfile::kLive> {
|
||||
public:
|
||||
~DynamicMpdBuilderTest() override {}
|
||||
~LiveMpdBuilderTest() override {}
|
||||
|
||||
// Anchors availabilityStartTime so that the test result doesn't depend on the
|
||||
// current time.
|
||||
void SetUp() override {
|
||||
SetPackagerVersionForTesting("<tag>-<hash>-<test>");
|
||||
mpd_.mpd_options_.mpd_type = MpdType::kDynamic;
|
||||
mpd_.availability_start_time_ = "2011-12-25T12:30:00";
|
||||
InjectTestClock();
|
||||
}
|
||||
|
||||
MpdOptions* mutable_mpd_options() { return &mpd_.mpd_options_; }
|
||||
|
||||
// Injects a clock that always returns 2016 Jan 11 15:10:24 in UTC.
|
||||
void InjectTestClock() {
|
||||
base::Time::Exploded test_time = { 2016, // year.
|
||||
|
@ -231,14 +232,14 @@ class DynamicMpdBuilderTest : public MpdBuilderTest<MpdBuilder::kDynamic> {
|
|||
uint32_t DefaultTimeScale() const { return 1000; };
|
||||
};
|
||||
|
||||
class SegmentTemplateTest : public DynamicMpdBuilderTest {
|
||||
class SegmentTemplateTest : public LiveMpdBuilderTest {
|
||||
public:
|
||||
SegmentTemplateTest()
|
||||
: bandwidth_estimator_(BandwidthEstimator::kUseAllBlocks) {}
|
||||
~SegmentTemplateTest() override {}
|
||||
|
||||
void SetUp() override {
|
||||
DynamicMpdBuilderTest::SetUp();
|
||||
LiveMpdBuilderTest::SetUp();
|
||||
ASSERT_NO_FATAL_FAILURE(AddRepresentationWithDefaultMediaInfo());
|
||||
}
|
||||
|
||||
|
@ -282,8 +283,9 @@ class SegmentTemplateTest : public DynamicMpdBuilderTest {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
|
||||
" availabilityStartTime=\"2011-12-25T12:30:00\" minBufferTime=\"PT2S\" "
|
||||
" type=\"dynamic\" profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
" availabilityStartTime=\"2011-12-25T12:30:00\" "
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
" minBufferTime=\"PT2S\" type=\"dynamic\" "
|
||||
" publishTime=\"2016-01-11T15:10:24Z\">\n"
|
||||
" <Period id=\"0\" start=\"PT0S\">\n"
|
||||
" <AdaptationSet id=\"0\" width=\"720\" height=\"480\""
|
||||
|
@ -331,7 +333,7 @@ class TimeShiftBufferDepthTest : public SegmentTemplateTest {
|
|||
// that it does not automatically add a representation, that has $Time$
|
||||
// template.
|
||||
void SetUp() override {
|
||||
DynamicMpdBuilderTest::SetUp();
|
||||
LiveMpdBuilderTest::SetUp();
|
||||
|
||||
// The only diff with current GetDefaultMediaInfo() is that this uses
|
||||
// $Number$ for segment template.
|
||||
|
@ -367,8 +369,9 @@ class TimeShiftBufferDepthTest : public SegmentTemplateTest {
|
|||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
|
||||
"xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
|
||||
"availabilityStartTime=\"2011-12-25T12:30:00\" minBufferTime=\"PT2S\" "
|
||||
"type=\"dynamic\" profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
"availabilityStartTime=\"2011-12-25T12:30:00\" "
|
||||
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
"minBufferTime=\"PT2S\" type=\"dynamic\" "
|
||||
"publishTime=\"2016-01-11T15:10:24Z\" "
|
||||
"timeShiftBufferDepth=\"PT%dS\">\n"
|
||||
" <Period id=\"0\" start=\"PT0S\">\n"
|
||||
|
@ -405,7 +408,7 @@ class TimeShiftBufferDepthTest : public SegmentTemplateTest {
|
|||
};
|
||||
|
||||
TEST_F(CommonMpdBuilderTest, AddAdaptationSetSwitching) {
|
||||
MpdBuilder mpd_builder(MpdBuilder::kStatic, MpdOptions());
|
||||
MpdBuilder mpd_builder(MpdOptions{});
|
||||
AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet("");
|
||||
adaptation_set->AddAdaptationSetSwitching(1);
|
||||
adaptation_set->AddAdaptationSetSwitching(2);
|
||||
|
@ -420,8 +423,8 @@ TEST_F(CommonMpdBuilderTest, AddAdaptationSetSwitching) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"\n"
|
||||
" minBufferTime=\"PT2S\" type=\"static\"\n"
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
|
||||
" minBufferTime=\"PT2S\" type=\"static\"\n"
|
||||
" mediaPresentationDuration=\"PT0S\">\n"
|
||||
" <Period id=\"0\">\n"
|
||||
" <AdaptationSet id=\"0\" contentType=\"\">\n"
|
||||
|
@ -454,9 +457,8 @@ TEST_F(CommonMpdBuilderTest, ValidMediaInfo) {
|
|||
"}\n"
|
||||
"container_type: 1\n";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
}
|
||||
|
||||
|
@ -464,9 +466,8 @@ TEST_F(CommonMpdBuilderTest, ValidMediaInfo) {
|
|||
TEST_F(CommonMpdBuilderTest, VideoAudioTextInfoNotSet) {
|
||||
const char kTestMediaInfo[] = "container_type: 1";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
|
||||
EXPECT_FALSE(representation->Init());
|
||||
}
|
||||
|
||||
|
@ -490,9 +491,8 @@ TEST_F(CommonMpdBuilderTest, VideoAndAudioInfoSet) {
|
|||
"}\n"
|
||||
"container_type: CONTAINER_MP4\n";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
|
||||
EXPECT_FALSE(representation->Init());
|
||||
}
|
||||
|
||||
|
@ -509,9 +509,8 @@ TEST_F(CommonMpdBuilderTest, InvalidMediaInfo) {
|
|||
" pixel_height: 1\n"
|
||||
"}\n"
|
||||
"container_type: 1\n";
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
|
||||
EXPECT_FALSE(representation->Init());
|
||||
}
|
||||
|
||||
|
@ -528,9 +527,8 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoReflectedInXml) {
|
|||
" pixel_height: 1\n"
|
||||
"}\n"
|
||||
"container_type: 1\n";
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
|
@ -559,7 +557,7 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInMp4) {
|
|||
"container_type: 1\n";
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8),
|
||||
MpdOptions(), kAnyRepresentationId, NoListener());
|
||||
kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
|
@ -582,7 +580,7 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInWebm) {
|
|||
"container_type: 3\n";
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8),
|
||||
MpdOptions(), kAnyRepresentationId, NoListener());
|
||||
kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
|
@ -605,7 +603,7 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp9CodecInWebm) {
|
|||
"container_type: 3\n";
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp9),
|
||||
MpdOptions(), kAnyRepresentationId, NoListener());
|
||||
kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
|
||||
EXPECT_NO_FATAL_FAILURE(
|
||||
|
@ -635,7 +633,7 @@ TEST_F(CommonMpdBuilderTest,
|
|||
EXPECT_CALL(*listener,
|
||||
OnNewSegmentForRepresentation(kStartTime, kDuration));
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo),
|
||||
kAnyRepresentationId, std::move(listener));
|
||||
EXPECT_TRUE(representation->Init());
|
||||
|
||||
|
@ -666,7 +664,7 @@ TEST_F(CommonMpdBuilderTest,
|
|||
EXPECT_CALL(*listener,
|
||||
OnSetFrameRateForRepresentation(kFrameDuration, kTimeScale));
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo),
|
||||
kAnyRepresentationId, std::move(listener));
|
||||
EXPECT_TRUE(representation->Init());
|
||||
|
||||
|
@ -690,8 +688,7 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetVideoContentType) {
|
|||
"container_type: CONTAINER_MP4\n";
|
||||
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo));
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
|
||||
|
@ -712,8 +709,7 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetAudioContentType) {
|
|||
"container_type: CONTAINER_MP4\n";
|
||||
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(kAudioMediaInfo));
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
|
||||
|
@ -732,8 +728,7 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetTextContentType) {
|
|||
"container_type: CONTAINER_TEXT\n";
|
||||
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo));
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
|
||||
|
@ -748,7 +743,7 @@ TEST_F(CommonMpdBuilderTest, TtmlXmlMimeType) {
|
|||
"container_type: CONTAINER_TEXT\n";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTtmlXmlMediaInfo), MpdOptions(),
|
||||
CreateRepresentation(ConvertToMediaInfo(kTtmlXmlMediaInfo),
|
||||
kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
|
||||
|
@ -763,7 +758,7 @@ TEST_F(CommonMpdBuilderTest, TtmlMp4MimeType) {
|
|||
"container_type: CONTAINER_MP4\n";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTtmlMp4MediaInfo), MpdOptions(),
|
||||
CreateRepresentation(ConvertToMediaInfo(kTtmlMp4MediaInfo),
|
||||
kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
|
||||
|
@ -777,9 +772,8 @@ TEST_F(CommonMpdBuilderTest, WebVttMimeType) {
|
|||
"}\n"
|
||||
"container_type: CONTAINER_TEXT\n";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kWebVttMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kWebVttMediaInfo), kAnyRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
|
||||
"mimeType", "text/vtt", representation->GetXml().get()));
|
||||
|
@ -796,8 +790,7 @@ TEST_F(CommonMpdBuilderTest, CheckLanguageAttributeSet) {
|
|||
"container_type: CONTAINER_TEXT\n";
|
||||
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "en", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "en", &sequence_counter);
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo));
|
||||
|
||||
xml::scoped_xml_ptr<xmlNode> node_xml(adaptation_set->GetXml());
|
||||
|
@ -818,8 +811,7 @@ TEST_F(CommonMpdBuilderTest, CheckConvertLanguageWithSubtag) {
|
|||
// "por-BR" is the long tag for Brazillian Portuguese. The short tag
|
||||
// is "pt-BR", which is what should appear in the manifest.
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "por-BR", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "por-BR", &sequence_counter);
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo));
|
||||
|
||||
xml::scoped_xml_ptr<xmlNode> node_xml(adaptation_set->GetXml());
|
||||
|
@ -831,14 +823,13 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetId) {
|
|||
base::AtomicSequenceNumber sequence_counter;
|
||||
const uint32_t kAdaptationSetId = 42;
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAdaptationSetId, "", &sequence_counter);
|
||||
ASSERT_NO_FATAL_FAILURE(CheckIdEqual(kAdaptationSetId, adaptation_set.get()));
|
||||
}
|
||||
|
||||
// Verify AdaptationSet::AddRole() works for "main" role.
|
||||
TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) {
|
||||
MpdBuilder mpd_builder(MpdBuilder::kStatic, MpdOptions());
|
||||
MpdBuilder mpd_builder(MpdOptions{});
|
||||
AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet("");
|
||||
|
||||
adaptation_set->AddRole(AdaptationSet::kRoleMain);
|
||||
|
@ -851,8 +842,8 @@ TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"\n"
|
||||
" minBufferTime=\"PT2S\" type=\"static\"\n"
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
|
||||
" minBufferTime=\"PT2S\" type=\"static\"\n"
|
||||
" mediaPresentationDuration=\"PT0S\">\n"
|
||||
" <Period id=\"0\">\n"
|
||||
" <AdaptationSet id=\"0\" contentType=\"\">\n"
|
||||
|
@ -871,7 +862,7 @@ TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) {
|
|||
// Add Role, ContentProtection, and Representation elements. Verify that
|
||||
// ContentProtection -> Role -> Representation are in order.
|
||||
TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) {
|
||||
MpdBuilder mpd_builder(MpdBuilder::kStatic, MpdOptions());
|
||||
MpdBuilder mpd_builder(MpdOptions{});
|
||||
AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet("");
|
||||
adaptation_set->AddRole(AdaptationSet::kRoleMain);
|
||||
ContentProtectionElement any_content_protection;
|
||||
|
@ -894,8 +885,8 @@ TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"\n"
|
||||
" minBufferTime=\"PT2S\" type=\"static\"\n"
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
|
||||
" minBufferTime=\"PT2S\" type=\"static\"\n"
|
||||
" mediaPresentationDuration=\"PT0S\">\n"
|
||||
" <Period id=\"0\">\n"
|
||||
" <AdaptationSet id=\"0\" contentType=\"audio\">\n"
|
||||
|
@ -1024,8 +1015,7 @@ TEST_F(CommonMpdBuilderTest,
|
|||
"container_type: 1\n";
|
||||
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
|
||||
Representation* representation_480p =
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo));
|
||||
Representation* representation_360p =
|
||||
|
@ -1250,9 +1240,8 @@ TEST_F(CommonMpdBuilderTest, SuppressRepresentationAttributes) {
|
|||
"}\n"
|
||||
"container_type: 1\n";
|
||||
|
||||
auto representation =
|
||||
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(),
|
||||
kAnyRepresentationId, NoListener());
|
||||
auto representation = CreateRepresentation(
|
||||
ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
|
||||
|
||||
representation->SuppressOnce(Representation::kSuppressWidth);
|
||||
xml::scoped_xml_ptr<xmlNode> no_width(representation->GetXml());
|
||||
|
@ -1382,7 +1371,7 @@ TEST_F(CommonMpdBuilderTest, BubbleUpAttributesToAdaptationSet) {
|
|||
// Also checking that not all Representations have to be added before calling
|
||||
// AddNewSegment() on a Representation.
|
||||
// The output MPD's schema is checked at the very end.
|
||||
TEST_F(StaticMpdBuilderTest, SubsegmentAlignment) {
|
||||
TEST_F(OnDemandMpdBuilderTest, SubsegmentAlignment) {
|
||||
base::AtomicSequenceNumber sequence_counter;
|
||||
const char k480pMediaInfo[] =
|
||||
"video_info {\n"
|
||||
|
@ -1448,7 +1437,7 @@ TEST_F(StaticMpdBuilderTest, SubsegmentAlignment) {
|
|||
}
|
||||
|
||||
// Verify that subsegmentAlignment can be force set to true.
|
||||
TEST_F(StaticMpdBuilderTest, ForceSetsubsegmentAlignment) {
|
||||
TEST_F(OnDemandMpdBuilderTest, ForceSetsubsegmentAlignment) {
|
||||
base::AtomicSequenceNumber sequence_counter;
|
||||
const char k480pMediaInfo[] =
|
||||
"video_info {\n"
|
||||
|
@ -1472,9 +1461,9 @@ TEST_F(StaticMpdBuilderTest, ForceSetsubsegmentAlignment) {
|
|||
" pixel_height: 1\n"
|
||||
"}\n"
|
||||
"container_type: 1\n";
|
||||
MpdOptions mpd_options;
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
|
||||
Representation* representation_480p =
|
||||
adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo));
|
||||
Representation* representation_360p =
|
||||
|
@ -1502,7 +1491,7 @@ TEST_F(StaticMpdBuilderTest, ForceSetsubsegmentAlignment) {
|
|||
// Verify that segmentAlignment is set to true if all the Representations
|
||||
// segments' are aligned and the MPD type is dynamic.
|
||||
// The output MPD's schema is checked at the very end.
|
||||
TEST_F(DynamicMpdBuilderTest, SegmentAlignment) {
|
||||
TEST_F(LiveMpdBuilderTest, SegmentAlignment) {
|
||||
base::AtomicSequenceNumber sequence_counter;
|
||||
const char k480pMediaInfo[] =
|
||||
"video_info {\n"
|
||||
|
@ -1559,7 +1548,7 @@ TEST_F(DynamicMpdBuilderTest, SegmentAlignment) {
|
|||
|
||||
// Verify that the width and height attribute are set if all the video
|
||||
// representations have the same width and height.
|
||||
TEST_F(StaticMpdBuilderTest, AdapatationSetWidthAndHeight) {
|
||||
TEST_F(OnDemandMpdBuilderTest, AdapatationSetWidthAndHeight) {
|
||||
// Both 720p.
|
||||
const char kVideoMediaInfo1[] =
|
||||
"video_info {\n"
|
||||
|
@ -1600,7 +1589,7 @@ TEST_F(StaticMpdBuilderTest, AdapatationSetWidthAndHeight) {
|
|||
|
||||
// Verify that the maxWidth and maxHeight attribute are set if there are
|
||||
// multiple video resolutions.
|
||||
TEST_F(StaticMpdBuilderTest, AdapatationSetMaxWidthAndMaxHeight) {
|
||||
TEST_F(OnDemandMpdBuilderTest, AdapatationSetMaxWidthAndMaxHeight) {
|
||||
const char kVideoMediaInfo1080p[] =
|
||||
"video_info {\n"
|
||||
" codec: \"avc1\"\n"
|
||||
|
@ -1642,8 +1631,8 @@ TEST_F(CommonMpdBuilderTest, CheckRepresentationId) {
|
|||
const MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
const uint32_t kRepresentationId = 1;
|
||||
|
||||
auto representation = CreateRepresentation(video_media_info, MpdOptions(),
|
||||
kRepresentationId, NoListener());
|
||||
auto representation =
|
||||
CreateRepresentation(video_media_info, kRepresentationId, NoListener());
|
||||
EXPECT_TRUE(representation->Init());
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
CheckIdEqual(kRepresentationId, representation.get()));
|
||||
|
@ -1664,8 +1653,7 @@ TEST_F(CommonMpdBuilderTest, SetSampleDuration) {
|
|||
|
||||
base::AtomicSequenceNumber sequence_counter;
|
||||
auto adaptation_set =
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(),
|
||||
MpdBuilder::kStatic, &sequence_counter);
|
||||
CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
|
||||
|
||||
const MediaInfo video_media_info = ConvertToMediaInfo(kVideoMediaInfo);
|
||||
Representation* representation =
|
||||
|
@ -1716,8 +1704,8 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetAddContentProtectionAndUpdate) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" mediaPresentationDuration=\"PT0S\">"
|
||||
" <Period id=\"0\">"
|
||||
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\""
|
||||
|
@ -1745,8 +1733,8 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetAddContentProtectionAndUpdate) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" mediaPresentationDuration=\"PT0S\">"
|
||||
" <Period id=\"0\">"
|
||||
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\""
|
||||
|
@ -1800,8 +1788,8 @@ TEST_F(CommonMpdBuilderTest, UpdateToRemovePsshElement) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" mediaPresentationDuration=\"PT0S\">"
|
||||
" <Period id=\"0\">"
|
||||
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\""
|
||||
|
@ -1829,8 +1817,8 @@ TEST_F(CommonMpdBuilderTest, UpdateToRemovePsshElement) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" mediaPresentationDuration=\"PT0S\">"
|
||||
" <Period id=\"0\">"
|
||||
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\""
|
||||
|
@ -1853,13 +1841,13 @@ TEST_F(CommonMpdBuilderTest, UpdateToRemovePsshElement) {
|
|||
}
|
||||
|
||||
// Add one video check the output.
|
||||
TEST_F(StaticMpdBuilderTest, Video) {
|
||||
TEST_F(OnDemandMpdBuilderTest, Video) {
|
||||
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
ASSERT_NO_FATAL_FAILURE(AddRepresentation(video_media_info));
|
||||
EXPECT_NO_FATAL_FAILURE(CheckMpd(kFileNameExpectedMpdOutputVideo1));
|
||||
}
|
||||
|
||||
TEST_F(StaticMpdBuilderTest, TwoVideosWithDifferentResolutions) {
|
||||
TEST_F(OnDemandMpdBuilderTest, TwoVideosWithDifferentResolutions) {
|
||||
AdaptationSet* adaptation_set = mpd_.AddAdaptationSet("");
|
||||
|
||||
MediaInfo media_info1 = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
|
@ -1872,7 +1860,7 @@ TEST_F(StaticMpdBuilderTest, TwoVideosWithDifferentResolutions) {
|
|||
}
|
||||
|
||||
// Add both video and audio and check the output.
|
||||
TEST_F(StaticMpdBuilderTest, VideoAndAudio) {
|
||||
TEST_F(OnDemandMpdBuilderTest, VideoAndAudio) {
|
||||
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
MediaInfo audio_media_info = GetTestMediaInfo(kFileNameAudioMediaInfo1);
|
||||
|
||||
|
@ -1897,7 +1885,7 @@ TEST_F(StaticMpdBuilderTest, VideoAndAudio) {
|
|||
// MPD schema has strict ordering. AudioChannelConfiguration must appear before
|
||||
// ContentProtection.
|
||||
// Also test that Representation::AddContentProtection() works.
|
||||
TEST_F(StaticMpdBuilderTest, AudioChannelConfigurationWithContentProtection) {
|
||||
TEST_F(OnDemandMpdBuilderTest, AudioChannelConfigurationWithContentProtection) {
|
||||
const char kTestMediaInfo[] =
|
||||
"bandwidth: 195857\n"
|
||||
"audio_info {\n"
|
||||
|
@ -1926,8 +1914,8 @@ TEST_F(StaticMpdBuilderTest, AudioChannelConfigurationWithContentProtection) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" mediaPresentationDuration=\"PT24.0094S\">"
|
||||
" <Period id=\"0\">"
|
||||
" <AdaptationSet id=\"0\" contentType=\"audio\">"
|
||||
|
@ -1972,7 +1960,7 @@ TEST_F(StaticMpdBuilderTest, AudioChannelConfigurationWithContentProtection) {
|
|||
|
||||
// Static profile requires bandwidth to be set because it has no other way to
|
||||
// get the bandwidth for the Representation.
|
||||
TEST_F(StaticMpdBuilderTest, MediaInfoMissingBandwidth) {
|
||||
TEST_F(OnDemandMpdBuilderTest, MediaInfoMissingBandwidth) {
|
||||
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
video_media_info.clear_bandwidth();
|
||||
AddRepresentation(video_media_info);
|
||||
|
@ -1981,7 +1969,7 @@ TEST_F(StaticMpdBuilderTest, MediaInfoMissingBandwidth) {
|
|||
ASSERT_FALSE(mpd_.ToString(&mpd_doc));
|
||||
}
|
||||
|
||||
TEST_F(StaticMpdBuilderTest, WriteToFile) {
|
||||
TEST_F(OnDemandMpdBuilderTest, WriteToFile) {
|
||||
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
|
||||
AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet("");
|
||||
ASSERT_TRUE(video_adaptation_set);
|
||||
|
@ -2007,7 +1995,7 @@ TEST_F(StaticMpdBuilderTest, WriteToFile) {
|
|||
}
|
||||
|
||||
// Verify that a text path works.
|
||||
TEST_F(StaticMpdBuilderTest, Text) {
|
||||
TEST_F(OnDemandMpdBuilderTest, Text) {
|
||||
const char kTextMediaInfo[] =
|
||||
"text_info {\n"
|
||||
" format: 'ttml'\n"
|
||||
|
@ -2026,8 +2014,8 @@ TEST_F(StaticMpdBuilderTest, Text) {
|
|||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
|
||||
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
|
||||
" minBufferTime=\"PT2S\" type=\"static\""
|
||||
" mediaPresentationDuration=\"PT35S\">"
|
||||
" <Period id=\"0\">"
|
||||
" <AdaptationSet id=\"0\" contentType=\"text\" lang=\"en\">"
|
||||
|
@ -2057,7 +2045,7 @@ TEST_F(StaticMpdBuilderTest, Text) {
|
|||
// Check whether the attributes are set correctly for dynamic <MPD> element.
|
||||
// This test must use ASSERT_EQ for comparison because XmlEqual() cannot
|
||||
// handle namespaces correctly yet.
|
||||
TEST_F(DynamicMpdBuilderTest, CheckMpdAttributes) {
|
||||
TEST_F(LiveMpdBuilderTest, DynamicCheckMpdAttributes) {
|
||||
static const char kExpectedOutput[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!--Generated with https://github.com/google/shaka-packager "
|
||||
|
@ -2068,15 +2056,40 @@ TEST_F(DynamicMpdBuilderTest, CheckMpdAttributes) {
|
|||
"xsi:schemaLocation="
|
||||
"\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
|
||||
"xmlns:cenc=\"urn:mpeg:cenc:2013\" "
|
||||
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
"minBufferTime=\"PT2S\" "
|
||||
"type=\"dynamic\" "
|
||||
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
"publishTime=\"2016-01-11T15:10:24Z\" "
|
||||
"availabilityStartTime=\"2011-12-25T12:30:00\">\n"
|
||||
" <Period id=\"0\" start=\"PT0S\"/>\n"
|
||||
"</MPD>\n";
|
||||
|
||||
std::string mpd_doc;
|
||||
mutable_mpd_options()->mpd_type = MpdType::kDynamic;
|
||||
ASSERT_TRUE(mpd_.ToString(&mpd_doc));
|
||||
ASSERT_EQ(kExpectedOutput, mpd_doc);
|
||||
}
|
||||
|
||||
TEST_F(LiveMpdBuilderTest, StaticCheckMpdAttributes) {
|
||||
static const char kExpectedOutput[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!--Generated with https://github.com/google/shaka-packager "
|
||||
"version <tag>-<hash>-<test>-->\n"
|
||||
"<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\" "
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
|
||||
"xsi:schemaLocation="
|
||||
"\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
|
||||
"xmlns:cenc=\"urn:mpeg:cenc:2013\" "
|
||||
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
|
||||
"minBufferTime=\"PT2S\" "
|
||||
"type=\"static\" "
|
||||
"mediaPresentationDuration=\"PT0S\">\n"
|
||||
" <Period id=\"0\"/>\n"
|
||||
"</MPD>\n";
|
||||
|
||||
std::string mpd_doc;
|
||||
mutable_mpd_options()->mpd_type = MpdType::kStatic;
|
||||
ASSERT_TRUE(mpd_.ToString(&mpd_doc));
|
||||
ASSERT_EQ(kExpectedOutput, mpd_doc);
|
||||
}
|
||||
|
|
|
@ -15,24 +15,20 @@
|
|||
#include <vector>
|
||||
|
||||
#include "packager/base/macros.h"
|
||||
#include "packager/mpd/base/mpd_options.h"
|
||||
|
||||
namespace shaka {
|
||||
|
||||
class MediaInfo;
|
||||
struct ContentProtectionElement;
|
||||
|
||||
enum DashProfile {
|
||||
kUnknownProfile,
|
||||
kOnDemandProfile,
|
||||
kLiveProfile,
|
||||
};
|
||||
|
||||
/// Interface for publish/subscribe publisher class which notifies MpdBuilder
|
||||
/// of media-related events.
|
||||
class MpdNotifier {
|
||||
public:
|
||||
MpdNotifier(DashProfile dash_profile) : dash_profile_(dash_profile) {};
|
||||
virtual ~MpdNotifier() {};
|
||||
explicit MpdNotifier(const MpdOptions& mpd_options)
|
||||
: mpd_options_(mpd_options) {}
|
||||
virtual ~MpdNotifier() {}
|
||||
|
||||
/// Initializes the notifier. For example, if this notifier uses a network for
|
||||
/// notification, then this would set up the connection with the remote host.
|
||||
|
@ -105,10 +101,13 @@ class MpdNotifier {
|
|||
virtual bool Flush() = 0;
|
||||
|
||||
/// @return The dash profile for this object.
|
||||
DashProfile dash_profile() const { return dash_profile_; }
|
||||
DashProfile dash_profile() const { return mpd_options_.dash_profile; }
|
||||
|
||||
/// @return The mpd type for this object.
|
||||
MpdType mpd_type() const { return mpd_options_.mpd_type; }
|
||||
|
||||
private:
|
||||
const DashProfile dash_profile_;
|
||||
const MpdOptions mpd_options_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MpdNotifier);
|
||||
};
|
||||
|
|
|
@ -11,27 +11,27 @@
|
|||
|
||||
namespace shaka {
|
||||
|
||||
enum class DashProfile {
|
||||
kUnknown,
|
||||
kOnDemand,
|
||||
kLive,
|
||||
};
|
||||
|
||||
enum class MpdType { kStatic, kDynamic };
|
||||
|
||||
/// Defines Mpd Options.
|
||||
struct MpdOptions {
|
||||
MpdOptions()
|
||||
: availability_time_offset(0),
|
||||
minimum_update_period(0),
|
||||
DashProfile dash_profile = DashProfile::kOnDemand;
|
||||
MpdType mpd_type = MpdType::kStatic;
|
||||
double availability_time_offset = 0;
|
||||
double minimum_update_period = 0;
|
||||
// TODO(tinskip): Set min_buffer_time in unit tests rather than here.
|
||||
min_buffer_time(2.0),
|
||||
time_shift_buffer_depth(0),
|
||||
suggested_presentation_delay(0) {}
|
||||
|
||||
~MpdOptions() {};
|
||||
|
||||
double availability_time_offset;
|
||||
double minimum_update_period;
|
||||
double min_buffer_time;
|
||||
double time_shift_buffer_depth;
|
||||
double suggested_presentation_delay;
|
||||
double min_buffer_time = 2.0;
|
||||
double time_shift_buffer_depth = 0;
|
||||
double suggested_presentation_delay = 0;
|
||||
std::string default_language;
|
||||
};
|
||||
|
||||
} // namespace shaka
|
||||
|
||||
#endif // MPD_BASE_MPD_OPTIONS_H_
|
||||
|
||||
|
|
|
@ -14,17 +14,12 @@
|
|||
|
||||
namespace shaka {
|
||||
|
||||
SimpleMpdNotifier::SimpleMpdNotifier(DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path)
|
||||
: MpdNotifier(dash_profile),
|
||||
: MpdNotifier(mpd_options),
|
||||
output_path_(output_path),
|
||||
mpd_builder_(new MpdBuilder(dash_profile == kLiveProfile
|
||||
? MpdBuilder::kDynamic
|
||||
: MpdBuilder::kStatic,
|
||||
mpd_options)) {
|
||||
DCHECK(dash_profile == kLiveProfile || dash_profile == kOnDemandProfile);
|
||||
mpd_builder_(new MpdBuilder(mpd_options)) {
|
||||
for (size_t i = 0; i < base_urls.size(); ++i)
|
||||
mpd_builder_->AddBaseUrl(base_urls[i]);
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ struct MpdOptions;
|
|||
/// generates an Mpd file.
|
||||
class SimpleMpdNotifier : public MpdNotifier {
|
||||
public:
|
||||
SimpleMpdNotifier(DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
SimpleMpdNotifier(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path);
|
||||
~SimpleMpdNotifier() override;
|
||||
|
|
|
@ -35,8 +35,7 @@ const char kValidMediaInfo[] =
|
|||
const uint32_t kDefaultAdaptationSetId = 0u;
|
||||
} // namespace
|
||||
|
||||
class SimpleMpdNotifierTest
|
||||
: public ::testing::TestWithParam<MpdBuilder::MpdType> {
|
||||
class SimpleMpdNotifierTest : public ::testing::Test {
|
||||
protected:
|
||||
SimpleMpdNotifierTest()
|
||||
: default_mock_adaptation_set_(
|
||||
|
@ -51,20 +50,6 @@ class SimpleMpdNotifierTest
|
|||
base::DeleteFile(temp_file_path_, false /* non recursive, just 1 file */);
|
||||
}
|
||||
|
||||
std::unique_ptr<MockMpdBuilder> StaticMpdBuilderMock() {
|
||||
return std::unique_ptr<MockMpdBuilder>(
|
||||
new MockMpdBuilder(MpdBuilder::kStatic));
|
||||
}
|
||||
|
||||
std::unique_ptr<MockMpdBuilder> DynamicMpdBuilderMock() {
|
||||
return std::unique_ptr<MockMpdBuilder>(
|
||||
new MockMpdBuilder(MpdBuilder::kDynamic));
|
||||
}
|
||||
|
||||
MpdBuilder::MpdType GetMpdBuilderType(const SimpleMpdNotifier& notifier) {
|
||||
return notifier.MpdBuilderForTesting()->type();
|
||||
}
|
||||
|
||||
void SetMpdBuilder(SimpleMpdNotifier* notifier,
|
||||
std::unique_ptr<MpdBuilder> mpd_builder) {
|
||||
notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
|
||||
|
@ -83,29 +68,12 @@ class SimpleMpdNotifierTest
|
|||
base::FilePath temp_file_path_;
|
||||
};
|
||||
|
||||
// Verify that it creates the correct MpdBuilder type using DashProfile passed
|
||||
// to the constructor.
|
||||
TEST_F(SimpleMpdNotifierTest, CreateCorrectMpdBuilderType) {
|
||||
SimpleMpdNotifier on_demand_notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
EXPECT_TRUE(on_demand_notifier.Init());
|
||||
EXPECT_EQ(MpdBuilder::kStatic,
|
||||
GetMpdBuilderType(on_demand_notifier));
|
||||
SimpleMpdNotifier live_notifier(kLiveProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
EXPECT_TRUE(live_notifier.Init());
|
||||
EXPECT_EQ(MpdBuilder::kDynamic, GetMpdBuilderType(live_notifier));
|
||||
}
|
||||
|
||||
// Verify NotifyNewContainer() works as expected for VOD.
|
||||
TEST_P(SimpleMpdNotifierTest, NotifyNewContainer) {
|
||||
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) {
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
|
||||
const uint32_t kRepresentationId = 1u;
|
||||
const MpdBuilder::MpdType mpd_type = GetParam();
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
|
||||
new MockMpdBuilder(mpd_type));
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
std::unique_ptr<MockRepresentation> mock_representation(
|
||||
new MockRepresentation(kRepresentationId));
|
||||
|
||||
|
@ -125,44 +93,11 @@ TEST_P(SimpleMpdNotifierTest, NotifyNewContainer) {
|
|||
EXPECT_TRUE(notifier.Flush());
|
||||
}
|
||||
|
||||
// Verify NotifySampleDuration() works as expected for Live.
|
||||
TEST_F(SimpleMpdNotifierTest, LiveNotifySampleDuration) {
|
||||
SimpleMpdNotifier notifier(kLiveProfile, empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) {
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
|
||||
const uint32_t kRepresentationId = 8u;
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(DynamicMpdBuilderMock());
|
||||
std::unique_ptr<MockRepresentation> mock_representation(
|
||||
new MockRepresentation(kRepresentationId));
|
||||
|
||||
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
|
||||
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
||||
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
||||
.WillOnce(Return(mock_representation.get()));
|
||||
|
||||
uint32_t container_id;
|
||||
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
||||
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
||||
&container_id));
|
||||
EXPECT_EQ(kRepresentationId, container_id);
|
||||
|
||||
const uint32_t kSampleDuration = 100;
|
||||
EXPECT_CALL(*mock_representation, SetSampleDuration(kSampleDuration));
|
||||
EXPECT_TRUE(
|
||||
notifier.NotifySampleDuration(kRepresentationId, kSampleDuration));
|
||||
}
|
||||
|
||||
// Verify that NotifySampleDuration works for OnDemand profile.
|
||||
// TODO(rkuroiwa): SimpleMpdNotifier returns a container ID but does not
|
||||
// register it to its map for VOD. Must fix and enable this test.
|
||||
// This test can be also parmeterized just like NotifyNewContainer() test, once
|
||||
// it is fixed.
|
||||
TEST_F(SimpleMpdNotifierTest, OnDemandNotifySampleDuration) {
|
||||
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
|
||||
const uint32_t kRepresentationId = 14u;
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(StaticMpdBuilderMock());
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
std::unique_ptr<MockRepresentation> mock_representation(
|
||||
new MockRepresentation(kRepresentationId));
|
||||
|
||||
|
@ -189,8 +124,7 @@ TEST_F(SimpleMpdNotifierTest, OnDemandNotifySampleDuration) {
|
|||
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
||||
// threads causes a deadlock.
|
||||
TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
||||
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
uint32_t container_id;
|
||||
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
|
||||
&container_id));
|
||||
|
@ -199,13 +133,11 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
|||
EXPECT_TRUE(notifier.Flush());
|
||||
}
|
||||
|
||||
// Verify that NotifyNewSegment() for live works.
|
||||
TEST_F(SimpleMpdNotifierTest, LiveNotifyNewSegment) {
|
||||
SimpleMpdNotifier notifier(kLiveProfile, empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
|
||||
const uint32_t kRepresentationId = 447834u;
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(DynamicMpdBuilderMock());
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
std::unique_ptr<MockRepresentation> mock_representation(
|
||||
new MockRepresentation(kRepresentationId));
|
||||
|
||||
|
@ -230,13 +162,11 @@ TEST_F(SimpleMpdNotifierTest, LiveNotifyNewSegment) {
|
|||
kSegmentDuration, kSegmentSize));
|
||||
}
|
||||
|
||||
// Verify AddContentProtectionElement() works. Profile doesn't matter.
|
||||
TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
|
||||
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
|
||||
const uint32_t kRepresentationId = 0u;
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(StaticMpdBuilderMock());
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
std::unique_ptr<MockRepresentation> mock_representation(
|
||||
new MockRepresentation(kRepresentationId));
|
||||
|
||||
|
@ -256,7 +186,7 @@ TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
|
|||
EXPECT_TRUE(notifier.AddContentProtectionElement(kRepresentationId, element));
|
||||
}
|
||||
|
||||
TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
|
||||
TEST_F(SimpleMpdNotifierTest, UpdateEncryption) {
|
||||
const char kProtectedContent[] =
|
||||
"video_info {\n"
|
||||
" codec: 'avc1'\n"
|
||||
|
@ -276,10 +206,9 @@ TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
|
|||
" default_key_id: '_default_key_id_'\n"
|
||||
"}\n"
|
||||
"container_type: 1\n";
|
||||
SimpleMpdNotifier notifier(kLiveProfile, empty_mpd_option_, empty_base_urls_,
|
||||
output_path_);
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
const uint32_t kRepresentationId = 447834u;
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(DynamicMpdBuilderMock());
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
std::unique_ptr<MockRepresentation> mock_representation(
|
||||
new MockRepresentation(kRepresentationId));
|
||||
|
||||
|
@ -312,7 +241,7 @@ TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
|
|||
}
|
||||
|
||||
// Don't put different audio languages or codecs in the same AdaptationSet.
|
||||
TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
||||
TEST_F(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
||||
// MP4, English
|
||||
const char kAudioContent1[] =
|
||||
"audio_info {\n"
|
||||
|
@ -365,9 +294,8 @@ TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
|||
"container_type: CONTAINER_WEBM\n"
|
||||
"media_duration_seconds: 10.5\n";
|
||||
|
||||
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
|
||||
empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(StaticMpdBuilderMock());
|
||||
SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
|
||||
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
||||
|
||||
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
||||
std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
|
||||
|
@ -410,9 +338,4 @@ TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
|
|||
ConvertToMediaInfo(kAudioContent4), &unused_container_id));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
|
||||
SimpleMpdNotifierTest,
|
||||
::testing::Values(MpdBuilder::kStatic,
|
||||
MpdBuilder::kDynamic));
|
||||
|
||||
} // namespace shaka
|
||||
|
|
|
@ -35,12 +35,11 @@ class DashIopMpdNotifierFactory : public MpdNotifierFactory {
|
|||
DashIopMpdNotifierFactory() {}
|
||||
~DashIopMpdNotifierFactory() override {}
|
||||
|
||||
std::unique_ptr<MpdNotifier> Create(DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) override {
|
||||
return std::unique_ptr<MpdNotifier>(new DashIopMpdNotifier(
|
||||
dash_profile, mpd_options, base_urls, output_path));
|
||||
return std::unique_ptr<MpdNotifier>(
|
||||
new DashIopMpdNotifier(mpd_options, base_urls, output_path));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -50,12 +49,11 @@ class SimpleMpdNotifierFactory : public MpdNotifierFactory {
|
|||
SimpleMpdNotifierFactory() {}
|
||||
~SimpleMpdNotifierFactory() override {}
|
||||
|
||||
std::unique_ptr<MpdNotifier> Create(DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) override {
|
||||
return std::unique_ptr<MpdNotifier>(new SimpleMpdNotifier(
|
||||
dash_profile, mpd_options, base_urls, output_path));
|
||||
return std::unique_ptr<MpdNotifier>(
|
||||
new SimpleMpdNotifier(mpd_options, base_urls, output_path));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -96,8 +94,8 @@ void MpdWriter::AddBaseUrl(const std::string& base_url) {
|
|||
|
||||
bool MpdWriter::WriteMpdToFile(const char* file_name) {
|
||||
CHECK(file_name);
|
||||
std::unique_ptr<MpdNotifier> notifier = notifier_factory_->Create(
|
||||
kOnDemandProfile, MpdOptions(), base_urls_, file_name);
|
||||
std::unique_ptr<MpdNotifier> notifier =
|
||||
notifier_factory_->Create(MpdOptions(), base_urls_, file_name);
|
||||
if (!notifier->Init()) {
|
||||
LOG(ERROR) << "failed to initialize MpdNotifier.";
|
||||
return false;
|
||||
|
|
|
@ -35,7 +35,6 @@ class MpdNotifierFactory {
|
|||
virtual ~MpdNotifierFactory() {}
|
||||
|
||||
virtual std::unique_ptr<MpdNotifier> Create(
|
||||
DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) = 0;
|
||||
|
|
|
@ -33,14 +33,13 @@ class TestMpdNotifierFactory : public MpdNotifierFactory {
|
|||
// std::unique_ptr.
|
||||
// For now we only need to return MockMpdNotifier() with these set of
|
||||
// expectations for all the tests.
|
||||
std::unique_ptr<MpdNotifier> Create(DashProfile dash_profile,
|
||||
const MpdOptions& mpd_options,
|
||||
std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
|
||||
const std::vector<std::string>& base_urls,
|
||||
const std::string& output_path) override {
|
||||
EXPECT_EQ(expected_base_urls_, base_urls);
|
||||
|
||||
std::unique_ptr<MockMpdNotifier> mock_notifier(
|
||||
new MockMpdNotifier(kOnDemandProfile));
|
||||
new MockMpdNotifier(mpd_options));
|
||||
|
||||
EXPECT_CALL(*mock_notifier, Init()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*mock_notifier, NotifyNewContainer(_, _))
|
||||
|
|
Loading…
Reference in New Issue