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

Side by Side Diff: webrtc/modules/video_coding/frame_buffer2.cc

Issue 1969403007: FrameBuffer for the new jitter buffer. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Implemented FrameKey and changed decoded_frames_ to a std::set<FrameKey>, also feedback fixes. Created 4 years, 7 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 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/frame_buffer2.h"
12
13 #include <algorithm>
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/modules/video_coding/frame_object.h"
17 #include "webrtc/modules/video_coding/jitter_estimator.h"
18 #include "webrtc/modules/video_coding/sequence_number_util.h"
19 #include "webrtc/modules/video_coding/timing.h"
20 #include "webrtc/system_wrappers/include/clock.h"
21
22 namespace webrtc {
23 namespace video_coding {
24
25 namespace {
26 // The maximum age of a frame stored in the frame buffer, compared to
danilchap 2016/05/17 16:21:39 'decoded frames tracked by' instead of 'frame stor
philipel 2016/05/18 09:00:56 Done.
27 // |newest_picture_id_|.
28 static constexpr int kMaxFrameAge = 4096;
danilchap 2016/05/17 16:21:38 since this constants are not inside class now, sta
philipel 2016/05/18 09:00:56 Done.
29
30 // The maximum number of decoded frames being tracked by the frame buffer.
31 static constexpr int kMaxNumHistoryFrames = 256;
32
33 // The maximum number of spatial layers.
34 static constexpr int kMaxSpatialLayers = 5;
35 } // namespace
36
37 bool FrameBuffer::FrameComp::operator()(const FrameKey& f1,
38 const FrameKey& f2) const {
39 // first = picture id
40 // second = spatial layer
41 if (f1.first == f2.first)
42 return f1.second < f2.second;
43 return AheadOf(f2.first, f1.first);
44 }
45
46 FrameBuffer::FrameBuffer(Clock* clock,
47 VCMJitterEstimator* jitter_estimator,
48 const VCMTiming* timing)
49 : clock_(clock),
50 frame_inserted_event_(false, false),
51 jitter_estimator_(jitter_estimator),
52 timing_(timing),
53 newest_picture_id_(-1) {}
54
55 std::unique_ptr<FrameObject> FrameBuffer::NextFrame(int64_t max_wait_time_ms) {
56 int64_t latest_return_time = clock_->TimeInMilliseconds() + max_wait_time_ms;
57 while (true) {
58 int64_t now = clock_->TimeInMilliseconds();
59 int64_t wait_ms = max_wait_time_ms;
60
61 crit_.Enter();
62 frame_inserted_event_.Reset();
63 auto next_frame = frames_.end();
64 for (auto frame_it = frames_.begin(); frame_it != frames_.end();
65 ++frame_it) {
66 const FrameObject& frame = *frame_it->second;
67 if (IsContinuous(frame)) {
68 next_frame = frame_it;
69 int64_t render_time = timing_->RenderTimeMs(frame.timestamp, now);
70 wait_ms = timing_->MaxWaitingTime(render_time, now);
71
72 // This will cause the frame buffer to prefer high framerate rather
73 // than high resolution in the case of the decoder not decoding fast
74 // enough and the stream has multiple spatial and temporal layers.
75 if (wait_ms == 0)
76 continue;
77
78 break;
79 }
80 }
81 crit_.Leave();
82
83 // If the timout occures, return. Otherwise a new frame has been inserted
84 // and the best frame to decode next will be selected again.
85 wait_ms = std::min<int64_t>(wait_ms, latest_return_time - now);
86 wait_ms = std::max<int64_t>(wait_ms, 0);
87 if (!frame_inserted_event_.Wait(wait_ms)) {
88 crit_.Enter();
89 if (next_frame != frames_.end()) {
90 // TODO(philipel): update jitter estimator with correct values.
91 jitter_estimator_->UpdateEstimate(100, 100);
92
93 std::unique_ptr<FrameObject> frame = std::move(next_frame->second);
94 frames_.erase(frames_.begin(), ++next_frame);
95 decoded_frames_.insert(
danilchap 2016/05/17 16:21:38 if you move this lines a bit above, you can write
philipel 2016/05/18 09:00:56 Nice, didn't think of that.
96 FrameKey(frame->picture_id, frame->spatial_layer));
97 crit_.Leave();
98 return frame;
99 } else {
100 crit_.Leave();
101 return std::unique_ptr<FrameObject>();
102 }
103 }
104 }
105 }
106
107 void FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) {
108 rtc::CritScope lock(&crit_);
109 if (newest_picture_id_ == -1)
110 newest_picture_id_ = frame->picture_id;
111
112 if (AheadOf<uint16_t>(frame->picture_id, newest_picture_id_))
113 newest_picture_id_ = frame->picture_id;
114
115 // Remove frames as long as we have to many, |kMaxNumHistoryFrames|.
danilchap 2016/05/17 16:21:38 too many
philipel 2016/05/18 09:00:56 Done.
116 while (decoded_frames_.size() > kMaxNumHistoryFrames)
117 decoded_frames_.erase(decoded_frames_.begin());
118
119 // Remove frames that are too old, |kMaxNumHistoryFrames|.
120 uint16_t old_picture_id = Subtract<1 << 16>(newest_picture_id_, kMaxFrameAge);
121 auto old_decoded_it =
122 decoded_frames_.lower_bound(FrameKey(old_picture_id, kMaxSpatialLayers));
danilchap 2016/05/17 16:21:38 old_picture_id is oldest allowed picture_id (it's
philipel 2016/05/18 09:00:56 erase removes the elements in the range [begin, ol
danilchap 2016/05/18 09:57:59 lower_bound find first element >= (old_picture_id,
philipel 2016/05/18 10:42:56 I don't want to create a unittest for this since t
danilchap 2016/05/18 11:46:25 Good point about unittest - forgot MaxAge is a pri
philipel 2016/05/18 12:07:57 Good point about clarity (and the off by one), rem
123 decoded_frames_.erase(decoded_frames_.begin(), old_decoded_it);
124
125 FrameKey key(frame->picture_id, frame->spatial_layer);
126 frames_[key] = std::move(frame);
127 frame_inserted_event_.Set();
128 }
129
130 bool FrameBuffer::IsContinuous(const FrameObject& frame) const {
131 // If a frame with an earlier picture id was inserted compared to the last
132 // decoded frames picture id then that frame arrived too late.
133 if (!decoded_frames_.empty() &&
134 AheadOf(decoded_frames_.rbegin()->first, frame.picture_id)) {
135 return false;
136 }
137
138 for (size_t r = 0; r < frame.num_references; ++r) {
139 FrameKey ref_key(frame.references[r], frame.spatial_layer);
140 if (decoded_frames_.find(ref_key) == decoded_frames_.end())
141 return false;
142 }
143
144 if (frame.inter_layer_predicted) {
145 RTC_DCHECK_GT(frame.spatial_layer, 0);
146 FrameKey ref_key(frame.picture_id, frame.spatial_layer);
danilchap 2016/05/17 16:21:38 frame.spatial_layer - 1
philipel 2016/05/18 09:00:56 Fixed, also found a bug in the unittest.
147 if (decoded_frames_.find(ref_key) == decoded_frames_.end())
148 return false;
149 }
150
151 return true;
152 }
153
154 } // namespace video_coding
155 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698