Skip to content

Commit

Permalink
[DASH] Specify initial sequence number.
Browse files Browse the repository at this point in the history
  • Loading branch information
sr1990 committed Jan 9, 2021
1 parent 96ec68b commit 89983c1
Show file tree
Hide file tree
Showing 18 changed files with 85 additions and 4 deletions.
5 changes: 5 additions & 0 deletions docs/source/options/mp4_output_options.rst
Expand Up @@ -17,3 +17,8 @@ MP4 output options
template).

Default enabled.

--mp4_initial_sequence_number

MP4 only: Sets the initialize sequence number in the mp4 moof->mfhd.
Otherwise defaults to -1.
4 changes: 4 additions & 0 deletions packager/app/muxer_flags.cc
Expand Up @@ -53,3 +53,7 @@ DEFINE_int32(transport_stream_timestamp_offset_ms,
"input. For example, timestamps from ISO-BMFF after adjusted by "
"EditList could be negative. In transport streams, timestamps are "
"not allowed to be less than zero.");
DEFINE_int32(mp4_initial_sequence_number,
-1,
"Sets the initialize sequence number in the mp4 moof->mfhd. "
"Otherwise defaults to -1.");
1 change: 1 addition & 0 deletions packager/app/muxer_flags.h
Expand Up @@ -20,5 +20,6 @@ DECLARE_bool(generate_sidx_in_media_segments);
DECLARE_string(temp_dir);
DECLARE_bool(mp4_include_pssh_in_stream);
DECLARE_int32(transport_stream_timestamp_offset_ms);
DECLARE_int32(mp4_initial_sequence_number);

#endif // APP_MUXER_FLAGS_H_
1 change: 1 addition & 0 deletions packager/app/packager_main.cc
Expand Up @@ -441,6 +441,7 @@ base::Optional<PackagingParams> GetPackagingParams() {
mp4_params.generate_sidx_in_media_segments =
FLAGS_generate_sidx_in_media_segments;
mp4_params.include_pssh_in_stream = FLAGS_mp4_include_pssh_in_stream;
mp4_params.initial_sequence_number = FLAGS_mp4_initial_sequence_number;

packaging_params.transport_stream_timestamp_offset_ms =
FLAGS_transport_stream_timestamp_offset_ms;
Expand Down
16 changes: 14 additions & 2 deletions packager/app/test/packager_test.py
Expand Up @@ -478,7 +478,8 @@ def _GetFlags(self,
default_language=None,
segment_duration=1.0,
use_fake_clock=True,
allow_codec_switching=False):
allow_codec_switching=False,
mp4_initial_sequence_number=-1):
flags = ['--single_threaded']

if not strip_parameter_set_nalus:
Expand Down Expand Up @@ -561,7 +562,11 @@ def _GetFlags(self,

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


if mp4_initial_sequence_number != -1:
flags += ['--mp4_initial_sequence_number={0}'.format(
mp4_initial_sequence_number)]

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

Expand Down Expand Up @@ -771,6 +776,13 @@ def testDashOnlyAndHlsOnlyWithCaptions(self):
output_hls=True))
self._CheckTestResults('hls-only-dash-only-captions')

def testMp4InitialSequenceNumber(self):
audio_video_streams = self._GetStreams(['audio', 'video'], segmented=True)
streams = audio_video_streams
self.assertPackageSuccess(streams, self._GetFlags(output_dash=True,
mp4_initial_sequence_number=15))
self._CheckTestResults('dash-mp4-initial-sequence-number')

def testDashOnlyAndHlsOnly(self):
streams = [
self._GetStream('video', hls_only=True),
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
<?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-live:2011" minBufferTime="PT2S" type="dynamic" publishTime="some_time" availabilityStartTime="some_time" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
<Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" segmentAlignment="true" par="16:9">
<Representation id="0" bandwidth="974154" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
<SegmentTemplate timescale="30000" initialization="bear-640x360-video-init.mp4" media="bear-640x360-video-$Number$.m4s" startNumber="15">
<SegmentTimeline>
<S t="0" d="30030" r="1"/>
<S t="60060" d="22022"/>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" segmentAlignment="true">
<Representation id="1" bandwidth="133961" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<SegmentTemplate timescale="44100" initialization="bear-640x360-audio-init.mp4" media="bear-640x360-audio-$Number$.m4s" startNumber="15">
<SegmentTimeline>
<S t="0" d="45056"/>
<S t="45056" d="44032"/>
<S t="89088" d="31744"/>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>
21 changes: 20 additions & 1 deletion packager/media/formats/mp4/multi_segment_segmenter.cc
Expand Up @@ -29,6 +29,7 @@ MultiSegmentSegmenter::MultiSegmentSegmenter(const MuxerOptions& options,
std::unique_ptr<Movie> moov)
: Segmenter(options, std::move(ftyp), std::move(moov)),
styp_(new SegmentType) {
num_segments_ = options.mp4_params.initial_sequence_number;
// Use the same brands for styp as ftyp.
styp_->major_brand = Segmenter::ftyp()->major_brand;
styp_->compatible_brands = Segmenter::ftyp()->compatible_brands;
Expand Down Expand Up @@ -109,9 +110,18 @@ Status MultiSegmentSegmenter::WriteSegment(int64_t segment_index) {
options().output_file_name);
}
} else {
file_name = GetSegmentName(options().segment_template,

// Get segment name from num_segments if valid.
if (num_segments_ == -1) {
file_name = GetSegmentName(options().segment_template,
sidx()->earliest_presentation_time,
segment_index, options().bandwidth);
} else {
file_name = GetSegmentName(options().segment_template,
sidx()->earliest_presentation_time,
num_segments_-1, options().bandwidth);
}

file.reset(File::Open(file_name.c_str(), "w"));
if (!file) {
return Status(error::FILE_FAILURE,
Expand Down Expand Up @@ -156,9 +166,18 @@ Status MultiSegmentSegmenter::WriteSegment(int64_t segment_index) {
UpdateProgress(segment_duration);
if (muxer_listener()) {
muxer_listener()->OnSampleDurationReady(sample_duration());
if (num_segments_ == -1) {
muxer_listener()->OnNewSegment(
file_name, sidx()->earliest_presentation_time, segment_duration,
segment_size, segment_index);
} else {
muxer_listener()->OnNewSegment(
file_name, sidx()->earliest_presentation_time, segment_duration,
segment_size, num_segments_-1);

num_segments_++;

}
}

return Status::OK;
Expand Down
2 changes: 2 additions & 0 deletions packager/media/formats/mp4/multi_segment_segmenter.h
Expand Up @@ -46,6 +46,8 @@ class MultiSegmentSegmenter : public Segmenter {

std::unique_ptr<SegmentType> styp_;

int32_t num_segments_;

DISALLOW_COPY_AND_ASSIGN(MultiSegmentSegmenter);
};

Expand Down
9 changes: 8 additions & 1 deletion packager/media/formats/mp4/segmenter.cc
Expand Up @@ -90,7 +90,14 @@ Status Segmenter::Initialize(

// Use the reference stream's time scale as movie time scale.
moov_->header.timescale = sidx_->timescale;
moof_->header.sequence_number = 1;

// set moof_->header.sequence number to mp4_params.initial_sequence_number
// if valid.
if (options_.mp4_params.initial_sequence_number != -1) {
moof_->header.sequence_number = options_.mp4_params.initial_sequence_number;
} else {
moof_->header.sequence_number = 1;
}

// Fill in version information.
const std::string version = GetPackagerVersion();
Expand Down
2 changes: 2 additions & 0 deletions packager/media/public/mp4_output_params.h
Expand Up @@ -20,6 +20,8 @@ struct Mp4OutputParams {
/// Note that it is required by spec if segment_template contains $Times$
/// specifier.
bool generate_sidx_in_media_segments = true;
/// Indicates the initial sequence number to generate segments.
int initial_sequence_number = -1;
};

} // namespace shaka
Expand Down

0 comments on commit 89983c1

Please sign in to comment.