Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: content/renderer/media/video_capture_impl.cc

Issue 23587018: Replace media::VideoCapture::VideoFrameBuffer with media::VideoFrame. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@git-svn
Patch Set: 6ccf4fd6 Final. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/video_capture_impl.h" 5 #include "content/renderer/media/video_capture_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "content/child/child_process.h" 9 #include "content/child/child_process.h"
10 #include "content/common/media/video_capture_messages.h" 10 #include "content/common/media/video_capture_messages.h"
11 #include "media/base/bind_to_loop.h"
11 #include "media/base/limits.h" 12 #include "media/base/limits.h"
12 13
13 namespace content { 14 namespace content {
14 15
15 struct VideoCaptureImpl::DIBBuffer { 16 class VideoCaptureImpl::ClientBuffer : public base::RefCounted<ClientBuffer> {
16 public: 17 public:
17 DIBBuffer( 18 ClientBuffer(scoped_ptr<base::SharedMemory> buffer,
18 base::SharedMemory* d, 19 size_t buffer_size,
19 media::VideoCapture::VideoFrameBuffer* ptr) 20 int frame_width,
20 : dib(d), 21 int frame_height,
21 mapped_memory(ptr), 22 int frame_stride)
22 references(0) { 23 : buffer(buffer.Pass()),
23 } 24 buffer_size(buffer_size),
24 ~DIBBuffer() {} 25 frame_width(frame_width),
26 frame_height(frame_height),
27 frame_stride(frame_stride) {}
28 const scoped_ptr<base::SharedMemory> buffer;
29 const size_t buffer_size;
30 const int frame_width; // In pixels.
31 const int frame_height; // In pixels.
32 const int frame_stride; // In pixels.
25 33
26 scoped_ptr<base::SharedMemory> dib; 34 private:
27 scoped_refptr<media::VideoCapture::VideoFrameBuffer> mapped_memory; 35 friend class base::RefCounted<ClientBuffer>;
28 36
29 // Number of clients which hold this DIB. 37 virtual ~ClientBuffer() {}
30 int references; 38
39 DISALLOW_COPY_AND_ASSIGN(ClientBuffer);
31 }; 40 };
32 41
33 bool VideoCaptureImpl::CaptureStarted() { 42 bool VideoCaptureImpl::CaptureStarted() {
34 return state_ == VIDEO_CAPTURE_STATE_STARTED; 43 return state_ == VIDEO_CAPTURE_STATE_STARTED;
35 } 44 }
36 45
37 int VideoCaptureImpl::CaptureWidth() { 46 int VideoCaptureImpl::CaptureWidth() {
38 return capture_format_.width; 47 return capture_format_.width;
39 } 48 }
40 49
41 int VideoCaptureImpl::CaptureHeight() { 50 int VideoCaptureImpl::CaptureHeight() {
42 return capture_format_.height; 51 return capture_format_.height;
43 } 52 }
44 53
45 int VideoCaptureImpl::CaptureFrameRate() { 54 int VideoCaptureImpl::CaptureFrameRate() {
46 return capture_format_.frame_rate; 55 return capture_format_.frame_rate;
47 } 56 }
48 57
49 VideoCaptureImpl::VideoCaptureImpl( 58 VideoCaptureImpl::VideoCaptureImpl(
50 const media::VideoCaptureSessionId id, 59 const media::VideoCaptureSessionId id,
51 base::MessageLoopProxy* capture_message_loop_proxy, 60 base::MessageLoopProxy* capture_message_loop_proxy,
52 VideoCaptureMessageFilter* filter) 61 VideoCaptureMessageFilter* filter)
53 : VideoCapture(), 62 : VideoCapture(),
54 message_filter_(filter), 63 message_filter_(filter),
55 capture_message_loop_proxy_(capture_message_loop_proxy), 64 capture_message_loop_proxy_(capture_message_loop_proxy),
56 io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), 65 io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()),
57 device_id_(0), 66 device_id_(0),
67 client_buffer_weak_this_factory_(this),
58 video_type_(media::PIXEL_FORMAT_I420), 68 video_type_(media::PIXEL_FORMAT_I420),
59 device_info_available_(false), 69 device_info_available_(false),
60 suspended_(false), 70 suspended_(false),
61 state_(VIDEO_CAPTURE_STATE_STOPPED) { 71 state_(VIDEO_CAPTURE_STATE_STOPPED) {
62 DCHECK(filter); 72 DCHECK(filter);
63 capture_format_.session_id = id; 73 capture_format_.session_id = id;
64 } 74 }
65 75
66 VideoCaptureImpl::~VideoCaptureImpl() { 76 VideoCaptureImpl::~VideoCaptureImpl() {}
67 STLDeleteValues(&cached_dibs_);
68 }
69 77
70 void VideoCaptureImpl::Init() { 78 void VideoCaptureImpl::Init() {
71 if (!io_message_loop_proxy_->BelongsToCurrentThread()) { 79 if (!io_message_loop_proxy_->BelongsToCurrentThread()) {
72 io_message_loop_proxy_->PostTask(FROM_HERE, 80 io_message_loop_proxy_->PostTask(FROM_HERE,
73 base::Bind(&VideoCaptureImpl::AddDelegateOnIOThread, 81 base::Bind(&VideoCaptureImpl::AddDelegateOnIOThread,
74 base::Unretained(this))); 82 base::Unretained(this)));
75 } else { 83 } else {
76 AddDelegateOnIOThread(); 84 AddDelegateOnIOThread();
77 } 85 }
78 } 86 }
(...skipping 13 matching lines...) Expand all
92 base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread, 100 base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread,
93 base::Unretained(this), handler, capability)); 101 base::Unretained(this), handler, capability));
94 } 102 }
95 103
96 void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { 104 void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
97 capture_message_loop_proxy_->PostTask(FROM_HERE, 105 capture_message_loop_proxy_->PostTask(FROM_HERE,
98 base::Bind(&VideoCaptureImpl::DoStopCaptureOnCaptureThread, 106 base::Bind(&VideoCaptureImpl::DoStopCaptureOnCaptureThread,
99 base::Unretained(this), handler)); 107 base::Unretained(this), handler));
100 } 108 }
101 109
102 void VideoCaptureImpl::FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) {
103 capture_message_loop_proxy_->PostTask(FROM_HERE,
104 base::Bind(&VideoCaptureImpl::DoFeedBufferOnCaptureThread,
105 base::Unretained(this), buffer));
106 }
107
108 void VideoCaptureImpl::OnBufferCreated( 110 void VideoCaptureImpl::OnBufferCreated(
109 base::SharedMemoryHandle handle, 111 base::SharedMemoryHandle handle,
110 int length, int buffer_id) { 112 int length, int buffer_id) {
111 capture_message_loop_proxy_->PostTask(FROM_HERE, 113 capture_message_loop_proxy_->PostTask(FROM_HERE,
112 base::Bind(&VideoCaptureImpl::DoBufferCreatedOnCaptureThread, 114 base::Bind(&VideoCaptureImpl::DoBufferCreatedOnCaptureThread,
113 base::Unretained(this), handle, length, buffer_id)); 115 base::Unretained(this), handle, length, buffer_id));
114 } 116 }
115 117
116 void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) { 118 void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) {
117 capture_message_loop_proxy_->PostTask(FROM_HERE, 119 capture_message_loop_proxy_->PostTask(FROM_HERE,
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 // A handler can be in only one client list. 230 // A handler can be in only one client list.
229 // If this handler is in any client list, we can just remove it from 231 // If this handler is in any client list, we can just remove it from
230 // that client list and don't have to run the other following RemoveClient(). 232 // that client list and don't have to run the other following RemoveClient().
231 RemoveClient(handler, &clients_pending_on_filter_) || 233 RemoveClient(handler, &clients_pending_on_filter_) ||
232 RemoveClient(handler, &clients_pending_on_restart_) || 234 RemoveClient(handler, &clients_pending_on_restart_) ||
233 RemoveClient(handler, &clients_); 235 RemoveClient(handler, &clients_);
234 236
235 if (clients_.empty()) { 237 if (clients_.empty()) {
236 DVLOG(1) << "StopCapture: No more client, stopping ..."; 238 DVLOG(1) << "StopCapture: No more client, stopping ...";
237 StopDevice(); 239 StopDevice();
240 client_buffers_.clear();
241 client_buffer_weak_this_factory_.InvalidateWeakPtrs();
238 } 242 }
239 } 243 }
240 244
241 void VideoCaptureImpl::DoFeedBufferOnCaptureThread(
242 scoped_refptr<VideoFrameBuffer> buffer) {
243 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
244
245 CachedDIB::iterator it;
246 for (it = cached_dibs_.begin(); it != cached_dibs_.end(); ++it) {
247 if (buffer.get() == it->second->mapped_memory.get())
248 break;
249 }
250
251 if (it != cached_dibs_.end() && it->second) {
252 DCHECK_GT(it->second->references, 0);
253 --it->second->references;
254 if (it->second->references == 0) {
255 Send(new VideoCaptureHostMsg_BufferReady(device_id_, it->first));
256 }
257 }
258 }
259
260 void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( 245 void VideoCaptureImpl::DoBufferCreatedOnCaptureThread(
261 base::SharedMemoryHandle handle, 246 base::SharedMemoryHandle handle,
262 int length, int buffer_id) { 247 int length, int buffer_id) {
263 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 248 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
264 249
265 // In case client calls StopCapture before the arrival of created buffer, 250 // In case client calls StopCapture before the arrival of created buffer,
266 // just close this buffer and return. 251 // just close this buffer and return.
267 if (state_ != VIDEO_CAPTURE_STATE_STARTED) { 252 if (state_ != VIDEO_CAPTURE_STATE_STARTED) {
268 base::SharedMemory::CloseHandle(handle); 253 base::SharedMemory::CloseHandle(handle);
269 return; 254 return;
270 } 255 }
271 256
272 DCHECK(device_info_available_); 257 DCHECK(device_info_available_);
273 258
274 media::VideoCapture::VideoFrameBuffer* buffer; 259 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false));
275 DCHECK(cached_dibs_.find(buffer_id) == cached_dibs_.end()); 260 if (!shm->Map(length)) {
261 DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed.";
262 return;
263 }
276 264
277 base::SharedMemory* dib = new base::SharedMemory(handle, false); 265 bool inserted =
278 dib->Map(length); 266 client_buffers_.insert(std::make_pair(
279 buffer = new VideoFrameBuffer(); 267 buffer_id,
280 buffer->memory_pointer = static_cast<uint8*>(dib->memory()); 268 new ClientBuffer(shm.Pass(),
281 buffer->buffer_size = length; 269 length,
282 buffer->width = device_info_.width; 270 device_info_.width,
283 buffer->height = device_info_.height; 271 device_info_.height,
284 buffer->stride = device_info_.width; 272 device_info_.width))).second;
285 273 DCHECK(inserted);
286 DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer);
287 cached_dibs_[buffer_id] = dib_buffer;
288 } 274 }
289 275
290 void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( 276 void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
291 int buffer_id, base::Time timestamp) { 277 int buffer_id, base::Time timestamp) {
292 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 278 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
293 279
294 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { 280 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
295 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id)); 281 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id));
296 return; 282 return;
297 } 283 }
298 284
299 media::VideoCapture::VideoFrameBuffer* buffer; 285 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id);
300 DCHECK(cached_dibs_.find(buffer_id) != cached_dibs_.end()); 286 DCHECK(iter != client_buffers_.end());
301 buffer = cached_dibs_[buffer_id]->mapped_memory.get(); 287 scoped_refptr<ClientBuffer> buffer = iter->second;
302 buffer->timestamp = timestamp; 288 scoped_refptr<media::VideoFrame> frame =
289 media::VideoFrame::WrapExternalSharedMemory(
290 media::VideoFrame::I420,
291 gfx::Size(buffer->frame_stride, buffer->frame_height),
292 gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height),
293 gfx::Size(buffer->frame_width, buffer->frame_height),
294 reinterpret_cast<uint8*>(buffer->buffer->memory()),
295 buffer->buffer_size,
296 buffer->buffer->handle(),
297 // TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use
298 // base::TimeTicks instead of base::Time. http://crbug.com/249215
299 timestamp - base::Time::UnixEpoch(),
300 media::BindToLoop(
301 capture_message_loop_proxy_,
302 base::Bind(
303 &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread,
304 client_buffer_weak_this_factory_.GetWeakPtr(),
305 buffer_id,
306 buffer)));
303 307
304 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { 308 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it)
305 it->first->OnBufferReady(this, buffer); 309 it->first->OnFrameReady(this, frame);
306 } 310 }
307 cached_dibs_[buffer_id]->references = clients_.size(); 311
312 void VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread(
313 int buffer_id,
314 const scoped_refptr<ClientBuffer>& buffer) {
315 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
316 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id));
308 } 317 }
309 318
310 void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { 319 void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
311 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 320 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
312 321
313 switch (state) { 322 switch (state) {
314 case VIDEO_CAPTURE_STATE_STARTED: 323 case VIDEO_CAPTURE_STATE_STARTED:
315 break; 324 break;
316 case VIDEO_CAPTURE_STATE_STOPPED: 325 case VIDEO_CAPTURE_STATE_STOPPED:
317 state_ = VIDEO_CAPTURE_STATE_STOPPED; 326 state_ = VIDEO_CAPTURE_STATE_STOPPED;
318 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; 327 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
319 STLDeleteValues(&cached_dibs_); 328 client_buffers_.clear();
329 client_buffer_weak_this_factory_.InvalidateWeakPtrs();
320 if (!clients_.empty() || !clients_pending_on_restart_.empty()) 330 if (!clients_.empty() || !clients_pending_on_restart_.empty())
321 RestartCapture(); 331 RestartCapture();
322 break; 332 break;
323 case VIDEO_CAPTURE_STATE_PAUSED: 333 case VIDEO_CAPTURE_STATE_PAUSED:
324 for (ClientInfo::iterator it = clients_.begin(); 334 for (ClientInfo::iterator it = clients_.begin();
325 it != clients_.end(); ++it) { 335 it != clients_.end(); ++it) {
326 it->first->OnPaused(this); 336 it->first->OnPaused(this);
327 } 337 }
328 break; 338 break;
329 case VIDEO_CAPTURE_STATE_ERROR: 339 case VIDEO_CAPTURE_STATE_ERROR:
(...skipping 17 matching lines...) Expand all
347 state_ = VIDEO_CAPTURE_STATE_ENDED; 357 state_ = VIDEO_CAPTURE_STATE_ENDED;
348 break; 358 break;
349 default: 359 default:
350 break; 360 break;
351 } 361 }
352 } 362 }
353 363
354 void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( 364 void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread(
355 const media::VideoCaptureParams& device_info) { 365 const media::VideoCaptureParams& device_info) {
356 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 366 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
357 DCHECK(!ClientHasDIB()); 367 DCHECK(client_buffers_.empty());
358
359 STLDeleteValues(&cached_dibs_);
360 368
361 device_info_ = device_info; 369 device_info_ = device_info;
362 device_info_available_ = true; 370 device_info_available_ = true;
363 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { 371 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) {
364 it->first->OnDeviceInfoReceived(this, device_info); 372 it->first->OnDeviceInfoReceived(this, device_info);
365 } 373 }
366 } 374 }
367 375
368 void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread( 376 void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread(
369 const media::VideoCaptureParams& device_info) { 377 const media::VideoCaptureParams& device_info) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 message_filter_->RemoveDelegate(this); 463 message_filter_->RemoveDelegate(this);
456 capture_message_loop_proxy_->PostTask(FROM_HERE, task); 464 capture_message_loop_proxy_->PostTask(FROM_HERE, task);
457 } 465 }
458 466
459 void VideoCaptureImpl::Send(IPC::Message* message) { 467 void VideoCaptureImpl::Send(IPC::Message* message) {
460 io_message_loop_proxy_->PostTask(FROM_HERE, 468 io_message_loop_proxy_->PostTask(FROM_HERE,
461 base::Bind(base::IgnoreResult(&VideoCaptureMessageFilter::Send), 469 base::Bind(base::IgnoreResult(&VideoCaptureMessageFilter::Send),
462 message_filter_.get(), message)); 470 message_filter_.get(), message));
463 } 471 }
464 472
465 bool VideoCaptureImpl::ClientHasDIB() const {
466 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
467 for (CachedDIB::const_iterator it = cached_dibs_.begin();
468 it != cached_dibs_.end(); ++it) {
469 if (it->second->references > 0)
470 return true;
471 }
472 return false;
473 }
474
475 bool VideoCaptureImpl::RemoveClient( 473 bool VideoCaptureImpl::RemoveClient(
476 media::VideoCapture::EventHandler* handler, 474 media::VideoCapture::EventHandler* handler,
477 ClientInfo* clients) { 475 ClientInfo* clients) {
478 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 476 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
479 bool found = false; 477 bool found = false;
480 478
481 ClientInfo::iterator it = clients->find(handler); 479 ClientInfo::iterator it = clients->find(handler);
482 if (it != clients->end()) { 480 if (it != clients->end()) {
483 handler->OnStopped(this); 481 handler->OnStopped(this);
484 handler->OnRemoved(this); 482 handler->OnRemoved(this);
485 clients->erase(it); 483 clients->erase(it);
486 found = true; 484 found = true;
487 } 485 }
488 return found; 486 return found;
489 } 487 }
490 488
491 } // namespace content 489 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/video_capture_impl.h ('k') | content/renderer/media/video_capture_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698