diff --git a/README.md b/README.md index fa62684a21e..ebc837843a3 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ host operating systems. # VOD: mp4 --> dash packager input=/media/example.mp4,stream=audio,output=audio.mp4 \ input=/media/example.mp4,stream=video,output=video.mp4 \ - --profile on-demand --mpd_output example.mpd + --mpd_output example.mpd # Leave the container. exit @@ -231,13 +231,11 @@ Demux audio from the input and generate a fragmented mp4: packager input=sintel.mp4,stream=audio,output=fragmented_sintel.mp4 ``` -Demux streams from the input and generates a mpd with on-demand profile along -with fragmented mp4: +Demux streams from the input and generates a mpd with fragmented mp4: ```Shell packager \ input=sintel.mp4,stream=audio,output=sintel_audio.mp4 \ input=sintel.mp4,stream=video,output=sintel_video.mp4 \ ---profile on-demand \ --mpd_output sintel_vod.mpd ``` @@ -247,19 +245,17 @@ packager \ input=sintel.mp4,stream=audio,output=sintel_audio.mp4 \ input=sintel.mp4,stream=video,output=sintel_video.mp4 \ input=sintel_english_input.vtt,stream=text,output=sintel_english.vtt \ ---profile on-demand \ --mpd_output sintel_vod.mpd ``` -You may also generate mpd with live profile. Here is an example with IPTV input -streams: +You may also generate mpd with live profile by specifying segment_template in +stream descriptors. Here is an example with IPTV input streams: ```Shell packager \ 'input=udp://224.1.1.5:5003,stream=audio,init_segment=live-audio.mp4,segment_template=live-audio-$Number$.mp4,bandwidth=130000' \ 'input=udp://224.1.1.5:5003,stream=video,init_segment=live-video-sd.mp4,segment_template=live-video-sd-$Number$.mp4,bandwidth=2000000' \ 'input=udp://224.1.1.5:5002,stream=video,init_segment=live-video-hd.mp4,segment_template=live-video-hd-$Number$.mp4,bandwidth=5000000' \ ---profile live \ --mpd_output live.mpd ``` @@ -274,6 +270,16 @@ Three options are supported right now: - timeout=microseconds Timeout in microseconds. Default to unlimited. +To generate static mpd with live profile. An additional flag needs to be +specified: +```Shell +packager \ + 'input=sintel.mp4,stream=audio,init_segment=audio.mp4,segment_template=audio-$Number$.mp4' \ + 'input=sintel.mp4,stream=video,init_segment=video.mp4,segment_template=video-$Number$.mp4' \ +--mpd_output live_static.mpd \ +--generate_static_mpd +``` + Demux video from the input and generate an encrypted fragmented mp4 using Widevine encryption with RSA signing key file *widevine_test_private.der*: ```Shell @@ -292,7 +298,6 @@ packager \ 'input=udp://224.1.1.5:5003,stream=audio,init_segment=live-audio.mp4,segment_template=live-audio-$Number$.mp4,bandwidth=130000' \ 'input=udp://224.1.1.5:5003,stream=video,init_segment=live-video-sd.mp4,segment_template=live-video-sd-$Number$.mp4,bandwidth=2000000' \ 'input=udp://224.1.1.5:5002,stream=video,init_segment=live-video-hd.mp4,segment_template=live-video-hd-$Number$.mp4,bandwidth=5000000' \ ---profile live \ --mpd_output live.mpd \ --enable_widevine_encryption \ --key_server_url "https://license.uat.widevine.com/cenc/getcontentkey/widevine_test" \ @@ -343,7 +348,6 @@ generated TS segments. ```Shell packager \ 'input=bear-1280x720.mp4,stream=video,segment_template=bear$Number$.ts,playlist_name=playlist.m3u8' \ - --single_segment=false \ --hls_master_playlist_output="master.m3u8" \ --hls_base_url="http://localhost:10000/" ``` @@ -354,7 +358,6 @@ specified. packager \ 'input=input.mp4,stream=video,segment_template=output$Number$.ts,playlist_name=video_playlist.m3u8' \ 'input=input.mp4,stream=audio,segment_template=output_audio$Number$.ts,playlist_name=audio_playlist.m3u8,hls_group_id=audio,hls_name=ENGLISH' \ - --single_segment=false \ --hls_master_playlist_output="master_playlist.m3u8" \ --hls_base_url="http://localhost:10000/" ``` diff --git a/packager/app/mpd_flags.cc b/packager/app/mpd_flags.cc index 63bb9232e71..22cae19ea6e 100644 --- a/packager/app/mpd_flags.cc +++ b/packager/app/mpd_flags.cc @@ -8,6 +8,14 @@ #include "packager/app/mpd_flags.h" +DEFINE_bool(generate_static_mpd, + false, + "Set to true to generate static mpd. If segment_template is " + "specified in stream descriptors, shaka-packager generates dynamic " + "mpd by default; if this flag is enabled, shaka-packager generates " + "static mpd instead. Note that if segment_template is not " + "specified, shaka-packager always generates static mpd regardless " + "of the value of this flag."); // TODO(rkuroiwa, kqyang): Remove the 'Exclusive' statements once // --output_media_info can work together with --mpd_output. DEFINE_bool(output_media_info, diff --git a/packager/app/mpd_flags.h b/packager/app/mpd_flags.h index ba7f657e3ab..e7c9b1e1a96 100644 --- a/packager/app/mpd_flags.h +++ b/packager/app/mpd_flags.h @@ -11,6 +11,7 @@ #include +DECLARE_bool(generate_static_mpd); DECLARE_bool(output_media_info); DECLARE_string(mpd_output); DECLARE_string(base_urls); diff --git a/packager/app/muxer_flags.cc b/packager/app/muxer_flags.cc index 2df3aab66b4..4ef5e27aa58 100644 --- a/packager/app/muxer_flags.cc +++ b/packager/app/muxer_flags.cc @@ -8,18 +8,9 @@ #include "packager/app/muxer_flags.h" -DEFINE_string(profile, - "", - "Specify the target DASH profile: on-demand or live. This will " - "set proper option values to ensure conformance to the desired " - "profile."); DEFINE_double(clear_lead, 10.0f, "Clear lead in seconds if encryption is enabled."); -DEFINE_bool(single_segment, - true, - "Generate a single segment for the media presentation. This option " - "should be set for on demand profile."); DEFINE_double(segment_duration, 10.0f, "Segment duration in seconds. If single_segment is specified, " diff --git a/packager/app/muxer_flags.h b/packager/app/muxer_flags.h index c1e450aa89c..a053794f315 100644 --- a/packager/app/muxer_flags.h +++ b/packager/app/muxer_flags.h @@ -11,9 +11,7 @@ #include -DECLARE_string(profile); DECLARE_double(clear_lead); -DECLARE_bool(single_segment); DECLARE_double(segment_duration); DECLARE_bool(segment_sap_aligned); DECLARE_double(fragment_duration); diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 5a3b1a3eac0..0e57dc9b68c 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -265,11 +265,6 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, return false; } stream_muxer_options.segment_template = stream_iter->segment_template; - if (stream_muxer_options.single_segment) { - LOG(WARNING) << "Segment template and single segment are incompatible, " - "setting single segment to false."; - stream_muxer_options.single_segment = false; - } } stream_muxer_options.bandwidth = stream_iter->bandwidth; @@ -419,20 +414,11 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) { if (protection_scheme == FOURCC_NULL) return false; - if (!AssignFlagsFromProfile()) - return false; - if (FLAGS_output_media_info && !FLAGS_mpd_output.empty()) { NOTIMPLEMENTED() << "ERROR: --output_media_info and --mpd_output do not " "work together."; return false; } - if (FLAGS_output_media_info && !FLAGS_single_segment) { - // TODO(rkuroiwa, kqyang): Support partial media info dump for live. - NOTIMPLEMENTED() << "ERROR: --output_media_info is only supported if " - "--single_segment is true."; - return false; - } // Since there isn't a muxer listener that can output both MPD and HLS, // disallow specifying both MPD and HLS flags. @@ -446,8 +432,28 @@ bool RunPackager(const StreamDescriptorList& stream_descriptors) { if (!GetMuxerOptions(&muxer_options)) return false; + DCHECK(!stream_descriptors.empty()); + // On demand profile generates single file segment while live profile + // generates multiple segments specified using segment template. + const bool on_demand_dash_profile = + stream_descriptors.begin()->segment_template.empty(); + for (const auto& stream_descriptor : stream_descriptors) { + if (on_demand_dash_profile != stream_descriptor.segment_template.empty()) { + LOG(ERROR) << "Inconsistent stream descriptor specification: " + "segment_template should be specified for none or all " + "stream descriptors."; + return false; + } + } + if (FLAGS_output_media_info && !on_demand_dash_profile) { + // TODO(rkuroiwa, kqyang): Support partial media info dump for live. + NOTIMPLEMENTED() << "ERROR: --output_media_info is only supported for " + "on-demand profile (not using segment_template)."; + return false; + } + MpdOptions mpd_options; - if (!GetMpdOptions(&mpd_options)) + if (!GetMpdOptions(on_demand_dash_profile, &mpd_options)) return false; // Create encryption key source if needed. diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index 8962d4cc27c..fba302fd3e2 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -125,30 +125,9 @@ std::unique_ptr CreateDecryptionKeySource() { return decryption_key_source; } -bool AssignFlagsFromProfile() { - bool single_segment = FLAGS_single_segment; - if (FLAGS_profile == "on-demand") { - single_segment = true; - } else if (FLAGS_profile == "live") { - single_segment = false; - } else if (FLAGS_profile != "") { - fprintf(stderr, "ERROR: --profile '%s' is not supported.\n", - FLAGS_profile.c_str()); - return false; - } - - if (FLAGS_single_segment != single_segment) { - FLAGS_single_segment = single_segment; - fprintf(stdout, "Profile %s: set --single_segment to %s.\n", - FLAGS_profile.c_str(), single_segment ? "true" : "false"); - } - return true; -} - bool GetMuxerOptions(MuxerOptions* muxer_options) { DCHECK(muxer_options); - muxer_options->single_segment = FLAGS_single_segment; muxer_options->segment_duration = FLAGS_segment_duration; muxer_options->fragment_duration = FLAGS_fragment_duration; muxer_options->segment_sap_aligned = FLAGS_segment_sap_aligned; @@ -168,15 +147,15 @@ bool GetMuxerOptions(MuxerOptions* muxer_options) { return true; } -bool GetMpdOptions(MpdOptions* mpd_options) { +bool GetMpdOptions(bool on_demand_profile, MpdOptions* mpd_options) { DCHECK(mpd_options); mpd_options->dash_profile = - FLAGS_single_segment ? DashProfile::kOnDemand : DashProfile::kLive; - // Single segment does not always mean static mpd. - // TODO(kqyang): Add a new flag for mpd type and update the code. + on_demand_profile ? DashProfile::kOnDemand : DashProfile::kLive; mpd_options->mpd_type = - FLAGS_single_segment ? MpdType::kStatic : MpdType::kDynamic; + (on_demand_profile || FLAGS_generate_static_mpd) + ? MpdType::kStatic + : MpdType::kDynamic; mpd_options->availability_time_offset = FLAGS_availability_time_offset; mpd_options->minimum_update_period = FLAGS_minimum_update_period; mpd_options->min_buffer_time = FLAGS_min_buffer_time; diff --git a/packager/app/packager_util.h b/packager/app/packager_util.h index e0342247600..ec1abad0ddb 100644 --- a/packager/app/packager_util.h +++ b/packager/app/packager_util.h @@ -42,14 +42,11 @@ std::unique_ptr CreateEncryptionKeySource(); /// decryption is not required. std::unique_ptr CreateDecryptionKeySource(); -/// Set flags according to profile. -bool AssignFlagsFromProfile(); - /// Fill MuxerOptions members using provided command line options. bool GetMuxerOptions(MuxerOptions* muxer_options); /// Fill MpdOptions members using provided command line options. -bool GetMpdOptions(MpdOptions* mpd_options); +bool GetMpdOptions(bool on_demand_profile, MpdOptions* mpd_options); /// Select and add a stream from a provided set to a muxer. /// @param streams contains the set of MediaStreams from which to select. diff --git a/packager/app/retired_flags.cc b/packager/app/retired_flags.cc new file mode 100644 index 00000000000..fb0eb08fd8a --- /dev/null +++ b/packager/app/retired_flags.cc @@ -0,0 +1,34 @@ +// 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 +// +// Defines retired / deprecated flags. These flags will be removed in later +// versions. + +#include "packager/app/retired_flags.h" + +#include + +DEFINE_string(profile, "", "This flag is deprecated. Do not use."); +DEFINE_bool(single_segment, true, "This flag is deprecated. Do not use."); + +// The current gflags library does not provide a way to check whether a flag is +// set in command line. If a flag has a different value to its default value, +// the flag must have been set. It is possible that the flag is set to the same +// value as its default value though. +bool InformRetiredStringFlag(const char* flagname, const std::string& value) { + if (!value.empty()) + fprintf(stderr, "WARNING: %s is deprecated and ignored.\n", flagname); + return true; +} + +bool InformRetiredDefaultTrueFlag(const char* flagname, bool value) { + if (!value) + fprintf(stderr, "WARNING: %s is deprecated and ignored.\n", flagname); + return true; +} + +DEFINE_validator(profile, &InformRetiredStringFlag); +DEFINE_validator(single_segment, &InformRetiredDefaultTrueFlag); diff --git a/packager/app/retired_flags.h b/packager/app/retired_flags.h new file mode 100644 index 00000000000..ae91a335e34 --- /dev/null +++ b/packager/app/retired_flags.h @@ -0,0 +1,10 @@ +// 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 + +#include + +DECLARE_string(profile); +DECLARE_bool(single_segment); diff --git a/packager/app/test/packager_test.py b/packager/app/test/packager_test.py index 610c61a2e5d..80b8bd7e6de 100755 --- a/packager/app/test/packager_test.py +++ b/packager/app/test/packager_test.py @@ -110,7 +110,7 @@ def testPackageAvcTs(self): output_format='ts', live=True, test_files=['bear-640x360.ts']), - self._GetFlags(live=True, output_hls=True)) + self._GetFlags(output_hls=True)) self._DiffLiveGold(self.output[0], 'bear-640x360-a-golden', output_format='ts') @@ -220,8 +220,7 @@ def testPackageAvcTsWithEncryption(self): output_format='ts', live=True, test_files=['bear-640x360.ts']), - self._GetFlags(encryption=True, - live=True, output_hls=True)) + self._GetFlags(encryption=True, output_hls=True)) self._DiffLiveGold(self.output[0], 'bear-640x360-a-enc-golden', output_format='ts') @@ -329,8 +328,7 @@ def testPackageWithEncryptionAndOutputMediaInfo(self): def testPackageWithLiveProfile(self): self.packager.Package( - self._GetStreams(['audio', 'video'], live=True), - self._GetFlags(live=True)) + self._GetStreams(['audio', 'video'], live=True), self._GetFlags()) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden') self._DiffLiveMpdGold(self.mpd_output, 'bear-640x360-av-live-golden.mpd') @@ -338,7 +336,7 @@ def testPackageWithLiveProfile(self): def testPackageWithLiveProfileAndEncryption(self): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), - self._GetFlags(encryption=True, live=True)) + self._GetFlags(encryption=True)) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden') self._DiffLiveMpdGold(self.mpd_output, @@ -347,8 +345,7 @@ def testPackageWithLiveProfileAndEncryption(self): def testPackageWithLiveProfileAndEncryptionAndDashIfIop(self): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), - self._GetFlags(encryption=True, - live=True, dash_if_iop=True)) + self._GetFlags(encryption=True, dash_if_iop=True)) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden') self._DiffLiveMpdGold(self.mpd_output, @@ -360,8 +357,7 @@ def testPackageWithLiveProfileAndEncryptionAndDashIfIopWithMultFiles(self): live=True, test_files=['bear-1280x720.mp4', 'bear-640x360.mp4', 'bear-320x180.mp4']), - self._GetFlags(encryption=True, - live=True, dash_if_iop=True)) + self._GetFlags(encryption=True, dash_if_iop=True)) self._DiffLiveGold(self.output[2], 'bear-640x360-a-live-cenc-golden') self._DiffLiveGold(self.output[3], 'bear-640x360-v-live-cenc-golden') # Mpd cannot be validated right now since we don't generate determinstic @@ -371,9 +367,7 @@ def testPackageWithLiveProfileAndEncryptionAndDashIfIopWithMultFiles(self): def testPackageWithLiveProfileAndKeyRotation(self): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), - self._GetFlags(encryption=True, - key_rotation=True, - live=True)) + self._GetFlags(encryption=True, key_rotation=True)) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-rotation-golden') self._DiffLiveGold(self.output[1], @@ -386,7 +380,6 @@ def testPackageWithLiveProfileAndKeyRotationAndDashIfIop(self): self._GetStreams(['audio', 'video'], live=True), self._GetFlags(encryption=True, key_rotation=True, - live=True, dash_if_iop=True)) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-rotation-golden') @@ -496,7 +489,6 @@ def _GetFlags(self, random_iv=False, widevine_encryption=False, key_rotation=False, - live=False, dash_if_iop=False, output_media_info=False, output_hls=False, @@ -526,8 +518,6 @@ def _GetFlags(self, if key_rotation: flags.append('--crypto_period_duration=1') - if live: - flags.append('--profile=live') if dash_if_iop: flags.append('--generate_dash_if_iop_compliant_mpd') if output_media_info: diff --git a/packager/media/base/muxer_options.cc b/packager/media/base/muxer_options.cc index 0e3bc82efb9..e5013c41759 100644 --- a/packager/media/base/muxer_options.cc +++ b/packager/media/base/muxer_options.cc @@ -9,17 +9,8 @@ namespace shaka { namespace media { -MuxerOptions::MuxerOptions() - : single_segment(false), - segment_duration(0), - fragment_duration(0), - segment_sap_aligned(false), - fragment_sap_aligned(false), - num_subsegments_per_sidx(0), - mp4_use_decoding_timestamp_in_timeline(false), - bandwidth(0), - webm_subsample_encryption(true) {} -MuxerOptions::~MuxerOptions() {} +MuxerOptions::MuxerOptions() = default; +MuxerOptions::~MuxerOptions() = default; } // namespace media } // namespace shaka diff --git a/packager/media/base/muxer_options.h b/packager/media/base/muxer_options.h index 5160df24b76..327c437c824 100644 --- a/packager/media/base/muxer_options.h +++ b/packager/media/base/muxer_options.h @@ -19,42 +19,38 @@ struct MuxerOptions { MuxerOptions(); ~MuxerOptions(); - /// Generate a single segment for each media presentation. This option - /// should be set for on demand profile. - bool single_segment; - /// Segment duration in seconds. If single_segment is specified, this /// parameter sets the duration of a subsegment; otherwise, this parameter /// sets the duration of a segment. A segment can contain one or many /// fragments. - double segment_duration; + double segment_duration = 0; /// Fragment duration in seconds. Should not be larger than the segment /// duration. - double fragment_duration; + double fragment_duration = 0; /// Force segments to begin with stream access points. Segment duration may /// not be exactly what specified by segment_duration. - bool segment_sap_aligned; + bool segment_sap_aligned = false; /// Force fragments to begin with stream access points. Fragment duration /// may not be exactly what specified by segment_duration. Setting to true /// implies that segment_sap_aligned is true as well. - bool fragment_sap_aligned; + bool fragment_sap_aligned = false; /// 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; + 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; + bool mp4_use_decoding_timestamp_in_timeline = false; /// Output file name. If segment_template is not specified, the Muxer /// generates this single output file with all segments concatenated; @@ -72,10 +68,10 @@ struct MuxerOptions { /// User-specified bit rate for the media stream. If zero, the muxer will /// attempt to estimate. - uint32_t bandwidth; + uint32_t bandwidth = 0; // Enable/disable subsample encryption for WebM containers. - bool webm_subsample_encryption; + bool webm_subsample_encryption = 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 768719a8647..98b6b412b05 100644 --- a/packager/media/event/mpd_notify_muxer_listener_unittest.cc +++ b/packager/media/event/mpd_notify_muxer_listener_unittest.cc @@ -44,7 +44,6 @@ MediaInfo ConvertToMediaInfo(const std::string& media_info_string) { } void SetDefaultLiveMuxerOptionsValues(media::MuxerOptions* muxer_options) { - muxer_options->single_segment = false; muxer_options->segment_duration = 10.0; muxer_options->fragment_duration = 10.0; muxer_options->segment_sap_aligned = true; diff --git a/packager/media/event/muxer_listener_internal.cc b/packager/media/event/muxer_listener_internal.cc index 9baf8f4d82c..6a937b31824 100644 --- a/packager/media/event/muxer_listener_internal.cc +++ b/packager/media/event/muxer_listener_internal.cc @@ -149,9 +149,8 @@ void SetMediaInfoStreamInfo(const StreamInfo& stream_info, void SetMediaInfoMuxerOptions(const MuxerOptions& muxer_options, MediaInfo* media_info) { DCHECK(media_info); - if (muxer_options.single_segment) { + if (muxer_options.segment_template.empty()) { media_info->set_media_file_name(muxer_options.output_file_name); - DCHECK(muxer_options.segment_template.empty()); } else { media_info->set_init_segment_name(muxer_options.output_file_name); media_info->set_segment_template(muxer_options.segment_template); diff --git a/packager/media/event/muxer_listener_test_helper.cc b/packager/media/event/muxer_listener_test_helper.cc index 11c7ef23f42..38b0f83f065 100644 --- a/packager/media/event/muxer_listener_test_helper.cc +++ b/packager/media/event/muxer_listener_test_helper.cc @@ -73,7 +73,6 @@ OnMediaEndParameters GetDefaultOnMediaEndParams() { } void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) { - muxer_options->single_segment = true; muxer_options->segment_duration = 10.0; muxer_options->fragment_duration = 10.0; muxer_options->segment_sap_aligned = true; diff --git a/packager/media/event/vod_media_info_dump_muxer_listener.cc b/packager/media/event/vod_media_info_dump_muxer_listener.cc index b598df62ba3..d3a07060c6e 100644 --- a/packager/media/event/vod_media_info_dump_muxer_listener.cc +++ b/packager/media/event/vod_media_info_dump_muxer_listener.cc @@ -45,7 +45,7 @@ void VodMediaInfoDumpMuxerListener::OnMediaStart( const StreamInfo& stream_info, uint32_t time_scale, ContainerType container_type) { - DCHECK(muxer_options.single_segment); + DCHECK(muxer_options.segment_template.empty()); media_info_.reset(new MediaInfo()); if (!internal::GenerateMediaInfo(muxer_options, stream_info, diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc index aac6028c563..58fbbdb554f 100644 --- a/packager/media/formats/mp4/mp4_muxer.cc +++ b/packager/media/formats/mp4/mp4_muxer.cc @@ -134,7 +134,7 @@ Status MP4Muxer::Initialize() { } } - if (options().single_segment) { + if (options().segment_template.empty()) { segmenter_.reset(new SingleSegmentSegmenter(options(), std::move(ftyp), std::move(moov))); } else { diff --git a/packager/media/formats/webm/multi_segment_segmenter_unittest.cc b/packager/media/formats/webm/multi_segment_segmenter_unittest.cc index 93faec2c3d5..30888b7516c 100644 --- a/packager/media/formats/webm/multi_segment_segmenter_unittest.cc +++ b/packager/media/formats/webm/multi_segment_segmenter_unittest.cc @@ -6,6 +6,7 @@ #include #include +#include "packager/media/base/muxer_util.h" #include "packager/media/formats/webm/segmenter_test_base.h" namespace shaka { @@ -27,12 +28,10 @@ const uint8_t kBasicSupportDataInit[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // ID: Info, Payload Size: 88 - 0x15, 0x49, 0xa9, 0x66, 0xd8, + // ID: Info, Payload Size: 81 + 0x15, 0x49, 0xa9, 0x66, 0xd1, // TimecodeScale: 1000000 0x2a, 0xd7, 0xb1, 0x83, 0x0f, 0x42, 0x40, - // Duration: float(0) - 0x44, 0x89, 0x84, 0x3f, 0x80, 0x00, 0x00, // MuxingApp: 'libwebm-0.2.1.0' 0x4d, 0x80, 0x8f, 0x6c, 0x69, 0x62, 0x77, 0x65, 0x62, 0x6d, 0x2d, 0x30, 0x2e, 0x32, 0x2e, 0x31, 0x2e, 0x30, @@ -93,7 +92,10 @@ const uint8_t kBasicSupportDataSegment[] = { class MultiSegmentSegmenterTest : public SegmentTestBase { public: - MultiSegmentSegmenterTest() : info_(CreateVideoStreamInfo()) {} + MultiSegmentSegmenterTest() + : info_(CreateVideoStreamInfo()), + segment_template_(std::string(kMemoryFilePrefix) + + "output-template-$Number$.webm") {} protected: void InitializeSegmenter(const MuxerOptions& options) { @@ -102,12 +104,18 @@ class MultiSegmentSegmenterTest : public SegmentTestBase { options, info_.get(), NULL, &segmenter_)); } + std::string TemplateFileName(int number) const { + return GetSegmentName(segment_template_, 0, number, 0); + } + scoped_refptr info_; + std::string segment_template_; std::unique_ptr segmenter_; }; TEST_F(MultiSegmentSegmenterTest, BasicSupport) { MuxerOptions options = CreateMuxerOptions(); + options.segment_template = segment_template_; ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options)); // Write the samples to the Segmenter. @@ -128,6 +136,7 @@ TEST_F(MultiSegmentSegmenterTest, BasicSupport) { TEST_F(MultiSegmentSegmenterTest, SplitsFilesOnSegmentDuration) { MuxerOptions options = CreateMuxerOptions(); + options.segment_template = segment_template_; options.segment_duration = 5; // seconds ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options)); @@ -154,6 +163,7 @@ TEST_F(MultiSegmentSegmenterTest, SplitsFilesOnSegmentDuration) { TEST_F(MultiSegmentSegmenterTest, RespectsSegmentSAPAlign) { MuxerOptions options = CreateMuxerOptions(); + options.segment_template = segment_template_; options.segment_duration = 3; // seconds options.segment_sap_aligned = true; ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options)); @@ -182,6 +192,7 @@ TEST_F(MultiSegmentSegmenterTest, RespectsSegmentSAPAlign) { TEST_F(MultiSegmentSegmenterTest, SplitsClustersOnFragmentDuration) { MuxerOptions options = CreateMuxerOptions(); + options.segment_template = segment_template_; options.fragment_duration = 5; // seconds ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options)); @@ -205,6 +216,7 @@ TEST_F(MultiSegmentSegmenterTest, SplitsClustersOnFragmentDuration) { TEST_F(MultiSegmentSegmenterTest, RespectsFragmentSAPAlign) { MuxerOptions options = CreateMuxerOptions(); + options.segment_template = segment_template_; options.fragment_duration = 3; // seconds options.fragment_sap_aligned = true; ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options)); @@ -230,4 +242,3 @@ TEST_F(MultiSegmentSegmenterTest, RespectsFragmentSAPAlign) { } // namespace media } // namespace shaka - diff --git a/packager/media/formats/webm/segmenter.cc b/packager/media/formats/webm/segmenter.cc index b6310b37ffa..78a0ab9f251 100644 --- a/packager/media/formats/webm/segmenter.cc +++ b/packager/media/formats/webm/segmenter.cc @@ -74,7 +74,7 @@ Status Segmenter::Initialize(std::unique_ptr writer, (GetPackagerProjectUrl() + " version " + version).c_str()); } - if (options().single_segment) { + if (options().segment_template.empty()) { // Set an initial duration so the duration element is written; will be // overwritten at the end. This works because this is a float and floats // are always the same size. diff --git a/packager/media/formats/webm/segmenter_test_base.cc b/packager/media/formats/webm/segmenter_test_base.cc index e994cc66a46..c8573ada706 100644 --- a/packager/media/formats/webm/segmenter_test_base.cc +++ b/packager/media/formats/webm/segmenter_test_base.cc @@ -6,7 +6,6 @@ #include "packager/media/formats/webm/segmenter_test_base.h" -#include "packager/media/base/muxer_util.h" #include "packager/media/file/memory_file.h" #include "packager/media/formats/webm/webm_constants.h" #include "packager/version/version.h" @@ -43,10 +42,7 @@ void SegmentTestBase::SetUp() { SetPackagerVersionForTesting("test"); output_file_name_ = std::string(kMemoryFilePrefix) + "output-file.webm"; - segment_template_ = - std::string(kMemoryFilePrefix) + "output-template-$Number$.webm"; cur_time_timescale_ = 0; - single_segment_ = true; } void SegmentTestBase::TearDown() { @@ -78,9 +74,7 @@ scoped_refptr SegmentTestBase::CreateSample( MuxerOptions SegmentTestBase::CreateMuxerOptions() const { MuxerOptions ret; - ret.single_segment = single_segment_; ret.output_file_name = output_file_name_; - ret.segment_template = segment_template_; ret.segment_duration = 30; // seconds ret.fragment_duration = 30; // seconds ret.segment_sap_aligned = false; @@ -102,10 +96,6 @@ std::string SegmentTestBase::OutputFileName() const { return output_file_name_; } -std::string SegmentTestBase::TemplateFileName(int number) const { - return GetSegmentName(segment_template_, 0, number, 0); -} - SegmentTestBase::ClusterParser::ClusterParser() : in_cluster_(false) {} SegmentTestBase::ClusterParser::~ClusterParser() {} diff --git a/packager/media/formats/webm/webm_muxer.cc b/packager/media/formats/webm/webm_muxer.cc index 9ba07cef845..d32259cbf77 100644 --- a/packager/media/formats/webm/webm_muxer.cc +++ b/packager/media/formats/webm/webm_muxer.cc @@ -43,7 +43,7 @@ Status WebMMuxer::Initialize() { if (!status.ok()) return status; - if (!options().single_segment) { + if (!options().segment_template.empty()) { segmenter_.reset(new MultiSegmentSegmenter(options())); } else { segmenter_.reset(new TwoPassSingleSegmentSegmenter(options())); diff --git a/packager/media/test/packager_test.cc b/packager/media/test/packager_test.cc index 0203447b50a..d89e33eff43 100644 --- a/packager/media/test/packager_test.cc +++ b/packager/media/test/packager_test.cc @@ -140,8 +140,6 @@ bool PackagerTestBasic::ContentsEqual(const std::string& file1, MuxerOptions PackagerTestBasic::SetupOptions(const std::string& output, bool single_segment) { MuxerOptions options; - options.single_segment = single_segment; - options.segment_duration = kSegmentDurationInSeconds; options.fragment_duration = kFragmentDurationInSecodns; options.segment_sap_aligned = kSegmentSapAligned; @@ -149,7 +147,8 @@ MuxerOptions PackagerTestBasic::SetupOptions(const std::string& output, options.num_subsegments_per_sidx = kNumSubsegmentsPerSidx; options.output_file_name = GetFullPath(output); - options.segment_template = GetFullPath(kSegmentTemplate); + if (!single_segment) + options.segment_template = GetFullPath(kSegmentTemplate); options.temp_dir = test_directory_.AsUTF8Unsafe(); return options; } diff --git a/packager/packager.gyp b/packager/packager.gyp index 202e58a1e2e..6347705a0d4 100644 --- a/packager/packager.gyp +++ b/packager/packager.gyp @@ -26,6 +26,8 @@ 'app/packager_main.cc', 'app/packager_util.cc', 'app/packager_util.h', + 'app/retired_flags.cc', + 'app/retired_flags.h', 'app/stream_descriptor.cc', 'app/stream_descriptor.h', 'app/validate_flag.cc',