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

Side by Side Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 12090109: Tab Capture: Backing store readbacks to YV12 VideoFrames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Style fix per wjia Created 7 years, 10 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 | Annotate | Revision Log
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/browser/renderer_host/media/video_capture_controller.h" 5 #include "content/browser/renderer_host/media/video_capture_controller.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "content/browser/renderer_host/media/media_stream_manager.h" 12 #include "content/browser/renderer_host/media/media_stream_manager.h"
13 #include "content/browser/renderer_host/media/video_capture_manager.h" 13 #include "content/browser/renderer_host/media/video_capture_manager.h"
14 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
15 #include "media/base/video_frame.h"
16 #include "media/base/video_util.h"
15 #include "media/base/yuv_convert.h" 17 #include "media/base/yuv_convert.h"
16 18
17 #if !defined(OS_IOS) && !defined(OS_ANDROID) 19 #if !defined(OS_IOS) && !defined(OS_ANDROID)
18 #include "third_party/libyuv/include/libyuv.h" 20 #include "third_party/libyuv/include/libyuv.h"
19 #endif 21 #endif
20 22
21 namespace content { 23 namespace content {
22 24
23 // The number of DIBs VideoCaptureController allocate. 25 // The number of DIBs VideoCaptureController allocate.
24 static const size_t kNoOfDIBS = 3; 26 static const size_t kNoOfDIBS = 3;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 } 240 }
239 241
240 // When all buffers have been returned by clients and device has been 242 // When all buffers have been returned by clients and device has been
241 // called to stop, check if restart is needed. This could happen when 243 // called to stop, check if restart is needed. This could happen when
242 // capture needs to be restarted due to resolution change. 244 // capture needs to be restarted due to resolution change.
243 if (!ClientHasDIB() && state_ == VIDEO_CAPTURE_STATE_STOPPING) { 245 if (!ClientHasDIB() && state_ == VIDEO_CAPTURE_STATE_STOPPING) {
244 PostStopping(); 246 PostStopping();
245 } 247 }
246 } 248 }
247 249
248 /////////////////////////////////////////////////////////////////////////////// 250 bool VideoCaptureController::ReserveSharedMemory(int* buffer_id_out,
249 // Implements VideoCaptureDevice::EventHandler. 251 uint8** yplane,
250 // OnIncomingCapturedFrame is called the thread running the capture device. 252 uint8** uplane,
251 // I.e.- DirectShow thread on windows and v4l2_thread on Linux. 253 uint8** vplane) {
252 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
253 int length,
254 base::Time timestamp) {
255 int buffer_id = 0; 254 int buffer_id = 0;
256 base::SharedMemory* dib = NULL; 255 base::SharedMemory* dib = NULL;
257 { 256 {
258 base::AutoLock lock(lock_); 257 base::AutoLock lock(lock_);
259 for (DIBMap::iterator dib_it = owned_dibs_.begin(); 258 for (DIBMap::iterator dib_it = owned_dibs_.begin();
260 dib_it != owned_dibs_.end(); dib_it++) { 259 dib_it != owned_dibs_.end(); dib_it++) {
261 if (dib_it->second->references == 0) { 260 if (dib_it->second->references == 0) {
262 buffer_id = dib_it->first; 261 buffer_id = dib_it->first;
263 // Use special value "-1" in order to not be treated as buffer at 262 // Use special value "-1" in order to not be treated as buffer at
264 // renderer side. 263 // renderer side.
265 dib_it->second->references = -1; 264 dib_it->second->references = -1;
266 dib = dib_it->second->shared_memory.get(); 265 dib = dib_it->second->shared_memory.get();
267 break; 266 break;
268 } 267 }
269 } 268 }
270 } 269 }
271 270
272 if (!dib) { 271 if (!dib)
272 return false;
273
274 *buffer_id_out = buffer_id;
275 CHECK_GE(dib->created_size(),
276 static_cast<size_t>(frame_info_.width * frame_info_.height * 3) / 2);
277 uint8* target = static_cast<uint8*>(dib->memory());
278 *yplane = target;
279 *uplane = *yplane + frame_info_.width * frame_info_.height;
280 *vplane = *uplane + (frame_info_.width * frame_info_.height) / 4;
281 return true;
282 }
283
284 // Implements VideoCaptureDevice::EventHandler.
285 // OnIncomingCapturedFrame is called the thread running the capture device.
286 // I.e.- DirectShow thread on windows and v4l2_thread on Linux.
287 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
288 int length,
289 base::Time timestamp) {
290 int buffer_id = 0;
291 uint8* yplane = NULL;
292 uint8* uplane = NULL;
293 uint8* vplane = NULL;
294 if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane))
273 return; 295 return;
274 }
275
276 uint8* target = static_cast<uint8*>(dib->memory());
277 CHECK(dib->created_size() >= static_cast<size_t> (frame_info_.width *
278 frame_info_.height * 3) /
279 2);
280 uint8* yplane = target;
281 uint8* uplane = target + frame_info_.width * frame_info_.height;
282 uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
283 296
284 // Do color conversion from the camera format to I420. 297 // Do color conversion from the camera format to I420.
285 switch (frame_info_.color) { 298 switch (frame_info_.color) {
286 case media::VideoCaptureCapability::kColorUnknown: // Color format not set. 299 case media::VideoCaptureCapability::kColorUnknown: // Color format not set.
287 break; 300 break;
288 case media::VideoCaptureCapability::kI420: { 301 case media::VideoCaptureCapability::kI420: {
289 DCHECK(!chopped_width_ && !chopped_height_); 302 DCHECK(!chopped_width_ && !chopped_height_);
290 memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2); 303 memcpy(yplane, data, (frame_info_.width * frame_info_.height * 3) / 2);
291 break; 304 break;
292 } 305 }
293 case media::VideoCaptureCapability::kYV12: { 306 case media::VideoCaptureCapability::kYV12: {
294 DCHECK(!chopped_width_ && !chopped_height_); 307 DCHECK(!chopped_width_ && !chopped_height_);
295 const uint8* ptr = data; 308 const uint8* ptr = data;
296 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height)); 309 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height));
297 ptr += frame_info_.width * frame_info_.height; 310 ptr += frame_info_.width * frame_info_.height;
298 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2); 311 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2);
299 ptr += (frame_info_.width * frame_info_.height) >> 2; 312 ptr += (frame_info_.width * frame_info_.height) >> 2;
300 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2); 313 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 default: 371 default:
359 NOTREACHED(); 372 NOTREACHED();
360 } 373 }
361 374
362 BrowserThread::PostTask(BrowserThread::IO, 375 BrowserThread::PostTask(BrowserThread::IO,
363 FROM_HERE, 376 FROM_HERE,
364 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 377 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
365 this, buffer_id, timestamp)); 378 this, buffer_id, timestamp));
366 } 379 }
367 380
381 // OnIncomingCapturedVideoFrame is called the thread running the capture device.
382 void VideoCaptureController::OnIncomingCapturedVideoFrame(
383 media::VideoFrame* frame,
384 base::Time timestamp) {
385 // Validate the inputs.
386 gfx::Size target_size = gfx::Size(frame_info_.width, frame_info_.height);
387 if (frame->coded_size() != target_size)
388 return; // Only exact copies are supported.
389 if (!(frame->format() == media::VideoFrame::I420 ||
390 frame->format() == media::VideoFrame::YV12 ||
391 frame->format() == media::VideoFrame::RGB32)) {
392 NOTREACHED() << "Unsupported format passed to OnIncomingCapturedVideoFrame";
393 return;
394 }
395
396 // Carve out a shared memory buffer.
397 int buffer_id = 0;
398 uint8* yplane = NULL;
399 uint8* uplane = NULL;
400 uint8* vplane = NULL;
401 if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane))
402 return;
403
404 scoped_refptr<media::VideoFrame> target_as_frame(
405 media::VideoFrame::WrapExternalYuvData(
406 media::VideoFrame::YV12, // Actually I420, but it's equivalent here.
407 target_size, gfx::Rect(target_size), target_size,
408 frame_info_.width, // y stride
409 frame_info_.width / 2, // v stride
410 frame_info_.width / 2, // u stride
411 yplane,
412 uplane,
413 vplane,
414 base::TimeDelta(),
415 base::Bind(&base::DoNothing)));
416
417 const int kYPlane = media::VideoFrame::kYPlane;
418 const int kUPlane = media::VideoFrame::kUPlane;
419 const int kVPlane = media::VideoFrame::kVPlane;
420 const int kRGBPlane = media::VideoFrame::kRGBPlane;
421
422 // Do color conversion from the camera format to I420.
423 switch (frame->format()) {
424 case media::VideoFrame::INVALID:
425 case media::VideoFrame::YV16:
426 case media::VideoFrame::EMPTY:
427 case media::VideoFrame::NATIVE_TEXTURE: {
428 NOTREACHED();
429 break;
430 }
431 case media::VideoFrame::I420:
432 case media::VideoFrame::YV12: {
433 DCHECK(!chopped_width_ && !chopped_height_);
434 media::CopyYPlane(frame->data(kYPlane),
435 frame->stride(kYPlane),
436 frame->rows(kYPlane),
437 target_as_frame);
438 media::CopyUPlane(frame->data(kUPlane),
439 frame->stride(kUPlane),
440 frame->rows(kUPlane),
441 target_as_frame);
442 media::CopyVPlane(frame->data(kVPlane),
443 frame->stride(kVPlane),
444 frame->rows(kVPlane),
445 target_as_frame);
446 break;
447 }
448 case media::VideoFrame::RGB32: {
449 media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
450 target_as_frame->data(kYPlane),
451 target_as_frame->data(kUPlane),
452 target_as_frame->data(kVPlane),
453 target_size.width(),
454 target_size.height(),
455 frame->stride(kRGBPlane),
456 target_as_frame->stride(kYPlane),
457 target_as_frame->stride(kUPlane));
458 break;
459 }
460 }
461
462 BrowserThread::PostTask(BrowserThread::IO,
463 FROM_HERE,
464 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
465 this, buffer_id, timestamp));
466 }
467
368 void VideoCaptureController::OnError() { 468 void VideoCaptureController::OnError() {
369 BrowserThread::PostTask(BrowserThread::IO, 469 BrowserThread::PostTask(BrowserThread::IO,
370 FROM_HERE, 470 FROM_HERE,
371 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); 471 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
372 } 472 }
373 473
374 void VideoCaptureController::OnFrameInfo( 474 void VideoCaptureController::OnFrameInfo(
375 const media::VideoCaptureCapability& info) { 475 const media::VideoCaptureCapability& info) {
376 frame_info_= info; 476 frame_info_= info;
377 // Handle cases when |info| has odd numbers for width/height. 477 // Handle cases when |info| has odd numbers for width/height.
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 base::AutoLock lock(lock_); 699 base::AutoLock lock(lock_);
600 for (DIBMap::iterator dib_it = owned_dibs_.begin(); 700 for (DIBMap::iterator dib_it = owned_dibs_.begin();
601 dib_it != owned_dibs_.end(); dib_it++) { 701 dib_it != owned_dibs_.end(); dib_it++) {
602 if (dib_it->second->references > 0) 702 if (dib_it->second->references > 0)
603 return true; 703 return true;
604 } 704 }
605 return false; 705 return false;
606 } 706 }
607 707
608 } // namespace content 708 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698