Support dash_only and hls_only parameters (#721)
This allows conditional stream descriptors which apply to DASH or HLS only. Closes #651.
This commit is contained in:
parent
055c67888b
commit
a1dd82d478
1
AUTHORS
1
AUTHORS
|
@ -23,5 +23,6 @@ More Screens Ltd. <*@morescreens.net>
|
|||
Philo Inc. <*@philo.com>
|
||||
Piotr Srebrny <srebrny.piotr@gmail.com>
|
||||
Richard Eklycke <richard@eklycke.se>
|
||||
Sanil Raut <sr1990003@gmail.com>
|
||||
Sergio Ammirata <sergio@ammirata.net>
|
||||
The Chromium Authors <*@chromium.org>
|
||||
|
|
|
@ -37,5 +37,6 @@ Leo Law <leoltlaw.gh@gmail.com>
|
|||
Piotr Srebrny <srebrny.piotr@gmail.com>
|
||||
Richard Eklycke <richard@eklycke.se>
|
||||
Rintaro Kuroiwa <rkuroiwa@google.com>
|
||||
Sanil Raut <sr1990003@gmail.com>
|
||||
Sergio Ammirata <sergio@ammirata.net>
|
||||
Thomas Inskip <tinskip@google.com>
|
||||
|
|
|
@ -85,3 +85,8 @@ DASH options
|
|||
|
||||
Ignored if $Time$ is used in segment template, since $Time$ requires
|
||||
accurate Segment Timeline.
|
||||
|
||||
--dash_only=0|1
|
||||
|
||||
Optional. Defaults to 0 if not specified. If it is set to 1, indicates the
|
||||
stream is DASH only.
|
||||
|
|
|
@ -75,3 +75,8 @@ HLS options
|
|||
|
||||
The EXT-X-MEDIA-SEQUENCE documentation can be read here:
|
||||
https://tools.ietf.org/html/rfc8216#section-4.3.3.2.
|
||||
|
||||
--hls_only=0|1
|
||||
|
||||
Optional. Defaults to 0 if not specified. If it is set to 1, indicates the
|
||||
stream is HLS only.
|
||||
|
|
|
@ -11,3 +11,21 @@
|
|||
|
||||
The above packaging command creates five single file MP4 streams, and HLS
|
||||
playlists as well as DASH manifests.
|
||||
|
||||
* Output DASH + HLS with dash_only and hls_only options
|
||||
|
||||
$ packager \
|
||||
'in=h264_baseline_360p_600.mp4,stream=audio,init_segment=audio/init.mp4,segment_template=audio/$Number$.m4s' \
|
||||
'in=input_text.vtt,stream=text,init_segment=text/init.mp4,segment_template=text/$Number$.m4s,dash_only=true' \
|
||||
'in=input_text.vtt,stream=text,segment_template=text/$Number$.vtt,hls_only=true' \
|
||||
'in=h264_baseline_360p_600.mp4,stream=video,init_segment=h264_360p/init.mp4,segment_template=h264_360p/$Number$.m4s' \
|
||||
'in=h264_main_480p_1000.mp4,stream=video,init_segment=h264_480p/init.mp4,segment_template=h264_480p/$Number$.m4s' \
|
||||
'in=h264_main_720p_3000.mp4,stream=video,init_segment=h264_720p/init.mp4,segment_template=h264_720p/$Number$.m4s' \
|
||||
'in=h264_high_1080p_6000.mp4,stream=video,init_segment=h264_1080p/init.mp4,segment_template=h264_1080p/$Number$.m4s' \
|
||||
--generate_static_live_mpd --mpd_output h264.mpd \
|
||||
--hls_master_playlist_output h264_master.m3u8
|
||||
|
||||
The above packaging command creates HLS playlists and DASH manifest while using
|
||||
dash_only for creating segmented WebVTT in mp4 format and hls_only option for
|
||||
creating WebVTT in text format.
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ enum FieldType {
|
|||
kHlsCharacteristicsField,
|
||||
kDashAccessiblitiesField,
|
||||
kDashRolesField,
|
||||
kDashOnlyField,
|
||||
kHlsOnlyField,
|
||||
};
|
||||
|
||||
struct FieldNameToTypeMapping {
|
||||
|
@ -77,6 +79,8 @@ const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
|
|||
{"dash_role", kDashRolesField},
|
||||
{"roles", kDashRolesField},
|
||||
{"role", kDashRolesField},
|
||||
{"dash_only", kDashOnlyField},
|
||||
{"hls_only", kHlsOnlyField},
|
||||
};
|
||||
|
||||
FieldType GetFieldType(const std::string& field_name) {
|
||||
|
@ -206,6 +210,32 @@ base::Optional<StreamDescriptor> ParseStreamDescriptor(
|
|||
base::SplitString(iter->second, ";", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
break;
|
||||
case kDashOnlyField:
|
||||
unsigned dash_only_value;
|
||||
if (!base::StringToUint(iter->second, &dash_only_value)) {
|
||||
LOG(ERROR) << "Non-numeric option for dash_only field "
|
||||
"specified (" << iter->second << ").";
|
||||
return base::nullopt;
|
||||
}
|
||||
if (dash_only_value > 1) {
|
||||
LOG(ERROR) << "dash_only should be either 0 or 1.";
|
||||
return base::nullopt;
|
||||
}
|
||||
descriptor.dash_only = dash_only_value > 0;
|
||||
break;
|
||||
case kHlsOnlyField:
|
||||
unsigned hls_only_value;
|
||||
if (!base::StringToUint(iter->second, &hls_only_value)) {
|
||||
LOG(ERROR) << "Non-numeric option for hls_only field "
|
||||
"specified (" << iter->second << ").";
|
||||
return base::nullopt;
|
||||
}
|
||||
if (hls_only_value > 1) {
|
||||
LOG(ERROR) << "hls_only should be either 0 or 1.";
|
||||
return base::nullopt;
|
||||
}
|
||||
descriptor.hls_only = hls_only_value > 0;
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first
|
||||
<< "\").";
|
||||
|
|
|
@ -275,8 +275,10 @@ class PackagerAppTest(unittest.TestCase):
|
|||
using_time_specifier=False,
|
||||
hls=False,
|
||||
hls_characteristics=None,
|
||||
hls_only=None,
|
||||
dash_accessibilities=None,
|
||||
dash_roles=None,
|
||||
dash_only=None,
|
||||
trick_play_factor=None,
|
||||
drm_label=None,
|
||||
skip_encryption=None,
|
||||
|
@ -303,8 +305,10 @@ class PackagerAppTest(unittest.TestCase):
|
|||
$Number$. This flag is only relevant if segmented is True.
|
||||
hls: Should the output be for an HLS manifest.
|
||||
hls_characteristics: CHARACTERISTICS attribute for the HLS stream.
|
||||
hls_only: If set to true, will indicate that the stream is for HLS only.
|
||||
dash_accessibilities: Accessibility element for the DASH stream.
|
||||
dash_roles: Role element for the DASH stream.
|
||||
dash_only: If set to true, will indicate that the stream is for DASH only.
|
||||
trick_play_factor: Signals the stream is to be used for a trick play
|
||||
stream and which key frames to use. A trick play factor of 0 is the
|
||||
same as not specifying a trick play factor.
|
||||
|
@ -360,11 +364,17 @@ class PackagerAppTest(unittest.TestCase):
|
|||
if hls_characteristics:
|
||||
stream.Append('hls_characteristics', hls_characteristics)
|
||||
|
||||
if hls_only:
|
||||
stream.Append('hls_only', 1)
|
||||
|
||||
if dash_accessibilities:
|
||||
stream.Append('dash_accessibilities', dash_accessibilities)
|
||||
if dash_roles:
|
||||
stream.Append('dash_roles', dash_roles)
|
||||
|
||||
if dash_only:
|
||||
stream.Append('dash_only', 1)
|
||||
|
||||
requires_init_segment = segmented and base_ext not in [
|
||||
'aac', 'ac3', 'ec3', 'ts', 'vtt'
|
||||
]
|
||||
|
@ -700,6 +710,14 @@ class PackagerFunctionalTest(PackagerAppTest):
|
|||
# order of trick play factors gets the same mpd.
|
||||
self._CheckTestResults('audio-video-with-two-trick-play')
|
||||
|
||||
def testDashOnlyAndHlsOnly(self):
|
||||
streams = [
|
||||
self._GetStream('video', hls_only=True),
|
||||
self._GetStream('audio', dash_only=True),
|
||||
]
|
||||
self.assertPackageSuccess(streams, self._GetFlags(output_dash=True,output_hls=True))
|
||||
self._CheckTestResults('hls-only-dash-only')
|
||||
|
||||
def testAudioVideoWithLanguageOverride(self):
|
||||
self.assertPackageSuccess(
|
||||
self._GetStreams(['audio', 'video'], language='por', hls=True),
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
#EXTM3U
|
||||
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||
|
||||
#EXT-X-STREAM-INF:BANDWIDTH=973483,AVERAGE-BANDWIDTH=879459,CODECS="avc1.64001e",RESOLUTION=640x360,FRAME-RATE=29.970
|
||||
stream_1.m3u8
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.739954710006714S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="audio" subsegmentAlignment="true">
|
||||
<Representation id="0" bandwidth="133334" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||
<BaseURL>bear-640x360-audio.mp4</BaseURL>
|
||||
<SegmentBase indexRange="793-860" timescale="44100">
|
||||
<Initialization range="0-792"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
|
@ -0,0 +1,16 @@
|
|||
#EXTM3U
|
||||
#EXT-X-VERSION:6
|
||||
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||
#EXT-X-TARGETDURATION:2
|
||||
#EXT-X-PLAYLIST-TYPE:VOD
|
||||
#EXT-X-MAP:URI="bear-640x360-video.mp4",BYTERANGE="859@0"
|
||||
#EXTINF:1.001,
|
||||
#EXT-X-BYTERANGE:99313@927
|
||||
bear-640x360-video.mp4
|
||||
#EXTINF:1.001,
|
||||
#EXT-X-BYTERANGE:121807
|
||||
bear-640x360-video.mp4
|
||||
#EXTINF:0.734,
|
||||
#EXT-X-BYTERANGE:79662
|
||||
bear-640x360-video.mp4
|
||||
#EXT-X-ENDLIST
|
|
@ -105,11 +105,13 @@ std::unique_ptr<MuxerListener> MuxerListenerFactory::CreateListener(
|
|||
combined_listener->AddListener(
|
||||
CreateMediaInfoDumpListenerInternal(stream.media_info_output));
|
||||
}
|
||||
if (mpd_notifier_) {
|
||||
|
||||
if (mpd_notifier_ && !stream.hls_only) {
|
||||
combined_listener->AddListener(
|
||||
CreateMpdListenerInternal(stream, mpd_notifier_));
|
||||
}
|
||||
if (hls_notifier_) {
|
||||
|
||||
if (hls_notifier_ && !stream.dash_only) {
|
||||
for (auto& listener :
|
||||
CreateHlsListenersInternal(stream, stream_index, hls_notifier_)) {
|
||||
combined_listener->AddListener(std::move(listener));
|
||||
|
|
|
@ -46,11 +46,13 @@ class MuxerListenerFactory {
|
|||
std::string hls_playlist_name;
|
||||
std::string hls_iframe_playlist_name;
|
||||
std::vector<std::string> hls_characteristics;
|
||||
bool hls_only = false;
|
||||
|
||||
// DASH specific values needed to write DASH mpd. Will only be used if an
|
||||
// MpdNotifier is given to the factory.
|
||||
std::vector<std::string> dash_accessiblities;
|
||||
std::vector<std::string> dash_roles;
|
||||
bool dash_only = false;
|
||||
};
|
||||
|
||||
/// Create a new muxer listener.
|
||||
|
|
|
@ -93,9 +93,11 @@ MuxerListenerFactory::StreamData ToMuxerListenerData(
|
|||
data.hls_playlist_name = stream.hls_playlist_name;
|
||||
data.hls_iframe_playlist_name = stream.hls_iframe_playlist_name;
|
||||
data.hls_characteristics = stream.hls_characteristics;
|
||||
data.hls_only = stream.hls_only;
|
||||
|
||||
data.dash_accessiblities = stream.dash_accessiblities;
|
||||
data.dash_roles = stream.dash_roles;
|
||||
data.dash_only = stream.dash_only;
|
||||
return data;
|
||||
};
|
||||
|
||||
|
|
|
@ -128,6 +128,11 @@ struct StreamDescriptor {
|
|||
std::vector<std::string> dash_accessiblities;
|
||||
/// Optional for DASH output. It defines Role elements of the stream.
|
||||
std::vector<std::string> dash_roles;
|
||||
|
||||
/// Set to true to indicate that the stream is for dash only.
|
||||
bool dash_only = false;
|
||||
/// Set to true to indicate that the stream is for hls only.
|
||||
bool hls_only = false;
|
||||
};
|
||||
|
||||
class SHAKA_EXPORT Packager {
|
||||
|
|
Loading…
Reference in New Issue