7 #include <packager/media/formats/mp4/fragmenter.h>
12 #include <absl/log/check.h>
14 #include <packager/macros/status.h>
15 #include <packager/media/base/audio_stream_info.h>
16 #include <packager/media/base/buffer_writer.h>
17 #include <packager/media/base/media_sample.h>
18 #include <packager/media/formats/mp4/box_definitions.h>
19 #include <packager/media/formats/mp4/key_frame_info.h>
26 const int64_t kInvalidTime = std::numeric_limits<int64_t>::max();
28 int64_t GetSeekPreroll(
const StreamInfo& stream_info) {
29 if (stream_info.stream_type() != kStreamAudio)
31 const AudioStreamInfo& audio_stream_info =
32 static_cast<const AudioStreamInfo&
>(stream_info);
33 return audio_stream_info.seek_preroll_ns();
36 void NewSampleEncryptionEntry(
const DecryptConfig& decrypt_config,
38 TrackFragment* traf) {
39 SampleEncryption& sample_encryption = traf->sample_encryption;
40 SampleEncryptionEntry sample_encryption_entry;
42 sample_encryption_entry.initialization_vector = decrypt_config.iv();
43 sample_encryption_entry.subsamples = decrypt_config.subsamples();
44 sample_encryption.sample_encryption_entries.push_back(
45 sample_encryption_entry);
46 traf->auxiliary_size.sample_info_sizes.push_back(
47 sample_encryption_entry.ComputeSize());
54 int64_t edit_list_offset)
55 : stream_info_(std::move(stream_info)),
57 edit_list_offset_(edit_list_offset),
58 seek_preroll_(GetSeekPreroll(*stream_info_)),
59 earliest_presentation_time_(kInvalidTime),
60 first_sap_time_(kInvalidTime) {
65 Fragmenter::~Fragmenter() {}
68 const int64_t pts = sample.pts();
69 const int64_t dts = sample.dts();
70 const int64_t duration = sample.duration();
72 LOG(WARNING) <<
"Unexpected sample with zero duration @ dts " << dts;
74 if (!fragment_initialized_)
77 if (sample.side_data_size() > 0)
78 LOG(WARNING) <<
"MP4 samples do not support side data. Side data ignored.";
81 traf_->runs[0].sample_sizes.push_back(
82 static_cast<uint32_t
>(sample.data_size()));
83 traf_->runs[0].sample_durations.push_back(duration);
84 traf_->runs[0].sample_flags.push_back(
85 sample.is_key_frame() ? TrackFragmentHeader::kUnset
86 : TrackFragmentHeader::kNonKeySampleMask);
88 if (sample.decrypt_config()) {
89 NewSampleEncryptionEntry(
90 *sample.decrypt_config(),
91 !stream_info_->encryption_config().constant_iv.empty(), traf_);
94 if (stream_info_->stream_type() == StreamType::kStreamVideo &&
95 sample.is_key_frame()) {
96 key_frame_infos_.push_back({pts, data_->Size(), sample.data_size()});
99 data_->AppendArray(sample.data(), sample.data_size());
101 traf_->runs[0].sample_composition_time_offsets.push_back(pts - dts);
103 traf_->runs[0].flags |= TrackFragmentRun::kSampleCompTimeOffsetsPresentMask;
108 const int64_t end_pts = pts + duration;
111 fragment_duration_ += end_pts;
113 earliest_presentation_time_ = 0;
114 if (sample.is_key_frame())
118 fragment_duration_ += duration;
120 if (earliest_presentation_time_ > pts)
121 earliest_presentation_time_ = pts;
123 if (sample.is_key_frame()) {
124 if (first_sap_time_ == kInvalidTime)
125 first_sap_time_ = pts;
132 fragment_initialized_ =
true;
133 fragment_finalized_ =
false;
138 const int64_t dts_before_edit = first_sample_dts + edit_list_offset_;
139 traf_->decode_time.decode_time = dts_before_edit;
142 traf_->runs.resize(1);
143 traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
144 traf_->auxiliary_size.sample_info_sizes.clear();
145 traf_->auxiliary_offset.offsets.clear();
146 traf_->sample_encryption.sample_encryption_entries.clear();
147 traf_->sample_group_descriptions.clear();
148 traf_->sample_to_groups.clear();
149 traf_->header.sample_description_index = 1;
150 traf_->header.flags = TrackFragmentHeader::kDefaultBaseIsMoofMask |
151 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
153 fragment_duration_ = 0;
154 earliest_presentation_time_ = kInvalidTime;
155 first_sap_time_ = kInvalidTime;
157 key_frame_infos_.clear();
162 if (!fragment_initialized_)
165 if (stream_info_->is_encrypted()) {
166 Status status = FinalizeFragmentForEncryption();
172 traf_->runs[0].sample_count =
173 static_cast<uint32_t
>(traf_->runs[0].sample_sizes.size());
175 &traf_->header.default_sample_duration)) {
176 traf_->header.flags |=
177 TrackFragmentHeader::kDefaultSampleDurationPresentMask;
179 traf_->runs[0].flags |= TrackFragmentRun::kSampleDurationPresentMask;
182 &traf_->header.default_sample_size)) {
183 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleSizePresentMask;
185 traf_->runs[0].flags |= TrackFragmentRun::kSampleSizePresentMask;
188 &traf_->header.default_sample_flags)) {
189 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleFlagsPresentMask;
191 traf_->runs[0].flags |= TrackFragmentRun::kSampleFlagsPresentMask;
199 DCHECK_EQ(traf_->sample_to_groups.size(), 0u);
200 if (seek_preroll_ > 0) {
201 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
202 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
203 sample_to_group.grouping_type = FOURCC_roll;
205 sample_to_group.entries.resize(1);
207 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
208 sample_to_group_entry.group_description_index =
209 SampleToGroupEntry::kTrackGroupDescriptionIndexBase + 1;
211 for (
const auto& sample_group_description :
212 traf_->sample_group_descriptions) {
213 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
214 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
215 sample_to_group.grouping_type = sample_group_description.grouping_type;
217 sample_to_group.entries.resize(1);
219 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
220 sample_to_group_entry.group_description_index =
221 SampleToGroupEntry::kTrackFragmentGroupDescriptionIndexBase + 1;
224 fragment_finalized_ =
true;
225 fragment_initialized_ =
false;
231 reference->reference_type =
false;
232 reference->subsegment_duration = fragment_duration_;
233 reference->starts_with_sap = StartsWithSAP();
234 if (kInvalidTime == first_sap_time_) {
235 reference->sap_type = SegmentReference::TypeUnknown;
236 reference->sap_delta_time = 0;
238 reference->sap_type = SegmentReference::Type1;
239 reference->sap_delta_time = first_sap_time_ - earliest_presentation_time_;
241 reference->earliest_presentation_time = earliest_presentation_time_;
244 Status Fragmenter::FinalizeFragmentForEncryption() {
246 if (sample_encryption.sample_encryption_entries.empty()) {
250 const uint32_t kClearSampleDescriptionIndex = 2;
251 traf_->header.sample_description_index = kClearSampleDescriptionIndex;
254 if (sample_encryption.sample_encryption_entries.size() !=
255 traf_->runs[0].sample_sizes.size()) {
256 LOG(ERROR) <<
"Partially encrypted segment is not supported";
257 return Status(error::MUXER_FAILURE,
258 "Partially encrypted segment is not supported.");
261 const SampleEncryptionEntry& sample_encryption_entry =
262 sample_encryption.sample_encryption_entries.front();
263 const bool use_subsample_encryption =
264 !sample_encryption_entry.subsamples.empty();
265 if (use_subsample_encryption)
266 traf_->sample_encryption.flags |= SampleEncryption::kUseSubsampleEncryption;
267 traf_->sample_encryption.iv_size =
static_cast<uint8_t
>(
268 sample_encryption_entry.initialization_vector.size());
271 traf_->auxiliary_offset.offsets.push_back(0);
274 SampleAuxiliaryInformationSize& saiz = traf_->auxiliary_size;
275 saiz.sample_count =
static_cast<uint32_t
>(saiz.sample_info_sizes.size());
276 DCHECK_EQ(saiz.sample_info_sizes.size(),
277 traf_->sample_encryption.sample_encryption_entries.size());
279 &saiz.default_sample_info_size)) {
280 saiz.default_sample_info_size = 0;
285 if (saiz.default_sample_info_size == 0 && saiz.sample_info_sizes.empty()) {
286 DCHECK(!use_subsample_encryption);
290 saiz.sample_count = 0;
291 traf_->auxiliary_offset.offsets.clear();
296 bool Fragmenter::StartsWithSAP()
const {
297 DCHECK(!traf_->runs.empty());
298 uint32_t start_sample_flag;
299 if (traf_->runs[0].flags & TrackFragmentRun::kSampleFlagsPresentMask) {
300 DCHECK(!traf_->runs[0].sample_flags.empty());
301 start_sample_flag = traf_->runs[0].sample_flags[0];
303 DCHECK(traf_->header.flags &
304 TrackFragmentHeader::kDefaultSampleFlagsPresentMask);
305 start_sample_flag = traf_->header.default_sample_flags;
307 return (start_sample_flag & TrackFragmentHeader::kNonKeySampleMask) == 0;
All the methods that are virtual are virtual for mocking.