7 #include "packager/media/formats/mp4/fragmenter.h"
11 #include "packager/media/base/buffer_writer.h"
12 #include "packager/media/base/audio_stream_info.h"
13 #include "packager/media/base/media_sample.h"
14 #include "packager/media/formats/mp4/box_definitions.h"
21 const int64_t kInvalidTime = std::numeric_limits<int64_t>::max();
23 uint64_t GetSeekPreroll(
const StreamInfo& stream_info) {
24 if (stream_info.stream_type() != kStreamAudio)
26 const AudioStreamInfo& audio_stream_info =
27 static_cast<const AudioStreamInfo&
>(stream_info);
28 return audio_stream_info.seek_preroll_ns();
31 void NewSampleEncryptionEntry(
const DecryptConfig& decrypt_config,
33 TrackFragment* traf) {
34 SampleEncryption& sample_encryption = traf->sample_encryption;
35 SampleEncryptionEntry sample_encryption_entry;
37 sample_encryption_entry.initialization_vector = decrypt_config.iv();
38 sample_encryption_entry.subsamples = decrypt_config.subsamples();
39 sample_encryption.sample_encryption_entries.push_back(
40 sample_encryption_entry);
41 traf->auxiliary_size.sample_info_sizes.push_back(
42 sample_encryption_entry.ComputeSize());
49 : stream_info_(std::move(stream_info)),
50 use_decoding_timestamp_in_timeline_(false),
52 seek_preroll_(GetSeekPreroll(*stream_info_)),
53 fragment_initialized_(false),
54 fragment_finalized_(false),
55 fragment_duration_(0),
56 earliest_presentation_time_(kInvalidTime),
57 first_sap_time_(kInvalidTime) {
62 Fragmenter::~Fragmenter() {}
66 if (sample->duration() == 0) {
67 LOG(WARNING) <<
"Unexpected sample with zero duration @ dts "
71 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(sample->duration());
84 traf_->runs[0].sample_flags.push_back(
85 sample->is_key_frame() ? 0 : TrackFragmentHeader::kNonKeySampleMask);
87 if (sample->decrypt_config()) {
88 NewSampleEncryptionEntry(
89 *sample->decrypt_config(),
90 !stream_info_->encryption_config().constant_iv.empty(), traf_);
93 data_->AppendArray(sample->data(), sample->data_size());
94 fragment_duration_ += sample->duration();
96 const int64_t pts = sample->pts();
97 const int64_t dts = sample->dts();
99 const int64_t timestamp = use_decoding_timestamp_in_timeline_ ? dts : pts;
102 if (earliest_presentation_time_ > timestamp)
103 earliest_presentation_time_ = timestamp;
105 traf_->runs[0].sample_composition_time_offsets.push_back(pts - dts);
107 traf_->runs[0].flags |= TrackFragmentRun::kSampleCompTimeOffsetsPresentMask;
109 if (sample->is_key_frame()) {
110 if (first_sap_time_ == kInvalidTime)
111 first_sap_time_ = pts;
117 fragment_initialized_ =
true;
118 fragment_finalized_ =
false;
119 traf_->decode_time.decode_time = first_sample_dts;
121 traf_->runs.resize(1);
122 traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
123 traf_->auxiliary_size.sample_info_sizes.clear();
124 traf_->auxiliary_offset.offsets.clear();
125 traf_->sample_encryption.sample_encryption_entries.clear();
126 traf_->sample_group_descriptions.clear();
127 traf_->sample_to_groups.clear();
128 traf_->header.sample_description_index = 1;
129 traf_->header.flags = TrackFragmentHeader::kDefaultBaseIsMoofMask |
130 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
132 fragment_duration_ = 0;
133 earliest_presentation_time_ = kInvalidTime;
134 first_sap_time_ = kInvalidTime;
140 if (stream_info_->is_encrypted()) {
141 Status status = FinalizeFragmentForEncryption();
147 traf_->runs[0].sample_count =
148 static_cast<uint32_t
>(traf_->runs[0].sample_sizes.size());
150 &traf_->header.default_sample_duration)) {
151 traf_->header.flags |=
152 TrackFragmentHeader::kDefaultSampleDurationPresentMask;
154 traf_->runs[0].flags |= TrackFragmentRun::kSampleDurationPresentMask;
157 &traf_->header.default_sample_size)) {
158 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleSizePresentMask;
160 traf_->runs[0].flags |= TrackFragmentRun::kSampleSizePresentMask;
163 &traf_->header.default_sample_flags)) {
164 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleFlagsPresentMask;
166 traf_->runs[0].flags |= TrackFragmentRun::kSampleFlagsPresentMask;
174 DCHECK_EQ(traf_->sample_to_groups.size(), 0u);
175 if (seek_preroll_ > 0) {
176 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
177 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
178 sample_to_group.grouping_type = FOURCC_roll;
180 sample_to_group.entries.resize(1);
182 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
183 sample_to_group_entry.group_description_index =
184 SampleToGroupEntry::kTrackGroupDescriptionIndexBase + 1;
186 for (
const auto& sample_group_description :
187 traf_->sample_group_descriptions) {
188 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
189 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
190 sample_to_group.grouping_type = sample_group_description.grouping_type;
192 sample_to_group.entries.resize(1);
194 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
195 sample_to_group_entry.group_description_index =
196 SampleToGroupEntry::kTrackFragmentGroupDescriptionIndexBase + 1;
199 fragment_finalized_ =
true;
200 fragment_initialized_ =
false;
206 reference->reference_type =
false;
207 reference->subsegment_duration = fragment_duration_;
208 reference->starts_with_sap = StartsWithSAP();
209 if (kInvalidTime == first_sap_time_) {
210 reference->sap_type = SegmentReference::TypeUnknown;
211 reference->sap_delta_time = 0;
213 reference->sap_type = SegmentReference::Type1;
214 reference->sap_delta_time = first_sap_time_ - earliest_presentation_time_;
216 reference->earliest_presentation_time = earliest_presentation_time_;
219 Status Fragmenter::FinalizeFragmentForEncryption() {
221 if (sample_encryption.sample_encryption_entries.empty()) {
225 const uint32_t kClearSampleDescriptionIndex = 2;
226 traf_->header.sample_description_index = kClearSampleDescriptionIndex;
229 if (sample_encryption.sample_encryption_entries.size() !=
230 traf_->runs[0].sample_sizes.size()) {
231 LOG(ERROR) <<
"Partially encrypted segment is not supported";
232 return Status(error::MUXER_FAILURE,
233 "Partially encrypted segment is not supported.");
236 const SampleEncryptionEntry& sample_encryption_entry =
237 sample_encryption.sample_encryption_entries.front();
238 const bool use_subsample_encryption =
239 !sample_encryption_entry.subsamples.empty();
240 if (use_subsample_encryption)
241 traf_->sample_encryption.flags |= SampleEncryption::kUseSubsampleEncryption;
242 traf_->sample_encryption.iv_size =
static_cast<uint8_t
>(
243 sample_encryption_entry.initialization_vector.size());
246 traf_->auxiliary_offset.offsets.push_back(0);
249 SampleAuxiliaryInformationSize& saiz = traf_->auxiliary_size;
250 saiz.sample_count =
static_cast<uint32_t
>(saiz.sample_info_sizes.size());
251 DCHECK_EQ(saiz.sample_info_sizes.size(),
252 traf_->sample_encryption.sample_encryption_entries.size());
254 &saiz.default_sample_info_size)) {
255 saiz.default_sample_info_size = 0;
260 if (saiz.default_sample_info_size == 0 && saiz.sample_info_sizes.empty()) {
261 DCHECK(!use_subsample_encryption);
265 saiz.sample_count = 0;
266 traf_->auxiliary_offset.offsets.clear();
271 bool Fragmenter::StartsWithSAP() {
272 DCHECK(!traf_->runs.empty());
273 uint32_t start_sample_flag;
274 if (traf_->runs[0].flags & TrackFragmentRun::kSampleFlagsPresentMask) {
275 DCHECK(!traf_->runs[0].sample_flags.empty());
276 start_sample_flag = traf_->runs[0].sample_flags[0];
278 DCHECK(traf_->header.flags &
279 TrackFragmentHeader::kDefaultSampleFlagsPresentMask);
280 start_sample_flag = traf_->header.default_sample_flags;
282 return (start_sample_flag & TrackFragmentHeader::kNonKeySampleMask) == 0;