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

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: 727f973e fischman@ comments 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 DCHECK(client_buffers_.find(buffer_id) == client_buffers_.end());
Ami GONE FROM CHROMIUM 2013/09/13 00:26:35 fwiw, mymap.find(key) == mymap.end() is equivalen
sheu 2013/09/16 19:09:11 Sure, this way works.
275 DCHECK(cached_dibs_.find(buffer_id) == cached_dibs_.end());
276 260
277 base::SharedMemory* dib = new base::SharedMemory(handle, false); 261 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false));
278 dib->Map(length); 262 if (!shm->Map(length)) {
279 buffer = new VideoFrameBuffer(); 263 DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed.";
280 buffer->memory_pointer = static_cast<uint8*>(dib->memory()); 264 return;
281 buffer->buffer_size = length; 265 }
282 buffer->width = device_info_.width;
283 buffer->height = device_info_.height;
284 buffer->stride = device_info_.width;
285 266
286 DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer); 267 client_buffers_[buffer_id] =
287 cached_dibs_[buffer_id] = dib_buffer; 268 make_scoped_refptr(new ClientBuffer(shm.Pass(),
269 length,
270 device_info_.width,
271 device_info_.height,
272 device_info_.width));
288 } 273 }
289 274
290 void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( 275 void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
291 int buffer_id, base::Time timestamp) { 276 int buffer_id, base::Time timestamp) {
292 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 277 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
293 278
294 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { 279 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
295 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id)); 280 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id));
296 return; 281 return;
297 } 282 }
298 283
299 media::VideoCapture::VideoFrameBuffer* buffer; 284 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id);
300 DCHECK(cached_dibs_.find(buffer_id) != cached_dibs_.end()); 285 DCHECK(iter != client_buffers_.end());
301 buffer = cached_dibs_[buffer_id]->mapped_memory.get(); 286 scoped_refptr<ClientBuffer> buffer = iter->second;
302 buffer->timestamp = timestamp; 287 scoped_refptr<media::VideoFrame> frame =
288 media::VideoFrame::WrapExternalSharedMemory(
289 media::VideoFrame::I420,
290 gfx::Size(buffer->frame_stride, buffer->frame_height),
291 gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height),
292 gfx::Size(buffer->frame_width, buffer->frame_height),
293 reinterpret_cast<uint8*>(buffer->buffer->memory()),
294 buffer->buffer_size,
295 buffer->buffer->handle(),
296 // TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use
297 // base::TimeTicks instead of base::Time. http://crbug.com/249215
298 timestamp - base::Time::UnixEpoch(),
299 media::BindToLoop(
Ami GONE FROM CHROMIUM 2013/09/13 00:26:35 Only a lack of faith by base/bind's OWNERS that th
300 capture_message_loop_proxy_,
301 base::Bind(
302 &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread,
303 client_buffer_weak_this_factory_.GetWeakPtr(),
304 buffer_id,
305 buffer)));
303 306
304 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { 307 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it)
305 it->first->OnBufferReady(this, buffer); 308 it->first->OnFrameReady(this, frame);
306 } 309 }
307 cached_dibs_[buffer_id]->references = clients_.size(); 310
311 void VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread(
312 int buffer_id,
313 const scoped_refptr<ClientBuffer>& buffer) {
314 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
315 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id));
308 } 316 }
309 317
310 void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { 318 void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
311 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 319 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
312 320
313 switch (state) { 321 switch (state) {
314 case VIDEO_CAPTURE_STATE_STARTED: 322 case VIDEO_CAPTURE_STATE_STARTED:
315 break; 323 break;
316 case VIDEO_CAPTURE_STATE_STOPPED: 324 case VIDEO_CAPTURE_STATE_STOPPED:
317 state_ = VIDEO_CAPTURE_STATE_STOPPED; 325 state_ = VIDEO_CAPTURE_STATE_STOPPED;
318 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; 326 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
319 STLDeleteValues(&cached_dibs_); 327 client_buffers_.clear();
328 client_buffer_weak_this_factory_.InvalidateWeakPtrs();
320 if (!clients_.empty() || !clients_pending_on_restart_.empty()) 329 if (!clients_.empty() || !clients_pending_on_restart_.empty())
321 RestartCapture(); 330 RestartCapture();
322 break; 331 break;
323 case VIDEO_CAPTURE_STATE_PAUSED: 332 case VIDEO_CAPTURE_STATE_PAUSED:
324 for (ClientInfo::iterator it = clients_.begin(); 333 for (ClientInfo::iterator it = clients_.begin();
325 it != clients_.end(); ++it) { 334 it != clients_.end(); ++it) {
326 it->first->OnPaused(this); 335 it->first->OnPaused(this);
327 } 336 }
328 break; 337 break;
329 case VIDEO_CAPTURE_STATE_ERROR: 338 case VIDEO_CAPTURE_STATE_ERROR:
(...skipping 17 matching lines...) Expand all
347 state_ = VIDEO_CAPTURE_STATE_ENDED; 356 state_ = VIDEO_CAPTURE_STATE_ENDED;
348 break; 357 break;
349 default: 358 default:
350 break; 359 break;
351 } 360 }
352 } 361 }
353 362
354 void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( 363 void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread(
355 const media::VideoCaptureParams& device_info) { 364 const media::VideoCaptureParams& device_info) {
356 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 365 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
357 DCHECK(!ClientHasDIB()); 366 DCHECK(client_buffers_.empty());
358
359 STLDeleteValues(&cached_dibs_);
360 367
361 device_info_ = device_info; 368 device_info_ = device_info;
362 device_info_available_ = true; 369 device_info_available_ = true;
363 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { 370 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) {
364 it->first->OnDeviceInfoReceived(this, device_info); 371 it->first->OnDeviceInfoReceived(this, device_info);
365 } 372 }
366 } 373 }
367 374
368 void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread( 375 void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread(
369 const media::VideoCaptureParams& device_info) { 376 const media::VideoCaptureParams& device_info) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 message_filter_->RemoveDelegate(this); 462 message_filter_->RemoveDelegate(this);
456 capture_message_loop_proxy_->PostTask(FROM_HERE, task); 463 capture_message_loop_proxy_->PostTask(FROM_HERE, task);
457 } 464 }
458 465
459 void VideoCaptureImpl::Send(IPC::Message* message) { 466 void VideoCaptureImpl::Send(IPC::Message* message) {
460 io_message_loop_proxy_->PostTask(FROM_HERE, 467 io_message_loop_proxy_->PostTask(FROM_HERE,
461 base::Bind(base::IgnoreResult(&VideoCaptureMessageFilter::Send), 468 base::Bind(base::IgnoreResult(&VideoCaptureMessageFilter::Send),
462 message_filter_.get(), message)); 469 message_filter_.get(), message));
463 } 470 }
464 471
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( 472 bool VideoCaptureImpl::RemoveClient(
476 media::VideoCapture::EventHandler* handler, 473 media::VideoCapture::EventHandler* handler,
477 ClientInfo* clients) { 474 ClientInfo* clients) {
478 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); 475 DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
479 bool found = false; 476 bool found = false;
480 477
481 ClientInfo::iterator it = clients->find(handler); 478 ClientInfo::iterator it = clients->find(handler);
482 if (it != clients->end()) { 479 if (it != clients->end()) {
483 handler->OnStopped(this); 480 handler->OnStopped(this);
484 handler->OnRemoved(this); 481 handler->OnRemoved(this);
485 clients->erase(it); 482 clients->erase(it);
486 found = true; 483 found = true;
487 } 484 }
488 return found; 485 return found;
489 } 486 }
490 487
491 } // namespace content 488 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698