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:
Kongqun Yang 2016-12-21 15:28:56 -08:00 committed by KongQun Yang
parent ce23fbacc4
commit 5aaae303e8
43 changed files with 333 additions and 430 deletions

View File

@ -460,16 +460,14 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) {
std::unique_ptr<MpdNotifier> mpd_notifier; std::unique_ptr<MpdNotifier> mpd_notifier;
if (!FLAGS_mpd_output.empty()) { if (!FLAGS_mpd_output.empty()) {
DashProfile profile =
FLAGS_single_segment ? kOnDemandProfile : kLiveProfile;
std::vector<std::string> base_urls = base::SplitString( std::vector<std::string> base_urls = base::SplitString(
FLAGS_base_urls, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); FLAGS_base_urls, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (FLAGS_generate_dash_if_iop_compliant_mpd) { if (FLAGS_generate_dash_if_iop_compliant_mpd) {
mpd_notifier.reset(new DashIopMpdNotifier(profile, mpd_options, base_urls, mpd_notifier.reset(
FLAGS_mpd_output)); new DashIopMpdNotifier(mpd_options, base_urls, FLAGS_mpd_output));
} else { } else {
mpd_notifier.reset(new SimpleMpdNotifier(profile, mpd_options, base_urls, mpd_notifier.reset(
FLAGS_mpd_output)); new SimpleMpdNotifier(mpd_options, base_urls, FLAGS_mpd_output));
} }
if (!mpd_notifier->Init()) { if (!mpd_notifier->Init()) {
LOG(ERROR) << "MpdNotifier failed to initialize."; LOG(ERROR) << "MpdNotifier failed to initialize.";

View File

@ -171,6 +171,12 @@ bool GetMuxerOptions(MuxerOptions* muxer_options) {
bool GetMpdOptions(MpdOptions* mpd_options) { bool GetMpdOptions(MpdOptions* mpd_options) {
DCHECK(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->availability_time_offset = FLAGS_availability_time_offset;
mpd_options->minimum_update_period = FLAGS_minimum_update_period; mpd_options->minimum_update_period = FLAGS_minimum_update_period;
mpd_options->min_buffer_time = FLAGS_min_buffer_time; mpd_options->min_buffer_time = FLAGS_min_buffer_time;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="audio" subsegmentAlignment="true"> <AdaptationSet id="0" contentType="audio" subsegmentAlignment="true">
<Representation id="0" bandwidth="81545" codecs="opus" mimeType="audio/mp4" audioSamplingRate="48000"> <Representation id="0" bandwidth="81545" codecs="opus" mimeType="audio/mp4" audioSamplingRate="48000">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="audio"> <AdaptationSet id="0" contentType="audio">
<Representation id="0" bandwidth="69362" codecs="vorbis" mimeType="audio/webm" audioSamplingRate="44100"> <Representation id="0" bandwidth="69362" codecs="vorbis" mimeType="audio/webm" audioSamplingRate="44100">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="audio"> <AdaptationSet id="0" contentType="audio">
<Representation id="0" bandwidth="76531" codecs="opus" mimeType="audio/webm" audioSamplingRate="48000"> <Representation id="0" bandwidth="76531" codecs="opus" mimeType="audio/webm" audioSamplingRate="48000">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="885567" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="884377" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="885567" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"/> <ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="885567" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="882040" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="875620" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9"> <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"/> <ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="876506" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9"> <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"/> <ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="00000000-0000-0000-0000-000000000000"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="872999" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="text"> <AdaptationSet id="0" contentType="text">
<Representation id="0" bandwidth="256" mimeType="text/vtt"> <Representation id="0" bandwidth="256" mimeType="text/vtt">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="264870" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="882040" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" subsegmentAlignment="true" par="16:9"> <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"> <Representation id="0" bandwidth="342199" codecs="vp08.00.00.08.01.01.00.00" mimeType="video/mp4" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" par="16:9"> <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"> <Representation id="0" bandwidth="337062" codecs="vp8" mimeType="video/webm" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" par="16:9"> <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"> <Representation id="0" bandwidth="335457" codecs="vp8" mimeType="video/webm" sar="1:1">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>--> <!--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"> <Period id="0">
<AdaptationSet id="0" contentType="text"> <AdaptationSet id="0" contentType="text">
<Representation id="0" bandwidth="256" mimeType="text/vtt"> <Representation id="0" bandwidth="256" mimeType="text/vtt">

View File

@ -22,8 +22,8 @@ namespace media {
MpdNotifyMuxerListener::MpdNotifyMuxerListener(MpdNotifier* mpd_notifier) MpdNotifyMuxerListener::MpdNotifyMuxerListener(MpdNotifier* mpd_notifier)
: mpd_notifier_(mpd_notifier), notification_id_(0), is_encrypted_(false) { : mpd_notifier_(mpd_notifier), notification_id_(0), is_encrypted_(false) {
DCHECK(mpd_notifier); DCHECK(mpd_notifier);
DCHECK(mpd_notifier->dash_profile() == kOnDemandProfile || DCHECK(mpd_notifier->dash_profile() == DashProfile::kOnDemand ||
mpd_notifier->dash_profile() == kLiveProfile); mpd_notifier->dash_profile() == DashProfile::kLive);
} }
MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {} MpdNotifyMuxerListener::~MpdNotifyMuxerListener() {}
@ -76,7 +76,7 @@ void MpdNotifyMuxerListener::OnMediaStart(
key_system_info_, media_info.get()); key_system_info_, media_info.get());
} }
if (mpd_notifier_->dash_profile() == kLiveProfile) { if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
// TODO(kqyang): Check return result. // TODO(kqyang): Check return result.
mpd_notifier_->NotifyNewContainer(*media_info, &notification_id_); mpd_notifier_->NotifyNewContainer(*media_info, &notification_id_);
} else { } else {
@ -88,7 +88,7 @@ void MpdNotifyMuxerListener::OnMediaStart(
// the information is in the media info. // the information is in the media info.
void MpdNotifyMuxerListener::OnSampleDurationReady( void MpdNotifyMuxerListener::OnSampleDurationReady(
uint32_t sample_duration) { uint32_t sample_duration) {
if (mpd_notifier_->dash_profile() == kLiveProfile) { if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
mpd_notifier_->NotifySampleDuration(notification_id_, sample_duration); mpd_notifier_->NotifySampleDuration(notification_id_, sample_duration);
return; return;
} }
@ -117,8 +117,10 @@ void MpdNotifyMuxerListener::OnMediaEnd(bool has_init_range,
uint64_t index_range_end, uint64_t index_range_end,
float duration_seconds, float duration_seconds,
uint64_t file_size) { uint64_t file_size) {
if (mpd_notifier_->dash_profile() == kLiveProfile) { if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
DCHECK(subsegments_.empty()); DCHECK(subsegments_.empty());
if (mpd_notifier_->mpd_type() == MpdType::kStatic)
mpd_notifier_->Flush();
return; return;
} }
@ -152,10 +154,11 @@ void MpdNotifyMuxerListener::OnNewSegment(const std::string& file_name,
uint64_t start_time, uint64_t start_time,
uint64_t duration, uint64_t duration,
uint64_t segment_file_size) { uint64_t segment_file_size) {
if (mpd_notifier_->dash_profile() == kLiveProfile) { if (mpd_notifier_->dash_profile() == DashProfile::kLive) {
// TODO(kqyang): Check return result. // TODO(kqyang): Check return result.
mpd_notifier_->NotifyNewSegment( mpd_notifier_->NotifyNewSegment(
notification_id_, start_time, duration, segment_file_size); notification_id_, start_time, duration, segment_file_size);
if (mpd_notifier_->mpd_type() == MpdType::kDynamic)
mpd_notifier_->Flush(); mpd_notifier_->Flush();
} else { } else {
SubsegmentInfo subsegment = {start_time, duration, segment_file_size}; SubsegmentInfo subsegment = {start_time, duration, segment_file_size};

View File

@ -64,17 +64,25 @@ const uint8_t kBogusIv[] = {
namespace media { namespace media {
class MpdNotifyMuxerListenerTest : public ::testing::Test { class MpdNotifyMuxerListenerTest : public ::testing::TestWithParam<MpdType> {
public: public:
void SetupForVod() { 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( listener_.reset(
new MpdNotifyMuxerListener(notifier_.get())); new MpdNotifyMuxerListener(notifier_.get()));
} }
void SetupForLive() { 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())); listener_.reset(new MpdNotifyMuxerListener(notifier_.get()));
} }
@ -271,7 +279,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodOnNewSegment) {
// Live without key rotation. Note that OnEncryptionInfoReady() is called before // Live without key rotation. Note that OnEncryptionInfoReady() is called before
// OnMediaStart() but no more calls. // OnMediaStart() but no more calls.
TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) { TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
SetupForLive(); SetupForLive();
MuxerOptions muxer_options; MuxerOptions muxer_options;
SetDefaultLiveMuxerOptionsValues(&muxer_options); SetDefaultLiveMuxerOptionsValues(&muxer_options);
@ -317,9 +325,12 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
.Times(1); .Times(1);
EXPECT_CALL(*notifier_, EXPECT_CALL(*notifier_,
NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1)); NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
// Flush should only be called once in OnMediaEnd.
if (GetParam() == MpdType::kDynamic)
EXPECT_CALL(*notifier_, Flush()); EXPECT_CALL(*notifier_, Flush());
EXPECT_CALL(*notifier_, EXPECT_CALL(*notifier_,
NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2)); NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
if (GetParam() == MpdType::kDynamic)
EXPECT_CALL(*notifier_, Flush()); EXPECT_CALL(*notifier_, Flush());
std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv)); std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
@ -333,13 +344,14 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2); listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
::testing::Mock::VerifyAndClearExpectations(notifier_.get()); ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
EXPECT_CALL(*notifier_, Flush()).Times(0); EXPECT_CALL(*notifier_, Flush())
.Times(GetParam() == MpdType::kDynamic ? 0 : 1);
FireOnMediaEndWithParams(GetDefaultOnMediaEndParams()); FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
} }
// Live with key rotation. Note that OnEncryptionInfoReady() is called before // Live with key rotation. Note that OnEncryptionInfoReady() is called before
// and after OnMediaStart(). // and after OnMediaStart().
TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) { TEST_P(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
SetupForLive(); SetupForLive();
MuxerOptions muxer_options; MuxerOptions muxer_options;
SetDefaultLiveMuxerOptionsValues(&muxer_options); SetDefaultLiveMuxerOptionsValues(&muxer_options);
@ -382,9 +394,12 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
EXPECT_CALL(*notifier_, NotifyEncryptionUpdate(_, _, _, _)).Times(1); EXPECT_CALL(*notifier_, NotifyEncryptionUpdate(_, _, _, _)).Times(1);
EXPECT_CALL(*notifier_, EXPECT_CALL(*notifier_,
NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1)); NotifyNewSegment(_, kStartTime1, kDuration1, kSegmentFileSize1));
// Flush should only be called once in OnMediaEnd.
if (GetParam() == MpdType::kDynamic)
EXPECT_CALL(*notifier_, Flush()); EXPECT_CALL(*notifier_, Flush());
EXPECT_CALL(*notifier_, EXPECT_CALL(*notifier_,
NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2)); NotifyNewSegment(_, kStartTime2, kDuration2, kSegmentFileSize2));
if (GetParam() == MpdType::kDynamic)
EXPECT_CALL(*notifier_, Flush()); EXPECT_CALL(*notifier_, Flush());
std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv)); std::vector<uint8_t> iv(kBogusIv, kBogusIv + arraysize(kBogusIv));
@ -401,9 +416,14 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2); listener_->OnNewSegment("", kStartTime2, kDuration2, kSegmentFileSize2);
::testing::Mock::VerifyAndClearExpectations(notifier_.get()); ::testing::Mock::VerifyAndClearExpectations(notifier_.get());
EXPECT_CALL(*notifier_, Flush()).Times(0); EXPECT_CALL(*notifier_, Flush())
.Times(GetParam() == MpdType::kDynamic ? 0 : 1);
FireOnMediaEndWithParams(GetDefaultOnMediaEndParams()); FireOnMediaEndWithParams(GetDefaultOnMediaEndParams());
} }
INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
MpdNotifyMuxerListenerTest,
::testing::Values(MpdType::kStatic, MpdType::kDynamic));
} // namespace media } // namespace media
} // namespace shaka } // namespace shaka

View File

@ -39,17 +39,12 @@ std::set<std::string> GetUUIDs(
} // namespace } // namespace
DashIopMpdNotifier::DashIopMpdNotifier( DashIopMpdNotifier::DashIopMpdNotifier(
DashProfile dash_profile,
const MpdOptions& mpd_options, const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path) const std::string& output_path)
: MpdNotifier(dash_profile), : MpdNotifier(mpd_options),
output_path_(output_path), output_path_(output_path),
mpd_builder_(new MpdBuilder(dash_profile == kLiveProfile mpd_builder_(new MpdBuilder(mpd_options)) {
? MpdBuilder::kDynamic
: MpdBuilder::kStatic,
mpd_options)) {
DCHECK(dash_profile == kLiveProfile || dash_profile == kOnDemandProfile);
for (size_t i = 0; i < base_urls.size(); ++i) for (size_t i = 0; i < base_urls.size(); ++i)
mpd_builder_->AddBaseUrl(base_urls[i]); mpd_builder_->AddBaseUrl(base_urls[i]);
} }

View File

@ -29,8 +29,7 @@ namespace shaka {
/// All video Adaptation Sets have Role set to "main". /// All video Adaptation Sets have Role set to "main".
class DashIopMpdNotifier : public MpdNotifier { class DashIopMpdNotifier : public MpdNotifier {
public: public:
DashIopMpdNotifier(DashProfile dash_profile, DashIopMpdNotifier(const MpdOptions& mpd_options,
const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path); const std::string& output_path);
~DashIopMpdNotifier() override; ~DashIopMpdNotifier() override;

View File

@ -91,8 +91,7 @@ MATCHER_P(ContentProtectionElementEq, expected, "") {
// (https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests); // (https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests);
// also because SimpleMpdNotifier and DashIopMpdNotifier have common behavior // also because SimpleMpdNotifier and DashIopMpdNotifier have common behavior
// for most of the public functions. // for most of the public functions.
class DashIopMpdNotifierTest class DashIopMpdNotifierTest : public ::testing::Test {
: public ::testing::TestWithParam<MpdBuilder::MpdType> {
protected: protected:
DashIopMpdNotifierTest() DashIopMpdNotifierTest()
: default_mock_adaptation_set_( : default_mock_adaptation_set_(
@ -109,23 +108,11 @@ class DashIopMpdNotifierTest
base::DeleteFile(temp_file_path_, false /* non recursive, just 1 file */); 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, void SetMpdBuilder(DashIopMpdNotifier* notifier,
std::unique_ptr<MpdBuilder> mpd_builder) { std::unique_ptr<MpdBuilder> mpd_builder) {
notifier->SetMpdBuilderForTesting(std::move(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 // Use output_path_ for specifying the MPD output path so that
// WriteMpdToFile() doesn't crash. // WriteMpdToFile() doesn't crash.
std::string output_path_; std::string output_path_;
@ -142,27 +129,13 @@ class DashIopMpdNotifierTest
base::FilePath temp_file_path_; 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. // Verify that basic VOD NotifyNewContainer() operation works.
// No encrypted contents. // No encrypted contents.
TEST_P(DashIopMpdNotifierTest, NotifyNewContainer) { TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) {
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)) EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
.WillOnce(Return(default_mock_adaptation_set_.get())); .WillOnce(Return(default_mock_adaptation_set_.get()));
@ -183,18 +156,17 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainer) {
// Verify that if the MediaInfo contains text information, then // Verify that if the MediaInfo contains text information, then
// MpdBuilder::ForceSetSegmentAlignment() is called. // MpdBuilder::ForceSetSegmentAlignment() is called.
TEST_P(DashIopMpdNotifierTest, NotifyNewTextContainer) { TEST_F(DashIopMpdNotifierTest, NotifyNewTextContainer) {
const char kTextMediaInfo[] = const char kTextMediaInfo[] =
"text_info {\n" "text_info {\n"
" format: 'ttml'\n" " format: 'ttml'\n"
" language: 'en'\n" " language: 'en'\n"
"}\n" "}\n"
"container_type: CONTAINER_TEXT\n"; "container_type: CONTAINER_TEXT\n";
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(StrEq("en"))) EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(StrEq("en")))
.WillOnce(Return(default_mock_adaptation_set_.get())); .WillOnce(Return(default_mock_adaptation_set_.get()));
@ -218,12 +190,11 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewTextContainer) {
// MediaInfo::ProtectedContent. // MediaInfo::ProtectedContent.
// Two AdaptationSets should be created. // Two AdaptationSets should be created.
// AdaptationSets with different DRM won't be switchable. // AdaptationSets with different DRM won't be switchable.
TEST_P(DashIopMpdNotifierTest, TEST_F(DashIopMpdNotifierTest,
NotifyNewContainersWithDifferentProtectedContent) { NotifyNewContainersWithDifferentProtectedContent) {
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
// Note they both have different (bogus) pssh, like real use case. // Note they both have different (bogus) pssh, like real use case.
// default Key ID = _default_key_id_ // default Key ID = _default_key_id_
@ -338,11 +309,10 @@ TEST_P(DashIopMpdNotifierTest,
// Verify VOD NotifyNewContainer() operation works with same // Verify VOD NotifyNewContainer() operation works with same
// MediaInfo::ProtectedContent. Only one AdaptationSet should be // MediaInfo::ProtectedContent. Only one AdaptationSet should be
// created. // created.
TEST_P(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) { TEST_F(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
// These have the same default key ID and PSSH. // These have the same default key ID and PSSH.
const char kSdProtectedContent[] = const char kSdProtectedContent[] =
@ -441,12 +411,11 @@ TEST_P(DashIopMpdNotifierTest, NotifyNewContainersWithSameProtectedContent) {
} }
// AddContentProtection() should not work and should always return false. // AddContentProtection() should not work and should always return false.
TEST_P(DashIopMpdNotifierTest, AddContentProtection) { TEST_F(DashIopMpdNotifierTest, AddContentProtection) {
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)) EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
.WillOnce(Return(default_mock_adaptation_set_.get())); .WillOnce(Return(default_mock_adaptation_set_.get()));
@ -473,11 +442,10 @@ TEST_P(DashIopMpdNotifierTest, AddContentProtection) {
// should be switchable. // should be switchable.
// 3. Add a 4k protected content. This should also make a new AdaptationSet. // 3. Add a 4k protected content. This should also make a new AdaptationSet.
// It should be switchable with SD/HD AdaptationSet. // It should be switchable with SD/HD AdaptationSet.
TEST_P(DashIopMpdNotifierTest, SetAdaptationSetSwitching) { TEST_F(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
// These have the same default key ID and PSSH. // These have the same default key ID and PSSH.
const char kSdProtectedContent[] = const char kSdProtectedContent[] =
@ -610,12 +578,11 @@ TEST_P(DashIopMpdNotifierTest, SetAdaptationSetSwitching) {
// Even if the UUIDs match, video and audio AdaptationSets should not be // Even if the UUIDs match, video and audio AdaptationSets should not be
// switchable. // switchable.
TEST_P(DashIopMpdNotifierTest, TEST_F(DashIopMpdNotifierTest,
DoNotSetAdaptationSetSwitchingIfContentTypesDifferent) { DoNotSetAdaptationSetSwitchingIfContentTypesDifferent) {
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
// These have the same default key ID and PSSH. // These have the same default key ID and PSSH.
const char kVideoContent[] = const char kVideoContent[] =
@ -699,7 +666,7 @@ TEST_P(DashIopMpdNotifierTest,
ElementsAre()); ElementsAre());
} }
TEST_P(DashIopMpdNotifierTest, UpdateEncryption) { TEST_F(DashIopMpdNotifierTest, UpdateEncryption) {
const char kProtectedContent[] = const char kProtectedContent[] =
"video_info {\n" "video_info {\n"
" codec: 'avc1'\n" " codec: 'avc1'\n"
@ -720,11 +687,10 @@ TEST_P(DashIopMpdNotifierTest, UpdateEncryption) {
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_)) EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
.WillOnce(Return(default_mock_adaptation_set_.get())); .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 // This issue identified a bug where using SimpleMpdNotifier with multiple
// threads causes a deadlock. This tests with DashIopMpdNotifier. // threads causes a deadlock. This tests with DashIopMpdNotifier.
TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) { TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
DashIopMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
uint32_t container_id; uint32_t container_id;
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo), EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
&container_id)); &container_id));
@ -772,7 +738,7 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
} }
// Don't put different audio languages or codecs in the same AdaptationSet. // Don't put different audio languages or codecs in the same AdaptationSet.
TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) { TEST_F(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
// MP4, English // MP4, English
const char kAudioContent1[] = const char kAudioContent1[] =
"audio_info {\n" "audio_info {\n"
@ -825,10 +791,9 @@ TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
"container_type: CONTAINER_WEBM\n" "container_type: CONTAINER_WEBM\n"
"media_duration_seconds: 10.5\n"; "media_duration_seconds: 10.5\n";
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_, DashIopMpdNotifier notifier(empty_mpd_option_, empty_base_urls_,
empty_base_urls_, output_path_); output_path_);
std::unique_ptr<MockMpdBuilder> mock_mpd_builder( std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
new MockMpdBuilder(mpd_type()));
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1)); std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2)); std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
@ -871,10 +836,4 @@ TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
ConvertToMediaInfo(kAudioContent4), &unused_container_id)); ConvertToMediaInfo(kAudioContent4), &unused_container_id));
} }
INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
DashIopMpdNotifierTest,
::testing::Values(MpdBuilder::kStatic,
MpdBuilder::kDynamic));
} // namespace shaka } // namespace shaka

View File

@ -6,20 +6,17 @@ namespace shaka {
namespace { namespace {
const char kEmptyLang[] = ""; const char kEmptyLang[] = "";
const MpdOptions kDefaultMpdOptions; const MpdOptions kDefaultMpdOptions;
const MpdBuilder::MpdType kDefaultMpdType = MpdBuilder::kStatic;
} // namespace } // namespace
// Doesn't matter what values get passed to the super class' constructor. // Doesn't matter what values get passed to the super class' constructor.
// All methods used for testing should be mocked. // All methods used for testing should be mocked.
MockMpdBuilder::MockMpdBuilder(MpdType type) MockMpdBuilder::MockMpdBuilder() : MpdBuilder(kDefaultMpdOptions) {}
: MpdBuilder(type, kDefaultMpdOptions) {}
MockMpdBuilder::~MockMpdBuilder() {} MockMpdBuilder::~MockMpdBuilder() {}
MockAdaptationSet::MockAdaptationSet(uint32_t adaptation_set_id) MockAdaptationSet::MockAdaptationSet(uint32_t adaptation_set_id)
: AdaptationSet(adaptation_set_id, : AdaptationSet(adaptation_set_id,
kEmptyLang, kEmptyLang,
kDefaultMpdOptions, kDefaultMpdOptions,
kDefaultMpdType,
&sequence_counter_) {} &sequence_counter_) {}
MockAdaptationSet::~MockAdaptationSet() {} MockAdaptationSet::~MockAdaptationSet() {}

View File

@ -18,9 +18,7 @@ namespace shaka {
class MockMpdBuilder : public MpdBuilder { class MockMpdBuilder : public MpdBuilder {
public: public:
// |type| indicates whether the MPD should be for VOD or live content (kStatic MockMpdBuilder();
// for VOD profile, or kDynamic for live profile).
explicit MockMpdBuilder(MpdType type);
~MockMpdBuilder() override; ~MockMpdBuilder() override;
MOCK_METHOD1(AddAdaptationSet, AdaptationSet*(const std::string& lang)); MOCK_METHOD1(AddAdaptationSet, AdaptationSet*(const std::string& lang));

View File

@ -2,7 +2,8 @@
namespace shaka { namespace shaka {
MockMpdNotifier::MockMpdNotifier(DashProfile profile) : MpdNotifier(profile) {} MockMpdNotifier::MockMpdNotifier(const MpdOptions& mpd_options)
: MpdNotifier(mpd_options) {}
MockMpdNotifier::~MockMpdNotifier() {} MockMpdNotifier::~MockMpdNotifier() {}
} // namespace shaka } // namespace shaka

View File

@ -18,7 +18,7 @@ namespace shaka {
class MockMpdNotifier : public MpdNotifier { class MockMpdNotifier : public MpdNotifier {
public: public:
MockMpdNotifier(DashProfile profile); explicit MockMpdNotifier(const MpdOptions& mpd_options);
virtual ~MockMpdNotifier(); virtual ~MockMpdNotifier();
MOCK_METHOD0(Init, bool()); MOCK_METHOD0(Init, bool());

View File

@ -396,10 +396,8 @@ class RepresentationStateChangeListenerImpl
} // namespace } // namespace
MpdBuilder::MpdBuilder(MpdType type, const MpdOptions& mpd_options) MpdBuilder::MpdBuilder(const MpdOptions& mpd_options)
: type_(type), : mpd_options_(mpd_options), clock_(new base::DefaultClock()) {}
mpd_options_(mpd_options),
clock_(new base::DefaultClock()) {}
MpdBuilder::~MpdBuilder() {} MpdBuilder::~MpdBuilder() {}
@ -410,7 +408,7 @@ void MpdBuilder::AddBaseUrl(const std::string& base_url) {
AdaptationSet* MpdBuilder::AddAdaptationSet(const std::string& lang) { AdaptationSet* MpdBuilder::AddAdaptationSet(const std::string& lang) {
std::unique_ptr<AdaptationSet> adaptation_set( std::unique_ptr<AdaptationSet> adaptation_set(
new AdaptationSet(adaptation_set_counter_.GetNext(), lang, mpd_options_, new AdaptationSet(adaptation_set_counter_.GetNext(), lang, mpd_options_,
type_, &representation_counter_)); &representation_counter_));
DCHECK(adaptation_set); DCHECK(adaptation_set);
if (!lang.empty() && lang == mpd_options_.default_language) { if (!lang.empty() && lang == mpd_options_.default_language) {
@ -482,7 +480,8 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
return NULL; 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. // This is the only Period and it is a regular period.
period.SetStringAttribute("start", "PT0S"); period.SetStringAttribute("start", "PT0S");
} }
@ -491,16 +490,35 @@ xmlDocPtr MpdBuilder::GenerateMpd() {
return NULL; return NULL;
AddMpdNameSpaceInfo(&mpd); 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); AddCommonMpdInfo(&mpd);
switch (type_) { switch (mpd_options_.mpd_type) {
case kStatic: case MpdType::kStatic:
AddStaticMpdInfo(&mpd); AddStaticMpdInfo(&mpd);
break; break;
case kDynamic: case MpdType::kDynamic:
AddDynamicMpdInfo(&mpd); AddDynamicMpdInfo(&mpd);
break; break;
default: default:
NOTREACHED() << "Unknown MPD type: " << type_; NOTREACHED() << "Unknown MPD type: "
<< static_cast<int>(mpd_options_.mpd_type);
break; break;
} }
@ -532,13 +550,10 @@ void MpdBuilder::AddCommonMpdInfo(XmlNode* mpd_node) {
void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) { void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) {
DCHECK(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 kStaticMpdType[] = "static";
static const char kStaticMpdProfile[] =
"urn:mpeg:dash:profile:isoff-on-demand:2011";
mpd_node->SetStringAttribute("type", kStaticMpdType); mpd_node->SetStringAttribute("type", kStaticMpdType);
mpd_node->SetStringAttribute("profiles", kStaticMpdProfile);
mpd_node->SetStringAttribute( mpd_node->SetStringAttribute(
"mediaPresentationDuration", "mediaPresentationDuration",
SecondsToXmlDuration(GetStaticMpdDuration(mpd_node))); SecondsToXmlDuration(GetStaticMpdDuration(mpd_node)));
@ -546,13 +561,10 @@ void MpdBuilder::AddStaticMpdInfo(XmlNode* mpd_node) {
void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) { void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
DCHECK(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 kDynamicMpdType[] = "dynamic";
static const char kDynamicMpdProfile[] =
"urn:mpeg:dash:profile:isoff-live:2011";
mpd_node->SetStringAttribute("type", kDynamicMpdType); mpd_node->SetStringAttribute("type", kDynamicMpdType);
mpd_node->SetStringAttribute("profiles", kDynamicMpdProfile);
// No offset from NOW. // No offset from NOW.
mpd_node->SetStringAttribute("publishTime", mpd_node->SetStringAttribute("publishTime",
@ -594,12 +606,13 @@ void MpdBuilder::AddDynamicMpdInfo(XmlNode* mpd_node) {
float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) { float MpdBuilder::GetStaticMpdDuration(XmlNode* mpd_node) {
DCHECK(mpd_node); DCHECK(mpd_node);
DCHECK_EQ(MpdBuilder::kStatic, type_); DCHECK_EQ(MpdType::kStatic, mpd_options_.mpd_type);
xmlNodePtr period_node = FindPeriodNode(mpd_node); xmlNodePtr period_node = FindPeriodNode(mpd_node);
DCHECK(period_node) << "Period element must be a child of mpd_node."; DCHECK(period_node) << "Period element must be a child of mpd_node.";
DCHECK(IsPeriodNode(period_node)); DCHECK(IsPeriodNode(period_node));
// TODO(kqyang): Verify if this works for static + live profile.
// Attribute mediaPresentationDuration must be present for 'static' MPD. So // Attribute mediaPresentationDuration must be present for 'static' MPD. So
// setting "PT0S" is required even if none of the representaions have duration // setting "PT0S" is required even if none of the representaions have duration
// attribute. // attribute.
@ -673,13 +686,11 @@ void MpdBuilder::MakePathsRelativeToMpd(const std::string& mpd_path,
AdaptationSet::AdaptationSet(uint32_t adaptation_set_id, AdaptationSet::AdaptationSet(uint32_t adaptation_set_id,
const std::string& lang, const std::string& lang,
const MpdOptions& mpd_options, const MpdOptions& mpd_options,
MpdBuilder::MpdType mpd_type,
base::AtomicSequenceNumber* counter) base::AtomicSequenceNumber* counter)
: representation_counter_(counter), : representation_counter_(counter),
id_(adaptation_set_id), id_(adaptation_set_id),
lang_(lang), lang_(lang),
mpd_options_(mpd_options), mpd_options_(mpd_options),
mpd_type_(mpd_type),
segments_aligned_(kSegmentAlignmentUnknown), segments_aligned_(kSegmentAlignmentUnknown),
force_set_segment_alignment_(false) { force_set_segment_alignment_(false) {
DCHECK(counter); DCHECK(counter);
@ -791,12 +802,13 @@ xml::scoped_xml_ptr<xmlNode> AdaptationSet::GetXml() {
// Note: must be checked before checking segments_aligned_ (below). So that // Note: must be checked before checking segments_aligned_ (below). So that
// segments_aligned_ is set before checking below. // segments_aligned_ is set before checking below.
if (mpd_type_ == MpdBuilder::kStatic) { if (mpd_options_.dash_profile == DashProfile::kOnDemand) {
CheckVodSegmentAlignment(); CheckVodSegmentAlignment();
} }
if (segments_aligned_ == kSegmentAlignmentTrue) { if (segments_aligned_ == kSegmentAlignmentTrue) {
adaptation_set.SetStringAttribute(mpd_type_ == MpdBuilder::kStatic adaptation_set.SetStringAttribute(
mpd_options_.dash_profile == DashProfile::kOnDemand
? "subsegmentAlignment" ? "subsegmentAlignment"
: "segmentAlignment", : "segmentAlignment",
"true"); "true");
@ -860,7 +872,7 @@ void AdaptationSet::AddAdaptationSetSwitching(uint32_t adaptation_set_id) {
void AdaptationSet::OnNewSegmentForRepresentation(uint32_t representation_id, void AdaptationSet::OnNewSegmentForRepresentation(uint32_t representation_id,
uint64_t start_time, uint64_t start_time,
uint64_t duration) { uint64_t duration) {
if (mpd_type_ == MpdBuilder::kDynamic) { if (mpd_options_.dash_profile == DashProfile::kLive) {
CheckLiveSegmentAlignment(representation_id, start_time, duration); CheckLiveSegmentAlignment(representation_id, start_time, duration);
} else { } else {
representation_segment_start_times_[representation_id].push_back( representation_segment_start_times_[representation_id].push_back(

View File

@ -56,15 +56,9 @@ class RepresentationXmlNode;
/// This class generates DASH MPDs (Media Presentation Descriptions). /// This class generates DASH MPDs (Media Presentation Descriptions).
class MpdBuilder { class MpdBuilder {
public: public:
enum MpdType {
kStatic = 0,
kDynamic
};
/// Constructs MpdBuilder. /// Constructs MpdBuilder.
/// @param type indicates whether the MPD should be for VOD or live content /// @param mpd_options contains options on how this MPD should be built.
/// (kStatic for VOD profile, or kDynamic for live profile). explicit MpdBuilder(const MpdOptions& mpd_options);
MpdBuilder(MpdType type, const MpdOptions& mpd_options);
virtual ~MpdBuilder(); virtual ~MpdBuilder();
/// Add <BaseURL> entry to the MPD. /// Add <BaseURL> entry to the MPD.
@ -88,9 +82,6 @@ class MpdBuilder {
/// @return true on success, false otherwise. /// @return true on success, false otherwise.
virtual bool ToString(std::string* output); 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 /// Adjusts the fields of MediaInfo so that paths are relative to the
/// specified MPD path. /// specified MPD path.
/// @param mpd_path is the file path of the MPD file. /// @param mpd_path is the file path of the MPD file.
@ -106,9 +97,11 @@ class MpdBuilder {
} }
private: 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. // 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); bool ToStringImpl(std::string* output);
@ -143,7 +136,6 @@ class MpdBuilder {
// successful, false otherwise. // successful, false otherwise.
bool GetEarliestTimestamp(double* timestamp_seconds); bool GetEarliestTimestamp(double* timestamp_seconds);
MpdType type_;
MpdOptions mpd_options_; MpdOptions mpd_options_;
std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_; std::list<std::unique_ptr<AdaptationSet>> adaptation_sets_;
@ -286,12 +278,11 @@ class AdaptationSet {
AdaptationSet(uint32_t adaptation_set_id, AdaptationSet(uint32_t adaptation_set_id,
const std::string& lang, const std::string& lang,
const MpdOptions& mpd_options, const MpdOptions& mpd_options,
MpdBuilder::MpdType mpd_type,
base::AtomicSequenceNumber* representation_counter); base::AtomicSequenceNumber* representation_counter);
private: private:
friend class MpdBuilder; friend class MpdBuilder;
template <MpdBuilder::MpdType type> template <DashProfile profile>
friend class MpdBuilderTest; friend class MpdBuilderTest;
// kSegmentAlignmentUnknown means that it is uncertain if the // kSegmentAlignmentUnknown means that it is uncertain if the
@ -345,7 +336,6 @@ class AdaptationSet {
const uint32_t id_; const uint32_t id_;
const std::string lang_; const std::string lang_;
const MpdOptions& mpd_options_; const MpdOptions& mpd_options_;
const MpdBuilder::MpdType mpd_type_;
// The ids of the adaptation sets this adaptation set can switch to. // The ids of the adaptation sets this adaptation set can switch to.
std::vector<uint32_t> adaptation_set_switching_ids_; std::vector<uint32_t> adaptation_set_switching_ids_;
@ -513,7 +503,7 @@ class Representation {
private: private:
friend class AdaptationSet; friend class AdaptationSet;
template <MpdBuilder::MpdType type> template <DashProfile profile>
friend class MpdBuilderTest; friend class MpdBuilderTest;
bool AddLiveInfo(xml::RepresentationXmlNode* representation); bool AddLiveInfo(xml::RepresentationXmlNode* representation);

View File

@ -104,12 +104,16 @@ class MockRepresentationStateChangeListener
}; };
} // namespace } // namespace
template <MpdBuilder::MpdType type> template <DashProfile profile>
class MpdBuilderTest : public ::testing::Test { class MpdBuilderTest : public ::testing::Test {
public: public:
MpdBuilderTest() : mpd_(type, MpdOptions()), representation_() {} MpdBuilderTest() : mpd_(MpdOptions()), representation_() {
mpd_.mpd_options_.dash_profile = profile;
}
~MpdBuilderTest() override {} ~MpdBuilderTest() override {}
MpdOptions* mutable_mpd_options() { return &mpd_.mpd_options_; }
void CheckMpd(const std::string& expected_output_file) { void CheckMpd(const std::string& expected_output_file) {
std::string mpd_doc; std::string mpd_doc;
ASSERT_TRUE(mpd_.ToString(&mpd_doc)); ASSERT_TRUE(mpd_.ToString(&mpd_doc));
@ -138,24 +142,20 @@ class MpdBuilderTest : public ::testing::Test {
// constructor signatures. // constructor signatures.
std::unique_ptr<Representation> CreateRepresentation( std::unique_ptr<Representation> CreateRepresentation(
const MediaInfo& media_info, const MediaInfo& media_info,
const MpdOptions& mpd_options,
uint32_t representation_id, uint32_t representation_id,
std::unique_ptr<RepresentationStateChangeListener> std::unique_ptr<RepresentationStateChangeListener>
state_change_listener) { state_change_listener) {
return std::unique_ptr<Representation>( 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::move(state_change_listener)));
} }
std::unique_ptr<AdaptationSet> CreateAdaptationSet( std::unique_ptr<AdaptationSet> CreateAdaptationSet(
uint32_t adaptation_set_id, uint32_t adaptation_set_id,
const std::string& lang, const std::string& lang,
const MpdOptions& mpd_options,
MpdBuilder::MpdType mpd_type,
base::AtomicSequenceNumber* representation_counter) { base::AtomicSequenceNumber* representation_counter) {
return std::unique_ptr<AdaptationSet>( return std::unique_ptr<AdaptationSet>(new AdaptationSet(
new AdaptationSet(adaptation_set_id, lang, mpd_options, mpd_type, adaptation_set_id, lang, mpd_options_, representation_counter));
representation_counter));
} }
// Helper function to return an empty listener for tests that don't need // 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_|. Representation* representation_; // Owned by |mpd_|.
private: private:
MpdOptions mpd_options_;
DISALLOW_COPY_AND_ASSIGN(MpdBuilderTest); 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 // Use this test name for things that are common to both static an dynamic
// mpd builder tests. // mpd builder tests.
typedef StaticMpdBuilderTest CommonMpdBuilderTest; typedef OnDemandMpdBuilderTest CommonMpdBuilderTest;
class DynamicMpdBuilderTest : public MpdBuilderTest<MpdBuilder::kDynamic> { class LiveMpdBuilderTest : public MpdBuilderTest<DashProfile::kLive> {
public: public:
~DynamicMpdBuilderTest() override {} ~LiveMpdBuilderTest() override {}
// Anchors availabilityStartTime so that the test result doesn't depend on the // Anchors availabilityStartTime so that the test result doesn't depend on the
// current time. // current time.
void SetUp() override { void SetUp() override {
SetPackagerVersionForTesting("<tag>-<hash>-<test>"); SetPackagerVersionForTesting("<tag>-<hash>-<test>");
mpd_.mpd_options_.mpd_type = MpdType::kDynamic;
mpd_.availability_start_time_ = "2011-12-25T12:30:00"; mpd_.availability_start_time_ = "2011-12-25T12:30:00";
InjectTestClock(); InjectTestClock();
} }
MpdOptions* mutable_mpd_options() { return &mpd_.mpd_options_; }
// Injects a clock that always returns 2016 Jan 11 15:10:24 in UTC. // Injects a clock that always returns 2016 Jan 11 15:10:24 in UTC.
void InjectTestClock() { void InjectTestClock() {
base::Time::Exploded test_time = { 2016, // year. base::Time::Exploded test_time = { 2016, // year.
@ -231,14 +232,14 @@ class DynamicMpdBuilderTest : public MpdBuilderTest<MpdBuilder::kDynamic> {
uint32_t DefaultTimeScale() const { return 1000; }; uint32_t DefaultTimeScale() const { return 1000; };
}; };
class SegmentTemplateTest : public DynamicMpdBuilderTest { class SegmentTemplateTest : public LiveMpdBuilderTest {
public: public:
SegmentTemplateTest() SegmentTemplateTest()
: bandwidth_estimator_(BandwidthEstimator::kUseAllBlocks) {} : bandwidth_estimator_(BandwidthEstimator::kUseAllBlocks) {}
~SegmentTemplateTest() override {} ~SegmentTemplateTest() override {}
void SetUp() override { void SetUp() override {
DynamicMpdBuilderTest::SetUp(); LiveMpdBuilderTest::SetUp();
ASSERT_NO_FATAL_FAILURE(AddRepresentationWithDefaultMediaInfo()); ASSERT_NO_FATAL_FAILURE(AddRepresentationWithDefaultMediaInfo());
} }
@ -282,8 +283,9 @@ class SegmentTemplateTest : public DynamicMpdBuilderTest {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
" xmlns:xlink=\"http://www.w3.org/1999/xlink\" " " xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" " " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
" availabilityStartTime=\"2011-12-25T12:30:00\" minBufferTime=\"PT2S\" " " availabilityStartTime=\"2011-12-25T12:30:00\" "
" type=\"dynamic\" profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" " " profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
" minBufferTime=\"PT2S\" type=\"dynamic\" "
" publishTime=\"2016-01-11T15:10:24Z\">\n" " publishTime=\"2016-01-11T15:10:24Z\">\n"
" <Period id=\"0\" start=\"PT0S\">\n" " <Period id=\"0\" start=\"PT0S\">\n"
" <AdaptationSet id=\"0\" width=\"720\" height=\"480\"" " <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$ // that it does not automatically add a representation, that has $Time$
// template. // template.
void SetUp() override { void SetUp() override {
DynamicMpdBuilderTest::SetUp(); LiveMpdBuilderTest::SetUp();
// The only diff with current GetDefaultMediaInfo() is that this uses // The only diff with current GetDefaultMediaInfo() is that this uses
// $Number$ for segment template. // $Number$ for segment template.
@ -367,8 +369,9 @@ class TimeShiftBufferDepthTest : public SegmentTemplateTest {
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xmlns:xlink=\"http://www.w3.org/1999/xlink\" " "xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
"xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" " "xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
"availabilityStartTime=\"2011-12-25T12:30:00\" minBufferTime=\"PT2S\" " "availabilityStartTime=\"2011-12-25T12:30:00\" "
"type=\"dynamic\" profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" " "profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
"minBufferTime=\"PT2S\" type=\"dynamic\" "
"publishTime=\"2016-01-11T15:10:24Z\" " "publishTime=\"2016-01-11T15:10:24Z\" "
"timeShiftBufferDepth=\"PT%dS\">\n" "timeShiftBufferDepth=\"PT%dS\">\n"
" <Period id=\"0\" start=\"PT0S\">\n" " <Period id=\"0\" start=\"PT0S\">\n"
@ -405,7 +408,7 @@ class TimeShiftBufferDepthTest : public SegmentTemplateTest {
}; };
TEST_F(CommonMpdBuilderTest, AddAdaptationSetSwitching) { TEST_F(CommonMpdBuilderTest, AddAdaptationSetSwitching) {
MpdBuilder mpd_builder(MpdBuilder::kStatic, MpdOptions()); MpdBuilder mpd_builder(MpdOptions{});
AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet(""); AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet("");
adaptation_set->AddAdaptationSetSwitching(1); adaptation_set->AddAdaptationSetSwitching(1);
adaptation_set->AddAdaptationSetSwitching(2); adaptation_set->AddAdaptationSetSwitching(2);
@ -420,8 +423,8 @@ TEST_F(CommonMpdBuilderTest, AddAdaptationSetSwitching) {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"\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" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
" minBufferTime=\"PT2S\" type=\"static\"\n"
" mediaPresentationDuration=\"PT0S\">\n" " mediaPresentationDuration=\"PT0S\">\n"
" <Period id=\"0\">\n" " <Period id=\"0\">\n"
" <AdaptationSet id=\"0\" contentType=\"\">\n" " <AdaptationSet id=\"0\" contentType=\"\">\n"
@ -454,9 +457,8 @@ TEST_F(CommonMpdBuilderTest, ValidMediaInfo) {
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
} }
@ -464,9 +466,8 @@ TEST_F(CommonMpdBuilderTest, ValidMediaInfo) {
TEST_F(CommonMpdBuilderTest, VideoAudioTextInfoNotSet) { TEST_F(CommonMpdBuilderTest, VideoAudioTextInfoNotSet) {
const char kTestMediaInfo[] = "container_type: 1"; const char kTestMediaInfo[] = "container_type: 1";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
EXPECT_FALSE(representation->Init()); EXPECT_FALSE(representation->Init());
} }
@ -490,9 +491,8 @@ TEST_F(CommonMpdBuilderTest, VideoAndAudioInfoSet) {
"}\n" "}\n"
"container_type: CONTAINER_MP4\n"; "container_type: CONTAINER_MP4\n";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
EXPECT_FALSE(representation->Init()); EXPECT_FALSE(representation->Init());
} }
@ -509,9 +509,8 @@ TEST_F(CommonMpdBuilderTest, InvalidMediaInfo) {
" pixel_height: 1\n" " pixel_height: 1\n"
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
EXPECT_FALSE(representation->Init()); EXPECT_FALSE(representation->Init());
} }
@ -528,9 +527,8 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoReflectedInXml) {
" pixel_height: 1\n" " pixel_height: 1\n"
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml()); xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
EXPECT_NO_FATAL_FAILURE( EXPECT_NO_FATAL_FAILURE(
@ -559,7 +557,7 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInMp4) {
"container_type: 1\n"; "container_type: 1\n";
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8), CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8),
MpdOptions(), kAnyRepresentationId, NoListener()); kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml()); xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
EXPECT_NO_FATAL_FAILURE( EXPECT_NO_FATAL_FAILURE(
@ -582,7 +580,7 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInWebm) {
"container_type: 3\n"; "container_type: 3\n";
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8), CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8),
MpdOptions(), kAnyRepresentationId, NoListener()); kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml()); xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
EXPECT_NO_FATAL_FAILURE( EXPECT_NO_FATAL_FAILURE(
@ -605,7 +603,7 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp9CodecInWebm) {
"container_type: 3\n"; "container_type: 3\n";
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp9), CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp9),
MpdOptions(), kAnyRepresentationId, NoListener()); kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml()); xml::scoped_xml_ptr<xmlNode> node_xml(representation->GetXml());
EXPECT_NO_FATAL_FAILURE( EXPECT_NO_FATAL_FAILURE(
@ -635,7 +633,7 @@ TEST_F(CommonMpdBuilderTest,
EXPECT_CALL(*listener, EXPECT_CALL(*listener,
OnNewSegmentForRepresentation(kStartTime, kDuration)); OnNewSegmentForRepresentation(kStartTime, kDuration));
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo),
kAnyRepresentationId, std::move(listener)); kAnyRepresentationId, std::move(listener));
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
@ -666,7 +664,7 @@ TEST_F(CommonMpdBuilderTest,
EXPECT_CALL(*listener, EXPECT_CALL(*listener,
OnSetFrameRateForRepresentation(kFrameDuration, kTimeScale)); OnSetFrameRateForRepresentation(kFrameDuration, kTimeScale));
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo),
kAnyRepresentationId, std::move(listener)); kAnyRepresentationId, std::move(listener));
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
@ -690,8 +688,7 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetVideoContentType) {
"container_type: CONTAINER_MP4\n"; "container_type: CONTAINER_MP4\n";
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo));
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
@ -712,8 +709,7 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetAudioContentType) {
"container_type: CONTAINER_MP4\n"; "container_type: CONTAINER_MP4\n";
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
adaptation_set->AddRepresentation(ConvertToMediaInfo(kAudioMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(kAudioMediaInfo));
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
@ -732,8 +728,7 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetTextContentType) {
"container_type: CONTAINER_TEXT\n"; "container_type: CONTAINER_TEXT\n";
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo));
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
@ -748,7 +743,7 @@ TEST_F(CommonMpdBuilderTest, TtmlXmlMimeType) {
"container_type: CONTAINER_TEXT\n"; "container_type: CONTAINER_TEXT\n";
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTtmlXmlMediaInfo), MpdOptions(), CreateRepresentation(ConvertToMediaInfo(kTtmlXmlMediaInfo),
kAnyRepresentationId, NoListener()); kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
@ -763,7 +758,7 @@ TEST_F(CommonMpdBuilderTest, TtmlMp4MimeType) {
"container_type: CONTAINER_MP4\n"; "container_type: CONTAINER_MP4\n";
auto representation = auto representation =
CreateRepresentation(ConvertToMediaInfo(kTtmlMp4MediaInfo), MpdOptions(), CreateRepresentation(ConvertToMediaInfo(kTtmlMp4MediaInfo),
kAnyRepresentationId, NoListener()); kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
@ -777,9 +772,8 @@ TEST_F(CommonMpdBuilderTest, WebVttMimeType) {
"}\n" "}\n"
"container_type: CONTAINER_TEXT\n"; "container_type: CONTAINER_TEXT\n";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kWebVttMediaInfo), MpdOptions(), ConvertToMediaInfo(kWebVttMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString(
"mimeType", "text/vtt", representation->GetXml().get())); "mimeType", "text/vtt", representation->GetXml().get()));
@ -796,8 +790,7 @@ TEST_F(CommonMpdBuilderTest, CheckLanguageAttributeSet) {
"container_type: CONTAINER_TEXT\n"; "container_type: CONTAINER_TEXT\n";
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "en", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "en", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo));
xml::scoped_xml_ptr<xmlNode> node_xml(adaptation_set->GetXml()); 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 // "por-BR" is the long tag for Brazillian Portuguese. The short tag
// is "pt-BR", which is what should appear in the manifest. // is "pt-BR", which is what should appear in the manifest.
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "por-BR", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "por-BR", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo));
xml::scoped_xml_ptr<xmlNode> node_xml(adaptation_set->GetXml()); xml::scoped_xml_ptr<xmlNode> node_xml(adaptation_set->GetXml());
@ -831,14 +823,13 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetId) {
base::AtomicSequenceNumber sequence_counter; base::AtomicSequenceNumber sequence_counter;
const uint32_t kAdaptationSetId = 42; const uint32_t kAdaptationSetId = 42;
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
ASSERT_NO_FATAL_FAILURE(CheckIdEqual(kAdaptationSetId, adaptation_set.get())); ASSERT_NO_FATAL_FAILURE(CheckIdEqual(kAdaptationSetId, adaptation_set.get()));
} }
// Verify AdaptationSet::AddRole() works for "main" role. // Verify AdaptationSet::AddRole() works for "main" role.
TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) { TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) {
MpdBuilder mpd_builder(MpdBuilder::kStatic, MpdOptions()); MpdBuilder mpd_builder(MpdOptions{});
AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet(""); AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet("");
adaptation_set->AddRole(AdaptationSet::kRoleMain); adaptation_set->AddRole(AdaptationSet::kRoleMain);
@ -851,8 +842,8 @@ TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"\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" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
" minBufferTime=\"PT2S\" type=\"static\"\n"
" mediaPresentationDuration=\"PT0S\">\n" " mediaPresentationDuration=\"PT0S\">\n"
" <Period id=\"0\">\n" " <Period id=\"0\">\n"
" <AdaptationSet id=\"0\" contentType=\"\">\n" " <AdaptationSet id=\"0\" contentType=\"\">\n"
@ -871,7 +862,7 @@ TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) {
// Add Role, ContentProtection, and Representation elements. Verify that // Add Role, ContentProtection, and Representation elements. Verify that
// ContentProtection -> Role -> Representation are in order. // ContentProtection -> Role -> Representation are in order.
TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) { TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) {
MpdBuilder mpd_builder(MpdBuilder::kStatic, MpdOptions()); MpdBuilder mpd_builder(MpdOptions{});
AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet(""); AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet("");
adaptation_set->AddRole(AdaptationSet::kRoleMain); adaptation_set->AddRole(AdaptationSet::kRoleMain);
ContentProtectionElement any_content_protection; ContentProtectionElement any_content_protection;
@ -894,8 +885,8 @@ TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"\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" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
" minBufferTime=\"PT2S\" type=\"static\"\n"
" mediaPresentationDuration=\"PT0S\">\n" " mediaPresentationDuration=\"PT0S\">\n"
" <Period id=\"0\">\n" " <Period id=\"0\">\n"
" <AdaptationSet id=\"0\" contentType=\"audio\">\n" " <AdaptationSet id=\"0\" contentType=\"audio\">\n"
@ -1024,8 +1015,7 @@ TEST_F(CommonMpdBuilderTest,
"container_type: 1\n"; "container_type: 1\n";
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
Representation* representation_480p = Representation* representation_480p =
adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo));
Representation* representation_360p = Representation* representation_360p =
@ -1250,9 +1240,8 @@ TEST_F(CommonMpdBuilderTest, SuppressRepresentationAttributes) {
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
auto representation = auto representation = CreateRepresentation(
CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), MpdOptions(), ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener());
kAnyRepresentationId, NoListener());
representation->SuppressOnce(Representation::kSuppressWidth); representation->SuppressOnce(Representation::kSuppressWidth);
xml::scoped_xml_ptr<xmlNode> no_width(representation->GetXml()); 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 // Also checking that not all Representations have to be added before calling
// AddNewSegment() on a Representation. // AddNewSegment() on a Representation.
// The output MPD's schema is checked at the very end. // The output MPD's schema is checked at the very end.
TEST_F(StaticMpdBuilderTest, SubsegmentAlignment) { TEST_F(OnDemandMpdBuilderTest, SubsegmentAlignment) {
base::AtomicSequenceNumber sequence_counter; base::AtomicSequenceNumber sequence_counter;
const char k480pMediaInfo[] = const char k480pMediaInfo[] =
"video_info {\n" "video_info {\n"
@ -1448,7 +1437,7 @@ TEST_F(StaticMpdBuilderTest, SubsegmentAlignment) {
} }
// Verify that subsegmentAlignment can be force set to true. // Verify that subsegmentAlignment can be force set to true.
TEST_F(StaticMpdBuilderTest, ForceSetsubsegmentAlignment) { TEST_F(OnDemandMpdBuilderTest, ForceSetsubsegmentAlignment) {
base::AtomicSequenceNumber sequence_counter; base::AtomicSequenceNumber sequence_counter;
const char k480pMediaInfo[] = const char k480pMediaInfo[] =
"video_info {\n" "video_info {\n"
@ -1472,9 +1461,9 @@ TEST_F(StaticMpdBuilderTest, ForceSetsubsegmentAlignment) {
" pixel_height: 1\n" " pixel_height: 1\n"
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
MpdOptions mpd_options;
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
Representation* representation_480p = Representation* representation_480p =
adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo)); adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo));
Representation* representation_360p = Representation* representation_360p =
@ -1502,7 +1491,7 @@ TEST_F(StaticMpdBuilderTest, ForceSetsubsegmentAlignment) {
// Verify that segmentAlignment is set to true if all the Representations // Verify that segmentAlignment is set to true if all the Representations
// segments' are aligned and the MPD type is dynamic. // segments' are aligned and the MPD type is dynamic.
// The output MPD's schema is checked at the very end. // The output MPD's schema is checked at the very end.
TEST_F(DynamicMpdBuilderTest, SegmentAlignment) { TEST_F(LiveMpdBuilderTest, SegmentAlignment) {
base::AtomicSequenceNumber sequence_counter; base::AtomicSequenceNumber sequence_counter;
const char k480pMediaInfo[] = const char k480pMediaInfo[] =
"video_info {\n" "video_info {\n"
@ -1559,7 +1548,7 @@ TEST_F(DynamicMpdBuilderTest, SegmentAlignment) {
// Verify that the width and height attribute are set if all the video // Verify that the width and height attribute are set if all the video
// representations have the same width and height. // representations have the same width and height.
TEST_F(StaticMpdBuilderTest, AdapatationSetWidthAndHeight) { TEST_F(OnDemandMpdBuilderTest, AdapatationSetWidthAndHeight) {
// Both 720p. // Both 720p.
const char kVideoMediaInfo1[] = const char kVideoMediaInfo1[] =
"video_info {\n" "video_info {\n"
@ -1600,7 +1589,7 @@ TEST_F(StaticMpdBuilderTest, AdapatationSetWidthAndHeight) {
// Verify that the maxWidth and maxHeight attribute are set if there are // Verify that the maxWidth and maxHeight attribute are set if there are
// multiple video resolutions. // multiple video resolutions.
TEST_F(StaticMpdBuilderTest, AdapatationSetMaxWidthAndMaxHeight) { TEST_F(OnDemandMpdBuilderTest, AdapatationSetMaxWidthAndMaxHeight) {
const char kVideoMediaInfo1080p[] = const char kVideoMediaInfo1080p[] =
"video_info {\n" "video_info {\n"
" codec: \"avc1\"\n" " codec: \"avc1\"\n"
@ -1642,8 +1631,8 @@ TEST_F(CommonMpdBuilderTest, CheckRepresentationId) {
const MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); const MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
const uint32_t kRepresentationId = 1; const uint32_t kRepresentationId = 1;
auto representation = CreateRepresentation(video_media_info, MpdOptions(), auto representation =
kRepresentationId, NoListener()); CreateRepresentation(video_media_info, kRepresentationId, NoListener());
EXPECT_TRUE(representation->Init()); EXPECT_TRUE(representation->Init());
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
CheckIdEqual(kRepresentationId, representation.get())); CheckIdEqual(kRepresentationId, representation.get()));
@ -1664,8 +1653,7 @@ TEST_F(CommonMpdBuilderTest, SetSampleDuration) {
base::AtomicSequenceNumber sequence_counter; base::AtomicSequenceNumber sequence_counter;
auto adaptation_set = auto adaptation_set =
CreateAdaptationSet(kAnyAdaptationSetId, "", MpdOptions(), CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter);
MpdBuilder::kStatic, &sequence_counter);
const MediaInfo video_media_info = ConvertToMediaInfo(kVideoMediaInfo); const MediaInfo video_media_info = ConvertToMediaInfo(kVideoMediaInfo);
Representation* representation = Representation* representation =
@ -1716,8 +1704,8 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetAddContentProtectionAndUpdate) {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"" " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
" minBufferTime=\"PT2S\" type=\"static\""
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
" minBufferTime=\"PT2S\" type=\"static\""
" mediaPresentationDuration=\"PT0S\">" " mediaPresentationDuration=\"PT0S\">"
" <Period id=\"0\">" " <Period id=\"0\">"
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\"" " <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:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"" " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
" minBufferTime=\"PT2S\" type=\"static\""
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
" minBufferTime=\"PT2S\" type=\"static\""
" mediaPresentationDuration=\"PT0S\">" " mediaPresentationDuration=\"PT0S\">"
" <Period id=\"0\">" " <Period id=\"0\">"
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\"" " <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:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"" " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
" minBufferTime=\"PT2S\" type=\"static\""
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
" minBufferTime=\"PT2S\" type=\"static\""
" mediaPresentationDuration=\"PT0S\">" " mediaPresentationDuration=\"PT0S\">"
" <Period id=\"0\">" " <Period id=\"0\">"
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\"" " <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:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"" " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
" minBufferTime=\"PT2S\" type=\"static\""
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
" minBufferTime=\"PT2S\" type=\"static\""
" mediaPresentationDuration=\"PT0S\">" " mediaPresentationDuration=\"PT0S\">"
" <Period id=\"0\">" " <Period id=\"0\">"
" <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\"" " <AdaptationSet id=\"0\" contentType=\"video\" width=\"1920\""
@ -1853,13 +1841,13 @@ TEST_F(CommonMpdBuilderTest, UpdateToRemovePsshElement) {
} }
// Add one video check the output. // Add one video check the output.
TEST_F(StaticMpdBuilderTest, Video) { TEST_F(OnDemandMpdBuilderTest, Video) {
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
ASSERT_NO_FATAL_FAILURE(AddRepresentation(video_media_info)); ASSERT_NO_FATAL_FAILURE(AddRepresentation(video_media_info));
EXPECT_NO_FATAL_FAILURE(CheckMpd(kFileNameExpectedMpdOutputVideo1)); EXPECT_NO_FATAL_FAILURE(CheckMpd(kFileNameExpectedMpdOutputVideo1));
} }
TEST_F(StaticMpdBuilderTest, TwoVideosWithDifferentResolutions) { TEST_F(OnDemandMpdBuilderTest, TwoVideosWithDifferentResolutions) {
AdaptationSet* adaptation_set = mpd_.AddAdaptationSet(""); AdaptationSet* adaptation_set = mpd_.AddAdaptationSet("");
MediaInfo media_info1 = GetTestMediaInfo(kFileNameVideoMediaInfo1); MediaInfo media_info1 = GetTestMediaInfo(kFileNameVideoMediaInfo1);
@ -1872,7 +1860,7 @@ TEST_F(StaticMpdBuilderTest, TwoVideosWithDifferentResolutions) {
} }
// Add both video and audio and check the output. // Add both video and audio and check the output.
TEST_F(StaticMpdBuilderTest, VideoAndAudio) { TEST_F(OnDemandMpdBuilderTest, VideoAndAudio) {
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
MediaInfo audio_media_info = GetTestMediaInfo(kFileNameAudioMediaInfo1); MediaInfo audio_media_info = GetTestMediaInfo(kFileNameAudioMediaInfo1);
@ -1897,7 +1885,7 @@ TEST_F(StaticMpdBuilderTest, VideoAndAudio) {
// MPD schema has strict ordering. AudioChannelConfiguration must appear before // MPD schema has strict ordering. AudioChannelConfiguration must appear before
// ContentProtection. // ContentProtection.
// Also test that Representation::AddContentProtection() works. // Also test that Representation::AddContentProtection() works.
TEST_F(StaticMpdBuilderTest, AudioChannelConfigurationWithContentProtection) { TEST_F(OnDemandMpdBuilderTest, AudioChannelConfigurationWithContentProtection) {
const char kTestMediaInfo[] = const char kTestMediaInfo[] =
"bandwidth: 195857\n" "bandwidth: 195857\n"
"audio_info {\n" "audio_info {\n"
@ -1926,8 +1914,8 @@ TEST_F(StaticMpdBuilderTest, AudioChannelConfigurationWithContentProtection) {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"" " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
" minBufferTime=\"PT2S\" type=\"static\""
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
" minBufferTime=\"PT2S\" type=\"static\""
" mediaPresentationDuration=\"PT24.0094S\">" " mediaPresentationDuration=\"PT24.0094S\">"
" <Period id=\"0\">" " <Period id=\"0\">"
" <AdaptationSet id=\"0\" contentType=\"audio\">" " <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 // Static profile requires bandwidth to be set because it has no other way to
// get the bandwidth for the Representation. // get the bandwidth for the Representation.
TEST_F(StaticMpdBuilderTest, MediaInfoMissingBandwidth) { TEST_F(OnDemandMpdBuilderTest, MediaInfoMissingBandwidth) {
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
video_media_info.clear_bandwidth(); video_media_info.clear_bandwidth();
AddRepresentation(video_media_info); AddRepresentation(video_media_info);
@ -1981,7 +1969,7 @@ TEST_F(StaticMpdBuilderTest, MediaInfoMissingBandwidth) {
ASSERT_FALSE(mpd_.ToString(&mpd_doc)); ASSERT_FALSE(mpd_.ToString(&mpd_doc));
} }
TEST_F(StaticMpdBuilderTest, WriteToFile) { TEST_F(OnDemandMpdBuilderTest, WriteToFile) {
MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1);
AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet("");
ASSERT_TRUE(video_adaptation_set); ASSERT_TRUE(video_adaptation_set);
@ -2007,7 +1995,7 @@ TEST_F(StaticMpdBuilderTest, WriteToFile) {
} }
// Verify that a text path works. // Verify that a text path works.
TEST_F(StaticMpdBuilderTest, Text) { TEST_F(OnDemandMpdBuilderTest, Text) {
const char kTextMediaInfo[] = const char kTextMediaInfo[] =
"text_info {\n" "text_info {\n"
" format: 'ttml'\n" " format: 'ttml'\n"
@ -2026,8 +2014,8 @@ TEST_F(StaticMpdBuilderTest, Text) {
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\"" " xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\""
" minBufferTime=\"PT2S\" type=\"static\""
" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"" " profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
" minBufferTime=\"PT2S\" type=\"static\""
" mediaPresentationDuration=\"PT35S\">" " mediaPresentationDuration=\"PT35S\">"
" <Period id=\"0\">" " <Period id=\"0\">"
" <AdaptationSet id=\"0\" contentType=\"text\" lang=\"en\">" " <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. // Check whether the attributes are set correctly for dynamic <MPD> element.
// This test must use ASSERT_EQ for comparison because XmlEqual() cannot // This test must use ASSERT_EQ for comparison because XmlEqual() cannot
// handle namespaces correctly yet. // handle namespaces correctly yet.
TEST_F(DynamicMpdBuilderTest, CheckMpdAttributes) { TEST_F(LiveMpdBuilderTest, DynamicCheckMpdAttributes) {
static const char kExpectedOutput[] = static const char kExpectedOutput[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!--Generated with https://github.com/google/shaka-packager " "<!--Generated with https://github.com/google/shaka-packager "
@ -2068,15 +2056,40 @@ TEST_F(DynamicMpdBuilderTest, CheckMpdAttributes) {
"xsi:schemaLocation=" "xsi:schemaLocation="
"\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" " "\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" "
"xmlns:cenc=\"urn:mpeg:cenc:2013\" " "xmlns:cenc=\"urn:mpeg:cenc:2013\" "
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
"minBufferTime=\"PT2S\" " "minBufferTime=\"PT2S\" "
"type=\"dynamic\" " "type=\"dynamic\" "
"profiles=\"urn:mpeg:dash:profile:isoff-live:2011\" "
"publishTime=\"2016-01-11T15:10:24Z\" " "publishTime=\"2016-01-11T15:10:24Z\" "
"availabilityStartTime=\"2011-12-25T12:30:00\">\n" "availabilityStartTime=\"2011-12-25T12:30:00\">\n"
" <Period id=\"0\" start=\"PT0S\"/>\n" " <Period id=\"0\" start=\"PT0S\"/>\n"
"</MPD>\n"; "</MPD>\n";
std::string mpd_doc; 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_TRUE(mpd_.ToString(&mpd_doc));
ASSERT_EQ(kExpectedOutput, mpd_doc); ASSERT_EQ(kExpectedOutput, mpd_doc);
} }

View File

@ -15,24 +15,20 @@
#include <vector> #include <vector>
#include "packager/base/macros.h" #include "packager/base/macros.h"
#include "packager/mpd/base/mpd_options.h"
namespace shaka { namespace shaka {
class MediaInfo; class MediaInfo;
struct ContentProtectionElement; struct ContentProtectionElement;
enum DashProfile {
kUnknownProfile,
kOnDemandProfile,
kLiveProfile,
};
/// Interface for publish/subscribe publisher class which notifies MpdBuilder /// Interface for publish/subscribe publisher class which notifies MpdBuilder
/// of media-related events. /// of media-related events.
class MpdNotifier { class MpdNotifier {
public: public:
MpdNotifier(DashProfile dash_profile) : dash_profile_(dash_profile) {}; explicit MpdNotifier(const MpdOptions& mpd_options)
virtual ~MpdNotifier() {}; : mpd_options_(mpd_options) {}
virtual ~MpdNotifier() {}
/// Initializes the notifier. For example, if this notifier uses a network for /// Initializes the notifier. For example, if this notifier uses a network for
/// notification, then this would set up the connection with the remote host. /// notification, then this would set up the connection with the remote host.
@ -105,10 +101,13 @@ class MpdNotifier {
virtual bool Flush() = 0; virtual bool Flush() = 0;
/// @return The dash profile for this object. /// @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: private:
const DashProfile dash_profile_; const MpdOptions mpd_options_;
DISALLOW_COPY_AND_ASSIGN(MpdNotifier); DISALLOW_COPY_AND_ASSIGN(MpdNotifier);
}; };

View File

@ -11,27 +11,27 @@
namespace shaka { namespace shaka {
enum class DashProfile {
kUnknown,
kOnDemand,
kLive,
};
enum class MpdType { kStatic, kDynamic };
/// Defines Mpd Options. /// Defines Mpd Options.
struct MpdOptions { struct MpdOptions {
MpdOptions() DashProfile dash_profile = DashProfile::kOnDemand;
: availability_time_offset(0), MpdType mpd_type = MpdType::kStatic;
minimum_update_period(0), double availability_time_offset = 0;
double minimum_update_period = 0;
// TODO(tinskip): Set min_buffer_time in unit tests rather than here. // TODO(tinskip): Set min_buffer_time in unit tests rather than here.
min_buffer_time(2.0), double min_buffer_time = 2.0;
time_shift_buffer_depth(0), double time_shift_buffer_depth = 0;
suggested_presentation_delay(0) {} double 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;
std::string default_language; std::string default_language;
}; };
} // namespace shaka } // namespace shaka
#endif // MPD_BASE_MPD_OPTIONS_H_ #endif // MPD_BASE_MPD_OPTIONS_H_

View File

@ -14,17 +14,12 @@
namespace shaka { namespace shaka {
SimpleMpdNotifier::SimpleMpdNotifier(DashProfile dash_profile, SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options,
const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path) const std::string& output_path)
: MpdNotifier(dash_profile), : MpdNotifier(mpd_options),
output_path_(output_path), output_path_(output_path),
mpd_builder_(new MpdBuilder(dash_profile == kLiveProfile mpd_builder_(new MpdBuilder(mpd_options)) {
? MpdBuilder::kDynamic
: MpdBuilder::kStatic,
mpd_options)) {
DCHECK(dash_profile == kLiveProfile || dash_profile == kOnDemandProfile);
for (size_t i = 0; i < base_urls.size(); ++i) for (size_t i = 0; i < base_urls.size(); ++i)
mpd_builder_->AddBaseUrl(base_urls[i]); mpd_builder_->AddBaseUrl(base_urls[i]);
} }

View File

@ -30,8 +30,7 @@ struct MpdOptions;
/// generates an Mpd file. /// generates an Mpd file.
class SimpleMpdNotifier : public MpdNotifier { class SimpleMpdNotifier : public MpdNotifier {
public: public:
SimpleMpdNotifier(DashProfile dash_profile, SimpleMpdNotifier(const MpdOptions& mpd_options,
const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path); const std::string& output_path);
~SimpleMpdNotifier() override; ~SimpleMpdNotifier() override;

View File

@ -35,8 +35,7 @@ const char kValidMediaInfo[] =
const uint32_t kDefaultAdaptationSetId = 0u; const uint32_t kDefaultAdaptationSetId = 0u;
} // namespace } // namespace
class SimpleMpdNotifierTest class SimpleMpdNotifierTest : public ::testing::Test {
: public ::testing::TestWithParam<MpdBuilder::MpdType> {
protected: protected:
SimpleMpdNotifierTest() SimpleMpdNotifierTest()
: default_mock_adaptation_set_( : default_mock_adaptation_set_(
@ -51,20 +50,6 @@ class SimpleMpdNotifierTest
base::DeleteFile(temp_file_path_, false /* non recursive, just 1 file */); 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, void SetMpdBuilder(SimpleMpdNotifier* notifier,
std::unique_ptr<MpdBuilder> mpd_builder) { std::unique_ptr<MpdBuilder> mpd_builder) {
notifier->SetMpdBuilderForTesting(std::move(mpd_builder)); notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
@ -83,29 +68,12 @@ class SimpleMpdNotifierTest
base::FilePath temp_file_path_; 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. // Verify NotifyNewContainer() works as expected for VOD.
TEST_P(SimpleMpdNotifierTest, NotifyNewContainer) { TEST_F(SimpleMpdNotifierTest, NotifyNewContainer) {
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_, SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
empty_base_urls_, output_path_);
const uint32_t kRepresentationId = 1u; const uint32_t kRepresentationId = 1u;
const MpdBuilder::MpdType mpd_type = GetParam(); std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(
new MockMpdBuilder(mpd_type));
std::unique_ptr<MockRepresentation> mock_representation( std::unique_ptr<MockRepresentation> mock_representation(
new MockRepresentation(kRepresentationId)); new MockRepresentation(kRepresentationId));
@ -125,44 +93,11 @@ TEST_P(SimpleMpdNotifierTest, NotifyNewContainer) {
EXPECT_TRUE(notifier.Flush()); EXPECT_TRUE(notifier.Flush());
} }
// Verify NotifySampleDuration() works as expected for Live. TEST_F(SimpleMpdNotifierTest, NotifySampleDuration) {
TEST_F(SimpleMpdNotifierTest, LiveNotifySampleDuration) { SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
SimpleMpdNotifier notifier(kLiveProfile, empty_mpd_option_, empty_base_urls_,
output_path_);
const uint32_t kRepresentationId = 8u; const uint32_t kRepresentationId = 8u;
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));
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(&notifier, 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<MockRepresentation> mock_representation( std::unique_ptr<MockRepresentation> mock_representation(
new MockRepresentation(kRepresentationId)); new MockRepresentation(kRepresentationId));
@ -189,8 +124,7 @@ TEST_F(SimpleMpdNotifierTest, OnDemandNotifySampleDuration) {
// This issue identified a bug where using SimpleMpdNotifier with multiple // This issue identified a bug where using SimpleMpdNotifier with multiple
// threads causes a deadlock. // threads causes a deadlock.
TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) { TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_, SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
empty_base_urls_, output_path_);
uint32_t container_id; uint32_t container_id;
EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo), EXPECT_TRUE(notifier.NotifyNewContainer(ConvertToMediaInfo(kValidMediaInfo),
&container_id)); &container_id));
@ -199,13 +133,11 @@ TEST_F(SimpleMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
EXPECT_TRUE(notifier.Flush()); EXPECT_TRUE(notifier.Flush());
} }
// Verify that NotifyNewSegment() for live works. TEST_F(SimpleMpdNotifierTest, NotifyNewSegment) {
TEST_F(SimpleMpdNotifierTest, LiveNotifyNewSegment) { SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
SimpleMpdNotifier notifier(kLiveProfile, empty_mpd_option_, empty_base_urls_,
output_path_);
const uint32_t kRepresentationId = 447834u; 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( std::unique_ptr<MockRepresentation> mock_representation(
new MockRepresentation(kRepresentationId)); new MockRepresentation(kRepresentationId));
@ -230,13 +162,11 @@ TEST_F(SimpleMpdNotifierTest, LiveNotifyNewSegment) {
kSegmentDuration, kSegmentSize)); kSegmentDuration, kSegmentSize));
} }
// Verify AddContentProtectionElement() works. Profile doesn't matter.
TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) { TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_, SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
empty_base_urls_, output_path_);
const uint32_t kRepresentationId = 0u; 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( std::unique_ptr<MockRepresentation> mock_representation(
new MockRepresentation(kRepresentationId)); new MockRepresentation(kRepresentationId));
@ -256,7 +186,7 @@ TEST_F(SimpleMpdNotifierTest, AddContentProtectionElement) {
EXPECT_TRUE(notifier.AddContentProtectionElement(kRepresentationId, element)); EXPECT_TRUE(notifier.AddContentProtectionElement(kRepresentationId, element));
} }
TEST_P(SimpleMpdNotifierTest, UpdateEncryption) { TEST_F(SimpleMpdNotifierTest, UpdateEncryption) {
const char kProtectedContent[] = const char kProtectedContent[] =
"video_info {\n" "video_info {\n"
" codec: 'avc1'\n" " codec: 'avc1'\n"
@ -276,10 +206,9 @@ TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
" default_key_id: '_default_key_id_'\n" " default_key_id: '_default_key_id_'\n"
"}\n" "}\n"
"container_type: 1\n"; "container_type: 1\n";
SimpleMpdNotifier notifier(kLiveProfile, empty_mpd_option_, empty_base_urls_, SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
output_path_);
const uint32_t kRepresentationId = 447834u; 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( std::unique_ptr<MockRepresentation> mock_representation(
new MockRepresentation(kRepresentationId)); new MockRepresentation(kRepresentationId));
@ -312,7 +241,7 @@ TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
} }
// Don't put different audio languages or codecs in the same AdaptationSet. // Don't put different audio languages or codecs in the same AdaptationSet.
TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) { TEST_F(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
// MP4, English // MP4, English
const char kAudioContent1[] = const char kAudioContent1[] =
"audio_info {\n" "audio_info {\n"
@ -365,9 +294,8 @@ TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
"container_type: CONTAINER_WEBM\n" "container_type: CONTAINER_WEBM\n"
"media_duration_seconds: 10.5\n"; "media_duration_seconds: 10.5\n";
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_, SimpleMpdNotifier notifier(empty_mpd_option_, empty_base_urls_, output_path_);
empty_base_urls_, output_path_); std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(StaticMpdBuilderMock());
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1)); std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2)); std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
@ -410,9 +338,4 @@ TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
ConvertToMediaInfo(kAudioContent4), &unused_container_id)); ConvertToMediaInfo(kAudioContent4), &unused_container_id));
} }
INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
SimpleMpdNotifierTest,
::testing::Values(MpdBuilder::kStatic,
MpdBuilder::kDynamic));
} // namespace shaka } // namespace shaka

View File

@ -35,12 +35,11 @@ class DashIopMpdNotifierFactory : public MpdNotifierFactory {
DashIopMpdNotifierFactory() {} DashIopMpdNotifierFactory() {}
~DashIopMpdNotifierFactory() override {} ~DashIopMpdNotifierFactory() override {}
std::unique_ptr<MpdNotifier> Create(DashProfile dash_profile, std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path) override { const std::string& output_path) override {
return std::unique_ptr<MpdNotifier>(new DashIopMpdNotifier( return std::unique_ptr<MpdNotifier>(
dash_profile, mpd_options, base_urls, output_path)); new DashIopMpdNotifier(mpd_options, base_urls, output_path));
} }
}; };
@ -50,12 +49,11 @@ class SimpleMpdNotifierFactory : public MpdNotifierFactory {
SimpleMpdNotifierFactory() {} SimpleMpdNotifierFactory() {}
~SimpleMpdNotifierFactory() override {} ~SimpleMpdNotifierFactory() override {}
std::unique_ptr<MpdNotifier> Create(DashProfile dash_profile, std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path) override { const std::string& output_path) override {
return std::unique_ptr<MpdNotifier>(new SimpleMpdNotifier( return std::unique_ptr<MpdNotifier>(
dash_profile, mpd_options, base_urls, output_path)); 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) { bool MpdWriter::WriteMpdToFile(const char* file_name) {
CHECK(file_name); CHECK(file_name);
std::unique_ptr<MpdNotifier> notifier = notifier_factory_->Create( std::unique_ptr<MpdNotifier> notifier =
kOnDemandProfile, MpdOptions(), base_urls_, file_name); notifier_factory_->Create(MpdOptions(), base_urls_, file_name);
if (!notifier->Init()) { if (!notifier->Init()) {
LOG(ERROR) << "failed to initialize MpdNotifier."; LOG(ERROR) << "failed to initialize MpdNotifier.";
return false; return false;

View File

@ -35,7 +35,6 @@ class MpdNotifierFactory {
virtual ~MpdNotifierFactory() {} virtual ~MpdNotifierFactory() {}
virtual std::unique_ptr<MpdNotifier> Create( virtual std::unique_ptr<MpdNotifier> Create(
DashProfile dash_profile,
const MpdOptions& mpd_options, const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path) = 0; const std::string& output_path) = 0;

View File

@ -33,14 +33,13 @@ class TestMpdNotifierFactory : public MpdNotifierFactory {
// std::unique_ptr. // std::unique_ptr.
// For now we only need to return MockMpdNotifier() with these set of // For now we only need to return MockMpdNotifier() with these set of
// expectations for all the tests. // expectations for all the tests.
std::unique_ptr<MpdNotifier> Create(DashProfile dash_profile, std::unique_ptr<MpdNotifier> Create(const MpdOptions& mpd_options,
const MpdOptions& mpd_options,
const std::vector<std::string>& base_urls, const std::vector<std::string>& base_urls,
const std::string& output_path) override { const std::string& output_path) override {
EXPECT_EQ(expected_base_urls_, base_urls); EXPECT_EQ(expected_base_urls_, base_urls);
std::unique_ptr<MockMpdNotifier> mock_notifier( 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, Init()).WillOnce(Return(true));
EXPECT_CALL(*mock_notifier, NotifyNewContainer(_, _)) EXPECT_CALL(*mock_notifier, NotifyNewContainer(_, _))