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

Side by Side Diff: content/renderer/media/video_track_adapter.cc

Issue 2777703002: Introduce SelectSettings algorithm for MediaStream video tracks. (Closed)
Patch Set: static asserts Created 3 years, 8 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 | « content/renderer/media/video_track_adapter.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/renderer/media/video_track_adapter.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698