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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 DCHECK(buf); | 112 DCHECK(buf); |
113 message_loop_proxy_->PostTask( | 113 message_loop_proxy_->PostTask( |
114 FROM_HERE, | 114 FROM_HERE, |
115 base::Bind(&CaptureVideoDecoder::OnBufferReadyOnDecoderThread, | 115 base::Bind(&CaptureVideoDecoder::OnBufferReadyOnDecoderThread, |
116 this, capture, buf)); | 116 this, capture, buf)); |
117 } | 117 } |
118 | 118 |
119 void CaptureVideoDecoder::OnDeviceInfoReceived( | 119 void CaptureVideoDecoder::OnDeviceInfoReceived( |
120 media::VideoCapture* capture, | 120 media::VideoCapture* capture, |
121 const media::VideoCaptureParams& device_info) { | 121 const media::VideoCaptureParams& device_info) { |
122 NOTIMPLEMENTED(); | 122 message_loop_proxy_->PostTask( |
| 123 FROM_HERE, |
| 124 base::Bind(&CaptureVideoDecoder::OnDeviceInfoReceivedOnDecoderThread, |
| 125 this, capture, device_info)); |
123 } | 126 } |
124 | 127 |
125 void CaptureVideoDecoder::InitializeOnDecoderThread( | 128 void CaptureVideoDecoder::InitializeOnDecoderThread( |
126 media::DemuxerStream* demuxer_stream, | 129 media::DemuxerStream* demuxer_stream, |
127 const base::Closure& filter_callback, | 130 const base::Closure& filter_callback, |
128 const media::StatisticsCallback& stat_callback) { | 131 const media::StatisticsCallback& stat_callback) { |
129 VLOG(1) << "InitializeOnDecoderThread."; | 132 DVLOG(1) << "InitializeOnDecoderThread"; |
130 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 133 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
131 | 134 |
132 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); | 135 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); |
133 | 136 |
134 statistics_callback_ = stat_callback; | 137 statistics_callback_ = stat_callback; |
135 filter_callback.Run(); | 138 filter_callback.Run(); |
136 state_ = kNormal; | 139 state_ = kNormal; |
137 } | 140 } |
138 | 141 |
139 void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) { | 142 void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) { |
140 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 143 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
141 CHECK(read_cb_.is_null()); | 144 CHECK(read_cb_.is_null()); |
142 read_cb_ = callback; | 145 read_cb_ = callback; |
143 } | 146 } |
144 | 147 |
145 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) { | 148 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) { |
146 VLOG(1) << "PlayOnDecoderThread."; | 149 DVLOG(1) << "PlayOnDecoderThread"; |
147 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 150 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
148 callback.Run(); | 151 callback.Run(); |
149 } | 152 } |
150 | 153 |
151 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) { | 154 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) { |
152 VLOG(1) << "PauseOnDecoderThread."; | 155 DVLOG(1) << "PauseOnDecoderThread"; |
153 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 156 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
154 state_ = kPaused; | 157 state_ = kPaused; |
155 media::VideoDecoder::Pause(callback); | 158 media::VideoDecoder::Pause(callback); |
156 } | 159 } |
157 | 160 |
158 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) { | 161 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) { |
159 VLOG(1) << "StopOnDecoderThread."; | 162 DVLOG(1) << "StopOnDecoderThread"; |
160 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 163 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
161 pending_stop_cb_ = callback; | 164 pending_stop_cb_ = callback; |
162 state_ = kStopped; | 165 state_ = kStopped; |
163 capture_engine_->StopCapture(this); | 166 capture_engine_->StopCapture(this); |
164 } | 167 } |
165 | 168 |
166 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time, | 169 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time, |
167 const media::FilterStatusCB& cb) { | 170 const media::FilterStatusCB& cb) { |
168 VLOG(1) << "SeekOnDecoderThread."; | 171 DVLOG(1) << "SeekOnDecoderThread"; |
169 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 172 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
170 | 173 |
171 cb.Run(media::PIPELINE_OK); | 174 cb.Run(media::PIPELINE_OK); |
172 state_ = kNormal; | 175 state_ = kNormal; |
173 capture_engine_->StartCapture(this, capability_); | 176 capture_engine_->StartCapture(this, capability_); |
174 } | 177 } |
175 | 178 |
176 void CaptureVideoDecoder::OnStoppedOnDecoderThread( | 179 void CaptureVideoDecoder::OnStoppedOnDecoderThread( |
177 media::VideoCapture* capture) { | 180 media::VideoCapture* capture) { |
178 VLOG(1) << "OnStoppedOnDecoderThread."; | 181 DVLOG(1) << "OnStoppedOnDecoderThread"; |
179 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 182 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
180 if (!pending_stop_cb_.is_null()) | 183 if (!pending_stop_cb_.is_null()) |
181 media::ResetAndRunCB(&pending_stop_cb_); | 184 media::ResetAndRunCB(&pending_stop_cb_); |
182 vc_manager_->RemoveDevice(video_stream_id_, this); | 185 vc_manager_->RemoveDevice(video_stream_id_, this); |
183 } | 186 } |
184 | 187 |
| 188 void CaptureVideoDecoder::OnDeviceInfoReceivedOnDecoderThread( |
| 189 media::VideoCapture* capture, |
| 190 const media::VideoCaptureParams& device_info) { |
| 191 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 192 if (device_info.width != natural_size_.width() || |
| 193 device_info.height != natural_size_.height()) { |
| 194 natural_size_.SetSize(device_info.width, device_info.height); |
| 195 host()->SetNaturalVideoSize(natural_size_); |
| 196 } |
| 197 } |
| 198 |
185 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread( | 199 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread( |
186 media::VideoCapture* capture, | 200 media::VideoCapture* capture, |
187 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { | 201 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { |
188 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | 202 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
189 | 203 |
190 if (read_cb_.is_null() || kNormal != state_) { | 204 if (read_cb_.is_null() || kNormal != state_) { |
191 capture->FeedBuffer(buf); | 205 capture->FeedBuffer(buf); |
192 return; | 206 return; |
193 } | 207 } |
194 | 208 |
195 if (buf->width != capability_.width || buf->height != capability_.height) { | 209 // TODO(wjia): should we always expect device to send device info before |
196 capability_.width = buf->width; | 210 // any buffer, and buffers should have dimension stated in device info? |
197 capability_.height = buf->height; | 211 // Or should we be flexible as in following code? |
| 212 if (buf->width != natural_size_.width() || |
| 213 buf->height != natural_size_.height()) { |
198 natural_size_.SetSize(buf->width, buf->height); | 214 natural_size_.SetSize(buf->width, buf->height); |
199 host()->SetNaturalVideoSize(natural_size_); | 215 host()->SetNaturalVideoSize(natural_size_); |
200 } | 216 } |
201 | 217 |
202 // Always allocate a new frame. | 218 // Always allocate a new frame. |
203 // | 219 // |
204 // TODO(scherkus): migrate this to proper buffer recycling. | 220 // TODO(scherkus): migrate this to proper buffer recycling. |
205 scoped_refptr<media::VideoFrame> video_frame = | 221 scoped_refptr<media::VideoFrame> video_frame = |
206 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, | 222 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, |
207 natural_size_.width(), | 223 natural_size_.width(), |
208 natural_size_.height(), | 224 natural_size_.height(), |
209 buf->timestamp - start_time_, | 225 buf->timestamp - start_time_, |
210 base::TimeDelta::FromMilliseconds(33)); | 226 base::TimeDelta::FromMilliseconds(33)); |
211 | 227 |
212 uint8* buffer = buf->memory_pointer; | 228 uint8* buffer = buf->memory_pointer; |
213 | 229 |
214 // Assume YV12 format. | 230 // Assume YV12 format. Note that camera gives YUV and media pipeline video |
215 // TODO(vrk): This DCHECK fails in content_unittests ... it should not! | 231 // renderer asks for YVU. The following code did the conversion. |
216 // DCHECK(capability_.raw_type == media::VideoFrame::YV12); | 232 DCHECK_EQ(capability_.raw_type, media::VideoFrame::I420); |
217 int y_width = capability_.width; | 233 int y_width = buf->width; |
218 int y_height = capability_.height; | 234 int y_height = buf->height; |
219 int uv_width = capability_.width / 2; | 235 int uv_width = buf->width / 2; |
220 int uv_height = capability_.height / 2; // YV12 format. | 236 int uv_height = buf->height / 2; // YV12 format. |
221 CopyYPlane(buffer, y_width, y_height, video_frame); | 237 CopyYPlane(buffer, y_width, y_height, video_frame); |
222 buffer += y_width * y_height; | 238 buffer += y_width * y_height; |
223 CopyUPlane(buffer, uv_width, uv_height, video_frame); | 239 CopyUPlane(buffer, uv_width, uv_height, video_frame); |
224 buffer += uv_width * uv_height; | 240 buffer += uv_width * uv_height; |
225 CopyVPlane(buffer, uv_width, uv_height, video_frame); | 241 CopyVPlane(buffer, uv_width, uv_height, video_frame); |
226 | 242 |
227 DeliverFrame(video_frame); | 243 DeliverFrame(video_frame); |
228 capture->FeedBuffer(buf); | 244 capture->FeedBuffer(buf); |
229 } | 245 } |
230 | 246 |
231 void CaptureVideoDecoder::DeliverFrame( | 247 void CaptureVideoDecoder::DeliverFrame( |
232 const scoped_refptr<media::VideoFrame>& video_frame) { | 248 const scoped_refptr<media::VideoFrame>& video_frame) { |
233 // Reset the callback before running to protect against reentrancy. | 249 // Reset the callback before running to protect against reentrancy. |
234 ReadCB read_cb = read_cb_; | 250 ReadCB read_cb = read_cb_; |
235 read_cb_.Reset(); | 251 read_cb_.Reset(); |
236 read_cb.Run(video_frame); | 252 read_cb.Run(video_frame); |
237 } | 253 } |
OLD | NEW |