Drepcate --num_subsegments_per_sidx
This flag was designed for two purpose: - Grouping fragments into subsegments, achieving three level hierarchy: segment < subsegment < fragment. - Indicate whether to generate 'sidx' box in media segments (when the value is set to a negative number). There are no practical use case for the first purpose. Removing it to simplify the code and reduce the confusion. Introduce another flag --generate_sidx_in_media_segments for the second purpose. Change-Id: I4be7cd42662fb324c1158b978e05768ee49dd048
This commit is contained in:
parent
f089d1d0d4
commit
1742e03471
|
@ -9,9 +9,9 @@ MP4 output options
|
|||
|
||||
Deprecated. Do not use.
|
||||
|
||||
--num_subsegments_per_sidx <number>
|
||||
--generate_sidx_in_media_segments
|
||||
--nogenerate_sidx_in_media_segments
|
||||
|
||||
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 packs N
|
||||
subsegments in the root SIDX of the segment, with
|
||||
segment_duration/N/fragment_duration fragments per subsegment.
|
||||
For MP4 with DASH live profile only: Indicates whether to generate 'sidx'
|
||||
box in media segments. Note that it is reuqired by spec if segment template
|
||||
contains $Time$ specifier.
|
||||
|
|
|
@ -29,14 +29,11 @@ DEFINE_bool(fragment_sap_aligned,
|
|||
true,
|
||||
"Force fragments to begin with stream access points. This flag "
|
||||
"implies segment_sap_aligned.");
|
||||
DEFINE_int32(num_subsegments_per_sidx,
|
||||
1,
|
||||
"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 packs N "
|
||||
"subsegments in the root SIDX of the segment, with "
|
||||
"segment_duration/N/fragment_duration fragments per "
|
||||
"subsegment.");
|
||||
DEFINE_bool(generate_sidx_in_media_segments,
|
||||
true,
|
||||
"For ISO BMFF with DASH live profile only. Indicates whether to "
|
||||
"generate 'sidx' box in media segments. Note that it is required "
|
||||
"by spec if segment template contains $Time$ specifier.");
|
||||
DEFINE_string(temp_dir,
|
||||
"",
|
||||
"Specify a directory in which to store temporary (intermediate) "
|
||||
|
|
|
@ -16,7 +16,7 @@ DECLARE_double(segment_duration);
|
|||
DECLARE_bool(segment_sap_aligned);
|
||||
DECLARE_double(fragment_duration);
|
||||
DECLARE_bool(fragment_sap_aligned);
|
||||
DECLARE_int32(num_subsegments_per_sidx);
|
||||
DECLARE_bool(generate_sidx_in_media_segments);
|
||||
DECLARE_string(temp_dir);
|
||||
DECLARE_bool(mp4_include_pssh_in_stream);
|
||||
|
||||
|
|
|
@ -377,7 +377,8 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
|||
}
|
||||
|
||||
Mp4OutputParams& mp4_params = packaging_params.mp4_output_params;
|
||||
mp4_params.num_subsegments_per_sidx = FLAGS_num_subsegments_per_sidx;
|
||||
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;
|
||||
|
||||
packaging_params.output_media_info = FLAGS_output_media_info;
|
||||
|
|
|
@ -31,6 +31,10 @@ DEFINE_string(playready_key,
|
|||
DEFINE_bool(mp4_use_decoding_timestamp_in_timeline,
|
||||
false,
|
||||
"This flag is deprecated. Do not use.");
|
||||
DEFINE_int32(
|
||||
num_subsegments_per_sidx,
|
||||
0,
|
||||
"This flag is deprecated. Use --generate_sidx_in_media_segments instead.");
|
||||
|
||||
// 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,
|
||||
|
@ -60,6 +64,12 @@ bool InformRetiredDefaultDoubleFlag(const char* flagname, double value) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool InformRetiredDefaultInt32Flag(const char* flagname, int32_t value) {
|
||||
if (value != 0)
|
||||
fprintf(stderr, "WARNING: %s is deprecated and ignored.\n", flagname);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_validator(profile, &InformRetiredStringFlag);
|
||||
DEFINE_validator(single_segment, &InformRetiredDefaultTrueFlag);
|
||||
DEFINE_validator(webm_subsample_encryption, &InformRetiredDefaultTrueFlag);
|
||||
|
@ -68,3 +78,4 @@ DEFINE_validator(playready_key_id, &InformRetiredStringFlag);
|
|||
DEFINE_validator(playready_key, &InformRetiredStringFlag);
|
||||
DEFINE_validator(mp4_use_decoding_timestamp_in_timeline,
|
||||
&InformRetiredDefaultFalseFlag);
|
||||
DEFINE_validator(num_subsegments_per_sidx, &InformRetiredDefaultInt32Flag);
|
||||
|
|
|
@ -13,3 +13,4 @@ DECLARE_double(availability_time_offset);
|
|||
DECLARE_string(playready_key_id);
|
||||
DECLARE_string(playready_key);
|
||||
DECLARE_bool(mp4_use_decoding_timestamp_in_timeline);
|
||||
DECLARE_int32(num_subsegments_per_sidx);
|
||||
|
|
|
@ -46,7 +46,6 @@ MediaInfo ConvertToMediaInfo(const std::string& media_info_string) {
|
|||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -87,7 +87,6 @@ OnMediaEndParameters GetDefaultOnMediaEndParams() {
|
|||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -68,63 +68,6 @@ Status MultiSegmentSegmenter::DoFinalize() {
|
|||
}
|
||||
|
||||
Status MultiSegmentSegmenter::DoFinalizeSegment() {
|
||||
DCHECK(sidx());
|
||||
// earliest_presentation_time is the earliest presentation time of any
|
||||
// access unit in the reference stream in the first subsegment.
|
||||
// It will be re-calculated later when subsegments are finalized.
|
||||
sidx()->earliest_presentation_time =
|
||||
sidx()->references[0].earliest_presentation_time;
|
||||
|
||||
if (options().mp4_params.num_subsegments_per_sidx <= 0)
|
||||
return WriteSegment();
|
||||
|
||||
// sidx() contains pre-generated segment references with one reference per
|
||||
// fragment. Calculate |num_fragments_per_subsegment| and combine
|
||||
// pre-generated references into final subsegment references.
|
||||
size_t num_fragments = sidx()->references.size();
|
||||
size_t num_fragments_per_subsegment =
|
||||
(num_fragments - 1) / options().mp4_params.num_subsegments_per_sidx + 1;
|
||||
if (num_fragments_per_subsegment <= 1)
|
||||
return WriteSegment();
|
||||
|
||||
size_t frag_index = 0;
|
||||
size_t subseg_index = 0;
|
||||
std::vector<SegmentReference>& refs = sidx()->references;
|
||||
uint64_t first_sap_time =
|
||||
refs[0].sap_delta_time + refs[0].earliest_presentation_time;
|
||||
for (size_t i = 1; i < num_fragments; ++i) {
|
||||
refs[subseg_index].referenced_size += refs[i].referenced_size;
|
||||
refs[subseg_index].subsegment_duration += refs[i].subsegment_duration;
|
||||
refs[subseg_index].earliest_presentation_time =
|
||||
std::min(refs[subseg_index].earliest_presentation_time,
|
||||
refs[i].earliest_presentation_time);
|
||||
if (refs[subseg_index].sap_type == SegmentReference::TypeUnknown &&
|
||||
refs[i].sap_type != SegmentReference::TypeUnknown) {
|
||||
refs[subseg_index].sap_type = refs[i].sap_type;
|
||||
first_sap_time =
|
||||
refs[i].sap_delta_time + refs[i].earliest_presentation_time;
|
||||
}
|
||||
if (++frag_index >= num_fragments_per_subsegment) {
|
||||
// Calculate sap delta time w.r.t. sidx_->earliest_presentation_time.
|
||||
if (refs[subseg_index].sap_type != SegmentReference::TypeUnknown) {
|
||||
refs[subseg_index].sap_delta_time =
|
||||
first_sap_time - refs[subseg_index].earliest_presentation_time;
|
||||
}
|
||||
if (++i >= num_fragments)
|
||||
break;
|
||||
refs[++subseg_index] = refs[i];
|
||||
first_sap_time =
|
||||
refs[i].sap_delta_time + refs[i].earliest_presentation_time;
|
||||
frag_index = 1;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
sidx()->earliest_presentation_time = refs[0].earliest_presentation_time;
|
||||
|
||||
return WriteSegment();
|
||||
}
|
||||
|
||||
|
@ -172,9 +115,15 @@ Status MultiSegmentSegmenter::WriteSegment() {
|
|||
styp_->Write(buffer.get());
|
||||
}
|
||||
|
||||
// If num_subsegments_per_sidx is negative, no SIDX box is generated.
|
||||
if (options().mp4_params.num_subsegments_per_sidx >= 0)
|
||||
if (options().mp4_params.generate_sidx_in_media_segments) {
|
||||
DCHECK(sidx());
|
||||
DCHECK(!sidx()->references.empty());
|
||||
// earliest_presentation_time is the earliest presentation time of any
|
||||
// access unit in the reference stream in the first subsegment.
|
||||
sidx()->earliest_presentation_time =
|
||||
sidx()->references[0].earliest_presentation_time;
|
||||
sidx()->Write(buffer.get());
|
||||
}
|
||||
|
||||
const size_t segment_header_size = buffer->Size();
|
||||
const size_t segment_size = segment_header_size + fragment_buffer()->Size();
|
||||
|
|
|
@ -15,19 +15,11 @@ namespace mp4 {
|
|||
|
||||
struct SegmentType;
|
||||
|
||||
/// Segmenter for MP4 live, main and simple profiles. The generated media file
|
||||
/// can contain one or many segments with segment duration defined by @b
|
||||
/// MuxerOptions.segment_duration. A segment can contain one or many
|
||||
/// subsegments defined by @b num_subsegments_per_sidx. A subsegment can
|
||||
/// contain one or many fragments with fragment duration defined by @b
|
||||
/// MuxerOptions.fragment_duration. The actual segment or fragment duration
|
||||
/// may not match the requested duration exactly, but will be approximated.
|
||||
/// That is, the Segmenter tries to end segment/fragment at the first sample
|
||||
/// with overall segment/fragment duration not smaller than defined duration
|
||||
/// and yet meet SAP requirements. The generated segments are written to files
|
||||
/// defined by @b MuxerOptions.segment_template if specified; otherwise,
|
||||
/// the segments are appended to the main output file specified by @b
|
||||
/// MuxerOptions.output_file_name.
|
||||
/// Segmenter for MP4 live, main and simple profiles. There can be multiple
|
||||
/// media segments, which can contain multiple fragments. The generated segments
|
||||
/// are written to files defined by @b MuxerOptions.segment_template if
|
||||
/// specified; otherwise, the segments are appended to the main output file
|
||||
/// specified by @b MuxerOptions.output_file_name.
|
||||
class MultiSegmentSegmenter : public Segmenter {
|
||||
public:
|
||||
MultiSegmentSegmenter(const MuxerOptions& options,
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace mp4 {
|
|||
/// is, the Segmenter tries to end subsegment/fragment at the first sample with
|
||||
/// overall subsegment/fragment duration not smaller than defined duration and
|
||||
/// yet meet SAP requirements. SingleSegmentSegmenter ignores @b
|
||||
/// MuxerOptions.num_subsegments_per_sidx.
|
||||
/// MuxerOptions.mp4_params.generate_sidx_in_media_segments.
|
||||
class SingleSegmentSegmenter : public Segmenter {
|
||||
public:
|
||||
SingleSegmentSegmenter(const MuxerOptions& options,
|
||||
|
|
|
@ -11,19 +11,15 @@ 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.)
|
||||
/// 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;
|
||||
/// Indicates whether a 'sidx' box should be generated in the media segments.
|
||||
/// Note that it is required by spec if segment_template contains $Times$
|
||||
/// specifier.
|
||||
bool generate_sidx_in_media_segments = true;
|
||||
};
|
||||
|
||||
} // namespace shaka
|
||||
|
|
Loading…
Reference in New Issue