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

Side by Side Diff: content/browser/media/capture/video_capture_oracle.cc

Issue 1162863003: Move ContentVideoCaptureDeviceCore from src/content to src/media (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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) 2013 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 "content/browser/media/capture/video_capture_oracle.h"
6
7 #include <algorithm>
8
9 #include "base/format_macros.h"
10 #include "base/strings/stringprintf.h"
11
12 namespace content {
13
14 namespace {
15
16 // This value controls how many redundant, timer-base captures occur when the
17 // content is static. Redundantly capturing the same frame allows iterative
18 // quality enhancement, and also allows the buffer to fill in "buffered mode".
19 //
20 // TODO(nick): Controlling this here is a hack and a layering violation, since
21 // it's a strategy specific to the WebRTC consumer, and probably just papers
22 // over some frame dropping and quality bugs. It should either be controlled at
23 // a higher level, or else redundant frame generation should be pushed down
24 // further into the WebRTC encoding stack.
25 const int kNumRedundantCapturesOfStaticContent = 200;
26
27 // Given the amount of time between frames, compare to the expected amount of
28 // time between frames at |frame_rate| and return the fractional difference.
29 double FractionFromExpectedFrameRate(base::TimeDelta delta, int frame_rate) {
30 DCHECK_GT(frame_rate, 0);
31 const base::TimeDelta expected_delta =
32 base::TimeDelta::FromSeconds(1) / frame_rate;
33 return (delta - expected_delta).InMillisecondsF() /
34 expected_delta.InMillisecondsF();
35 }
36
37 } // anonymous namespace
38
39 VideoCaptureOracle::VideoCaptureOracle(base::TimeDelta min_capture_period)
40 : next_frame_number_(0),
41 last_delivered_frame_number_(-1),
42 smoothing_sampler_(min_capture_period,
43 kNumRedundantCapturesOfStaticContent),
44 content_sampler_(min_capture_period) {
45 }
46
47 VideoCaptureOracle::~VideoCaptureOracle() {}
48
49 bool VideoCaptureOracle::ObserveEventAndDecideCapture(
50 Event event,
51 const gfx::Rect& damage_rect,
52 base::TimeTicks event_time) {
53 DCHECK_GE(event, 0);
54 DCHECK_LT(event, kNumEvents);
55 if (event_time < last_event_time_[event]) {
56 LOG(WARNING) << "Event time is not monotonically non-decreasing. "
57 << "Deciding not to capture this frame.";
58 return false;
59 }
60 last_event_time_[event] = event_time;
61
62 bool should_sample = false;
63 duration_of_next_frame_ = base::TimeDelta();
64 switch (event) {
65 case kCompositorUpdate:
66 smoothing_sampler_.ConsiderPresentationEvent(event_time);
67 content_sampler_.ConsiderPresentationEvent(damage_rect, event_time);
68 if (content_sampler_.HasProposal()) {
69 should_sample = content_sampler_.ShouldSample();
70 if (should_sample) {
71 event_time = content_sampler_.frame_timestamp();
72 duration_of_next_frame_ = content_sampler_.sampling_period();
73 }
74 } else {
75 should_sample = smoothing_sampler_.ShouldSample();
76 if (should_sample)
77 duration_of_next_frame_ = smoothing_sampler_.min_capture_period();
78 }
79 break;
80 case kTimerPoll:
81 // While the timer is firing, only allow a sampling if there are none
82 // currently in-progress.
83 if (last_delivered_frame_number_ == (next_frame_number_ - 1)) {
84 should_sample = smoothing_sampler_.IsOverdueForSamplingAt(event_time);
85 if (should_sample)
86 duration_of_next_frame_ = smoothing_sampler_.min_capture_period();
87 }
88 break;
89 case kNumEvents:
90 NOTREACHED();
91 break;
92 }
93
94 SetFrameTimestamp(next_frame_number_, event_time);
95 return should_sample;
96 }
97
98 int VideoCaptureOracle::RecordCapture() {
99 smoothing_sampler_.RecordSample();
100 content_sampler_.RecordSample(GetFrameTimestamp(next_frame_number_));
101 return next_frame_number_++;
102 }
103
104 bool VideoCaptureOracle::CompleteCapture(int frame_number,
105 bool capture_was_successful,
106 base::TimeTicks* frame_timestamp) {
107 // Drop frame if previous frame number is higher.
108 if (last_delivered_frame_number_ > frame_number) {
109 LOG_IF(WARNING, capture_was_successful)
110 << "Out of order frame delivery detected (have #" << frame_number
111 << ", last was #" << last_delivered_frame_number_
112 << "). Dropping frame.";
113 return false;
114 }
115 DCHECK_NE(last_delivered_frame_number_, frame_number);
116 last_delivered_frame_number_ = frame_number;
117
118 if (!capture_was_successful) {
119 VLOG(2) << "Capture of frame #" << frame_number << " was not successful.";
120 return false;
121 }
122
123 *frame_timestamp = GetFrameTimestamp(frame_number);
124
125 // If enabled, log a measurement of how this frame timestamp has incremented
126 // in relation to an ideal increment.
127 if (VLOG_IS_ON(2) && frame_number > 0) {
128 const base::TimeDelta delta =
129 *frame_timestamp - GetFrameTimestamp(frame_number - 1);
130 if (content_sampler_.HasProposal()) {
131 const double estimated_frame_rate =
132 1000000.0 / content_sampler_.detected_period().InMicroseconds();
133 const int rounded_frame_rate =
134 static_cast<int>(estimated_frame_rate + 0.5);
135 VLOG(2) << base::StringPrintf(
136 "Captured #%d: delta=%" PRId64 " usec"
137 ", now locked into {%s}, %+0.1f%% slower than %d FPS",
138 frame_number,
139 delta.InMicroseconds(),
140 content_sampler_.detected_region().ToString().c_str(),
141 100.0 * FractionFromExpectedFrameRate(delta, rounded_frame_rate),
142 rounded_frame_rate);
143 } else {
144 VLOG(2) << base::StringPrintf(
145 "Captured #%d: delta=%" PRId64 " usec"
146 ", d/30fps=%+0.1f%%, d/25fps=%+0.1f%%, d/24fps=%+0.1f%%",
147 frame_number,
148 delta.InMicroseconds(),
149 100.0 * FractionFromExpectedFrameRate(delta, 30),
150 100.0 * FractionFromExpectedFrameRate(delta, 25),
151 100.0 * FractionFromExpectedFrameRate(delta, 24));
152 }
153 }
154
155 return !frame_timestamp->is_null();
156 }
157
158 base::TimeTicks VideoCaptureOracle::GetFrameTimestamp(int frame_number) const {
159 DCHECK_LE(frame_number, next_frame_number_);
160 DCHECK_LT(next_frame_number_ - frame_number, kMaxFrameTimestamps);
161 return frame_timestamps_[frame_number % kMaxFrameTimestamps];
162 }
163
164 void VideoCaptureOracle::SetFrameTimestamp(int frame_number,
165 base::TimeTicks timestamp) {
166 frame_timestamps_[frame_number % kMaxFrameTimestamps] = timestamp;
167 }
168
169 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698