OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/renderer/media/video_capture_relay.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" |
| 9 #include "content/renderer/media/video_capture_impl_manager.h" |
| 10 //#include "media/base/filters.h" |
| 11 #include "media/base/limits.h" |
| 12 #include "media/base/video_util.h" |
| 13 |
| 14 using media::CopyYPlane; |
| 15 using media::CopyUPlane; |
| 16 using media::CopyVPlane; |
| 17 |
| 18 VideoCaptureRelay::VideoCaptureRelay( |
| 19 media::VideoCaptureSessionId video_stream_id, |
| 20 VideoCaptureImplManager* vc_manager, |
| 21 const media::VideoCaptureCapability& capability, |
| 22 const base::Closure& paint_cb) |
| 23 : thread_("VideoCaptureRelay"), |
| 24 vc_manager_(vc_manager), |
| 25 capability_(capability), |
| 26 is_active_(false), |
| 27 pending_paint_(false), |
| 28 paint_cb_(paint_cb), |
| 29 video_stream_id_(video_stream_id), |
| 30 capture_engine_(NULL) { |
| 31 VLOG(1) << "VideoCaptureRelay::VideoCaptureRelay"; |
| 32 DCHECK(vc_manager); |
| 33 thread_.Start(); |
| 34 message_loop_proxy_ = thread_.message_loop_proxy(); |
| 35 } |
| 36 |
| 37 VideoCaptureRelay::~VideoCaptureRelay() { |
| 38 VLOG(1) << "VideoCaptureRelay::~VideoCaptureRelay"; |
| 39 thread_.Stop(); |
| 40 } |
| 41 |
| 42 void VideoCaptureRelay::Start() { |
| 43 message_loop_proxy_->PostTask( |
| 44 FROM_HERE, |
| 45 base::Bind(&VideoCaptureRelay::StartOnRelayThread, this)); |
| 46 } |
| 47 |
| 48 void VideoCaptureRelay::Stop(const base::Closure& callback) { |
| 49 message_loop_proxy_->PostTask( |
| 50 FROM_HERE, |
| 51 base::Bind(&VideoCaptureRelay::StopOnRelayThread, |
| 52 this, callback)); |
| 53 } |
| 54 |
| 55 void VideoCaptureRelay::OnStarted(media::VideoCapture* capture) { |
| 56 NOTIMPLEMENTED(); |
| 57 } |
| 58 |
| 59 void VideoCaptureRelay::OnStopped(media::VideoCapture* capture) { |
| 60 message_loop_proxy_->PostTask( |
| 61 FROM_HERE, |
| 62 base::Bind(&VideoCaptureRelay::OnStoppedOnRelayThread, |
| 63 this, capture)); |
| 64 } |
| 65 |
| 66 void VideoCaptureRelay::OnPaused(media::VideoCapture* capture) { |
| 67 NOTIMPLEMENTED(); |
| 68 } |
| 69 |
| 70 void VideoCaptureRelay::OnError(media::VideoCapture* capture, |
| 71 int error_code) { |
| 72 NOTIMPLEMENTED(); |
| 73 } |
| 74 |
| 75 void VideoCaptureRelay::OnRemoved(media::VideoCapture* capture) { |
| 76 NOTIMPLEMENTED(); |
| 77 } |
| 78 |
| 79 void VideoCaptureRelay::OnBufferReady( |
| 80 media::VideoCapture* capture, |
| 81 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { |
| 82 DCHECK(buf); |
| 83 message_loop_proxy_->PostTask( |
| 84 FROM_HERE, |
| 85 base::Bind(&VideoCaptureRelay::OnBufferReadyOnRelayThread, |
| 86 this, capture, buf)); |
| 87 } |
| 88 |
| 89 void VideoCaptureRelay::OnDeviceInfoReceived( |
| 90 media::VideoCapture* capture, |
| 91 const media::VideoCaptureParams& device_info) { |
| 92 message_loop_proxy_->PostTask( |
| 93 FROM_HERE, |
| 94 base::Bind(&VideoCaptureRelay::OnDeviceInfoReceivedOnRelayThread, |
| 95 this, capture, device_info)); |
| 96 } |
| 97 |
| 98 void VideoCaptureRelay::StartOnRelayThread() { |
| 99 DVLOG(1) << "StartOnRelayThread"; |
| 100 VLOG(1) << "VideoCaptureRelay::StartOnRelayThread"; |
| 101 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 102 |
| 103 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); |
| 104 is_active_ = true; |
| 105 capture_engine_->StartCapture(this, capability_); |
| 106 } |
| 107 |
| 108 void VideoCaptureRelay::StopOnRelayThread(const base::Closure& callback) { |
| 109 DVLOG(1) << "StopOnRelayThread"; |
| 110 VLOG(1) << "VideoCaptureRelay::StopOnRelayThread"; |
| 111 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 112 pending_stop_cb_ = callback; |
| 113 is_active_ = false; |
| 114 capture_engine_->StopCapture(this); |
| 115 } |
| 116 |
| 117 void VideoCaptureRelay::OnStoppedOnRelayThread( |
| 118 media::VideoCapture* capture) { |
| 119 DVLOG(1) << "OnStoppedOnRelayThread"; |
| 120 VLOG(1) << "VideoCaptureRelay::OnStoppedOnRelayThread"; |
| 121 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 122 if (!pending_stop_cb_.is_null()) |
| 123 base::ResetAndReturn(&pending_stop_cb_).Run(); |
| 124 vc_manager_->RemoveDevice(video_stream_id_, this); |
| 125 } |
| 126 |
| 127 void VideoCaptureRelay::OnDeviceInfoReceivedOnRelayThread( |
| 128 media::VideoCapture* capture, |
| 129 const media::VideoCaptureParams& device_info) { |
| 130 VLOG(1) << "VideoCaptureRelay::OnDeviceInfoReceivedOnRelayThread"; |
| 131 } |
| 132 |
| 133 void VideoCaptureRelay::OnBufferReadyOnRelayThread( |
| 134 media::VideoCapture* capture, |
| 135 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { |
| 136 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
| 137 //VLOG(1) << "VideoCaptureRelay::OnBufferReadyOnRelayThread"; |
| 138 |
| 139 base::AutoLock auto_lock(lock_); |
| 140 if (pending_paint_ || !is_active_) { |
| 141 VLOG(1) << "VideoCaptureRelay::OnBufferReadyOnRelayThread, drop a frame"; |
| 142 capture->FeedBuffer(buf); |
| 143 return; |
| 144 } |
| 145 |
| 146 if (!current_frame_ || |
| 147 static_cast<int>(current_frame_->width()) != buf->width || |
| 148 static_cast<int>(current_frame_->height()) != buf->height) { |
| 149 const base::TimeDelta kZero; |
| 150 current_frame_ = |
| 151 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, |
| 152 buf->width, buf->height, |
| 153 kZero, kZero); |
| 154 } |
| 155 |
| 156 uint8* buffer = buf->memory_pointer; |
| 157 |
| 158 // Assume YV12 format. Note that camera gives YUV and media pipeline video |
| 159 // renderer asks for YVU. The following code did the conversion. |
| 160 DCHECK_EQ(capability_.color, media::VideoCaptureCapability::kI420); |
| 161 int y_width = buf->width; |
| 162 int y_height = buf->height; |
| 163 int uv_width = buf->width / 2; |
| 164 int uv_height = buf->height / 2; // YV12 format. |
| 165 CopyYPlane(buffer, y_width, y_height, current_frame_); |
| 166 buffer += y_width * y_height; |
| 167 CopyUPlane(buffer, uv_width, uv_height, current_frame_); |
| 168 buffer += uv_width * uv_height; |
| 169 CopyVPlane(buffer, uv_width, uv_height, current_frame_); |
| 170 |
| 171 base::AutoUnlock auto_unlock(lock_); |
| 172 capture->FeedBuffer(buf); |
| 173 paint_cb_.Run(); |
| 174 } |
| 175 |
| 176 void VideoCaptureRelay::GetCurrentFrame( |
| 177 scoped_refptr<media::VideoFrame>* frame_out) { |
| 178 base::AutoLock auto_lock(lock_); |
| 179 DCHECK(!pending_paint_); |
| 180 |
| 181 *frame_out = current_frame_; |
| 182 if (current_frame_) { |
| 183 pending_paint_ = true; |
| 184 } |
| 185 } |
| 186 |
| 187 void VideoCaptureRelay::PutCurrentFrame( |
| 188 scoped_refptr<media::VideoFrame> frame) { |
| 189 base::AutoLock auto_lock(lock_); |
| 190 |
| 191 if (pending_paint_) { |
| 192 DCHECK_EQ(current_frame_, frame); |
| 193 pending_paint_ = false; |
| 194 } else { |
| 195 DCHECK(!frame); |
| 196 } |
| 197 } |
| 198 |
OLD | NEW |