Skip to content

Commit

Permalink
feat: order streams in manifest based on command-line order (#1329)
Browse files Browse the repository at this point in the history
This will force the muxer to order streams in the order given on the
command-line.

Closes #560
Closes #1280
Closes #1313

---------

Co-authored-by: Joey Parrish <[email protected]>
Co-authored-by: Cosmin Stejerean <[email protected]>
  • Loading branch information
3 people authored Feb 14, 2024
1 parent df04d0e commit aad2a12
Show file tree
Hide file tree
Showing 94 changed files with 980 additions and 584 deletions.
7 changes: 6 additions & 1 deletion docs/source/options/dash_options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,9 @@ DASH options
--low_latency_dash_mode

If enabled, LL-DASH streaming will be used,
reducing overall latency by decoupling latency from segment duration.
reducing overall latency by decoupling latency from segment duration.

--force_cl_index

True forces the muxer to order streams in the order given
on the command-line. False uses the previous unordered behavior.
5 changes: 5 additions & 0 deletions docs/source/options/hls_options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,8 @@ HLS options

Optional. Defaults to 0 if not specified. If it is set to 1, indicates the
stream is HLS only.

--force_cl_index

True forces the muxer to order streams in the order given
on the command-line. False uses the previous unordered behavior.
5 changes: 5 additions & 0 deletions include/packager/packager.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>

Expand Down Expand Up @@ -62,6 +63,7 @@ struct PackagingParams {
/// Only use a single thread to generate output. This is useful in tests to
/// avoid non-deterministic outputs.
bool single_threaded = false;

/// DASH MPD related parameters.
MpdParams mpd_params;
/// HLS related parameters.
Expand All @@ -80,6 +82,9 @@ struct PackagingParams {

/// Defines a single input/output stream.
struct StreamDescriptor {
/// index of the stream to enforce ordering
std::optional<uint32_t> index;

/// Input/source media file path or network stream URL. Required.
std::string input;

Expand Down
5 changes: 5 additions & 0 deletions packager/app/manifest_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ ABSL_FLAG(std::string,
"",
"Same as above, but this applies to text tracks only, and "
"overrides the default language for text tracks.");
ABSL_FLAG(bool,
force_cl_index,
true,
"True forces the muxer to order streams in the order given "
"on the command-line. False uses the previous unordered behavior.");
1 change: 1 addition & 0 deletions packager/app/manifest_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ ABSL_DECLARE_FLAG(double, time_shift_buffer_depth);
ABSL_DECLARE_FLAG(uint64_t, preserved_segments_outside_live_window);
ABSL_DECLARE_FLAG(std::string, default_language);
ABSL_DECLARE_FLAG(std::string, default_text_language);
ABSL_DECLARE_FLAG(bool, force_cl_index);

#endif // PACKAGER_APP_MANIFEST_FLAGS_H_
8 changes: 8 additions & 0 deletions packager/app/packager_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,14 @@ int PackagerMain(int argc, char** argv) {
return kArgumentValidationFailed;
stream_descriptors.push_back(stream_descriptor.value());
}

if (absl::GetFlag(FLAGS_force_cl_index)) {
int index = 0;
for (auto& descriptor : stream_descriptors) {
descriptor.index = index++;
}
}

Packager packager;
Status status =
packager.Initialize(packaging_params.value(), stream_descriptors);
Expand Down
50 changes: 49 additions & 1 deletion packager/app/test/packager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,9 @@ def _GetFlags(self,
segment_duration=1.0,
use_fake_clock=True,
allow_codec_switching=False,
dash_force_segment_list=False):
dash_force_segment_list=False,
force_cl_index=False):

flags = ['--single_threaded']

if not strip_parameter_set_nalus:
Expand Down Expand Up @@ -558,6 +560,9 @@ def _GetFlags(self,
if allow_codec_switching:
flags += ['--allow_codec_switching']

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

if ad_cues:
flags += ['--ad_cues', ad_cues]

Expand Down Expand Up @@ -1657,6 +1662,49 @@ def testAllowCodecSwitchingWithEncryptionAndTrickplay(self):
self._CheckTestResults(
'audio-video-with-codec-switching-encryption-trick-play')

def testForcedCommandlineOrdering(self):
streams = [
self._GetStream('text', test_file='bear-english.vtt'),
self._GetStream('audio', test_file='bear-640x360.mp4'),
self._GetStream('video', test_file='bear-640x360-hevc.mp4'),
self._GetStream('video', test_file='bear-1280x720.mp4'),
self._GetStream('video', test_file='bear-640x360.mp4'),
]

self.assertPackageSuccess(streams,
self._GetFlags(output_dash=True, output_hls=True,
force_cl_index=True))
self._CheckTestResults('forced-commandline-ordering')

def testAllowCodecSwitchingWithCommandlineOrdering(self):
streams = [
self._GetStream('audio', test_file='bear-640x360.mp4'),
self._GetStream('video', test_file='bear-640x360-hevc.mp4'),
self._GetStream('video', test_file='bear-640x360.mp4'),
self._GetStream('video', test_file='bear-1280x720.mp4'),
]

self.assertPackageSuccess(streams,
self._GetFlags(output_dash=True,
allow_codec_switching=True,
force_cl_index=True))
self._CheckTestResults(
'audio-video-with-codec-switching-and-forced-commandline_order')

def testAudioVideoWithTrickPlayAndCommandlineOrdering(self):
streams = [
self._GetStream('audio', test_file='bear-640x360.mp4'),
self._GetStream('video', test_file='bear-640x360-hevc.mp4'),
self._GetStream('video', test_file='bear-640x360.mp4'),
self._GetStream('video', test_file='bear-1280x720.mp4',
trick_play_factor=1),
]

self.assertPackageSuccess(streams, self._GetFlags(output_dash=True,
force_cl_index=True))
self._CheckTestResults(
'audio-video-with-trick-play-and-forced-commandline-order')

def testLiveProfileAndEncryption(self):
self.assertPackageSuccess(
self._GetStreams(['audio', 'video'], segmented=True),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
<!--Generated with https:/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.736067S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<Representation id="0" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="870-937" timescale="30000">
<Initialization range="0-869"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
<AdaptationSet id="0" contentType="audio" subsegmentAlignment="true">
<Accessibility schemeIdUri="urn:tva:metadata:cs:AudioPurposeCS:2007" value="1"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="description"/>
<Representation id="1" bandwidth="133334" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<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="804-871" timescale="44100">
<Initialization range="0-803"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<Representation id="1" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="870-937" timescale="30000">
<Initialization range="0-869"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="2" contentType="text" subsegmentAlignment="true">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="caption"/>
<Representation id="2" bandwidth="317" mimeType="text/vtt">
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https:/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.8028S">
<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="804-871" timescale="44100">
<Initialization range="0-803"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="2"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="1" bandwidth="277411" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-hevc-video.mp4</BaseURL>
<SegmentBase indexRange="1910-1977" timescale="30000">
<Initialization range="0-1909"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="2" contentType="video" maxWidth="1280" maxHeight="720" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="1"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="2" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="870-937" timescale="30000">
<Initialization range="0-869"/>
</SegmentBase>
</Representation>
<Representation id="3" bandwidth="2627285" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" width="1280" height="720">
<BaseURL>bear-1280x720-video.mp4</BaseURL>
<SegmentBase indexRange="869-936" timescale="30000">
<Initialization range="0-868"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,50 @@
<!--Generated with https:/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.8028S">
<Period id="0">
<AdaptationSet id="0" contentType="video" maxWidth="1280" maxHeight="720" 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 schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
</ContentProtection>
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="2"/>
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="1"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="0" bandwidth="2631545" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" width="1280" height="720">
<BaseURL>bear-1280x720-video.mp4</BaseURL>
<SegmentBase indexRange="1136-1203" timescale="30000">
<Initialization range="0-1135"/>
</SegmentBase>
</Representation>
<Representation id="3" bandwidth="977743" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="1138-1205" timescale="30000">
<Initialization range="0-1137"/>
<Representation id="0" bandwidth="281671" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-hevc-video.mp4</BaseURL>
<SegmentBase indexRange="3222-3289" timescale="30000">
<Initialization range="0-3221"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" width="1280" height="720" frameRate="30000/30030" subsegmentAlignment="true" par="16:9">
<AdaptationSet id="1" contentType="video" maxWidth="1280" maxHeight="720" 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 schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
</ContentProtection>
<EssentialProperty schemeIdUri="http://dashif.org/guidelines/trickmode" value="0"/>
<Representation id="1" bandwidth="470530" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" maxPlayoutRate="30" codingDependency="false">
<BaseURL>bear-1280x720-video-trick_play_factor_1.mp4</BaseURL>
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="0"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="1" bandwidth="977743" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="1138-1205" timescale="30000">
<Initialization range="0-1137"/>
</SegmentBase>
</Representation>
<Representation id="2" bandwidth="2631545" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" width="1280" height="720">
<BaseURL>bear-1280x720-video.mp4</BaseURL>
<SegmentBase indexRange="1136-1203" timescale="30000">
<Initialization range="0-1135"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="2" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<AdaptationSet id="2" contentType="video" width="1280" height="720" frameRate="30000/30030" subsegmentAlignment="true" par="16:9">
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
</ContentProtection>
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="0"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="2" bandwidth="281671" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-hevc-video.mp4</BaseURL>
<SegmentBase indexRange="3222-3289" timescale="30000">
<Initialization range="0-3221"/>
<EssentialProperty schemeIdUri="http://dashif.org/guidelines/trickmode" value="1"/>
<Representation id="3" bandwidth="470530" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" maxPlayoutRate="30" codingDependency="false">
<BaseURL>bear-1280x720-video-trick_play_factor_1.mp4</BaseURL>
<SegmentBase indexRange="1136-1203" timescale="30000">
<Initialization range="0-1135"/>
</SegmentBase>
</Representation>
</AdaptationSet>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@
<!--Generated with https:/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.8028S">
<Period id="0">
<AdaptationSet id="0" contentType="video" maxWidth="1280" maxHeight="720" 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">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="1"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="0" bandwidth="2627285" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" width="1280" height="720">
<BaseURL>bear-1280x720-video.mp4</BaseURL>
<SegmentBase indexRange="869-936" timescale="30000">
<Initialization range="0-868"/>
<Representation id="0" bandwidth="277411" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-hevc-video.mp4</BaseURL>
<SegmentBase indexRange="1910-1977" timescale="30000">
<Initialization range="0-1909"/>
</SegmentBase>
</Representation>
<Representation id="2" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
</AdaptationSet>
<AdaptationSet id="1" contentType="video" maxWidth="1280" maxHeight="720" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="0"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="1" bandwidth="973483" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1" width="640" height="360">
<BaseURL>bear-640x360-video.mp4</BaseURL>
<SegmentBase indexRange="870-937" timescale="30000">
<Initialization range="0-869"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="0"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation id="1" bandwidth="277411" codecs="hev1.1.6.L63.90" mimeType="video/mp4" sar="1:1">
<BaseURL>bear-640x360-hevc-video.mp4</BaseURL>
<SegmentBase indexRange="1910-1977" timescale="30000">
<Initialization range="0-1909"/>
<Representation id="2" bandwidth="2627285" codecs="avc1.64001f" mimeType="video/mp4" sar="1:1" width="1280" height="720">
<BaseURL>bear-1280x720-video.mp4</BaseURL>
<SegmentBase indexRange="869-936" timescale="30000">
<Initialization range="0-868"/>
</SegmentBase>
</Representation>
</AdaptationSet>
Expand Down
Loading

0 comments on commit aad2a12

Please sign in to comment.