Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: media/mp4/track_run_iterator.cc

Issue 10536014: Implement ISO BMFF support in Media Source. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/mp4/track_run_iterator.h"
6
7 #include "media/mp4/rcheck.h"
8 #include <algorithm>
9
10 namespace media {
11 namespace mp4 {
12
13 base::TimeDelta TimeDeltaFromFrac(int64 numer, uint64 denom) {
14 return base::TimeDelta::FromMicroseconds(
acolwell GONE FROM CHROMIUM 2012/06/06 17:32:39 nit: Add a DCHECK_LT(numer, xxx) to alert us if we
strobe_ 2012/06/07 16:33:54 Overflow happens around 300,000 years. But since i
15 base::Time::kMicrosecondsPerSecond * numer / denom);
16 }
17
18 const static uint32 kSampleIsDifferenceSampleFlagMask = 0x10000;
19
20 TrackRunInfo::TrackRunInfo() {}
21 TrackRunInfo::~TrackRunInfo() {}
22
23 TrackRunIterator::TrackRunIterator() {}
24 TrackRunIterator::~TrackRunIterator() {}
25
26 template<typename T> bool FindByTrackID(uint32 track_id,
27 const std::vector<T>& ts,
acolwell GONE FROM CHROMIUM 2012/06/06 17:32:39 nit: more descriptive name please.
strobe_ 2012/06/07 16:33:54 Oops, that was dead code.
28 const T** result) {
29 for (size_t i = 0; i < ts.size(); i++) {
30 if (ts[i].track_id == track_id) {
31 *result = &ts[i];
32 return true;
33 }
34 }
35 return false;
36 }
37
38 void PopulateSampleInfo(const Track& trak,
39 const TrackExtends& trex,
40 const TrackFragmentHeader& tfhd,
41 const TrackFragmentRun& trun,
42 const size_t i,
43 SampleInfo* si) {
44 if (i < trun.sample_sizes.size()) {
45 si->size = trun.sample_sizes[i];
46 } else if (tfhd.default_sample_size > 0) {
47 si->size = tfhd.default_sample_size;
48 } else {
49 si->size = trex.default_sample_size;
50 }
51
52 const uint64 timescale = trak.media.header.timescale;
53 uint64 duration;
54 if (i < trun.sample_durations.size()) {
55 duration = trun.sample_durations[i];
56 } else if (tfhd.default_sample_duration > 0) {
57 duration = tfhd.default_sample_duration;
58 } else {
59 duration = trex.default_sample_duration;
60 }
61 si->duration = TimeDeltaFromFrac(duration, timescale);
62
63 if (i < trun.sample_composition_time_offsets.size()) {
64 si->cts_offset = TimeDeltaFromFrac(trun.sample_composition_time_offsets[i],
65 timescale);
66 } else {
67 si->cts_offset = TimeDelta::FromMicroseconds(0);
68 }
69
70 uint32 flags;
71 if (i < trun.sample_flags.size()) {
72 flags = trun.sample_flags[i];
73 } else if (tfhd.has_default_sample_flags) {
74 flags = tfhd.default_sample_flags;
75 } else {
76 flags = trex.default_sample_flags;
77 }
78 si->is_keyframe = !(flags & kSampleIsDifferenceSampleFlagMask);
79 }
80
81 class CompareOffset {
82 public:
83 bool operator()(TrackRunInfo a, TrackRunInfo b) {
84 size_t a_min = a.sample_start_offset;
85 if (a.is_encrypted && a.cenc_start_offset < a_min)
86 a_min = a.cenc_start_offset;
87 size_t b_min = b.sample_start_offset;
88 if (b.is_encrypted && b.cenc_start_offset < b_min)
89 b_min = b.cenc_start_offset;
90 return a_min < b_min;
91 }
92 };
93
94 bool TrackRunIterator::Init(const Movie& moov, const MovieFragment& moof) {
95 runs_.clear();
96
97 for (size_t i = 0; i < moof.tracks.size(); i++) {
98 const TrackFragment& traf = moof.tracks[i];
99
100 const Track* trak = NULL;
101 for (size_t t = 0; t < moov.tracks.size(); t++) {
102 if (moov.tracks[t].header.track_id == traf.header.track_id)
103 trak = &moov.tracks[t];
104 }
105
106 const TrackExtends* trex = NULL;
107 for (size_t t = 0; t < moov.extends.tracks.size(); t++) {
108 if (moov.extends.tracks[t].track_id == traf.header.track_id)
109 trex = &moov.extends.tracks[t];
110 }
111 RCHECK(trak && trex);
112
113 const ProtectionSchemeInfo* sinf = NULL;
114 const SampleDescription& stsd =
115 trak->media.information.sample_table.description;
116 if (stsd.type == kAudio) {
117 sinf = &stsd.audio_entries[0].sinf;
118 } else if (stsd.type == kVideo) {
119 sinf = &stsd.video_entries[0].sinf;
120 } else {
121 DVLOG(1) << "Skipping unhandled track type";
122 continue;
123 }
124
125 for (size_t j = 0; j < traf.runs.size(); j++) {
126 const TrackFragmentRun& trun = traf.runs[j];
127 TrackRunInfo tri;
128 tri.track_id = traf.header.track_id;
129 tri.start_dts = TimeDeltaFromFrac(traf.decode_time.decode_time,
130 trak->media.header.timescale);
131 tri.sample_start_offset = trun.data_offset;
132 tri.is_encrypted = sinf->info.track_encryption.is_encrypted;
133 // TODO(strobe): CENC recovery and testing
134
135 tri.samples.resize(trun.sample_count);
136
137 for (size_t k = 0; k < trun.sample_count; k++) {
138 PopulateSampleInfo(*trak, *trex, traf.header, trun, k, &tri.samples[k]);
139 }
140 runs_.push_back(tri);
141 }
142 }
143
144 std::sort(runs_.begin(), runs_.end(), CompareOffset());
145 run_itr_ = runs_.begin();
146 min_clear_offset_itr_ = min_clear_offsets_.begin();
147 ResetRun();
148 return true;
149 }
150
151 void TrackRunIterator::AdvanceRun() {
152 ++run_itr_;
153 if (min_clear_offset_itr_ != min_clear_offsets_.end())
154 ++min_clear_offset_itr_;
155 ResetRun();
156 }
157
158 void TrackRunIterator::ResetRun() {
159 if (RunValid()) {
acolwell GONE FROM CHROMIUM 2012/06/06 17:32:39 nit: reverse check and return early.
strobe_ 2012/06/07 16:33:54 Done.
160 sample_dts_ = run_itr_->start_dts;
161 sample_offset_ = run_itr_->sample_start_offset;
162 sample_itr_ = run_itr_->samples.begin();
163 }
164 }
165
166 void TrackRunIterator::AdvanceSample() {
167 DCHECK(SampleValid());
168 sample_dts_ += sample_itr_->duration;
169 sample_offset_ += sample_itr_->size;
170 // XXX frame_cenc_info_
acolwell GONE FROM CHROMIUM 2012/06/06 17:32:39 Change this to a TODO?
strobe_ 2012/06/07 16:33:54 Done.
171 ++sample_itr_;
172 }
173
174 bool TrackRunIterator::NeedsCENC() {
175 return is_encrypted();
176 }
177
178 bool TrackRunIterator::CacheCENC(const uint8* buf, size_t size) {
179 LOG(FATAL) << "Not implemented";
180 return false;
181 }
182
183 bool TrackRunIterator::RunValid() {
184 return run_itr_ != runs_.end();
185 }
186
187 bool TrackRunIterator::SampleValid() {
188 return RunValid() && (sample_itr_ != run_itr_->samples.end());
189 }
190
191 size_t TrackRunIterator::GetMaxClearOffset() {
192 size_t offset = kuint64max;
193
194 if (SampleValid()) {
195 offset = std::min(offset, sample_offset_);
196 if (NeedsCENC()) {
197 offset = std::min(offset, cenc_offset());
198 }
199 }
200 if (min_clear_offset_itr_ != min_clear_offsets_.end()) {
201 offset = std::min(offset, *min_clear_offset_itr_);
202 }
203 if (offset == kuint64max) return 0;
204 return offset;
205 }
206
207 const FrameCENCInfo& TrackRunIterator::frame_cenc_info() {
208 DCHECK(is_encrypted());
209 return frame_cenc_info_;
210 }
211
212 } // namespace mp4
213 } // namespace media
OLDNEW
« media/mp4/track_run_iterator.h ('K') | « media/mp4/track_run_iterator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698