7 #include "packager/media/formats/mp4/multi_segment_segmenter.h"
9 #include "packager/base/strings/string_number_conversions.h"
10 #include "packager/base/strings/string_util.h"
11 #include "packager/media/base/buffer_writer.h"
12 #include "packager/media/base/media_stream.h"
13 #include "packager/media/base/muxer_options.h"
14 #include "packager/media/base/muxer_util.h"
15 #include "packager/media/event/muxer_listener.h"
16 #include "packager/media/file/file.h"
17 #include "packager/media/formats/mp4/box_definitions.h"
19 namespace edash_packager {
23 MultiSegmentSegmenter::MultiSegmentSegmenter(
const MuxerOptions& options,
24 scoped_ptr<FileType> ftyp,
25 scoped_ptr<Movie> moov)
26 : Segmenter(options, ftyp.Pass(), moov.Pass()),
27 styp_(new SegmentType),
30 styp_->major_brand = Segmenter::ftyp()->major_brand;
31 styp_->compatible_brands = Segmenter::ftyp()->compatible_brands;
34 MultiSegmentSegmenter::~MultiSegmentSegmenter() {}
37 DLOG(INFO) <<
"MultiSegmentSegmenter outputs init segment: "
43 DLOG(INFO) <<
"MultiSegmentSegmenter does not have index range.";
47 Status MultiSegmentSegmenter::DoInitialize() {
53 return Status(error::FILE_FAILURE,
54 "Cannot open file for write " + options().output_file_name);
57 ftyp()->
Write(buffer.get());
58 moov()->
Write(buffer.get());
59 Status status = buffer->WriteToFile(file);
61 LOG(WARNING) <<
"Failed to close the file properly: "
67 Status MultiSegmentSegmenter::DoFinalize() {
72 Status MultiSegmentSegmenter::DoFinalizeSegment() {
77 sidx()->earliest_presentation_time =
78 sidx()->references[0].earliest_presentation_time;
80 if (options().num_subsegments_per_sidx <= 0)
81 return WriteSegment();
86 uint32_t num_fragments = sidx()->references.size();
87 uint32_t num_fragments_per_subsegment =
89 if (num_fragments_per_subsegment <= 1)
90 return WriteSegment();
92 uint32_t frag_index = 0;
93 uint32_t subseg_index = 0;
94 std::vector<SegmentReference>& refs = sidx()->references;
95 uint64_t first_sap_time =
96 refs[0].sap_delta_time + refs[0].earliest_presentation_time;
97 for (uint32_t i = 1; i < num_fragments; ++i) {
98 refs[subseg_index].referenced_size += refs[i].referenced_size;
99 refs[subseg_index].subsegment_duration += refs[i].subsegment_duration;
100 refs[subseg_index].earliest_presentation_time =
101 std::min(refs[subseg_index].earliest_presentation_time,
102 refs[i].earliest_presentation_time);
103 if (refs[subseg_index].sap_type == SegmentReference::TypeUnknown &&
104 refs[i].sap_type != SegmentReference::TypeUnknown) {
105 refs[subseg_index].sap_type = refs[i].sap_type;
107 refs[i].sap_delta_time + refs[i].earliest_presentation_time;
109 if (++frag_index >= num_fragments_per_subsegment) {
111 if (refs[subseg_index].sap_type != SegmentReference::TypeUnknown) {
112 refs[subseg_index].sap_delta_time =
113 first_sap_time - refs[subseg_index].earliest_presentation_time;
115 if (++i >= num_fragments)
117 refs[++subseg_index] = refs[i];
119 refs[i].sap_delta_time + refs[i].earliest_presentation_time;
124 refs.resize(options().num_subsegments_per_sidx);
128 sidx()->earliest_presentation_time = refs[0].earliest_presentation_time;
130 return WriteSegment();
133 Status MultiSegmentSegmenter::WriteSegment() {
135 DCHECK(fragment_buffer());
138 scoped_ptr<BufferWriter> buffer(
new BufferWriter());
140 std::string file_name;
141 if (options().segment_template.empty()) {
148 "Cannot open file for append " + options().output_file_name);
151 file =
File::Open(GetSegmentName(options().segment_template,
152 sidx()->earliest_presentation_time,
154 options().bandwidth).c_str(),
157 return Status(error::FILE_FAILURE,
158 "Cannot open file for write " + file_name);
160 styp_->Write(buffer.get());
165 sidx()->
Write(buffer.get());
167 const size_t segment_size = buffer->Size() + fragment_buffer()->Size();
168 DCHECK_NE(segment_size, 0u);
170 Status status = buffer->WriteToFile(file);
175 LOG(WARNING) <<
"Failed to close the file properly: " << file_name;
180 uint64_t segment_duration = 0;
183 for (
size_t i = 0; i < sidx()->references.size(); ++i)
184 segment_duration += sidx()->references[i].subsegment_duration;
187 if (muxer_listener()) {
189 muxer_listener()->OnNewSegment(
190 sidx()->earliest_presentation_time, segment_duration, segment_size);