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

Side by Side Diff: webrtc/media/base/capturemanager.cc

Issue 1757843003: Remove CaptureManager and related calls in ChannelManager. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebased Created 4 years, 9 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
« no previous file with comments | « webrtc/media/base/capturemanager.h ('k') | webrtc/media/base/capturemanager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/media/base/capturemanager.h" 11 #include "webrtc/media/base/capturemanager.h"
12 12
13 #include <algorithm> 13 // TODO(perkj): Remove this file once Chrome's gyp file doesn't depend on it.
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/media/base/videocapturer.h"
18
19 namespace cricket {
20
21 // CaptureManager helper class.
22 class VideoCapturerState {
23 public:
24 static const VideoFormatPod kDefaultCaptureFormat;
25
26 explicit VideoCapturerState(VideoCapturer* capturer);
27 ~VideoCapturerState() {}
28
29 void AddCaptureResolution(const VideoFormat& desired_format);
30 bool RemoveCaptureResolution(const VideoFormat& format);
31 VideoFormat GetHighestFormat(VideoCapturer* video_capturer) const;
32
33 int IncCaptureStartRef();
34 int DecCaptureStartRef();
35 VideoCapturer* GetVideoCapturer() {
36 RTC_DCHECK(thread_checker_.CalledOnValidThread());
37 return video_capturer_;
38 }
39
40 int start_count() const {
41 RTC_DCHECK(thread_checker_.CalledOnValidThread());
42 return start_count_;
43 }
44
45 private:
46 struct CaptureResolutionInfo {
47 VideoFormat video_format;
48 int format_ref_count;
49 };
50 typedef std::vector<CaptureResolutionInfo> CaptureFormats;
51
52 rtc::ThreadChecker thread_checker_;
53
54 VideoCapturer* video_capturer_;
55 int start_count_;
56 CaptureFormats capture_formats_;
57 };
58
59 const VideoFormatPod VideoCapturerState::kDefaultCaptureFormat = {
60 640, 360, FPS_TO_INTERVAL(30), FOURCC_ANY
61 };
62
63 VideoCapturerState::VideoCapturerState(VideoCapturer* capturer)
64 : video_capturer_(capturer), start_count_(1) {}
65
66 void VideoCapturerState::AddCaptureResolution(
67 const VideoFormat& desired_format) {
68 RTC_DCHECK(thread_checker_.CalledOnValidThread());
69 for (CaptureFormats::iterator iter = capture_formats_.begin();
70 iter != capture_formats_.end(); ++iter) {
71 if (desired_format == iter->video_format) {
72 ++(iter->format_ref_count);
73 return;
74 }
75 }
76 CaptureResolutionInfo capture_resolution = { desired_format, 1 };
77 capture_formats_.push_back(capture_resolution);
78 }
79
80 bool VideoCapturerState::RemoveCaptureResolution(const VideoFormat& format) {
81 RTC_DCHECK(thread_checker_.CalledOnValidThread());
82 for (CaptureFormats::iterator iter = capture_formats_.begin();
83 iter != capture_formats_.end(); ++iter) {
84 if (format == iter->video_format) {
85 --(iter->format_ref_count);
86 if (iter->format_ref_count == 0) {
87 capture_formats_.erase(iter);
88 }
89 return true;
90 }
91 }
92 return false;
93 }
94
95 VideoFormat VideoCapturerState::GetHighestFormat(
96 VideoCapturer* video_capturer) const {
97 RTC_DCHECK(thread_checker_.CalledOnValidThread());
98 VideoFormat highest_format(0, 0, VideoFormat::FpsToInterval(1), FOURCC_ANY);
99 if (capture_formats_.empty()) {
100 VideoFormat default_format(kDefaultCaptureFormat);
101 return default_format;
102 }
103 for (CaptureFormats::const_iterator iter = capture_formats_.begin();
104 iter != capture_formats_.end(); ++iter) {
105 if (iter->video_format.width > highest_format.width) {
106 highest_format.width = iter->video_format.width;
107 }
108 if (iter->video_format.height > highest_format.height) {
109 highest_format.height = iter->video_format.height;
110 }
111 if (iter->video_format.interval < highest_format.interval) {
112 highest_format.interval = iter->video_format.interval;
113 }
114 }
115 return highest_format;
116 }
117
118 int VideoCapturerState::IncCaptureStartRef() {
119 RTC_DCHECK(thread_checker_.CalledOnValidThread());
120 return ++start_count_;
121 }
122
123 int VideoCapturerState::DecCaptureStartRef() {
124 RTC_DCHECK(thread_checker_.CalledOnValidThread());
125 if (start_count_ > 0) {
126 // Start count may be 0 if a capturer was added but never started.
127 --start_count_;
128 }
129 return start_count_;
130 }
131
132 CaptureManager::CaptureManager() {
133 // Allowing construction of manager in any thread as long as subsequent calls
134 // are all from the same thread.
135 thread_checker_.DetachFromThread();
136 }
137
138 CaptureManager::~CaptureManager() {
139 RTC_DCHECK(thread_checker_.CalledOnValidThread());
140
141 // Since we don't own any of the capturers, all capturers should have been
142 // cleaned up before we get here. In fact, in the normal shutdown sequence,
143 // all capturers *will* be shut down by now, so trying to stop them here
144 // will crash. If we're still tracking any, it's a dangling pointer.
145 // TODO(hbos): RTC_DCHECK instead of RTC_CHECK until we figure out why
146 // capture_states_ is not always empty here.
147 RTC_DCHECK(capture_states_.empty());
148 }
149
150 bool CaptureManager::StartVideoCapture(VideoCapturer* video_capturer,
151 const VideoFormat& desired_format) {
152 RTC_DCHECK(thread_checker_.CalledOnValidThread());
153 if (desired_format.width == 0 || desired_format.height == 0) {
154 return false;
155 }
156 if (!video_capturer) {
157 return false;
158 }
159 VideoCapturerState* capture_state = GetCaptureState(video_capturer);
160 if (capture_state) {
161 const int ref_count = capture_state->IncCaptureStartRef();
162 if (ref_count < 1) {
163 ASSERT(false);
164 }
165 // VideoCapturer has already been started. Don't start listening to
166 // callbacks since that has already been done.
167 capture_state->AddCaptureResolution(desired_format);
168 return true;
169 }
170 if (!RegisterVideoCapturer(video_capturer)) {
171 return false;
172 }
173 capture_state = GetCaptureState(video_capturer);
174 ASSERT(capture_state != NULL);
175 capture_state->AddCaptureResolution(desired_format);
176 if (!StartWithBestCaptureFormat(capture_state, video_capturer)) {
177 UnregisterVideoCapturer(capture_state);
178 return false;
179 }
180 return true;
181 }
182
183 bool CaptureManager::StopVideoCapture(VideoCapturer* video_capturer,
184 const VideoFormat& format) {
185 RTC_DCHECK(thread_checker_.CalledOnValidThread());
186 VideoCapturerState* capture_state = GetCaptureState(video_capturer);
187 if (!capture_state) {
188 return false;
189 }
190 if (!capture_state->RemoveCaptureResolution(format)) {
191 return false;
192 }
193
194 if (capture_state->DecCaptureStartRef() == 0) {
195 // Unregistering cannot fail as capture_state is not NULL.
196 UnregisterVideoCapturer(capture_state);
197 }
198 return true;
199 }
200
201 void CaptureManager::AddVideoSink(VideoCapturer* video_capturer,
202 rtc::VideoSinkInterface<VideoFrame>* sink) {
203 RTC_DCHECK(thread_checker_.CalledOnValidThread());
204 // TODO(nisse): Do we really need to tolerate NULL inputs?
205 if (!video_capturer || !sink) {
206 return;
207 }
208 rtc::VideoSinkWants wants;
209 // Renderers must be able to apply rotation.
210 wants.rotation_applied = false;
211 video_capturer->AddOrUpdateSink(sink, wants);
212 }
213
214 void CaptureManager::RemoveVideoSink(
215 VideoCapturer* video_capturer,
216 rtc::VideoSinkInterface<VideoFrame>* sink) {
217 RTC_DCHECK(thread_checker_.CalledOnValidThread());
218 if (!video_capturer || !sink) {
219 return;
220 }
221 video_capturer->RemoveSink(sink);
222 }
223
224 bool CaptureManager::IsCapturerRegistered(VideoCapturer* video_capturer) const {
225 RTC_DCHECK(thread_checker_.CalledOnValidThread());
226 return GetCaptureState(video_capturer) != NULL;
227 }
228
229 bool CaptureManager::RegisterVideoCapturer(VideoCapturer* video_capturer) {
230 RTC_DCHECK(thread_checker_.CalledOnValidThread());
231 VideoCapturerState* capture_state = new VideoCapturerState(video_capturer);
232 capture_states_[video_capturer] = capture_state;
233 SignalCapturerStateChange.repeat(video_capturer->SignalStateChange);
234 return true;
235 }
236
237 void CaptureManager::UnregisterVideoCapturer(
238 VideoCapturerState* capture_state) {
239 RTC_DCHECK(thread_checker_.CalledOnValidThread());
240 VideoCapturer* video_capturer = capture_state->GetVideoCapturer();
241 capture_states_.erase(video_capturer);
242 delete capture_state;
243
244 // When unregistering a VideoCapturer, the CaptureManager needs to unregister
245 // from all state change callbacks from the VideoCapturer. E.g. to avoid
246 // problems with multiple callbacks if registering the same VideoCapturer
247 // multiple times. The VideoCapturer will update the capturer state. However,
248 // this is done through Post-calls which means it may happen at any time. If
249 // the CaptureManager no longer is listening to the VideoCapturer it will not
250 // receive those callbacks. Here it is made sure that the the callback is
251 // indeed sent by letting the ChannelManager do the signaling. The downside is
252 // that the callback may happen before the VideoCapturer is stopped. However,
253 // for the CaptureManager it doesn't matter as it will no longer receive any
254 // frames from the VideoCapturer.
255 SignalCapturerStateChange.stop(video_capturer->SignalStateChange);
256 if (video_capturer->IsRunning()) {
257 video_capturer->Stop();
258 SignalCapturerStateChange(video_capturer, CS_STOPPED);
259 }
260 }
261
262 bool CaptureManager::StartWithBestCaptureFormat(
263 VideoCapturerState* capture_state, VideoCapturer* video_capturer) {
264 RTC_DCHECK(thread_checker_.CalledOnValidThread());
265 VideoFormat highest_asked_format =
266 capture_state->GetHighestFormat(video_capturer);
267 VideoFormat capture_format;
268 if (!video_capturer->GetBestCaptureFormat(highest_asked_format,
269 &capture_format)) {
270 LOG(LS_WARNING) << "Unsupported format:"
271 << " width=" << highest_asked_format.width
272 << " height=" << highest_asked_format.height
273 << ". Supported formats are:";
274 const std::vector<VideoFormat>* formats =
275 video_capturer->GetSupportedFormats();
276 ASSERT(formats != NULL);
277 for (std::vector<VideoFormat>::const_iterator i = formats->begin();
278 i != formats->end(); ++i) {
279 const VideoFormat& format = *i;
280 LOG(LS_WARNING) << " " << GetFourccName(format.fourcc)
281 << ":" << format.width << "x" << format.height << "x"
282 << format.framerate();
283 }
284 return false;
285 }
286 return video_capturer->StartCapturing(capture_format);
287 }
288
289 VideoCapturerState* CaptureManager::GetCaptureState(
290 VideoCapturer* video_capturer) const {
291 RTC_DCHECK(thread_checker_.CalledOnValidThread());
292 CaptureStates::const_iterator iter = capture_states_.find(video_capturer);
293 if (iter == capture_states_.end()) {
294 return NULL;
295 }
296 return iter->second;
297 }
298
299 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/media/base/capturemanager.h ('k') | webrtc/media/base/capturemanager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698