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.
|
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
|
For MP4 with DASH live profile only: Indicates whether to generate 'sidx'
|
||||||
used per segment; if -1, no SIDX box is used; Otherwise, the muxer packs N
|
box in media segments. Note that it is reuqired by spec if segment template
|
||||||
subsegments in the root SIDX of the segment, with
|
contains $Time$ specifier.
|
||||||
segment_duration/N/fragment_duration fragments per subsegment.
|
|
||||||
|
|
|
@ -29,14 +29,11 @@ DEFINE_bool(fragment_sap_aligned,
|
||||||
true,
|
true,
|
||||||
"Force fragments to begin with stream access points. This flag "
|
"Force fragments to begin with stream access points. This flag "
|
||||||
"implies segment_sap_aligned.");
|
"implies segment_sap_aligned.");
|
||||||
DEFINE_int32(num_subsegments_per_sidx,
|
DEFINE_bool(generate_sidx_in_media_segments,
|
||||||
1,
|
true,
|
||||||
"For ISO BMFF only. Set the number of subsegments in each "
|
"For ISO BMFF with DASH live profile only. Indicates whether to "
|
||||||
"SIDX box. If 0, a single SIDX box is used per segment; if "
|
"generate 'sidx' box in media segments. Note that it is required "
|
||||||
"-1, no SIDX box is used; Otherwise, the muxer packs N "
|
"by spec if segment template contains $Time$ specifier.");
|
||||||
"subsegments in the root SIDX of the segment, with "
|
|
||||||
"segment_duration/N/fragment_duration fragments per "
|
|
||||||
"subsegment.");
|
|
||||||
DEFINE_string(temp_dir,
|
DEFINE_string(temp_dir,
|
||||||
"",
|
"",
|
||||||
"Specify a directory in which to store temporary (intermediate) "
|
"Specify a directory in which to store temporary (intermediate) "
|
||||||
|
|
|
@ -16,7 +16,7 @@ DECLARE_double(segment_duration);
|
||||||
DECLARE_bool(segment_sap_aligned);
|
DECLARE_bool(segment_sap_aligned);
|
||||||
DECLARE_double(fragment_duration);
|
DECLARE_double(fragment_duration);
|
||||||
DECLARE_bool(fragment_sap_aligned);
|
DECLARE_bool(fragment_sap_aligned);
|
||||||
DECLARE_int32(num_subsegments_per_sidx);
|
DECLARE_bool(generate_sidx_in_media_segments);
|
||||||
DECLARE_string(temp_dir);
|
DECLARE_string(temp_dir);
|
||||||
DECLARE_bool(mp4_include_pssh_in_stream);
|
DECLARE_bool(mp4_include_pssh_in_stream);
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,8 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Mp4OutputParams& mp4_params = packaging_params.mp4_output_params;
|
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;
|
mp4_params.include_pssh_in_stream = FLAGS_mp4_include_pssh_in_stream;
|
||||||
|
|
||||||
packaging_params.output_media_info = FLAGS_output_media_info;
|
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,
|
DEFINE_bool(mp4_use_decoding_timestamp_in_timeline,
|
||||||
false,
|
false,
|
||||||
"This flag is deprecated. Do not use.");
|
"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
|
// 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,
|
// 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;
|
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(profile, &InformRetiredStringFlag);
|
||||||
DEFINE_validator(single_segment, &InformRetiredDefaultTrueFlag);
|
DEFINE_validator(single_segment, &InformRetiredDefaultTrueFlag);
|
||||||
DEFINE_validator(webm_subsample_encryption, &InformRetiredDefaultTrueFlag);
|
DEFINE_validator(webm_subsample_encryption, &InformRetiredDefaultTrueFlag);
|
||||||
|
@ -68,3 +78,4 @@ DEFINE_validator(playready_key_id, &InformRetiredStringFlag);
|
||||||
DEFINE_validator(playready_key, &InformRetiredStringFlag);
|
DEFINE_validator(playready_key, &InformRetiredStringFlag);
|
||||||
DEFINE_validator(mp4_use_decoding_timestamp_in_timeline,
|
DEFINE_validator(mp4_use_decoding_timestamp_in_timeline,
|
||||||
&InformRetiredDefaultFalseFlag);
|
&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_id);
|
||||||
DECLARE_string(playready_key);
|
DECLARE_string(playready_key);
|
||||||
DECLARE_bool(mp4_use_decoding_timestamp_in_timeline);
|
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) {
|
void SetDefaultLiveMuxerOptions(media::MuxerOptions* muxer_options) {
|
||||||
muxer_options->mp4_params.num_subsegments_per_sidx = 0;
|
|
||||||
muxer_options->output_file_name = "liveinit.mp4";
|
muxer_options->output_file_name = "liveinit.mp4";
|
||||||
muxer_options->segment_template = "live-$NUMBER$.mp4";
|
muxer_options->segment_template = "live-$NUMBER$.mp4";
|
||||||
muxer_options->temp_dir.clear();
|
muxer_options->temp_dir.clear();
|
||||||
|
|
|
@ -87,7 +87,6 @@ OnMediaEndParameters GetDefaultOnMediaEndParams() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDefaultMuxerOptions(MuxerOptions* muxer_options) {
|
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->output_file_name = "test_output_file_name.mp4";
|
||||||
muxer_options->segment_template.clear();
|
muxer_options->segment_template.clear();
|
||||||
muxer_options->temp_dir.clear();
|
muxer_options->temp_dir.clear();
|
||||||
|
|
|
@ -68,63 +68,6 @@ Status MultiSegmentSegmenter::DoFinalize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MultiSegmentSegmenter::DoFinalizeSegment() {
|
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();
|
return WriteSegment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,9 +115,15 @@ Status MultiSegmentSegmenter::WriteSegment() {
|
||||||
styp_->Write(buffer.get());
|
styp_->Write(buffer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If num_subsegments_per_sidx is negative, no SIDX box is generated.
|
if (options().mp4_params.generate_sidx_in_media_segments) {
|
||||||
if (options().mp4_params.num_subsegments_per_sidx >= 0)
|
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());
|
sidx()->Write(buffer.get());
|
||||||
|
}
|
||||||
|
|
||||||
const size_t segment_header_size = buffer->Size();
|
const size_t segment_header_size = buffer->Size();
|
||||||
const size_t segment_size = segment_header_size + fragment_buffer()->Size();
|
const size_t segment_size = segment_header_size + fragment_buffer()->Size();
|
||||||
|
|
|
@ -15,19 +15,11 @@ namespace mp4 {
|
||||||
|
|
||||||
struct SegmentType;
|
struct SegmentType;
|
||||||
|
|
||||||
/// Segmenter for MP4 live, main and simple profiles. The generated media file
|
/// Segmenter for MP4 live, main and simple profiles. There can be multiple
|
||||||
/// can contain one or many segments with segment duration defined by @b
|
/// media segments, which can contain multiple fragments. The generated segments
|
||||||
/// MuxerOptions.segment_duration. A segment can contain one or many
|
/// are written to files defined by @b MuxerOptions.segment_template if
|
||||||
/// subsegments defined by @b num_subsegments_per_sidx. A subsegment can
|
/// specified; otherwise, the segments are appended to the main output file
|
||||||
/// contain one or many fragments with fragment duration defined by @b
|
/// specified by @b MuxerOptions.output_file_name.
|
||||||
/// 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.
|
|
||||||
class MultiSegmentSegmenter : public Segmenter {
|
class MultiSegmentSegmenter : public Segmenter {
|
||||||
public:
|
public:
|
||||||
MultiSegmentSegmenter(const MuxerOptions& options,
|
MultiSegmentSegmenter(const MuxerOptions& options,
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace mp4 {
|
||||||
/// is, the Segmenter tries to end subsegment/fragment at the first sample with
|
/// is, the Segmenter tries to end subsegment/fragment at the first sample with
|
||||||
/// overall subsegment/fragment duration not smaller than defined duration and
|
/// overall subsegment/fragment duration not smaller than defined duration and
|
||||||
/// yet meet SAP requirements. SingleSegmentSegmenter ignores @b
|
/// yet meet SAP requirements. SingleSegmentSegmenter ignores @b
|
||||||
/// MuxerOptions.num_subsegments_per_sidx.
|
/// MuxerOptions.mp4_params.generate_sidx_in_media_segments.
|
||||||
class SingleSegmentSegmenter : public Segmenter {
|
class SingleSegmentSegmenter : public Segmenter {
|
||||||
public:
|
public:
|
||||||
SingleSegmentSegmenter(const MuxerOptions& options,
|
SingleSegmentSegmenter(const MuxerOptions& options,
|
||||||
|
|
|
@ -11,19 +11,15 @@ namespace shaka {
|
||||||
|
|
||||||
/// MP4 (ISO-BMFF) output related parameters.
|
/// MP4 (ISO-BMFF) output related parameters.
|
||||||
struct Mp4OutputParams {
|
struct Mp4OutputParams {
|
||||||
// Include pssh in the encrypted stream. CMAF and DASH-IF recommends carrying
|
/// Include pssh in the encrypted stream. CMAF and DASH-IF recommends carrying
|
||||||
// license acquisition information in the manifest and not duplicate the
|
/// license acquisition information in the manifest and not duplicate the
|
||||||
// information in the stream. (This is not a hard requirement so we are still
|
/// information in the stream. (This is not a hard requirement so we are still
|
||||||
// CMAF compatible even if pssh is included in the stream.)
|
/// CMAF compatible even if pssh is included in the stream.)
|
||||||
bool include_pssh_in_stream = true;
|
bool include_pssh_in_stream = true;
|
||||||
/// Set the number of subsegments in each SIDX box. If 0, a single SIDX box
|
/// Indicates whether a 'sidx' box should be generated in the media segments.
|
||||||
/// is used per segment. If -1, no SIDX box is used. Otherwise, the Muxer
|
/// Note that it is required by spec if segment_template contains $Times$
|
||||||
/// will pack N subsegments in the root SIDX of the segment, with
|
/// specifier.
|
||||||
/// segment_duration/N/subsegment_duration fragments per subsegment.
|
bool generate_sidx_in_media_segments = true;
|
||||||
/// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
Loading…
Reference in New Issue