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_frame_compositor.h" | 5 #include "content/renderer/media/video_frame_compositor.h" |
6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "base/single_thread_task_runner.h" |
| 10 #include "cc/layers/video_frame_provider.h" |
| 11 #include "content/renderer/render_thread_impl.h" |
7 #include "media/base/video_frame.h" | 12 #include "media/base/video_frame.h" |
8 | 13 |
9 namespace content { | 14 namespace content { |
10 | 15 |
11 static bool IsOpaque(const scoped_refptr<media::VideoFrame>& frame) { | 16 static bool IsOpaque(const scoped_refptr<media::VideoFrame>& frame) { |
12 switch (frame->format()) { | 17 switch (frame->format()) { |
13 case media::VideoFrame::UNKNOWN: | 18 case media::VideoFrame::UNKNOWN: |
14 case media::VideoFrame::YV12: | 19 case media::VideoFrame::YV12: |
15 case media::VideoFrame::YV12J: | 20 case media::VideoFrame::YV12J: |
16 case media::VideoFrame::YV16: | 21 case media::VideoFrame::YV16: |
17 case media::VideoFrame::I420: | 22 case media::VideoFrame::I420: |
18 return true; | 23 return true; |
19 | 24 |
20 case media::VideoFrame::YV12A: | 25 case media::VideoFrame::YV12A: |
21 #if defined(VIDEO_HOLE) | 26 #if defined(VIDEO_HOLE) |
22 case media::VideoFrame::HOLE: | 27 case media::VideoFrame::HOLE: |
23 #endif // defined(VIDEO_HOLE) | 28 #endif // defined(VIDEO_HOLE) |
24 case media::VideoFrame::NATIVE_TEXTURE: | 29 case media::VideoFrame::NATIVE_TEXTURE: |
25 break; | 30 break; |
26 } | 31 } |
27 return false; | 32 return false; |
28 } | 33 } |
29 | 34 |
| 35 class VideoFrameCompositor::Internal : public cc::VideoFrameProvider { |
| 36 public: |
| 37 Internal( |
| 38 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, |
| 39 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, |
| 40 const base::Callback<void(bool)>& opacity_changed_cb) |
| 41 : compositor_task_runner_(compositor_task_runner), |
| 42 natural_size_changed_cb_(natural_size_changed_cb), |
| 43 opacity_changed_cb_(opacity_changed_cb), |
| 44 client_(NULL), |
| 45 compositor_notification_pending_(false), |
| 46 frames_dropped_before_compositor_was_notified_(0) {} |
| 47 |
| 48 virtual ~Internal() { |
| 49 if (client_) |
| 50 client_->StopUsingProvider(); |
| 51 } |
| 52 |
| 53 void DeleteSoon() { |
| 54 compositor_task_runner_->DeleteSoon(FROM_HERE, this); |
| 55 } |
| 56 |
| 57 void UpdateCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) { |
| 58 base::AutoLock auto_lock(lock_); |
| 59 |
| 60 if (current_frame_ && |
| 61 current_frame_->natural_size() != frame->natural_size()) { |
| 62 natural_size_changed_cb_.Run(frame->natural_size()); |
| 63 } |
| 64 |
| 65 if (!current_frame_ || IsOpaque(current_frame_) != IsOpaque(frame)) { |
| 66 opacity_changed_cb_.Run(IsOpaque(frame)); |
| 67 } |
| 68 |
| 69 current_frame_ = frame; |
| 70 |
| 71 // Count frames as dropped if and only if we updated the frame but didn't |
| 72 // finish notifying the compositor for the previous frame. |
| 73 if (compositor_notification_pending_) { |
| 74 if (frames_dropped_before_compositor_was_notified_ < kuint32max) |
| 75 ++frames_dropped_before_compositor_was_notified_; |
| 76 return; |
| 77 } |
| 78 |
| 79 compositor_notification_pending_ = true; |
| 80 compositor_task_runner_->PostTask( |
| 81 FROM_HERE, |
| 82 base::Bind(&Internal::NotifyCompositorOfNewFrame, |
| 83 base::Unretained(this))); |
| 84 } |
| 85 |
| 86 uint32 GetFramesDroppedBeforeCompositorWasNotified() { |
| 87 base::AutoLock auto_lock(lock_); |
| 88 return frames_dropped_before_compositor_was_notified_; |
| 89 } |
| 90 |
| 91 void SetFramesDroppedBeforeCompositorWasNotifiedForTesting( |
| 92 uint32 dropped_frames) { |
| 93 base::AutoLock auto_lock(lock_); |
| 94 frames_dropped_before_compositor_was_notified_ = dropped_frames; |
| 95 } |
| 96 |
| 97 // cc::VideoFrameProvider implementation. |
| 98 virtual void SetVideoFrameProviderClient( |
| 99 cc::VideoFrameProvider::Client* client) OVERRIDE { |
| 100 if (client_) |
| 101 client_->StopUsingProvider(); |
| 102 client_ = client; |
| 103 } |
| 104 |
| 105 virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE { |
| 106 base::AutoLock auto_lock(lock_); |
| 107 return current_frame_; |
| 108 } |
| 109 |
| 110 virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) |
| 111 OVERRIDE {} |
| 112 |
| 113 private: |
| 114 void NotifyCompositorOfNewFrame() { |
| 115 base::AutoLock auto_lock(lock_); |
| 116 compositor_notification_pending_ = false; |
| 117 if (client_) |
| 118 client_->DidReceiveFrame(); |
| 119 } |
| 120 |
| 121 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; |
| 122 base::Callback<void(gfx::Size)> natural_size_changed_cb_; |
| 123 base::Callback<void(bool)> opacity_changed_cb_; |
| 124 |
| 125 cc::VideoFrameProvider::Client* client_; |
| 126 |
| 127 base::Lock lock_; |
| 128 scoped_refptr<media::VideoFrame> current_frame_; |
| 129 bool compositor_notification_pending_; |
| 130 uint32 frames_dropped_before_compositor_was_notified_; |
| 131 |
| 132 DISALLOW_COPY_AND_ASSIGN(Internal); |
| 133 }; |
| 134 |
30 VideoFrameCompositor::VideoFrameCompositor( | 135 VideoFrameCompositor::VideoFrameCompositor( |
| 136 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, |
31 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, | 137 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, |
32 const base::Callback<void(bool)>& opacity_changed_cb) | 138 const base::Callback<void(bool)>& opacity_changed_cb) |
33 : natural_size_changed_cb_(natural_size_changed_cb), | 139 : internal_(new Internal(compositor_task_runner, |
34 opacity_changed_cb_(opacity_changed_cb), | 140 natural_size_changed_cb, |
35 client_(NULL) { | 141 opacity_changed_cb)) { |
36 } | 142 } |
37 | 143 |
38 VideoFrameCompositor::~VideoFrameCompositor() { | 144 VideoFrameCompositor::~VideoFrameCompositor() { |
39 if (client_) | 145 internal_->DeleteSoon(); |
40 client_->StopUsingProvider(); | |
41 } | 146 } |
42 | 147 |
43 void VideoFrameCompositor::SetVideoFrameProviderClient( | 148 cc::VideoFrameProvider* VideoFrameCompositor::GetVideoFrameProvider() { |
44 cc::VideoFrameProvider::Client* client) { | 149 return internal_; |
45 if (client_) | |
46 client_->StopUsingProvider(); | |
47 client_ = client; | |
48 } | |
49 | |
50 scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() { | |
51 base::AutoLock auto_lock(lock_); | |
52 return current_frame_; | |
53 } | |
54 | |
55 void VideoFrameCompositor::PutCurrentFrame( | |
56 const scoped_refptr<media::VideoFrame>& frame) { | |
57 } | 150 } |
58 | 151 |
59 void VideoFrameCompositor::UpdateCurrentFrame( | 152 void VideoFrameCompositor::UpdateCurrentFrame( |
60 const scoped_refptr<media::VideoFrame>& frame) { | 153 const scoped_refptr<media::VideoFrame>& frame) { |
61 base::AutoLock auto_lock(lock_); | 154 internal_->UpdateCurrentFrame(frame); |
| 155 } |
62 | 156 |
63 if (current_frame_ && | 157 scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() { |
64 current_frame_->natural_size() != frame->natural_size()) { | 158 return internal_->GetCurrentFrame(); |
65 natural_size_changed_cb_.Run(frame->natural_size()); | 159 } |
66 } | |
67 | 160 |
68 if (!current_frame_ || IsOpaque(current_frame_) != IsOpaque(frame)) { | 161 uint32 VideoFrameCompositor::GetFramesDroppedBeforeCompositorWasNotified() { |
69 opacity_changed_cb_.Run(IsOpaque(frame)); | 162 return internal_->GetFramesDroppedBeforeCompositorWasNotified(); |
70 } | 163 } |
71 | 164 |
72 current_frame_ = frame; | 165 void |
73 | 166 VideoFrameCompositor::SetFramesDroppedBeforeCompositorWasNotifiedForTesting( |
74 if (client_) | 167 uint32 dropped_frames) { |
75 client_->DidReceiveFrame(); | 168 internal_->SetFramesDroppedBeforeCompositorWasNotifiedForTesting( |
| 169 dropped_frames); |
76 } | 170 } |
77 | 171 |
78 } // namespace content | 172 } // namespace content |
OLD | NEW |