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" | |
12 #include "media/base/video_frame.h" | 7 #include "media/base/video_frame.h" |
13 | 8 |
14 namespace content { | 9 namespace content { |
15 | 10 |
16 static bool IsOpaque(const scoped_refptr<media::VideoFrame>& frame) { | 11 static bool IsOpaque(const scoped_refptr<media::VideoFrame>& frame) { |
17 switch (frame->format()) { | 12 switch (frame->format()) { |
18 case media::VideoFrame::UNKNOWN: | 13 case media::VideoFrame::UNKNOWN: |
19 case media::VideoFrame::YV12: | 14 case media::VideoFrame::YV12: |
20 case media::VideoFrame::YV12J: | 15 case media::VideoFrame::YV12J: |
21 case media::VideoFrame::YV16: | 16 case media::VideoFrame::YV16: |
22 case media::VideoFrame::I420: | 17 case media::VideoFrame::I420: |
23 return true; | 18 return true; |
24 | 19 |
25 case media::VideoFrame::YV12A: | 20 case media::VideoFrame::YV12A: |
26 #if defined(VIDEO_HOLE) | 21 #if defined(VIDEO_HOLE) |
27 case media::VideoFrame::HOLE: | 22 case media::VideoFrame::HOLE: |
28 #endif // defined(VIDEO_HOLE) | 23 #endif // defined(VIDEO_HOLE) |
29 case media::VideoFrame::NATIVE_TEXTURE: | 24 case media::VideoFrame::NATIVE_TEXTURE: |
30 break; | 25 break; |
31 } | 26 } |
32 return false; | 27 return false; |
33 } | 28 } |
34 | 29 |
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 | |
135 VideoFrameCompositor::VideoFrameCompositor( | 30 VideoFrameCompositor::VideoFrameCompositor( |
136 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner, | |
137 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, | 31 const base::Callback<void(gfx::Size)>& natural_size_changed_cb, |
138 const base::Callback<void(bool)>& opacity_changed_cb) | 32 const base::Callback<void(bool)>& opacity_changed_cb) |
139 : internal_(new Internal(compositor_task_runner, | 33 : natural_size_changed_cb_(natural_size_changed_cb), |
140 natural_size_changed_cb, | 34 opacity_changed_cb_(opacity_changed_cb), |
141 opacity_changed_cb)) { | 35 client_(NULL) { |
142 } | 36 } |
143 | 37 |
144 VideoFrameCompositor::~VideoFrameCompositor() { | 38 VideoFrameCompositor::~VideoFrameCompositor() { |
145 internal_->DeleteSoon(); | 39 if (client_) |
| 40 client_->StopUsingProvider(); |
146 } | 41 } |
147 | 42 |
148 cc::VideoFrameProvider* VideoFrameCompositor::GetVideoFrameProvider() { | 43 void VideoFrameCompositor::SetVideoFrameProviderClient( |
149 return internal_; | 44 cc::VideoFrameProvider::Client* client) { |
| 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) { |
150 } | 57 } |
151 | 58 |
152 void VideoFrameCompositor::UpdateCurrentFrame( | 59 void VideoFrameCompositor::UpdateCurrentFrame( |
153 const scoped_refptr<media::VideoFrame>& frame) { | 60 const scoped_refptr<media::VideoFrame>& frame) { |
154 internal_->UpdateCurrentFrame(frame); | 61 base::AutoLock auto_lock(lock_); |
155 } | |
156 | 62 |
157 scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() { | 63 if (current_frame_ && |
158 return internal_->GetCurrentFrame(); | 64 current_frame_->natural_size() != frame->natural_size()) { |
159 } | 65 natural_size_changed_cb_.Run(frame->natural_size()); |
| 66 } |
160 | 67 |
161 uint32 VideoFrameCompositor::GetFramesDroppedBeforeCompositorWasNotified() { | 68 if (!current_frame_ || IsOpaque(current_frame_) != IsOpaque(frame)) { |
162 return internal_->GetFramesDroppedBeforeCompositorWasNotified(); | 69 opacity_changed_cb_.Run(IsOpaque(frame)); |
163 } | 70 } |
164 | 71 |
165 void | 72 current_frame_ = frame; |
166 VideoFrameCompositor::SetFramesDroppedBeforeCompositorWasNotifiedForTesting( | 73 |
167 uint32 dropped_frames) { | 74 if (client_) |
168 internal_->SetFramesDroppedBeforeCompositorWasNotifiedForTesting( | 75 client_->DidReceiveFrame(); |
169 dropped_frames); | |
170 } | 76 } |
171 | 77 |
172 } // namespace content | 78 } // namespace content |
OLD | NEW |