7 #include "packager/media/formats/mp4/fragmenter.h" 12 #include "packager/media/base/audio_stream_info.h" 13 #include "packager/media/base/buffer_writer.h" 14 #include "packager/media/base/media_sample.h" 15 #include "packager/media/formats/mp4/box_definitions.h" 16 #include "packager/media/formats/mp4/key_frame_info.h" 23 const int64_t kInvalidTime = std::numeric_limits<int64_t>::max();
25 uint64_t GetSeekPreroll(
const StreamInfo& stream_info) {
26 if (stream_info.stream_type() != kStreamAudio)
28 const AudioStreamInfo& audio_stream_info =
29 static_cast<const AudioStreamInfo&
>(stream_info);
30 return audio_stream_info.seek_preroll_ns();
33 void NewSampleEncryptionEntry(
const DecryptConfig& decrypt_config,
35 TrackFragment* traf) {
36 SampleEncryption& sample_encryption = traf->sample_encryption;
37 SampleEncryptionEntry sample_encryption_entry;
39 sample_encryption_entry.initialization_vector = decrypt_config.iv();
40 sample_encryption_entry.subsamples = decrypt_config.subsamples();
41 sample_encryption.sample_encryption_entries.push_back(
42 sample_encryption_entry);
43 traf->auxiliary_size.sample_info_sizes.push_back(
44 sample_encryption_entry.ComputeSize());
51 : stream_info_(
std::move(stream_info)),
52 use_decoding_timestamp_in_timeline_(false),
54 seek_preroll_(GetSeekPreroll(*stream_info_)),
55 fragment_initialized_(false),
56 fragment_finalized_(false),
57 fragment_duration_(0),
58 earliest_presentation_time_(kInvalidTime),
59 first_sap_time_(kInvalidTime) {
64 Fragmenter::~Fragmenter() {}
67 if (sample.duration() == 0) {
68 LOG(WARNING) <<
"Unexpected sample with zero duration @ dts " 72 if (!fragment_initialized_) {
78 if (sample.side_data_size() > 0)
79 LOG(WARNING) <<
"MP4 samples do not support side data. Side data ignored.";
82 traf_->runs[0].sample_sizes.push_back(
83 static_cast<uint32_t>(sample.data_size()));
84 traf_->runs[0].sample_durations.push_back(sample.duration());
85 traf_->runs[0].sample_flags.push_back(
86 sample.is_key_frame() ? 0 : 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({
static_cast<uint64_t
>(sample.pts()),
97 data_->Size(), sample.data_size()});
100 data_->AppendArray(sample.data(), sample.data_size());
101 fragment_duration_ += sample.duration();
103 const int64_t pts = sample.pts();
104 const int64_t dts = sample.dts();
106 const int64_t timestamp = use_decoding_timestamp_in_timeline_ ? dts : pts;
109 if (earliest_presentation_time_ > timestamp)
110 earliest_presentation_time_ = timestamp;
112 traf_->runs[0].sample_composition_time_offsets.push_back(pts - dts);
114 traf_->runs[0].flags |= TrackFragmentRun::kSampleCompTimeOffsetsPresentMask;
116 if (sample.is_key_frame()) {
117 if (first_sap_time_ == kInvalidTime)
118 first_sap_time_ = pts;
124 fragment_initialized_ =
true;
125 fragment_finalized_ =
false;
126 traf_->decode_time.decode_time = first_sample_dts;
128 traf_->runs.resize(1);
129 traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
130 traf_->auxiliary_size.sample_info_sizes.clear();
131 traf_->auxiliary_offset.offsets.clear();
132 traf_->sample_encryption.sample_encryption_entries.clear();
133 traf_->sample_group_descriptions.clear();
134 traf_->sample_to_groups.clear();
135 traf_->header.sample_description_index = 1;
136 traf_->header.flags = TrackFragmentHeader::kDefaultBaseIsMoofMask |
137 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
139 fragment_duration_ = 0;
140 earliest_presentation_time_ = kInvalidTime;
141 first_sap_time_ = kInvalidTime;
143 key_frame_infos_.clear();
148 if (stream_info_->is_encrypted()) {
149 Status status = FinalizeFragmentForEncryption();
154 if (first_fragment_) {
155 if (allow_adjust_earliest_presentation_time_) {
164 const int64_t dts = traf_->decode_time.decode_time;
165 if (earliest_presentation_time_ > dts) {
166 const uint64_t delta = earliest_presentation_time_ - dts;
167 earliest_presentation_time_ = dts;
168 fragment_duration_ += delta;
171 first_fragment_ =
false;
175 traf_->runs[0].sample_count =
176 static_cast<uint32_t
>(traf_->runs[0].sample_sizes.size());
178 &traf_->header.default_sample_duration)) {
179 traf_->header.flags |=
180 TrackFragmentHeader::kDefaultSampleDurationPresentMask;
182 traf_->runs[0].flags |= TrackFragmentRun::kSampleDurationPresentMask;
185 &traf_->header.default_sample_size)) {
186 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleSizePresentMask;
188 traf_->runs[0].flags |= TrackFragmentRun::kSampleSizePresentMask;
191 &traf_->header.default_sample_flags)) {
192 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleFlagsPresentMask;
194 traf_->runs[0].flags |= TrackFragmentRun::kSampleFlagsPresentMask;
202 DCHECK_EQ(traf_->sample_to_groups.size(), 0u);
203 if (seek_preroll_ > 0) {
204 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
205 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
206 sample_to_group.grouping_type = FOURCC_roll;
208 sample_to_group.entries.resize(1);
210 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
211 sample_to_group_entry.group_description_index =
212 SampleToGroupEntry::kTrackGroupDescriptionIndexBase + 1;
214 for (
const auto& sample_group_description :
215 traf_->sample_group_descriptions) {
216 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
217 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
218 sample_to_group.grouping_type = sample_group_description.grouping_type;
220 sample_to_group.entries.resize(1);
222 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
223 sample_to_group_entry.group_description_index =
224 SampleToGroupEntry::kTrackFragmentGroupDescriptionIndexBase + 1;
227 fragment_finalized_ =
true;
228 fragment_initialized_ =
false;
234 reference->reference_type =
false;
235 reference->subsegment_duration = fragment_duration_;
236 reference->starts_with_sap = StartsWithSAP();
237 if (kInvalidTime == first_sap_time_) {
238 reference->sap_type = SegmentReference::TypeUnknown;
239 reference->sap_delta_time = 0;
241 reference->sap_type = SegmentReference::Type1;
242 reference->sap_delta_time = first_sap_time_ - earliest_presentation_time_;
244 reference->earliest_presentation_time = earliest_presentation_time_;
247 Status Fragmenter::FinalizeFragmentForEncryption() {
249 if (sample_encryption.sample_encryption_entries.empty()) {
253 const uint32_t kClearSampleDescriptionIndex = 2;
254 traf_->header.sample_description_index = kClearSampleDescriptionIndex;
257 if (sample_encryption.sample_encryption_entries.size() !=
258 traf_->runs[0].sample_sizes.size()) {
259 LOG(ERROR) <<
"Partially encrypted segment is not supported";
260 return Status(error::MUXER_FAILURE,
261 "Partially encrypted segment is not supported.");
265 sample_encryption.sample_encryption_entries.front();
266 const bool use_subsample_encryption =
267 !sample_encryption_entry.subsamples.empty();
268 if (use_subsample_encryption)
269 traf_->sample_encryption.flags |= SampleEncryption::kUseSubsampleEncryption;
270 traf_->sample_encryption.iv_size =
static_cast<uint8_t
>(
271 sample_encryption_entry.initialization_vector.size());
274 traf_->auxiliary_offset.offsets.push_back(0);
278 saiz.sample_count =
static_cast<uint32_t
>(saiz.sample_info_sizes.size());
279 DCHECK_EQ(saiz.sample_info_sizes.size(),
280 traf_->sample_encryption.sample_encryption_entries.size());
282 &saiz.default_sample_info_size)) {
283 saiz.default_sample_info_size = 0;
288 if (saiz.default_sample_info_size == 0 && saiz.sample_info_sizes.empty()) {
289 DCHECK(!use_subsample_encryption);
293 saiz.sample_count = 0;
294 traf_->auxiliary_offset.offsets.clear();
299 bool Fragmenter::StartsWithSAP()
const {
300 DCHECK(!traf_->runs.empty());
301 uint32_t start_sample_flag;
302 if (traf_->runs[0].flags & TrackFragmentRun::kSampleFlagsPresentMask) {
303 DCHECK(!traf_->runs[0].sample_flags.empty());
304 start_sample_flag = traf_->runs[0].sample_flags[0];
306 DCHECK(traf_->header.flags &
307 TrackFragmentHeader::kDefaultSampleFlagsPresentMask);
308 start_sample_flag = traf_->header.default_sample_flags;
310 return (start_sample_flag & TrackFragmentHeader::kNonKeySampleMask) == 0;
All the methods that are virtual are virtual for mocking.