| 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 |