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

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

Issue 2870413004: Detect frames from rotated devices in VideoTrackAdapter on Android. (Closed)
Patch Set: address comment by tommi@ Created 3 years, 7 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> 9 #include <memory>
10 #include <string> 10 #include <string>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/macros.h" 16 #include "base/macros.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/trace_event/trace_event.h" 20 #include "base/trace_event/trace_event.h"
21 #include "build/build_config.h"
21 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
22 #include "media/base/bind_to_current_loop.h" 23 #include "media/base/bind_to_current_loop.h"
23 #include "media/base/video_util.h" 24 #include "media/base/video_util.h"
24 25
25 namespace content { 26 namespace content {
26 27
27 namespace { 28 namespace {
28 29
29 // Amount of frame intervals to wait before considering the source as muted, for 30 // Amount of frame intervals to wait before considering the source as muted, for
30 // the first frame and under normal conditions, respectively. First frame might 31 // the first frame and under normal conditions, respectively. First frame might
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 float source_frame_rate); 96 float source_frame_rate);
96 97
97 // Bound to the IO-thread. 98 // Bound to the IO-thread.
98 base::ThreadChecker io_thread_checker_; 99 base::ThreadChecker io_thread_checker_;
99 100
100 // The task runner where we will release VideoCaptureDeliverFrameCB 101 // The task runner where we will release VideoCaptureDeliverFrameCB
101 // registered in AddCallback. 102 // registered in AddCallback.
102 const scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_; 103 const scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_;
103 104
104 const gfx::Size max_frame_size_; 105 const gfx::Size max_frame_size_;
106 base::Optional<gfx::Size> expected_native_size_;
105 const double min_aspect_ratio_; 107 const double min_aspect_ratio_;
106 const double max_aspect_ratio_; 108 const double max_aspect_ratio_;
107 109
108 double frame_rate_; 110 double frame_rate_;
109 base::TimeDelta last_time_stamp_; 111 base::TimeDelta last_time_stamp_;
110 double max_frame_rate_; 112 double max_frame_rate_;
111 double keep_frame_counter_; 113 double keep_frame_counter_;
112 114
113 typedef std::pair<const MediaStreamVideoTrack*, VideoCaptureDeliverFrameCB> 115 typedef std::pair<const MediaStreamVideoTrack*, VideoCaptureDeliverFrameCB>
114 VideoIdCallbackPair; 116 VideoIdCallbackPair;
115 std::vector<VideoIdCallbackPair> callbacks_; 117 std::vector<VideoIdCallbackPair> callbacks_;
116 118
117 DISALLOW_COPY_AND_ASSIGN(VideoFrameResolutionAdapter); 119 DISALLOW_COPY_AND_ASSIGN(VideoFrameResolutionAdapter);
118 }; 120 };
119 121
120 VideoTrackAdapter::VideoFrameResolutionAdapter::VideoFrameResolutionAdapter( 122 VideoTrackAdapter::VideoFrameResolutionAdapter::VideoFrameResolutionAdapter(
121 scoped_refptr<base::SingleThreadTaskRunner> render_message_loop, 123 scoped_refptr<base::SingleThreadTaskRunner> render_message_loop,
122 const VideoTrackAdapterSettings& settings) 124 const VideoTrackAdapterSettings& settings)
123 : renderer_task_runner_(render_message_loop), 125 : renderer_task_runner_(render_message_loop),
124 max_frame_size_(settings.max_width, settings.max_height), 126 max_frame_size_(settings.max_width, settings.max_height),
127 expected_native_size_(settings.expected_native_size),
125 min_aspect_ratio_(settings.min_aspect_ratio), 128 min_aspect_ratio_(settings.min_aspect_ratio),
126 max_aspect_ratio_(settings.max_aspect_ratio), 129 max_aspect_ratio_(settings.max_aspect_ratio),
127 frame_rate_(MediaStreamVideoSource::kDefaultFrameRate), 130 frame_rate_(MediaStreamVideoSource::kDefaultFrameRate),
128 last_time_stamp_(base::TimeDelta::Max()), 131 last_time_stamp_(base::TimeDelta::Max()),
129 max_frame_rate_(settings.max_frame_rate), 132 max_frame_rate_(settings.max_frame_rate),
130 keep_frame_counter_(0.0) { 133 keep_frame_counter_(0.0) {
131 DCHECK(renderer_task_runner_.get()); 134 DCHECK(renderer_task_runner_.get());
132 DCHECK(io_thread_checker_.CalledOnValidThread()); 135 DCHECK(io_thread_checker_.CalledOnValidThread());
133 DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_); 136 DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_);
134 CHECK_NE(0, max_aspect_ratio_); 137 CHECK_NE(0, max_aspect_ratio_);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 return; 212 return;
210 213
211 // TODO(perkj): Allow cropping / scaling of textures once 214 // TODO(perkj): Allow cropping / scaling of textures once
212 // http://crbug/362521 is fixed. 215 // http://crbug/362521 is fixed.
213 if (frame->HasTextures()) { 216 if (frame->HasTextures()) {
214 DoDeliverFrame(frame, estimated_capture_time); 217 DoDeliverFrame(frame, estimated_capture_time);
215 return; 218 return;
216 } 219 }
217 scoped_refptr<media::VideoFrame> video_frame(frame); 220 scoped_refptr<media::VideoFrame> video_frame(frame);
218 221
222 bool is_rotated = false;
223 #if defined(OS_ANDROID)
224 // TODO(guidou): Use actual device information instead of this heuristic to
225 // detect frames from rotated devices. http://crbug.com/722748
226 if (expected_native_size_ &&
227 frame->natural_size().width() == expected_native_size_->height() &&
228 frame->natural_size().height() == expected_native_size_->width()) {
229 is_rotated = true;
230 }
231 #endif
219 gfx::Size desired_size; 232 gfx::Size desired_size;
220 CalculateTargetSize(frame->natural_size(), max_frame_size_, min_aspect_ratio_, 233 CalculateTargetSize(is_rotated, frame->natural_size(), max_frame_size_,
221 max_aspect_ratio_, &desired_size); 234 min_aspect_ratio_, max_aspect_ratio_, &desired_size);
222 if (desired_size != frame->natural_size()) { 235 if (desired_size != frame->natural_size()) {
223 // Get the largest centered rectangle with the same aspect ratio of 236 // Get the largest centered rectangle with the same aspect ratio of
224 // |desired_size| that fits entirely inside of |frame->visible_rect()|. 237 // |desired_size| that fits entirely inside of |frame->visible_rect()|.
225 // This will be the rect we need to crop the original frame to. 238 // This will be the rect we need to crop the original frame to.
226 // From this rect, the original frame can be scaled down to |desired_size|. 239 // From this rect, the original frame can be scaled down to |desired_size|.
227 const gfx::Rect region_in_frame = 240 const gfx::Rect region_in_frame =
228 media::ComputeLetterboxRegion(frame->visible_rect(), desired_size); 241 media::ComputeLetterboxRegion(frame->visible_rect(), desired_size);
229 242
230 video_frame = media::VideoFrame::WrapVideoFrame( 243 video_frame = media::VideoFrame::WrapVideoFrame(
231 frame, frame->format(), region_in_frame, desired_size); 244 frame, frame->format(), region_in_frame, desired_size);
(...skipping 11 matching lines...) Expand all
243 DoDeliverFrame(video_frame, estimated_capture_time); 256 DoDeliverFrame(video_frame, estimated_capture_time);
244 } 257 }
245 258
246 bool VideoTrackAdapter::VideoFrameResolutionAdapter::SettingsMatch( 259 bool VideoTrackAdapter::VideoFrameResolutionAdapter::SettingsMatch(
247 const VideoTrackAdapterSettings& settings) const { 260 const VideoTrackAdapterSettings& settings) const {
248 DCHECK(io_thread_checker_.CalledOnValidThread()); 261 DCHECK(io_thread_checker_.CalledOnValidThread());
249 return max_frame_size_.width() == settings.max_width && 262 return max_frame_size_.width() == settings.max_width &&
250 max_frame_size_.height() == settings.max_height && 263 max_frame_size_.height() == settings.max_height &&
251 min_aspect_ratio_ == settings.min_aspect_ratio && 264 min_aspect_ratio_ == settings.min_aspect_ratio &&
252 max_aspect_ratio_ == settings.max_aspect_ratio && 265 max_aspect_ratio_ == settings.max_aspect_ratio &&
253 max_frame_rate_ == settings.max_frame_rate; 266 max_frame_rate_ == settings.max_frame_rate &&
267 expected_native_size_ == settings.expected_native_size;
254 } 268 }
255 269
256 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { 270 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const {
257 DCHECK(io_thread_checker_.CalledOnValidThread()); 271 DCHECK(io_thread_checker_.CalledOnValidThread());
258 return callbacks_.empty(); 272 return callbacks_.empty();
259 } 273 }
260 274
261 void VideoTrackAdapter::VideoFrameResolutionAdapter::DoDeliverFrame( 275 void VideoTrackAdapter::VideoFrameResolutionAdapter::DoDeliverFrame(
262 const scoped_refptr<media::VideoFrame>& frame, 276 const scoped_refptr<media::VideoFrame>& frame,
263 const base::TimeTicks& estimated_capture_time) { 277 const base::TimeTicks& estimated_capture_time) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 336 }
323 DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << "."; 337 DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << ".";
324 return true; 338 return true;
325 } 339 }
326 340
327 VideoTrackAdapterSettings::VideoTrackAdapterSettings() 341 VideoTrackAdapterSettings::VideoTrackAdapterSettings()
328 : VideoTrackAdapterSettings(std::numeric_limits<int>::max(), 342 : VideoTrackAdapterSettings(std::numeric_limits<int>::max(),
329 std::numeric_limits<int>::max(), 343 std::numeric_limits<int>::max(),
330 0.0, 344 0.0,
331 std::numeric_limits<double>::max(), 345 std::numeric_limits<double>::max(),
332 0.0) {} 346 0.0,
347 base::Optional<gfx::Size>()) {}
333 348
334 VideoTrackAdapterSettings::VideoTrackAdapterSettings(int max_width, 349 VideoTrackAdapterSettings::VideoTrackAdapterSettings(
335 int max_height, 350 int max_width,
336 double min_aspect_ratio, 351 int max_height,
337 double max_aspect_ratio, 352 double min_aspect_ratio,
338 double max_frame_rate) 353 double max_aspect_ratio,
354 double max_frame_rate,
355 const base::Optional<gfx::Size>& expected_native_size)
339 : max_width(max_width), 356 : max_width(max_width),
340 max_height(max_height), 357 max_height(max_height),
341 min_aspect_ratio(min_aspect_ratio), 358 min_aspect_ratio(min_aspect_ratio),
342 max_aspect_ratio(max_aspect_ratio), 359 max_aspect_ratio(max_aspect_ratio),
343 max_frame_rate(max_frame_rate) { 360 max_frame_rate(max_frame_rate),
361 expected_native_size(expected_native_size) {
344 DCHECK_GE(max_width, 1); 362 DCHECK_GE(max_width, 1);
345 DCHECK_GE(max_height, 1); 363 DCHECK_GE(max_height, 1);
346 DCHECK_GE(min_aspect_ratio, 0.0); 364 DCHECK_GE(min_aspect_ratio, 0.0);
347 DCHECK_GE(max_aspect_ratio, min_aspect_ratio); 365 DCHECK_GE(max_aspect_ratio, min_aspect_ratio);
348 DCHECK_GE(max_frame_rate, 0.0); 366 DCHECK_GE(max_frame_rate, 0.0);
349 } 367 }
350 368
369 VideoTrackAdapterSettings::VideoTrackAdapterSettings(
370 const VideoTrackAdapterSettings& other) = default;
371 VideoTrackAdapterSettings& VideoTrackAdapterSettings::operator=(
372 const VideoTrackAdapterSettings& other) = default;
373
351 VideoTrackAdapter::VideoTrackAdapter( 374 VideoTrackAdapter::VideoTrackAdapter(
352 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) 375 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
353 : io_task_runner_(io_task_runner), 376 : io_task_runner_(io_task_runner),
354 renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()), 377 renderer_task_runner_(base::ThreadTaskRunnerHandle::Get()),
355 monitoring_frame_rate_(false), 378 monitoring_frame_rate_(false),
356 muted_state_(false), 379 muted_state_(false),
357 frame_counter_(0), 380 frame_counter_(0),
358 source_frame_rate_(0.0f) { 381 source_frame_rate_(0.0f) {
359 DCHECK(io_task_runner); 382 DCHECK(io_task_runner);
360 } 383 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 bound_on_muted_callback, source_frame_rate)); 435 bound_on_muted_callback, source_frame_rate));
413 } 436 }
414 437
415 void VideoTrackAdapter::StopFrameMonitoring() { 438 void VideoTrackAdapter::StopFrameMonitoring() {
416 DCHECK(thread_checker_.CalledOnValidThread()); 439 DCHECK(thread_checker_.CalledOnValidThread());
417 io_task_runner_->PostTask( 440 io_task_runner_->PostTask(
418 FROM_HERE, base::Bind(&VideoTrackAdapter::StopFrameMonitoringOnIO, this)); 441 FROM_HERE, base::Bind(&VideoTrackAdapter::StopFrameMonitoringOnIO, this));
419 } 442 }
420 443
421 // static 444 // static
422 void VideoTrackAdapter::CalculateTargetSize(const gfx::Size& input_size, 445 void VideoTrackAdapter::CalculateTargetSize(
423 const gfx::Size& max_frame_size, 446 bool is_rotated,
424 double min_aspect_ratio, 447 const gfx::Size& original_input_size,
425 double max_aspect_ratio, 448 const gfx::Size& max_frame_size,
426 gfx::Size* desired_size) { 449 double min_aspect_ratio,
450 double max_aspect_ratio,
451 gfx::Size* desired_size) {
452 const gfx::Size& input_size =
453 is_rotated
454 ? gfx::Size(original_input_size.height(), original_input_size.width())
455 : original_input_size;
456
427 // If |frame| has larger width or height than requested, or the aspect ratio 457 // If |frame| has larger width or height than requested, or the aspect ratio
428 // does not match the requested, we want to create a wrapped version of this 458 // does not match the requested, we want to create a wrapped version of this
429 // frame with a size that fulfills the constraints. 459 // frame with a size that fulfills the constraints.
430 const double input_ratio = 460 const double input_ratio =
431 static_cast<double>(input_size.width()) / input_size.height(); 461 static_cast<double>(input_size.width()) / input_size.height();
432 462
433 if (input_size.width() > max_frame_size.width() || 463 if (input_size.width() > max_frame_size.width() ||
434 input_size.height() > max_frame_size.height() || 464 input_size.height() > max_frame_size.height() ||
435 input_ratio > max_aspect_ratio || input_ratio < min_aspect_ratio) { 465 input_ratio > max_aspect_ratio || input_ratio < min_aspect_ratio) {
436 int desired_width = std::min(max_frame_size.width(), input_size.width()); 466 int desired_width = std::min(max_frame_size.width(), input_size.width());
(...skipping 10 matching lines...) Expand all
447 requested_ratio); 477 requested_ratio);
448 // Make sure we scale to an even height to avoid rounding errors 478 // Make sure we scale to an even height to avoid rounding errors
449 desired_height = (desired_height + 1) & ~1; 479 desired_height = (desired_height + 1) & ~1;
450 } else if (resulting_ratio > requested_ratio) { 480 } else if (resulting_ratio > requested_ratio) {
451 desired_width = 481 desired_width =
452 static_cast<int>((desired_width * requested_ratio) / resulting_ratio); 482 static_cast<int>((desired_width * requested_ratio) / resulting_ratio);
453 // Make sure we scale to an even width to avoid rounding errors. 483 // Make sure we scale to an even width to avoid rounding errors.
454 desired_width = (desired_width + 1) & ~1; 484 desired_width = (desired_width + 1) & ~1;
455 } 485 }
456 486
457 *desired_size = gfx::Size(desired_width, desired_height); 487 *desired_size = is_rotated ? gfx::Size(desired_height, desired_width)
488 : gfx::Size(desired_width, desired_height);
458 } else { 489 } else {
459 *desired_size = input_size; 490 *desired_size = original_input_size;
460 } 491 }
461 } 492 }
462 493
463 void VideoTrackAdapter::StartFrameMonitoringOnIO( 494 void VideoTrackAdapter::StartFrameMonitoringOnIO(
464 const OnMutedCallback& on_muted_callback, 495 const OnMutedCallback& on_muted_callback,
465 double source_frame_rate) { 496 double source_frame_rate) {
466 DCHECK(io_task_runner_->BelongsToCurrentThread()); 497 DCHECK(io_task_runner_->BelongsToCurrentThread());
467 DCHECK(!monitoring_frame_rate_); 498 DCHECK(!monitoring_frame_rate_);
468 499
469 monitoring_frame_rate_ = true; 500 monitoring_frame_rate_ = true;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 } 557 }
527 558
528 io_task_runner_->PostDelayedTask( 559 io_task_runner_->PostDelayedTask(
529 FROM_HERE, base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, 560 FROM_HERE, base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this,
530 set_muted_state_callback, frame_counter_), 561 set_muted_state_callback, frame_counter_),
531 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / 562 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals /
532 source_frame_rate_)); 563 source_frame_rate_));
533 } 564 }
534 565
535 } // namespace content 566 } // 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