17 #include <glog/logging.h> 24 #include <unordered_set> 40 template <
bool OrderByDts = true>
41 double GetTime(
const std::shared_ptr<BaseFrame>& a) {
45 double GetTime<false>(
const std::shared_ptr<BaseFrame>& a) {
50 template <
bool OrderByDts>
51 bool FrameLessThan(
const std::shared_ptr<BaseFrame>& a,
52 const std::shared_ptr<BaseFrame>& b) {
53 return GetTime<OrderByDts>(a) < GetTime<OrderByDts>(b);
57 template <
bool OrderByDts>
58 bool FrameExtendsPast(
const std::shared_ptr<BaseFrame>& a,
59 const std::shared_ptr<BaseFrame>& b) {
61 GetTime<OrderByDts>(b);
64 template <
typename Iter>
65 void UpdatePtsRanges(Iter range) {
66 DCHECK(!range->frames.empty());
67 range->start_pts = HUGE_VAL;
68 range->end_pts = -HUGE_VAL;
69 for (
auto&
frame : range->frames) {
70 range->start_pts = std::min(range->start_pts,
frame->pts);
71 range->end_pts = std::max(range->end_pts,
frame->pts +
frame->duration);
90 template <
bool OrderByDts>
91 std::list<std::shared_ptr<BaseFrame>>::iterator FrameLowerBound(
92 const std::list<std::shared_ptr<BaseFrame>>& list,
double time) {
94 const_cast<std::list<std::shared_ptr<BaseFrame>
>&>(list);
96 return mutable_list.end();
98 if (time - GetTime<OrderByDts>(list.front()) <
99 GetTime<OrderByDts>(list.back()) - time) {
101 auto notLessThan = [&time](
const std::shared_ptr<BaseFrame>& other) {
102 return GetTime<OrderByDts>(other) >= time;
104 return std::find_if(mutable_list.begin(), mutable_list.end(), notLessThan);
109 auto isLessThan = [&time](
const std::shared_ptr<BaseFrame>& other) {
110 return GetTime<OrderByDts>(other) < time;
113 std::find_if(mutable_list.rbegin(), mutable_list.rend(), isLessThan);
128 std::list<std::shared_ptr<BaseFrame>>
frames;
138 explicit Impl(
bool order_by_dts)
139 : mutex(
"StreamBase"), order_by_dts(order_by_dts) {}
152 std::unique_lock<Mutex> lock(impl_->mutex);
155 for (
auto& range : impl_->buffered_ranges) {
156 for (
auto&
frame : range.frames)
157 size +=
frame->EstimateSize();
163 std::unique_lock<Mutex> lock(impl_->mutex);
167 impl_->order_by_dts ? &FrameExtendsPast<true> : &FrameExtendsPast<false>;
169 impl_->order_by_dts ? &FrameLowerBound<true> : &FrameLowerBound<false>;
170 auto getTime = impl_->order_by_dts ? &GetTime<true> : &GetTime<false>;
174 std::find_if(impl_->buffered_ranges.begin(), impl_->buffered_ranges.end(),
175 [&](
const Range& range) {
176 return extendsPast(range.frames.back(),
frame);
179 if (range_it == impl_->buffered_ranges.end()) {
181 impl_->buffered_ranges.emplace_back();
182 impl_->buffered_ranges.back().start_pts = frame->pts;
183 impl_->buffered_ranges.back().end_pts = frame->pts + frame->duration;
184 impl_->buffered_ranges.back().frames.emplace_back(frame);
185 }
else if (!extendsPast(frame, range_it->frames.front())) {
187 auto it = impl_->buffered_ranges.emplace(range_it);
188 it->start_pts = frame->pts;
189 it->end_pts = frame->pts + frame->duration;
190 it->frames.emplace_back(frame);
193 auto frame_it = lowerBound(range_it->frames, getTime(frame));
194 range_it->start_pts = std::min(range_it->start_pts, frame->pts);
196 std::max(range_it->end_pts, frame->pts + frame->duration);
197 if (frame_it != range_it->frames.end() &&
198 getTime(*frame_it) == getTime(frame)) {
199 swap(*frame_it, frame);
201 range_it->frames.insert(frame_it, frame);
206 DCHECK_NE(0u, impl_->buffered_ranges.size());
207 for (
auto it = std::next(impl_->buffered_ranges.begin());
208 it != impl_->buffered_ranges.end();) {
209 auto prev = std::prev(it);
210 if (extendsPast(prev->frames.back(), it->frames.front())) {
213 prev->frames.splice(prev->frames.end(), it->frames);
214 prev->start_pts = std::min(prev->start_pts, it->start_pts);
215 prev->end_pts = std::max(prev->end_pts, it->end_pts);
216 it = impl_->buffered_ranges.erase(it);
222 AssertRangesSorted();
226 std::unique_lock<Mutex> lock(impl_->mutex);
227 AssertRangesSorted();
229 std::vector<BufferedRange> ret;
230 ret.reserve(impl_->buffered_ranges.size());
231 for (
const Range& range : impl_->buffered_ranges) {
232 ret.emplace_back(range.start_pts, range.end_pts);
238 double end_time)
const {
239 std::unique_lock<Mutex> lock(impl_->mutex);
240 AssertRangesSorted();
242 auto getTime = impl_->order_by_dts ? &GetTime<true> : &GetTime<false>;
244 impl_->order_by_dts ? &FrameLowerBound<true> : &FrameLowerBound<false>;
248 std::find_if(impl_->buffered_ranges.begin(), impl_->buffered_ranges.end(),
249 [&](
const Range& range) {
250 return getTime(range.frames.back()) >= start_time;
253 size_t num_frames = 0;
254 for (; range_it != impl_->buffered_ranges.end(); range_it++) {
257 auto start = lowerBound(range_it->frames, start_time);
258 auto end = lowerBound(range_it->frames, end_time);
259 DCHECK(start != range_it->frames.end());
260 num_frames += std::distance(start, end);
261 if (getTime(*start) == start_time && start != end)
263 if (end != range_it->frames.end())
274 std::unique_lock<Mutex> lock(impl_->mutex);
275 bool is_removing =
false;
276 for (
auto it = impl_->buffered_ranges.begin();
277 it != impl_->buffered_ranges.end();) {
279 auto frame_del_start = is_removing ? it->frames.begin() : it->frames.end();
280 auto frame_del_end = it->frames.end();
282 for (
auto frame = it->frames.begin();
frame != it->frames.end();
frame++) {
285 if ((*frame)->pts >= start && (*frame)->pts < end) {
287 frame_del_start =
frame;
289 }
else if ((*frame)->pts >= end && (*frame)->is_key_frame) {
291 frame_del_end =
frame;
297 if (frame_del_start != it->frames.begin() &&
298 frame_del_start != it->frames.end() &&
299 frame_del_end != it->frames.end()) {
301 auto new_it = impl_->buffered_ranges.emplace(it);
305 new_it->frames.splice(new_it->frames.end(), it->frames,
306 it->frames.begin(), frame_del_start);
308 it->frames.erase(it->frames.begin(), frame_del_end);
310 UpdatePtsRanges(new_it);
313 it->frames.erase(frame_del_start, frame_del_end);
314 if (it->frames.empty()) {
315 it = impl_->buffered_ranges.erase(it);
323 AssertRangesSorted();
327 std::unique_lock<Mutex> lock(impl_->mutex);
328 impl_->buffered_ranges.clear();
332 std::unique_lock<Mutex> lock(impl_->mutex);
333 AssertRangesSorted();
335 fprintf(stderr,
"Stream order by %s:\n", impl_->order_by_dts ?
"DTS" :
"PTS");
336 if (impl_->buffered_ranges.empty())
337 fprintf(stderr,
" Nothing buffered\n");
339 for (
const Range& range : impl_->buffered_ranges) {
340 fprintf(stderr,
" Range[%zu, %zu frames]: %.2f-%.2f\n", range_i,
341 range.frames.size(), range.start_pts, range.end_pts);
344 for (
const auto&
frame : range.frames) {
346 " Frame[%zu]: is_key_frame=%-5s, pts=%.2f, dts=%.2f\n",
347 frame_i,
frame->is_key_frame ?
"true" :
"false",
frame->pts,
358 std::unique_lock<Mutex> lock(impl_->mutex);
359 AssertRangesSorted();
361 auto getTime = impl_->order_by_dts ? &GetTime<true> : &GetTime<false>;
363 impl_->order_by_dts ? &FrameLowerBound<true> : &FrameLowerBound<false>;
366 auto it = std::find_if(
367 impl_->buffered_ranges.begin(), impl_->buffered_ranges.end(),
368 [&](
const Range& range) {
return getTime(range.frames.back()) >= time; });
370 if (it == impl_->buffered_ranges.end()) {
374 it = std::prev(impl_->buffered_ranges.end());
378 auto frame_it = lowerBound(it->frames, time);
383 DCHECK(frame_it != it->frames.end());
384 if (getTime(*frame_it) > time)
386 else if (std::next(frame_it) != it->frames.end())
387 return *std::next(frame_it);
388 else if (std::next(it) != impl_->buffered_ranges.end())
389 return *std::next(it)->frames.begin();
394 if (frame_it == it->frames.end())
395 return it->frames.back();
398 auto prev_it = frame_it;
399 if (frame_it != it->frames.begin())
400 prev_it = std::prev(frame_it);
401 else if (it != impl_->buffered_ranges.begin())
402 prev_it = std::prev(std::prev(it)->frames.end());
404 double prev_diff = time - getTime(*prev_it) - (*prev_it)->duration;
405 double diff = getTime(*frame_it) - time;
406 return prev_diff < diff && diff != 0 ? *prev_it : *frame_it;
410 if (frame_it == it->frames.end())
411 frame_it = std::prev(it->frames.end());
412 else if (frame_it != it->frames.begin() && getTime(*frame_it) > time)
415 DCHECK((*it->frames.begin())->is_key_frame);
416 while (!(*frame_it)->is_key_frame)
419 return getTime(*frame_it) <= time ? *frame_it :
nullptr;
423 void StreamBase::AssertRangesSorted()
const {
425 auto frame_less_than =
426 impl_->order_by_dts ? &FrameLessThan<true> : &FrameLessThan<false>;
427 auto range_is_valid = [&](
const Range& range) {
432 CHECK(!range.frames.empty());
433 CHECK(range.frames.front()->is_key_frame);
434 CHECK_LE(range.start_pts, range.end_pts);
435 CHECK(std::is_sorted(range.frames.begin(), range.frames.end(),
439 auto range_less_than = [&](
const Range& first,
const Range& second) {
442 if (&first == &second)
446 if (first.start_pts < second.start_pts) {
447 CHECK_LT(first.end_pts, second.start_pts);
450 CHECK_GT(first.start_pts, second.end_pts);
454 CHECK(std::all_of(impl_->buffered_ranges.begin(),
455 impl_->buffered_ranges.end(), range_is_valid));
456 CHECK(std::is_sorted(impl_->buffered_ranges.begin(),
457 impl_->buffered_ranges.end(), range_less_than));
std::shared_ptr< shaka::media::DecodedFrame > frame
void swap(shared_lock< Mutex > &a, shared_lock< Mutex > &b)
#define SHAKA_NON_COPYABLE_TYPE(Type)
std::list< std::shared_ptr< BaseFrame > > frames