From 7aab7a8b50cebc13eff0612e2a0f8135773fb426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Cantar=C3=ADn?= Date: Fri, 31 Jan 2020 15:25:19 -0300 Subject: [PATCH 1/2] Add --hls_media_sequence_number to support custom value in HLS HLS uses the EXT-X-MEDIA-SEQUENCE tag at the start of a live playlist in order to specify the first segment sequence number. This is because any live playlist have a limited number of segments, and they also keep updating with new segments while removing old ones. When a player refreshes the playlist, this information is important for keeping track of segments positions. When the packager starts, it naturally starts this count from zero. However, there are many situations where the packager may be restarted, without this meaning starting this value from zero (but continuing a previous sequence). The most common situations are problems in the encoder feeding the packager. With those cases in mind, this parameter allows to set the initial EXT-X-MEDIA-SEQUENCE value. This way, it's possible to continue the sequence number from previous packager run. Closes #691. --- docs/source/options/hls_options.rst | 24 ++++++++++++++++++++++++ packager/app/hls_flags.cc | 6 ++++++ packager/app/hls_flags.h | 1 + packager/app/packager_main.cc | 1 + packager/hls/base/media_playlist.cc | 10 ++++++++-- packager/hls/base/media_playlist.h | 2 +- packager/hls/public/hls_params.h | 3 +++ 7 files changed, 44 insertions(+), 3 deletions(-) diff --git a/docs/source/options/hls_options.rst b/docs/source/options/hls_options.rst index 476f354627..c2e77f7c9a 100644 --- a/docs/source/options/hls_options.rst +++ b/docs/source/options/hls_options.rst @@ -51,3 +51,27 @@ HLS options Same as above, but this applies to text tracks only, and overrides the default language for text tracks. + +--hls_media_sequence_number + + HLS uses the EXT-X-MEDIA-SEQUENCE tag at the start of a live playlist in + order to specify the first segment sequence number. This is because any + live playlist have a limited number of segments, and they also keep + updating with new segments while removing old ones. When a player refreshes + the playlist, this information is important for keeping track of segments + positions. + + When the packager starts, it naturally starts this count from zero. However, + there are many situations where the packager may be restarted, without this + meaning starting this value from zero (but continuing a previous sequence). + The most common situations are problems in the encoder feeding the packager. + + With those cases in mind, this parameter allows to set the initial + EXT-X-MEDIA-SEQUENCE value. This way, it's possible to continue the sequence + number from previous packager run. + + For more information about the reasoning of this, please see issue + `#691 `_. + + The EXT-X-MEDIA-SEQUENCE documentation can be read here: + https://tools.ietf.org/html/rfc8216#section-4.3.3.2. diff --git a/packager/app/hls_flags.cc b/packager/app/hls_flags.cc index 956041c8b3..2415ebe0e1 100644 --- a/packager/app/hls_flags.cc +++ b/packager/app/hls_flags.cc @@ -24,3 +24,9 @@ DEFINE_string(hls_playlist_type, "VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in " "the HLS specification. For hls_playlist_type of LIVE, " "EXT-X-PLAYLIST-TYPE tag is omitted."); +DEFINE_int32(hls_media_sequence_number, + 0, + "Number. This HLS-only parameter defines the initial " + "EXT-X-MEDIA-SEQUENCE value, which allows continuous media " + "sequence across packager restarts. See #691 for more " + "information about the reasoning of this and its use cases."); diff --git a/packager/app/hls_flags.h b/packager/app/hls_flags.h index aa4ea461c9..c48a528e43 100644 --- a/packager/app/hls_flags.h +++ b/packager/app/hls_flags.h @@ -13,5 +13,6 @@ DECLARE_string(hls_master_playlist_output); DECLARE_string(hls_base_url); DECLARE_string(hls_key_uri); DECLARE_string(hls_playlist_type); +DECLARE_int32(hls_media_sequence_number); #endif // PACKAGER_APP_HLS_FLAGS_H_ diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 926fb6ebe6..31fbb2edc4 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -470,6 +470,7 @@ base::Optional GetPackagingParams() { FLAGS_preserved_segments_outside_live_window; hls_params.default_language = FLAGS_default_language; hls_params.default_text_language = FLAGS_default_text_language; + hls_params.media_sequence_number = FLAGS_hls_media_sequence_number; TestParams& test_params = packaging_params.test_params; test_params.dump_stream_info = FLAGS_dump_stream_info; diff --git a/packager/hls/base/media_playlist.cc b/packager/hls/base/media_playlist.cc index 98362a0216..9d547f43b4 100644 --- a/packager/hls/base/media_playlist.cc +++ b/packager/hls/base/media_playlist.cc @@ -106,7 +106,7 @@ std::string CreatePlaylistHeader( uint32_t target_duration, HlsPlaylistType type, MediaPlaylist::MediaPlaylistStreamType stream_type, - int media_sequence_number, + uint32_t media_sequence_number, int discontinuity_sequence_number) { const std::string version = GetPackagerVersion(); std::string version_line; @@ -343,7 +343,12 @@ MediaPlaylist::MediaPlaylist(const HlsParams& hls_params, : hls_params_(hls_params), file_name_(file_name), name_(name), - group_id_(group_id) {} + group_id_(group_id), + media_sequence_number_(hls_params_.media_sequence_number) { + // When there's a forced media_sequence_number, start with discontinuity + if (media_sequence_number_ > 0) + entries_.emplace_back(new DiscontinuityEntry()); + } MediaPlaylist::~MediaPlaylist() {} @@ -390,6 +395,7 @@ bool MediaPlaylist::SetMediaInfo(const MediaInfo& media_info) { characteristics_ = std::vector(media_info_.hls_characteristics().begin(), media_info_.hls_characteristics().end()); + return true; } diff --git a/packager/hls/base/media_playlist.h b/packager/hls/base/media_playlist.h index 2f595dc2ab..52465c8835 100644 --- a/packager/hls/base/media_playlist.h +++ b/packager/hls/base/media_playlist.h @@ -236,7 +236,7 @@ class MediaPlaylist { std::string codec_; std::string language_; std::vector characteristics_; - int media_sequence_number_ = 0; + uint32_t media_sequence_number_ = 0; bool inserted_discontinuity_tag_ = false; int discontinuity_sequence_number_ = 0; diff --git a/packager/hls/public/hls_params.h b/packager/hls/public/hls_params.h index 65f31bffb3..0100fb7969 100644 --- a/packager/hls/public/hls_params.h +++ b/packager/hls/public/hls_params.h @@ -56,6 +56,9 @@ struct HlsParams { /// be populated from segment duration specified in ChunkingParams if not /// specified. double target_segment_duration = 0; + /// Custom EXT-X-MEDIA-SEQUENCE value to allow continuous media playback + /// across packager restarts. See #691 for details. + uint32_t media_sequence_number = 0; }; } // namespace shaka From 1ed7de268d23fc2c82a5666b1b976787d07db50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Cantar=C3=ADn?= Date: Sat, 1 Feb 2020 23:37:26 -0300 Subject: [PATCH 2/2] Fix timestamp truncated to 32 bits in TS segment with $Time$ in template Fixes #701. --- AUTHORS | 1 + CONTRIBUTORS | 1 + packager/media/formats/mp2t/ts_segmenter.cc | 2 +- packager/media/formats/mp2t/ts_segmenter.h | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index d2bdbd68e2..95b23e51f2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,6 +15,7 @@ Anders Hasselqvist Chun-da Chen +Daniel CantarĂ­n Google Inc. <*@google.com> Leandro Moreira Leo Law diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 3bdbfc1a95..3d9c544fb4 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -25,6 +25,7 @@ Anders Hasselqvist Bei Li Chun-da Chen +Daniel CantarĂ­n David Cavar Gabe Kopley Haoming Chen diff --git a/packager/media/formats/mp2t/ts_segmenter.cc b/packager/media/formats/mp2t/ts_segmenter.cc index 3474ec1a6c..aaea5ced17 100644 --- a/packager/media/formats/mp2t/ts_segmenter.cc +++ b/packager/media/formats/mp2t/ts_segmenter.cc @@ -125,7 +125,7 @@ void TsSegmenter::SetTsWriterFileOpenedForTesting(bool value) { ts_writer_file_opened_ = value; } -Status TsSegmenter::OpenNewSegmentIfClosed(uint32_t next_pts) { +Status TsSegmenter::OpenNewSegmentIfClosed(int64_t next_pts) { if (ts_writer_file_opened_) return Status::OK; const std::string segment_name = diff --git a/packager/media/formats/mp2t/ts_segmenter.h b/packager/media/formats/mp2t/ts_segmenter.h index 78a88d2213..b140040eb7 100644 --- a/packager/media/formats/mp2t/ts_segmenter.h +++ b/packager/media/formats/mp2t/ts_segmenter.h @@ -71,7 +71,7 @@ class TsSegmenter { void SetTsWriterFileOpenedForTesting(bool value); private: - Status OpenNewSegmentIfClosed(uint32_t next_pts); + Status OpenNewSegmentIfClosed(int64_t next_pts); // Writes PES packets (carried in TsPackets) to a file. If a file is not open, // it will open one. This will not close the file.