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();
33 : use_decoding_timestamp_in_timeline_(false),
35 seek_preroll_(GetSeekPreroll(*info)),
36 fragment_initialized_(false),
37 fragment_finalized_(false),
38 fragment_duration_(0),
39 earliest_presentation_time_(kInvalidTime),
40 first_sap_time_(kInvalidTime) {
44 Fragmenter::~Fragmenter() {}
48 if (sample->duration() == 0) {
49 LOG(WARNING) <<
"Unexpected sample with zero duration @ dts "
53 if (!fragment_initialized_) {
59 if (sample->side_data_size() > 0)
60 LOG(WARNING) <<
"MP4 samples do not support side data. Side data ignored.";
63 traf_->runs[0].sample_sizes.push_back(
64 static_cast<uint32_t>(sample->data_size()));
65 traf_->runs[0].sample_durations.push_back(sample->duration());
66 traf_->runs[0].sample_flags.push_back(
67 sample->is_key_frame() ? 0 : TrackFragmentHeader::kNonKeySampleMask);
69 data_->AppendArray(sample->data(), sample->data_size());
70 fragment_duration_ += sample->duration();
72 const int64_t pts = sample->pts();
73 const int64_t dts = sample->dts();
75 const int64_t timestamp = use_decoding_timestamp_in_timeline_ ? dts : pts;
78 if (earliest_presentation_time_ > timestamp)
79 earliest_presentation_time_ = timestamp;
81 traf_->runs[0].sample_composition_time_offsets.push_back(pts - dts);
83 traf_->runs[0].flags |= TrackFragmentRun::kSampleCompTimeOffsetsPresentMask;
85 if (sample->is_key_frame()) {
86 if (first_sap_time_ == kInvalidTime)
87 first_sap_time_ = pts;
93 fragment_initialized_ =
true;
94 fragment_finalized_ =
false;
95 traf_->decode_time.decode_time = first_sample_dts;
97 traf_->runs.resize(1);
98 traf_->runs[0].flags = TrackFragmentRun::kDataOffsetPresentMask;
99 traf_->sample_group_descriptions.clear();
100 traf_->sample_to_groups.clear();
101 traf_->header.sample_description_index = 1;
102 traf_->header.flags = TrackFragmentHeader::kDefaultBaseIsMoofMask |
103 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
104 fragment_duration_ = 0;
105 earliest_presentation_time_ = kInvalidTime;
106 first_sap_time_ = kInvalidTime;
113 traf_->runs[0].sample_count =
114 static_cast<uint32_t
>(traf_->runs[0].sample_sizes.size());
116 &traf_->header.default_sample_duration)) {
117 traf_->header.flags |=
118 TrackFragmentHeader::kDefaultSampleDurationPresentMask;
120 traf_->runs[0].flags |= TrackFragmentRun::kSampleDurationPresentMask;
123 &traf_->header.default_sample_size)) {
124 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleSizePresentMask;
126 traf_->runs[0].flags |= TrackFragmentRun::kSampleSizePresentMask;
129 &traf_->header.default_sample_flags)) {
130 traf_->header.flags |= TrackFragmentHeader::kDefaultSampleFlagsPresentMask;
132 traf_->runs[0].flags |= TrackFragmentRun::kSampleFlagsPresentMask;
140 DCHECK_EQ(traf_->sample_to_groups.size(), 0u);
141 if (seek_preroll_ > 0) {
142 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
143 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
144 sample_to_group.grouping_type = FOURCC_roll;
146 sample_to_group.entries.resize(1);
148 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
149 sample_to_group_entry.group_description_index =
150 SampleToGroupEntry::kTrackGroupDescriptionIndexBase + 1;
152 for (
const auto& sample_group_description :
153 traf_->sample_group_descriptions) {
154 traf_->sample_to_groups.resize(traf_->sample_to_groups.size() + 1);
155 SampleToGroup& sample_to_group = traf_->sample_to_groups.back();
156 sample_to_group.grouping_type = sample_group_description.grouping_type;
158 sample_to_group.entries.resize(1);
160 sample_to_group_entry.sample_count = traf_->runs[0].sample_count;
161 sample_to_group_entry.group_description_index =
162 SampleToGroupEntry::kTrackFragmentGroupDescriptionIndexBase + 1;
165 fragment_finalized_ =
true;
166 fragment_initialized_ =
false;
171 reference->reference_type =
false;
172 reference->subsegment_duration = fragment_duration_;
173 reference->starts_with_sap = StartsWithSAP();
174 if (kInvalidTime == first_sap_time_) {
175 reference->sap_type = SegmentReference::TypeUnknown;
176 reference->sap_delta_time = 0;
178 reference->sap_type = SegmentReference::Type1;
179 reference->sap_delta_time = first_sap_time_ - earliest_presentation_time_;
181 reference->earliest_presentation_time = earliest_presentation_time_;
184 bool Fragmenter::StartsWithSAP() {
185 DCHECK(!traf_->runs.empty());
186 uint32_t start_sample_flag;
187 if (traf_->runs[0].flags & TrackFragmentRun::kSampleFlagsPresentMask) {
188 DCHECK(!traf_->runs[0].sample_flags.empty());
189 start_sample_flag = traf_->runs[0].sample_flags[0];
191 DCHECK(traf_->header.flags &
192 TrackFragmentHeader::kDefaultSampleFlagsPresentMask);
193 start_sample_flag = traf_->header.default_sample_flags;
195 return (start_sample_flag & TrackFragmentHeader::kNonKeySampleMask) == 0;