OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/capture_video_decoder.h" | 5 #include "content/renderer/media/capture_video_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "content/renderer/media/video_capture_impl_manager.h" | 8 #include "content/renderer/media/video_capture_impl_manager.h" |
9 #include "media/base/filter_host.h" | 9 #include "media/base/filter_host.h" |
10 #include "media/base/limits.h" | 10 #include "media/base/limits.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 this, callback)); | 60 this, callback)); |
61 } | 61 } |
62 | 62 |
63 void CaptureVideoDecoder::Pause(const base::Closure& callback) { | 63 void CaptureVideoDecoder::Pause(const base::Closure& callback) { |
64 message_loop_proxy_->PostTask( | 64 message_loop_proxy_->PostTask( |
65 FROM_HERE, | 65 FROM_HERE, |
66 base::Bind(&CaptureVideoDecoder::PauseOnDecoderThread, | 66 base::Bind(&CaptureVideoDecoder::PauseOnDecoderThread, |
67 this, callback)); | 67 this, callback)); |
68 } | 68 } |
69 | 69 |
70 void CaptureVideoDecoder::Flush(const base::Closure& callback) { | |
71 message_loop_proxy_->PostTask( | |
72 FROM_HERE, | |
73 base::Bind(&CaptureVideoDecoder::FlushOnDecoderThread, | |
74 this, callback)); | |
75 } | |
76 | |
70 void CaptureVideoDecoder::Stop(const base::Closure& callback) { | 77 void CaptureVideoDecoder::Stop(const base::Closure& callback) { |
71 message_loop_proxy_->PostTask( | 78 message_loop_proxy_->PostTask( |
72 FROM_HERE, | 79 FROM_HERE, |
73 base::Bind(&CaptureVideoDecoder::StopOnDecoderThread, | 80 base::Bind(&CaptureVideoDecoder::StopOnDecoderThread, |
74 this, callback)); | 81 this, callback)); |
75 } | 82 } |
76 | 83 |
77 void CaptureVideoDecoder::Seek(base::TimeDelta time, | 84 void CaptureVideoDecoder::Seek(base::TimeDelta time, |
78 const media::FilterStatusCB& cb) { | 85 const media::FilterStatusCB& cb) { |
79 message_loop_proxy_->PostTask( | 86 message_loop_proxy_->PostTask( |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
134 | 141 |
135 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); | 142 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); |
136 | 143 |
137 statistics_callback_ = stat_callback; | 144 statistics_callback_ = stat_callback; |
138 filter_callback.Run(); | 145 filter_callback.Run(); |
139 state_ = kNormal; | 146 state_ = kNormal; |
140 } | 147 } |
141 | 148 |
142 void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) { | 149 void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) { |
143 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 150 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
144 CHECK(read_cb_.is_null()); | 151 CHECK(!callback.is_null()); |
145 read_cb_ = callback; | 152 if (state_ != kNormal) { |
scherkus (not reviewing)
2011/11/16 01:12:36
does this actually happen in practice?
I'd be int
wjia(left Chromium)
2011/11/16 05:25:54
It could happen in two cases:
1. When pipeline put
| |
153 DeliverBlackFrame(callback); | |
154 return; | |
155 } | |
156 read_cbs_.push(callback); | |
146 } | 157 } |
147 | 158 |
148 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) { | 159 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) { |
149 DVLOG(1) << "PlayOnDecoderThread"; | 160 DVLOG(1) << "PlayOnDecoderThread"; |
150 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 161 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
151 callback.Run(); | 162 callback.Run(); |
152 } | 163 } |
153 | 164 |
154 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) { | 165 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) { |
155 DVLOG(1) << "PauseOnDecoderThread"; | 166 DVLOG(1) << "PauseOnDecoderThread"; |
156 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 167 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
157 state_ = kPaused; | 168 state_ = kPaused; |
158 media::VideoDecoder::Pause(callback); | 169 media::VideoDecoder::Pause(callback); |
159 } | 170 } |
160 | 171 |
172 void CaptureVideoDecoder::FlushOnDecoderThread(const base::Closure& callback) { | |
173 DVLOG(1) << "FlushOnDecoderThread"; | |
174 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | |
175 while (!read_cbs_.empty()) { | |
176 DeliverBlackFrame(read_cbs_.front()); | |
177 read_cbs_.pop(); | |
178 } | |
179 media::VideoDecoder::Flush(callback); | |
180 } | |
181 | |
161 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) { | 182 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) { |
162 DVLOG(1) << "StopOnDecoderThread"; | 183 DVLOG(1) << "StopOnDecoderThread"; |
163 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 184 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
164 pending_stop_cb_ = callback; | 185 pending_stop_cb_ = callback; |
165 state_ = kStopped; | 186 state_ = kStopped; |
166 capture_engine_->StopCapture(this); | 187 capture_engine_->StopCapture(this); |
167 } | 188 } |
168 | 189 |
169 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time, | 190 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time, |
170 const media::FilterStatusCB& cb) { | 191 const media::FilterStatusCB& cb) { |
(...skipping 23 matching lines...) Expand all Loading... | |
194 natural_size_.SetSize(device_info.width, device_info.height); | 215 natural_size_.SetSize(device_info.width, device_info.height); |
195 host()->SetNaturalVideoSize(natural_size_); | 216 host()->SetNaturalVideoSize(natural_size_); |
196 } | 217 } |
197 } | 218 } |
198 | 219 |
199 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread( | 220 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread( |
200 media::VideoCapture* capture, | 221 media::VideoCapture* capture, |
201 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { | 222 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { |
202 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 223 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
203 | 224 |
204 if (read_cb_.is_null() || kNormal != state_) { | 225 if (read_cbs_.empty() || kNormal != state_) { |
205 capture->FeedBuffer(buf); | 226 capture->FeedBuffer(buf); |
206 return; | 227 return; |
207 } | 228 } |
208 | 229 |
209 // TODO(wjia): should we always expect device to send device info before | 230 // TODO(wjia): should we always expect device to send device info before |
210 // any buffer, and buffers should have dimension stated in device info? | 231 // any buffer, and buffers should have dimension stated in device info? |
211 // Or should we be flexible as in following code? | 232 // Or should we be flexible as in following code? |
212 if (buf->width != natural_size_.width() || | 233 if (buf->width != natural_size_.width() || |
213 buf->height != natural_size_.height()) { | 234 buf->height != natural_size_.height()) { |
214 natural_size_.SetSize(buf->width, buf->height); | 235 natural_size_.SetSize(buf->width, buf->height); |
(...skipping 18 matching lines...) Expand all Loading... | |
233 int y_width = buf->width; | 254 int y_width = buf->width; |
234 int y_height = buf->height; | 255 int y_height = buf->height; |
235 int uv_width = buf->width / 2; | 256 int uv_width = buf->width / 2; |
236 int uv_height = buf->height / 2; // YV12 format. | 257 int uv_height = buf->height / 2; // YV12 format. |
237 CopyYPlane(buffer, y_width, y_height, video_frame); | 258 CopyYPlane(buffer, y_width, y_height, video_frame); |
238 buffer += y_width * y_height; | 259 buffer += y_width * y_height; |
239 CopyUPlane(buffer, uv_width, uv_height, video_frame); | 260 CopyUPlane(buffer, uv_width, uv_height, video_frame); |
240 buffer += uv_width * uv_height; | 261 buffer += uv_width * uv_height; |
241 CopyVPlane(buffer, uv_width, uv_height, video_frame); | 262 CopyVPlane(buffer, uv_width, uv_height, video_frame); |
242 | 263 |
243 DeliverFrame(video_frame); | 264 read_cbs_.front().Run(video_frame); |
265 read_cbs_.pop(); | |
244 capture->FeedBuffer(buf); | 266 capture->FeedBuffer(buf); |
245 } | 267 } |
246 | 268 |
247 void CaptureVideoDecoder::DeliverFrame( | 269 void CaptureVideoDecoder::DeliverBlackFrame( |
248 const scoped_refptr<media::VideoFrame>& video_frame) { | 270 const ReadCB& read_cb) { |
249 // Reset the callback before running to protect against reentrancy. | 271 CHECK(!read_cb.is_null()); |
250 ReadCB read_cb = read_cb_; | 272 scoped_refptr<media::VideoFrame> video_frame = |
251 read_cb_.Reset(); | 273 media::VideoFrame::CreateBlackFrame(natural_size_.width(), |
274 natural_size_.height()); | |
252 read_cb.Run(video_frame); | 275 read_cb.Run(video_frame); |
253 } | 276 } |
OLD | NEW |