OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/video_track_adapter.h" | 5 #include "content/renderer/media/video_track_adapter.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
| 9 #include <memory> |
| 10 #include <string> |
9 #include <utility> | 11 #include <utility> |
10 | 12 |
11 #include "base/bind.h" | 13 #include "base/bind.h" |
12 #include "base/command_line.h" | 14 #include "base/command_line.h" |
13 #include "base/location.h" | 15 #include "base/location.h" |
14 #include "base/macros.h" | 16 #include "base/macros.h" |
15 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
16 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
17 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" |
18 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 // VideoFrameResolutionAdapter is created on and lives on the IO-thread. It does | 55 // VideoFrameResolutionAdapter is created on and lives on the IO-thread. It does |
54 // the resolution adaptation and delivers frames to all registered tracks on the | 56 // the resolution adaptation and delivers frames to all registered tracks on the |
55 // IO-thread. All method calls must be on the IO-thread. | 57 // IO-thread. All method calls must be on the IO-thread. |
56 class VideoTrackAdapter::VideoFrameResolutionAdapter | 58 class VideoTrackAdapter::VideoFrameResolutionAdapter |
57 : public base::RefCountedThreadSafe<VideoFrameResolutionAdapter> { | 59 : public base::RefCountedThreadSafe<VideoFrameResolutionAdapter> { |
58 public: | 60 public: |
59 // Setting |max_frame_rate| to 0.0, means that no frame rate limitation | 61 // Setting |max_frame_rate| to 0.0, means that no frame rate limitation |
60 // will be done. | 62 // will be done. |
61 VideoFrameResolutionAdapter( | 63 VideoFrameResolutionAdapter( |
62 scoped_refptr<base::SingleThreadTaskRunner> render_message_loop, | 64 scoped_refptr<base::SingleThreadTaskRunner> render_message_loop, |
63 const gfx::Size& max_size, | 65 const VideoTrackAdapterSettings& settings); |
64 double min_aspect_ratio, | |
65 double max_aspect_ratio, | |
66 double max_frame_rate); | |
67 | 66 |
68 // Add |callback| to receive video frames on the IO-thread. | 67 // Add |callback| to receive video frames on the IO-thread. |
69 // |callback| will however be released on the main render thread. | 68 // |callback| will however be released on the main render thread. |
70 void AddCallback(const MediaStreamVideoTrack* track, | 69 void AddCallback(const MediaStreamVideoTrack* track, |
71 const VideoCaptureDeliverFrameCB& callback); | 70 const VideoCaptureDeliverFrameCB& callback); |
72 | 71 |
73 // Removes |callback| associated with |track| from receiving video frames if | 72 // Removes |callback| associated with |track| from receiving video frames if |
74 // |track| has been added. It is ok to call RemoveCallback even if the |track| | 73 // |track| has been added. It is ok to call RemoveCallback even if the |track| |
75 // has not been added. The |callback| is released on the main render thread. | 74 // has not been added. The |callback| is released on the main render thread. |
76 void RemoveCallback(const MediaStreamVideoTrack* track); | 75 void RemoveCallback(const MediaStreamVideoTrack* track); |
77 | 76 |
78 void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame, | 77 void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame, |
79 const base::TimeTicks& estimated_capture_time); | 78 const base::TimeTicks& estimated_capture_time); |
80 | 79 |
81 // Returns true if all arguments match with the output of this adapter. | 80 // Returns true if all arguments match with the output of this adapter. |
82 bool ConstraintsMatch(const gfx::Size& max_size, | 81 bool SettingsMatch(const VideoTrackAdapterSettings& settings) const; |
83 double min_aspect_ratio, | |
84 double max_aspect_ratio, | |
85 double max_frame_rate) const; | |
86 | 82 |
87 bool IsEmpty() const; | 83 bool IsEmpty() const; |
88 | 84 |
89 private: | 85 private: |
90 virtual ~VideoFrameResolutionAdapter(); | 86 virtual ~VideoFrameResolutionAdapter(); |
91 friend class base::RefCountedThreadSafe<VideoFrameResolutionAdapter>; | 87 friend class base::RefCountedThreadSafe<VideoFrameResolutionAdapter>; |
92 | 88 |
93 void DoDeliverFrame(const scoped_refptr<media::VideoFrame>& frame, | 89 void DoDeliverFrame(const scoped_refptr<media::VideoFrame>& frame, |
94 const base::TimeTicks& estimated_capture_time); | 90 const base::TimeTicks& estimated_capture_time); |
95 | 91 |
(...skipping 18 matching lines...) Expand all Loading... |
114 double max_frame_rate_; | 110 double max_frame_rate_; |
115 double keep_frame_counter_; | 111 double keep_frame_counter_; |
116 | 112 |
117 typedef std::pair<const MediaStreamVideoTrack*, VideoCaptureDeliverFrameCB> | 113 typedef std::pair<const MediaStreamVideoTrack*, VideoCaptureDeliverFrameCB> |
118 VideoIdCallbackPair; | 114 VideoIdCallbackPair; |
119 std::vector<VideoIdCallbackPair> callbacks_; | 115 std::vector<VideoIdCallbackPair> callbacks_; |
120 | 116 |
121 DISALLOW_COPY_AND_ASSIGN(VideoFrameResolutionAdapter); | 117 DISALLOW_COPY_AND_ASSIGN(VideoFrameResolutionAdapter); |
122 }; | 118 }; |
123 | 119 |
124 VideoTrackAdapter:: | 120 VideoTrackAdapter::VideoFrameResolutionAdapter::VideoFrameResolutionAdapter( |
125 VideoFrameResolutionAdapter::VideoFrameResolutionAdapter( | |
126 scoped_refptr<base::SingleThreadTaskRunner> render_message_loop, | 121 scoped_refptr<base::SingleThreadTaskRunner> render_message_loop, |
127 const gfx::Size& max_size, | 122 const VideoTrackAdapterSettings& settings) |
128 double min_aspect_ratio, | |
129 double max_aspect_ratio, | |
130 double max_frame_rate) | |
131 : renderer_task_runner_(render_message_loop), | 123 : renderer_task_runner_(render_message_loop), |
132 max_frame_size_(max_size), | 124 max_frame_size_(settings.max_width, settings.max_height), |
133 min_aspect_ratio_(min_aspect_ratio), | 125 min_aspect_ratio_(settings.min_aspect_ratio), |
134 max_aspect_ratio_(max_aspect_ratio), | 126 max_aspect_ratio_(settings.max_aspect_ratio), |
135 frame_rate_(MediaStreamVideoSource::kDefaultFrameRate), | 127 frame_rate_(MediaStreamVideoSource::kDefaultFrameRate), |
136 last_time_stamp_(base::TimeDelta::Max()), | 128 last_time_stamp_(base::TimeDelta::Max()), |
137 max_frame_rate_(max_frame_rate), | 129 max_frame_rate_(settings.max_frame_rate), |
138 keep_frame_counter_(0.0) { | 130 keep_frame_counter_(0.0) { |
139 DCHECK(renderer_task_runner_.get()); | 131 DCHECK(renderer_task_runner_.get()); |
140 DCHECK(io_thread_checker_.CalledOnValidThread()); | 132 DCHECK(io_thread_checker_.CalledOnValidThread()); |
141 DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_); | 133 DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_); |
142 CHECK_NE(0, max_aspect_ratio_); | 134 CHECK_NE(0, max_aspect_ratio_); |
143 | 135 |
144 const std::string max_fps_str = | 136 const std::string max_fps_str = |
145 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 137 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
146 switches::kWebRtcMaxCaptureFramerate); | 138 switches::kWebRtcMaxCaptureFramerate); |
147 if (!max_fps_str.empty()) { | 139 if (!max_fps_str.empty()) { |
148 double value; | 140 double value; |
149 if (base::StringToDouble(max_fps_str, &value) && value >= 0.0) { | 141 if (base::StringToDouble(max_fps_str, &value) && value >= 0.0) { |
150 DVLOG(1) << "Overriding max frame rate. Was=" << max_frame_rate | 142 DVLOG(1) << "Overriding max frame rate. Was=" << max_frame_rate_ |
151 << ", Now=" << value; | 143 << ", Now=" << value; |
152 max_frame_rate_ = value; | 144 max_frame_rate_ = value; |
153 } else { | 145 } else { |
154 DLOG(ERROR) << "Unable to set max fps to " << max_fps_str; | 146 DLOG(ERROR) << "Unable to set max fps to " << max_fps_str; |
155 } | 147 } |
156 } | 148 } |
157 | 149 |
158 DVLOG(3) << "VideoFrameResolutionAdapter(" | 150 DVLOG(3) << "VideoFrameResolutionAdapter(" |
159 << "{ max_width =" << max_frame_size_.width() << "}, " | 151 << "{ max_width =" << max_frame_size_.width() << "}, " |
160 << "{ max_height =" << max_frame_size_.height() << "}, " | 152 << "{ max_height =" << max_frame_size_.height() << "}, " |
161 << "{ min_aspect_ratio =" << min_aspect_ratio << "}, " | 153 << "{ min_aspect_ratio =" << min_aspect_ratio_ << "}, " |
162 << "{ max_aspect_ratio_ =" << max_aspect_ratio_ << "}" | 154 << "{ max_aspect_ratio_ =" << max_aspect_ratio_ << "}" |
163 << "{ max_frame_rate_ =" << max_frame_rate_ << "}) "; | 155 << "{ max_frame_rate_ =" << max_frame_rate_ << "}) "; |
164 } | 156 } |
165 | 157 |
166 VideoTrackAdapter:: | 158 VideoTrackAdapter:: |
167 VideoFrameResolutionAdapter::~VideoFrameResolutionAdapter() { | 159 VideoFrameResolutionAdapter::~VideoFrameResolutionAdapter() { |
168 DCHECK(io_thread_checker_.CalledOnValidThread()); | 160 DCHECK(io_thread_checker_.CalledOnValidThread()); |
169 DCHECK(callbacks_.empty()); | 161 DCHECK(callbacks_.empty()); |
170 } | 162 } |
171 | 163 |
172 void VideoTrackAdapter::VideoFrameResolutionAdapter::AddCallback( | 164 void VideoTrackAdapter::VideoFrameResolutionAdapter::AddCallback( |
173 const MediaStreamVideoTrack* track, | 165 const MediaStreamVideoTrack* track, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 | 236 |
245 DVLOG(3) << "desired size " << desired_size.ToString() | 237 DVLOG(3) << "desired size " << desired_size.ToString() |
246 << " output natural size " | 238 << " output natural size " |
247 << video_frame->natural_size().ToString() | 239 << video_frame->natural_size().ToString() |
248 << " output visible rect " | 240 << " output visible rect " |
249 << video_frame->visible_rect().ToString(); | 241 << video_frame->visible_rect().ToString(); |
250 } | 242 } |
251 DoDeliverFrame(video_frame, estimated_capture_time); | 243 DoDeliverFrame(video_frame, estimated_capture_time); |
252 } | 244 } |
253 | 245 |
254 bool VideoTrackAdapter::VideoFrameResolutionAdapter::ConstraintsMatch( | 246 bool VideoTrackAdapter::VideoFrameResolutionAdapter::SettingsMatch( |
255 const gfx::Size& max_size, | 247 const VideoTrackAdapterSettings& settings) const { |
256 double min_aspect_ratio, | |
257 double max_aspect_ratio, | |
258 double max_frame_rate) const { | |
259 DCHECK(io_thread_checker_.CalledOnValidThread()); | 248 DCHECK(io_thread_checker_.CalledOnValidThread()); |
260 return max_frame_size_ == max_size && | 249 return max_frame_size_.width() == settings.max_width && |
261 min_aspect_ratio_ == min_aspect_ratio && | 250 max_frame_size_.height() == settings.max_height && |
262 max_aspect_ratio_ == max_aspect_ratio && | 251 min_aspect_ratio_ == settings.min_aspect_ratio && |
263 max_frame_rate_ == max_frame_rate; | 252 max_aspect_ratio_ == settings.max_aspect_ratio && |
| 253 max_frame_rate_ == settings.max_frame_rate; |
264 } | 254 } |
265 | 255 |
266 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { | 256 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { |
267 DCHECK(io_thread_checker_.CalledOnValidThread()); | 257 DCHECK(io_thread_checker_.CalledOnValidThread()); |
268 return callbacks_.empty(); | 258 return callbacks_.empty(); |
269 } | 259 } |
270 | 260 |
271 void VideoTrackAdapter::VideoFrameResolutionAdapter::DoDeliverFrame( | 261 void VideoTrackAdapter::VideoFrameResolutionAdapter::DoDeliverFrame( |
272 const scoped_refptr<media::VideoFrame>& frame, | 262 const scoped_refptr<media::VideoFrame>& frame, |
273 const base::TimeTicks& estimated_capture_time) { | 263 const base::TimeTicks& estimated_capture_time) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 keep_frame_counter_ += max_frame_rate_ / frame_rate_; | 317 keep_frame_counter_ += max_frame_rate_ / frame_rate_; |
328 if (keep_frame_counter_ >= 1) { | 318 if (keep_frame_counter_ >= 1) { |
329 keep_frame_counter_ -= 1; | 319 keep_frame_counter_ -= 1; |
330 // Keep the frame. | 320 // Keep the frame. |
331 return false; | 321 return false; |
332 } | 322 } |
333 DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << "."; | 323 DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << "."; |
334 return true; | 324 return true; |
335 } | 325 } |
336 | 326 |
| 327 VideoTrackAdapterSettings::VideoTrackAdapterSettings(int max_width, |
| 328 int max_height, |
| 329 double min_aspect_ratio, |
| 330 double max_aspect_ratio, |
| 331 double max_frame_rate) |
| 332 : max_width(max_width), |
| 333 max_height(max_height), |
| 334 min_aspect_ratio(min_aspect_ratio), |
| 335 max_aspect_ratio(max_aspect_ratio), |
| 336 max_frame_rate(max_frame_rate) { |
| 337 DCHECK_GE(max_width, 1); |
| 338 DCHECK_GE(max_height, 1); |
| 339 DCHECK_GE(min_aspect_ratio, 0.0); |
| 340 DCHECK_GE(max_aspect_ratio, min_aspect_ratio); |
| 341 DCHECK_GE(max_frame_rate, 0.0); |
| 342 } |
| 343 |
337 VideoTrackAdapter::VideoTrackAdapter( | 344 VideoTrackAdapter::VideoTrackAdapter( |
338 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) | 345 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) |
339 : io_task_runner_(io_task_runner), | 346 : io_task_runner_(io_task_runner), |
340 renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 347 renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
341 monitoring_frame_rate_(false), | 348 monitoring_frame_rate_(false), |
342 muted_state_(false), | 349 muted_state_(false), |
343 frame_counter_(0), | 350 frame_counter_(0), |
344 source_frame_rate_(0.0f) { | 351 source_frame_rate_(0.0f) { |
345 DCHECK(io_task_runner); | 352 DCHECK(io_task_runner); |
346 } | 353 } |
347 | 354 |
348 VideoTrackAdapter::~VideoTrackAdapter() { | 355 VideoTrackAdapter::~VideoTrackAdapter() { |
349 DCHECK(adapters_.empty()); | 356 DCHECK(adapters_.empty()); |
350 } | 357 } |
351 | 358 |
352 void VideoTrackAdapter::AddTrack(const MediaStreamVideoTrack* track, | 359 void VideoTrackAdapter::AddTrack(const MediaStreamVideoTrack* track, |
353 VideoCaptureDeliverFrameCB frame_callback, | 360 VideoCaptureDeliverFrameCB frame_callback, |
354 int max_width, | 361 const VideoTrackAdapterSettings& settings) { |
355 int max_height, | |
356 double min_aspect_ratio, | |
357 double max_aspect_ratio, | |
358 double max_frame_rate) { | |
359 DCHECK(thread_checker_.CalledOnValidThread()); | 362 DCHECK(thread_checker_.CalledOnValidThread()); |
360 | 363 |
361 io_task_runner_->PostTask( | 364 io_task_runner_->PostTask( |
362 FROM_HERE, | 365 FROM_HERE, base::Bind(&VideoTrackAdapter::AddTrackOnIO, this, track, |
363 base::Bind(&VideoTrackAdapter::AddTrackOnIO, this, track, frame_callback, | 366 frame_callback, settings)); |
364 gfx::Size(max_width, max_height), min_aspect_ratio, | |
365 max_aspect_ratio, max_frame_rate)); | |
366 } | 367 } |
367 | 368 |
368 void VideoTrackAdapter::AddTrackOnIO(const MediaStreamVideoTrack* track, | 369 void VideoTrackAdapter::AddTrackOnIO( |
369 VideoCaptureDeliverFrameCB frame_callback, | 370 const MediaStreamVideoTrack* track, |
370 const gfx::Size& max_frame_size, | 371 VideoCaptureDeliverFrameCB frame_callback, |
371 double min_aspect_ratio, | 372 const VideoTrackAdapterSettings& settings) { |
372 double max_aspect_ratio, | |
373 double max_frame_rate) { | |
374 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 373 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
375 scoped_refptr<VideoFrameResolutionAdapter> adapter; | 374 scoped_refptr<VideoFrameResolutionAdapter> adapter; |
376 for (const auto& frame_adapter : adapters_) { | 375 for (const auto& frame_adapter : adapters_) { |
377 if (frame_adapter->ConstraintsMatch(max_frame_size, min_aspect_ratio, | 376 if (frame_adapter->SettingsMatch(settings)) { |
378 max_aspect_ratio, max_frame_rate)) { | |
379 adapter = frame_adapter.get(); | 377 adapter = frame_adapter.get(); |
380 break; | 378 break; |
381 } | 379 } |
382 } | 380 } |
383 if (!adapter.get()) { | 381 if (!adapter.get()) { |
384 adapter = new VideoFrameResolutionAdapter(renderer_task_runner_, | 382 adapter = new VideoFrameResolutionAdapter(renderer_task_runner_, settings); |
385 max_frame_size, | |
386 min_aspect_ratio, | |
387 max_aspect_ratio, | |
388 max_frame_rate); | |
389 adapters_.push_back(adapter); | 383 adapters_.push_back(adapter); |
390 } | 384 } |
391 | 385 |
392 adapter->AddCallback(track, frame_callback); | 386 adapter->AddCallback(track, frame_callback); |
393 } | 387 } |
394 | 388 |
395 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) { | 389 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) { |
396 DCHECK(thread_checker_.CalledOnValidThread()); | 390 DCHECK(thread_checker_.CalledOnValidThread()); |
397 io_task_runner_->PostTask( | 391 io_task_runner_->PostTask( |
398 FROM_HERE, base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track)); | 392 FROM_HERE, base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track)); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 } | 519 } |
526 | 520 |
527 io_task_runner_->PostDelayedTask( | 521 io_task_runner_->PostDelayedTask( |
528 FROM_HERE, base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, | 522 FROM_HERE, base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, |
529 set_muted_state_callback, frame_counter_), | 523 set_muted_state_callback, frame_counter_), |
530 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / | 524 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / |
531 source_frame_rate_)); | 525 source_frame_rate_)); |
532 } | 526 } |
533 | 527 |
534 } // namespace content | 528 } // namespace content |
OLD | NEW |