Chromium Code Reviews| 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 |