diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index e3fa9cebca..8f6e69fb6d 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -171,17 +171,6 @@ std::unique_ptr CreateDecryptionKeySource( return decryption_key_source; } -MuxerOptions GetMuxerOptions(const std::string& temp_dir, - const Mp4OutputParams& mp4_params) { - MuxerOptions muxer_options; - muxer_options.num_subsegments_per_sidx = mp4_params.num_subsegments_per_sidx; - muxer_options.mp4_include_pssh_in_stream = mp4_params.include_pssh_in_stream; - muxer_options.mp4_use_decoding_timestamp_in_timeline = - mp4_params.use_decoding_timestamp_in_timeline; - muxer_options.temp_dir = temp_dir; - return muxer_options; -} - MpdOptions GetMpdOptions(bool on_demand_profile, const MpdParams& mpd_params) { MpdOptions mpd_options; mpd_options.dash_profile = diff --git a/packager/app/packager_util.h b/packager/app/packager_util.h index e169cb8f83..a08a0b17de 100644 --- a/packager/app/packager_util.h +++ b/packager/app/packager_util.h @@ -50,10 +50,6 @@ std::unique_ptr CreateEncryptionKeySource( std::unique_ptr CreateDecryptionKeySource( const DecryptionParams& decryption_params); -/// @return MuxerOptions from provided command line options. -MuxerOptions GetMuxerOptions(const std::string& temp_dir, - const Mp4OutputParams& mp4_params); - /// @return MpdOptions from provided command line options. MpdOptions GetMpdOptions(bool on_demand_profile, const MpdParams& mpd_params); diff --git a/packager/media/base/muxer_options.h b/packager/media/base/muxer_options.h index 640a0942f1..79cc0d18ce 100644 --- a/packager/media/base/muxer_options.h +++ b/packager/media/base/muxer_options.h @@ -11,6 +11,8 @@ #include +#include "packager/media/public/mp4_output_params.h" + namespace shaka { namespace media { @@ -19,19 +21,8 @@ struct MuxerOptions { MuxerOptions(); ~MuxerOptions(); - /// For ISO BMFF only. - /// Set the number of subsegments in each SIDX box. If 0, a single SIDX box - /// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer - /// will pack N subsegments in the root SIDX of the segment, with - /// segment_duration/N/fragment_duration fragments per subsegment. - int num_subsegments_per_sidx = 0; - - /// For ISO BMFF only. - /// Set the flag use_decoding_timestamp_in_timeline, which if set to true, use - /// decoding timestamp instead of presentation timestamp in media timeline, - /// which is needed to workaround a Chromium bug that decoding timestamp is - /// used in buffered range, https://crbug.com/398130. - bool mp4_use_decoding_timestamp_in_timeline = false; + /// MP4 (ISO-BMFF) specific parameters. + Mp4OutputParams mp4_params; /// Output file name. If segment_template is not specified, the Muxer /// generates this single output file with all segments concatenated; @@ -50,12 +41,6 @@ struct MuxerOptions { /// User-specified bit rate for the media stream. If zero, the muxer will /// attempt to estimate. uint32_t bandwidth = 0; - - // MP4 only: include pssh in the encrypted stream. CMAF recommends carrying - // license acquisition information in the manifest and not duplicate the - // information in the stream. (This is not a hard requirement so we are still - // CMAF compatible even if pssh is included in the stream.) - bool mp4_include_pssh_in_stream = true; }; } // namespace media diff --git a/packager/media/event/mpd_notify_muxer_listener_unittest.cc b/packager/media/event/mpd_notify_muxer_listener_unittest.cc index 8fce1eea8d..7cb1459691 100644 --- a/packager/media/event/mpd_notify_muxer_listener_unittest.cc +++ b/packager/media/event/mpd_notify_muxer_listener_unittest.cc @@ -43,8 +43,8 @@ MediaInfo ConvertToMediaInfo(const std::string& media_info_string) { return media_info; } -void SetDefaultLiveMuxerOptionsValues(media::MuxerOptions* muxer_options) { - muxer_options->num_subsegments_per_sidx = 0; +void SetDefaultLiveMuxerOptions(media::MuxerOptions* muxer_options) { + muxer_options->mp4_params.num_subsegments_per_sidx = 0; muxer_options->output_file_name = "liveinit.mp4"; muxer_options->segment_template = "live-$NUMBER$.mp4"; muxer_options->temp_dir.clear(); @@ -98,7 +98,7 @@ MATCHER_P(ExpectMediaInfoEq, expected_text_format, "") { TEST_F(MpdNotifyMuxerListenerTest, VodClearContent) { SetupForVod(); MuxerOptions muxer_options; - SetDefaultMuxerOptionsValues(&muxer_options); + SetDefaultMuxerOptions(&muxer_options); VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); std::shared_ptr video_stream_info = CreateVideoStreamInfo(video_params); @@ -143,7 +143,7 @@ MATCHER_P4(ProtectedContentEq, uuid, name, default_key_id, pssh, "") { TEST_F(MpdNotifyMuxerListenerTest, VodEncryptedContent) { SetupForVod(); MuxerOptions muxer_options; - SetDefaultMuxerOptionsValues(&muxer_options); + SetDefaultMuxerOptions(&muxer_options); VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); std::shared_ptr video_stream_info = CreateVideoStreamInfo(video_params); @@ -186,7 +186,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodEncryptedContent) { TEST_F(MpdNotifyMuxerListenerTest, VodOnSampleDurationReady) { SetupForVod(); MuxerOptions muxer_options; - SetDefaultMuxerOptionsValues(&muxer_options); + SetDefaultMuxerOptions(&muxer_options); VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); std::shared_ptr video_stream_info = CreateVideoStreamInfo(video_params); @@ -233,7 +233,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodOnSampleDurationReady) { TEST_F(MpdNotifyMuxerListenerTest, VodOnNewSegment) { SetupForVod(); MuxerOptions muxer_options; - SetDefaultMuxerOptionsValues(&muxer_options); + SetDefaultMuxerOptions(&muxer_options); VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); std::shared_ptr video_stream_info = CreateVideoStreamInfo(video_params); @@ -270,7 +270,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodOnNewSegment) { TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) { SetupForLive(); MuxerOptions muxer_options; - SetDefaultLiveMuxerOptionsValues(&muxer_options); + SetDefaultLiveMuxerOptions(&muxer_options); VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); std::shared_ptr video_stream_info = CreateVideoStreamInfo(video_params); @@ -343,7 +343,7 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) { TEST_P(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) { SetupForLive(); MuxerOptions muxer_options; - SetDefaultLiveMuxerOptionsValues(&muxer_options); + SetDefaultLiveMuxerOptions(&muxer_options); VideoStreamInfoParameters video_params = GetDefaultVideoStreamInfoParams(); std::shared_ptr video_stream_info = CreateVideoStreamInfo(video_params); diff --git a/packager/media/event/muxer_listener_test_helper.cc b/packager/media/event/muxer_listener_test_helper.cc index d40db1d26a..8a1b5f8c87 100644 --- a/packager/media/event/muxer_listener_test_helper.cc +++ b/packager/media/event/muxer_listener_test_helper.cc @@ -86,8 +86,8 @@ OnMediaEndParameters GetDefaultOnMediaEndParams() { return param; } -void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) { - muxer_options->num_subsegments_per_sidx = 0; +void SetDefaultMuxerOptions(MuxerOptions* muxer_options) { + muxer_options->mp4_params.num_subsegments_per_sidx = 0; muxer_options->output_file_name = "test_output_file_name.mp4"; muxer_options->segment_template.clear(); muxer_options->temp_dir.clear(); diff --git a/packager/media/event/muxer_listener_test_helper.h b/packager/media/event/muxer_listener_test_helper.h index b2ec566d15..5b568e90c6 100644 --- a/packager/media/event/muxer_listener_test_helper.h +++ b/packager/media/event/muxer_listener_test_helper.h @@ -92,7 +92,7 @@ OnMediaEndParameters GetDefaultOnMediaEndParams(); std::vector GetDefaultKeySystemInfo(); // Sets "default" values for muxer_options for testing. -void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options); +void SetDefaultMuxerOptions(MuxerOptions* muxer_options); // Expect that expect and actual are equal. void ExpectMediaInfoEqual(const MediaInfo& expect, const MediaInfo& actual); diff --git a/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc b/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc index 3c9413d6a9..b5689c1419 100644 --- a/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc +++ b/packager/media/event/vod_media_info_dump_muxer_listener_unittest.cc @@ -77,7 +77,7 @@ class VodMediaInfoDumpMuxerListenerTest : public ::testing::Test { const StreamInfo& stream_info, bool enable_encryption) { MuxerOptions muxer_options; - SetDefaultMuxerOptionsValues(&muxer_options); + SetDefaultMuxerOptions(&muxer_options); const uint32_t kReferenceTimeScale = 1000; if (enable_encryption) { std::vector bogus_default_key_id( diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc index ee5035a62c..df22fef135 100644 --- a/packager/media/formats/mp4/mp4_muxer.cc +++ b/packager/media/formats/mp4/mp4_muxer.cc @@ -171,7 +171,8 @@ Status MP4Muxer::InitializeMuxer() { << streams()[i]->stream_type(); } - if (streams()[i]->is_encrypted() && options().mp4_include_pssh_in_stream) { + if (streams()[i]->is_encrypted() && + options().mp4_params.include_pssh_in_stream) { const auto& key_system_info = streams()[i]->encryption_config().key_system_info; moov->pssh.resize(key_system_info.size()); diff --git a/packager/media/formats/mp4/multi_segment_segmenter.cc b/packager/media/formats/mp4/multi_segment_segmenter.cc index abd08d79ba..8c29a7f83c 100644 --- a/packager/media/formats/mp4/multi_segment_segmenter.cc +++ b/packager/media/formats/mp4/multi_segment_segmenter.cc @@ -86,7 +86,7 @@ Status MultiSegmentSegmenter::DoFinalizeSegment() { sidx()->earliest_presentation_time = sidx()->references[0].earliest_presentation_time; - if (options().num_subsegments_per_sidx <= 0) + if (options().mp4_params.num_subsegments_per_sidx <= 0) return WriteSegment(); // sidx() contains pre-generated segment references with one reference per @@ -94,7 +94,7 @@ Status MultiSegmentSegmenter::DoFinalizeSegment() { // pre-generated references into final subsegment references. size_t num_fragments = sidx()->references.size(); size_t num_fragments_per_subsegment = - (num_fragments - 1) / options().num_subsegments_per_sidx + 1; + (num_fragments - 1) / options().mp4_params.num_subsegments_per_sidx + 1; if (num_fragments_per_subsegment <= 1) return WriteSegment(); @@ -130,7 +130,7 @@ Status MultiSegmentSegmenter::DoFinalizeSegment() { } } - refs.resize(options().num_subsegments_per_sidx); + refs.resize(options().mp4_params.num_subsegments_per_sidx); // earliest_presentation_time is the earliest presentation time of any // access unit in the reference stream in the first subsegment. @@ -169,7 +169,7 @@ Status MultiSegmentSegmenter::WriteSegment() { } // If num_subsegments_per_sidx is negative, no SIDX box is generated. - if (options().num_subsegments_per_sidx >= 0) + if (options().mp4_params.num_subsegments_per_sidx >= 0) sidx()->Write(buffer.get()); const size_t segment_size = buffer->Size() + fragment_buffer()->Size(); diff --git a/packager/media/formats/mp4/segmenter.cc b/packager/media/formats/mp4/segmenter.cc index 9dd804c42b..8e1bb56b64 100644 --- a/packager/media/formats/mp4/segmenter.cc +++ b/packager/media/formats/mp4/segmenter.cc @@ -69,7 +69,7 @@ Status Segmenter::Initialize( fragmenters_[i].reset(new Fragmenter(streams[i], &moof_->tracks[i])); } - if (options_.mp4_use_decoding_timestamp_in_timeline) { + if (options_.mp4_params.use_decoding_timestamp_in_timeline) { for (uint32_t i = 0; i < streams.size(); ++i) fragmenters_[i]->set_use_decoding_timestamp_in_timeline(true); } @@ -252,7 +252,7 @@ void Segmenter::FinalizeFragmentForKeyRotation( size_t stream_id, bool fragment_encrypted, const EncryptionConfig& encryption_config) { - if (options_.mp4_include_pssh_in_stream) { + if (options_.mp4_params.include_pssh_in_stream) { const std::vector& system_info = encryption_config.key_system_info; moof_->pssh.resize(system_info.size()); diff --git a/packager/media/public/mp4_output_params.h b/packager/media/public/mp4_output_params.h new file mode 100644 index 0000000000..f9b83f1942 --- /dev/null +++ b/packager/media/public/mp4_output_params.h @@ -0,0 +1,36 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#ifndef PACKAGER_MEDIA_PUBLIC_MP4_OUTPUT_PARAMS_H_ +#define PACKAGER_MEDIA_PUBLIC_MP4_OUTPUT_PARAMS_H_ + +namespace shaka { + +/// MP4 (ISO-BMFF) output related parameters. +struct Mp4OutputParams { + // Include pssh in the encrypted stream. CMAF and DASH-IF recommends carrying + // license acquisition information in the manifest and not duplicate the + // information in the stream. (This is not a hard requirement so we are still + // CMAF compatible even if pssh is included in the stream.) + bool include_pssh_in_stream = true; + /// Set the number of subsegments in each SIDX box. If 0, a single SIDX box + /// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer + /// will pack N subsegments in the root SIDX of the segment, with + /// segment_duration/N/subsegment_duration fragments per subsegment. + /// This flag is ingored for DASH MPD with on-demand profile. + static constexpr int kNoSidxBoxInSegment = -1; + static constexpr int kSingleSidxPerSegment = 0; + int num_subsegments_per_sidx = kSingleSidxPerSegment; + /// Set the flag use_decoding_timestamp_in_timeline, which if set to true, use + /// decoding timestamp instead of presentation timestamp in media timeline, + /// which is needed to workaround a Chromium bug that decoding timestamp is + /// used in buffered range, https://crbug.com/398130. + bool use_decoding_timestamp_in_timeline = false; +}; + +} // namespace shaka + +#endif // PACKAGER_MEDIA_PUBLIC_MP4_OUTPUT_PARAMS_H_ diff --git a/packager/packager.cc b/packager/packager.cc index c79fe36ed7..746dd8fc52 100644 --- a/packager/packager.cc +++ b/packager/packager.cc @@ -315,7 +315,6 @@ std::shared_ptr CreateOutputMuxer(const MuxerOptions& options, bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, const PackagingParams& packaging_params, - const MuxerOptions& muxer_options, FakeClock* fake_clock, KeySource* encryption_key_source, MpdNotifier* mpd_notifier, @@ -338,7 +337,9 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, MediaContainerName output_format = GetOutputFormat(*stream_iter); // Process stream descriptor. - MuxerOptions stream_muxer_options(muxer_options); + MuxerOptions stream_muxer_options; + stream_muxer_options.mp4_params = packaging_params.mp4_output_params; + stream_muxer_options.temp_dir = packaging_params.temp_dir; stream_muxer_options.output_file_name = stream_iter->output; if (!stream_iter->segment_template.empty()) { if (!ValidateSegmentTemplate(stream_iter->segment_template)) { @@ -583,9 +584,6 @@ Status Packager::Initialize( std::unique_ptr internal(new PackagerInternal); - MuxerOptions muxer_options = media::GetMuxerOptions( - packaging_params.temp_dir, packaging_params.mp4_output_params); - const bool on_demand_dash_profile = stream_descriptors.begin()->segment_template.empty(); MpdOptions mpd_options = @@ -634,10 +632,9 @@ Status Packager::Initialize( for (const StreamDescriptor& descriptor : stream_descriptors) stream_descriptor_list.insert(descriptor); if (!media::CreateRemuxJobs( - stream_descriptor_list, packaging_params, muxer_options, - &internal->fake_clock, internal->encryption_key_source.get(), - internal->mpd_notifier.get(), internal->hls_notifier.get(), - &internal->jobs)) { + stream_descriptor_list, packaging_params, &internal->fake_clock, + internal->encryption_key_source.get(), internal->mpd_notifier.get(), + internal->hls_notifier.get(), &internal->jobs)) { return Status(error::INVALID_ARGUMENT, "Failed to create remux jobs."); } internal_ = std::move(internal); diff --git a/packager/packager.h b/packager/packager.h index 1f84a44396..a89300561d 100644 --- a/packager/packager.h +++ b/packager/packager.h @@ -14,32 +14,11 @@ #include "packager/hls/public/hls_playlist_type.h" #include "packager/media/public/chunking_params.h" #include "packager/media/public/crypto_params.h" +#include "packager/media/public/mp4_output_params.h" #include "packager/status.h" namespace shaka { -/// MP4 (ISO-BMFF) output related parameters. -struct Mp4OutputParams { - // Include pssh in the encrypted stream. CMAF recommends carrying - // license acquisition information in the manifest and not duplicate the - // information in the stream. (This is not a hard requirement so we are still - // CMAF compatible even if pssh is included in the stream.) - bool include_pssh_in_stream = true; - /// Set the number of subsegments in each SIDX box. If 0, a single SIDX box - /// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer - /// will pack N subsegments in the root SIDX of the segment, with - /// segment_duration/N/subsegment_duration fragments per subsegment. - /// This flag is ingored for DASH MPD with on-demand profile. - const int kNoSidxBoxInSegment = -1; - const int kSingleSidxPerSegment = 0; - int num_subsegments_per_sidx = kSingleSidxPerSegment; - /// Set the flag use_decoding_timestamp_in_timeline, which if set to true, use - /// decoding timestamp instead of presentation timestamp in media timeline, - /// which is needed to workaround a Chromium bug that decoding timestamp is - /// used in buffered range, https://crbug.com/398130. - bool use_decoding_timestamp_in_timeline = false; -}; - /// DASH MPD related parameters. struct MpdParams { /// MPD output file path.