| 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 |