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

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: USE_AURA ifdefs for win7_aura, scherkus nits. 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 ///////////////////////////////////////////////////////////////////////////////
brettw 2013/02/08 21:44:51 Remove /////...
285 // Implements VideoCaptureDevice::EventHandler.
286 // OnIncomingCapturedFrame is called the thread running the capture device.
287 // I.e.- DirectShow thread on windows and v4l2_thread on Linux.
288 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
289 int length,
290 base::Time timestamp) {
291 int buffer_id = 0;
292 uint8* yplane = NULL;
293 uint8* uplane = NULL;
294 uint8* vplane = NULL;
295 if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane))
273 return; 296 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 297
284 // Do color conversion from the camera format to I420. 298 // Do color conversion from the camera format to I420.
285 switch (frame_info_.color) { 299 switch (frame_info_.color) {
286 case media::VideoCaptureCapability::kColorUnknown: // Color format not set. 300 case media::VideoCaptureCapability::kColorUnknown: // Color format not set.
287 break; 301 break;
288 case media::VideoCaptureCapability::kI420: { 302 case media::VideoCaptureCapability::kI420: {
289 DCHECK(!chopped_width_ && !chopped_height_); 303 DCHECK(!chopped_width_ && !chopped_height_);
290 memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2); 304 memcpy(yplane, data, (frame_info_.width * frame_info_.height * 3) / 2);
291 break; 305 break;
292 } 306 }
293 case media::VideoCaptureCapability::kYV12: { 307 case media::VideoCaptureCapability::kYV12: {
294 DCHECK(!chopped_width_ && !chopped_height_); 308 DCHECK(!chopped_width_ && !chopped_height_);
295 const uint8* ptr = data; 309 const uint8* ptr = data;
296 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height)); 310 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height));
297 ptr += frame_info_.width * frame_info_.height; 311 ptr += frame_info_.width * frame_info_.height;
298 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2); 312 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2);
299 ptr += (frame_info_.width * frame_info_.height) >> 2; 313 ptr += (frame_info_.width * frame_info_.height) >> 2;
300 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2); 314 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 default: 366 default:
353 NOTREACHED(); 367 NOTREACHED();
354 } 368 }
355 369
356 BrowserThread::PostTask(BrowserThread::IO, 370 BrowserThread::PostTask(BrowserThread::IO,
357 FROM_HERE, 371 FROM_HERE,
358 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 372 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
359 this, buffer_id, timestamp)); 373 this, buffer_id, timestamp));
360 } 374 }
361 375
376 // OnIncomingCapturedVideoFrame is called the thread running the capture device.
377 void VideoCaptureController::OnIncomingCapturedVideoFrame(
378 media::VideoFrame* frame,
379 base::Time timestamp) {
380 // Validate the inputs.
381 gfx::Size target_size = gfx::Size(frame_info_.width, frame_info_.height);
382 if (frame->coded_size() != target_size)
383 return; // Only exact copies are supported.
384 if (!(frame->format() == media::VideoFrame::I420 ||
385 frame->format() == media::VideoFrame::YV12 ||
386 frame->format() == media::VideoFrame::RGB32)) {
387 NOTREACHED() << "Unsupported format passed to OnIncomingCapturedVideoFrame";
388 return;
389 }
390
391 // Carve out a shared memory buffer.
392 int buffer_id = 0;
393 uint8* yplane = NULL;
394 uint8* uplane = NULL;
395 uint8* vplane = NULL;
396 if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane))
397 return;
398
399 scoped_refptr<media::VideoFrame> target_as_frame(
400 media::VideoFrame::WrapExternalYuvData(
401 media::VideoFrame::YV12, // Actually I420, but it's equivalent here.
402 target_size, gfx::Rect(target_size), target_size,
403 frame_info_.width, // y stride
404 frame_info_.width / 2, // v stride
405 frame_info_.width / 2, // u stride
406 yplane,
407 uplane,
408 vplane,
409 base::TimeDelta(),
410 base::Bind(&base::DoNothing)));
411
412 const int kYPlane = media::VideoFrame::kYPlane;
413 const int kUPlane = media::VideoFrame::kUPlane;
414 const int kVPlane = media::VideoFrame::kVPlane;
415 const int kRGBPlane = media::VideoFrame::kRGBPlane;
416
417 // Do color conversion from the camera format to I420.
418 switch (frame->format()) {
419 case media::VideoFrame::INVALID:
420 case media::VideoFrame::YV16:
421 case media::VideoFrame::EMPTY:
422 case media::VideoFrame::NATIVE_TEXTURE: {
423 NOTREACHED();
424 break;
425 }
426 case media::VideoFrame::I420:
427 case media::VideoFrame::YV12: {
428 DCHECK(!chopped_width_ && !chopped_height_);
429 media::CopyYPlane(frame->data(kYPlane),
430 frame->stride(kYPlane),
431 frame->rows(kYPlane),
432 target_as_frame);
433 media::CopyUPlane(frame->data(kUPlane),
434 frame->stride(kUPlane),
435 frame->rows(kUPlane),
436 target_as_frame);
437 media::CopyVPlane(frame->data(kVPlane),
438 frame->stride(kVPlane),
439 frame->rows(kVPlane),
440 target_as_frame);
441 break;
442 }
443 case media::VideoFrame::RGB32: {
444 media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
445 target_as_frame->data(kYPlane),
446 target_as_frame->data(kUPlane),
447 target_as_frame->data(kVPlane),
448 target_size.width(),
449 target_size.height(),
450 frame->stride(kRGBPlane),
451 target_as_frame->stride(kYPlane),
452 target_as_frame->stride(kUPlane));
453 break;
454 }
455 }
456
457 BrowserThread::PostTask(BrowserThread::IO,
458 FROM_HERE,
459 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
460 this, buffer_id, timestamp));
461 }
462
362 void VideoCaptureController::OnError() { 463 void VideoCaptureController::OnError() {
363 BrowserThread::PostTask(BrowserThread::IO, 464 BrowserThread::PostTask(BrowserThread::IO,
364 FROM_HERE, 465 FROM_HERE,
365 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); 466 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
366 } 467 }
367 468
368 void VideoCaptureController::OnFrameInfo( 469 void VideoCaptureController::OnFrameInfo(
369 const media::VideoCaptureCapability& info) { 470 const media::VideoCaptureCapability& info) {
370 frame_info_= info; 471 frame_info_= info;
371 // Handle cases when |info| has odd numbers for width/height. 472 // Handle cases when |info| has odd numbers for width/height.
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 base::AutoLock lock(lock_); 694 base::AutoLock lock(lock_);
594 for (DIBMap::iterator dib_it = owned_dibs_.begin(); 695 for (DIBMap::iterator dib_it = owned_dibs_.begin();
595 dib_it != owned_dibs_.end(); dib_it++) { 696 dib_it != owned_dibs_.end(); dib_it++) {
596 if (dib_it->second->references > 0) 697 if (dib_it->second->references > 0)
597 return true; 698 return true;
598 } 699 }
599 return false; 700 return false;
600 } 701 }
601 702
602 } // namespace content 703 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698