62Status Segmenter::Initialize(
63 const std::vector<std::shared_ptr<const StreamInfo>>& streams,
66 DCHECK_LT(0u, streams.size());
67 muxer_listener_ = muxer_listener;
68 progress_listener_ = progress_listener;
69 moof_->header.sequence_number = 0;
71 moof_->tracks.resize(streams.size());
72 fragmenters_.resize(streams.size());
73 stream_durations_.resize(streams.size());
75 for (uint32_t i = 0; i < streams.size(); ++i) {
76 moof_->tracks[i].header.track_id = i + 1;
77 if (streams[i]->stream_type() == kStreamVideo) {
79 if (sidx_->reference_id == 0)
80 sidx_->reference_id = i + 1;
83 const EditList& edit_list = moov_->tracks[i].edit.list;
84 int64_t edit_list_offset = 0;
85 if (edit_list.edits.size() > 0) {
86 DCHECK_EQ(edit_list.edits.size(), 1u);
87 edit_list_offset = edit_list.edits.front().media_time;
90 fragmenters_[i].reset(
91 new Fragmenter(streams[i], &moof_->tracks[i], edit_list_offset));
95 if (sidx_->reference_id == 0)
96 sidx_->reference_id = 1;
97 sidx_->timescale = streams[GetReferenceStreamId()]->time_scale();
100 progress_target_ = streams[GetReferenceStreamId()]->duration();
103 moov_->header.timescale = sidx_->timescale;
104 moof_->header.sequence_number = 1;
107 const std::string version = GetPackagerVersion();
108 if (!version.empty()) {
109 moov_->metadata.handler.handler_type = FOURCC_ID32;
110 moov_->metadata.id3v2.language.code =
"eng";
114 CHECK(id3_tag.
WriteToVector(&moov_->metadata.id3v2.id3v2_data));
116 return DoInitialize();
119Status Segmenter::Finalize() {
123 moov_->extends.header.fragment_duration = 0;
124 for (
size_t i = 0; i < stream_durations_.size(); ++i) {
126 Rescale(stream_durations_[i], moov_->tracks[i].media.header.timescale,
127 moov_->header.timescale);
129 static_cast<int64_t
>(moov_->extends.header.fragment_duration))
130 moov_->extends.header.fragment_duration = duration;
135Status Segmenter::AddSample(
size_t stream_id,
const MediaSample& sample) {
137 if (moov_->extends.tracks[stream_id].default_sample_duration == 0) {
138 moov_->extends.tracks[stream_id].default_sample_duration =
142 DCHECK_LT(stream_id, fragmenters_.size());
143 Fragmenter* fragmenter = fragmenters_[stream_id].get();
144 if (fragmenter->fragment_finalized()) {
145 return Status(error::FRAGMENT_FINALIZED,
146 "Current fragment is finalized already.");
149 Status status = fragmenter->
AddSample(sample);
155 if (num_samples_ < 2) {
156 sample_durations_[num_samples_] = sample.duration();
159 stream_durations_[stream_id] += sample.duration();
163Status Segmenter::FinalizeSegment(
size_t stream_id,
165 if (segment_info.key_rotation_encryption_config) {
166 FinalizeFragmentForKeyRotation(
167 stream_id, segment_info.is_encrypted,
168 *segment_info.key_rotation_encryption_config);
171 DCHECK_LT(stream_id, fragmenters_.size());
172 Fragmenter* specified_fragmenter = fragmenters_[stream_id].get();
173 DCHECK(specified_fragmenter);
179 for (
const std::unique_ptr<Fragmenter>& fragmenter : fragmenters_) {
180 if (!fragmenter->fragment_finalized())
189 uint64_t next_traf_position = moof_->HeaderSize() + moof_->header.box_size();
190 for (
size_t i = 0; i < moof_->tracks.size(); ++i) {
192 if (traf.auxiliary_offset.offsets.size() > 0) {
193 DCHECK_EQ(traf.auxiliary_offset.offsets.size(), 1u);
194 DCHECK(!traf.sample_encryption.sample_encryption_entries.empty());
196 next_traf_position += traf.
box_size();
199 traf.auxiliary_offset.offsets[0] =
200 next_traf_position - traf.sample_encryption.
box_size() +
204 traf.runs[0].data_offset = data_offset + mdat.data_size;
205 mdat.data_size +=
static_cast<uint32_t
>(fragmenters_[i]->data()->Size());
209 sidx_->references.resize(sidx_->references.size() + 1);
210 fragmenters_[GetReferenceStreamId()]->GenerateSegmentReference(
211 &sidx_->references[sidx_->references.size() - 1]);
212 sidx_->references[sidx_->references.size() - 1].referenced_size =
213 data_offset + mdat.data_size;
215 const uint64_t moof_start_offset = fragment_buffer_->Size();
218 moof_->Write(fragment_buffer_.get());
221 bool first_key_frame =
true;
222 for (
const std::unique_ptr<Fragmenter>& fragmenter : fragmenters_) {
227 if (!fragmenter->key_frame_infos().empty() && first_key_frame) {
229 fragmenter->key_frame_infos().front();
230 first_key_frame =
false;
231 key_frame_infos_.push_back(
232 {key_frame_info.timestamp, moof_start_offset,
233 fragment_buffer_->Size() - moof_start_offset + key_frame_info.size});
235 fragment_buffer_->AppendBuffer(*fragmenter->data());
239 ++moof_->header.sequence_number;
241 for (std::unique_ptr<Fragmenter>& fragmenter : fragmenters_)
242 fragmenter->ClearFragmentFinalized();
244 if (segment_info.is_chunk) {
246 status = DoFinalizeChunk(segment_info.segment_number);
251 if (!segment_info.is_subsegment || segment_info.is_final_chunk_in_seg) {
253 status = DoFinalizeSegment(segment_info.segment_number);
256 sidx_->references.clear();
257 key_frame_infos_.clear();