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

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: Patch for review. 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(
249 // Implements VideoCaptureDevice::EventHandler. 251 int* buffer_id_out, uint8** yplane, uint8** uplane, uint8** vplane) {
250 // OnIncomingCapturedFrame is called the thread running the capture device.
251 // I.e.- DirectShow thread on windows and v4l2_thread on Linux.
252 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
253 int length,
254 base::Time timestamp) {
255 int buffer_id = 0; 252 int buffer_id = 0;
256 base::SharedMemory* dib = NULL; 253 base::SharedMemory* dib = NULL;
257 { 254 {
258 base::AutoLock lock(lock_); 255 base::AutoLock lock(lock_);
259 for (DIBMap::iterator dib_it = owned_dibs_.begin(); 256 for (DIBMap::iterator dib_it = owned_dibs_.begin();
260 dib_it != owned_dibs_.end(); dib_it++) { 257 dib_it != owned_dibs_.end(); dib_it++) {
261 if (dib_it->second->references == 0) { 258 if (dib_it->second->references == 0) {
262 buffer_id = dib_it->first; 259 buffer_id = dib_it->first;
263 // Use special value "-1" in order to not be treated as buffer at 260 // Use special value "-1" in order to not be treated as buffer at
264 // renderer side. 261 // renderer side.
265 dib_it->second->references = -1; 262 dib_it->second->references = -1;
266 dib = dib_it->second->shared_memory.get(); 263 dib = dib_it->second->shared_memory.get();
267 break; 264 break;
268 } 265 }
269 } 266 }
270 } 267 }
271 268
272 if (!dib) { 269 if (!dib)
270 return false;
271
272 *buffer_id_out = buffer_id;
273 CHECK(dib->created_size() >= static_cast<size_t>(frame_info_.width *
274 frame_info_.height * 3) / 2);
275 uint8* target = static_cast<uint8*>(dib->memory());
276 *yplane = target;
277 *uplane = *yplane + frame_info_.width * frame_info_.height;
278 *vplane = *uplane + (frame_info_.width * frame_info_.height) / 4;
279 return true;
280 }
281
282 ///////////////////////////////////////////////////////////////////////////////
283 // Implements VideoCaptureDevice::EventHandler.
284 // OnIncomingCapturedFrame is called the thread running the capture device.
285 // I.e.- DirectShow thread on windows and v4l2_thread on Linux.
286 void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
287 int length,
288 base::Time timestamp) {
289 int buffer_id = 0;
290 uint8* yplane = NULL;
291 uint8* uplane = NULL;
292 uint8* vplane = NULL;
293 if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane))
273 return; 294 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 295
284 // Do color conversion from the camera format to I420. 296 // Do color conversion from the camera format to I420.
285 switch (frame_info_.color) { 297 switch (frame_info_.color) {
286 case media::VideoCaptureCapability::kColorUnknown: // Color format not set. 298 case media::VideoCaptureCapability::kColorUnknown: // Color format not set.
287 break; 299 break;
288 case media::VideoCaptureCapability::kI420: { 300 case media::VideoCaptureCapability::kI420: {
289 DCHECK(!chopped_width_ && !chopped_height_); 301 DCHECK(!chopped_width_ && !chopped_height_);
290 memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2); 302 memcpy(yplane, data, (frame_info_.width * frame_info_.height * 3) / 2);
291 break; 303 break;
292 } 304 }
293 case media::VideoCaptureCapability::kYV12: { 305 case media::VideoCaptureCapability::kYV12: {
294 DCHECK(!chopped_width_ && !chopped_height_); 306 DCHECK(!chopped_width_ && !chopped_height_);
295 const uint8* ptr = data; 307 const uint8* ptr = data;
296 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height)); 308 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height));
297 ptr += frame_info_.width * frame_info_.height; 309 ptr += frame_info_.width * frame_info_.height;
298 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2); 310 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2);
299 ptr += (frame_info_.width * frame_info_.height) >> 2; 311 ptr += (frame_info_.width * frame_info_.height) >> 2;
300 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2); 312 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 default: 364 default:
353 NOTREACHED(); 365 NOTREACHED();
354 } 366 }
355 367
356 BrowserThread::PostTask(BrowserThread::IO, 368 BrowserThread::PostTask(BrowserThread::IO,
357 FROM_HERE, 369 FROM_HERE,
358 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 370 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
359 this, buffer_id, timestamp)); 371 this, buffer_id, timestamp));
360 } 372 }
361 373
374 // OnIncomingCapturedVideoFrame is called the thread running the capture device.
375 void VideoCaptureController::OnIncomingCapturedVideoFrame(
376 media::VideoFrame* frame, base::Time timestamp) {
377 int buffer_id = 0;
378 uint8* yplane = NULL;
379 uint8* uplane = NULL;
380 uint8* vplane = NULL;
381 if (!ReserveSharedMemory(&buffer_id, &yplane, &uplane, &vplane))
382 return;
383
384 gfx::Size target_size = gfx::Size(frame_info_.width, frame_info_.height);
385
386 if (frame->coded_size() != target_size)
387 return; // Only exact copies are supported.
388
389 scoped_refptr<media::VideoFrame> target_as_frame(
390 media::VideoFrame::WrapExternalYuvData(
391 media::VideoFrame::YV12, // Actually I420, but it's equivalent here.
wjia(left Chromium) 2013/02/04 23:48:40 nit: indent by 4.
ncarter (slow) 2013/02/05 17:36:08 Done.
392 target_size, gfx::Rect(target_size), target_size,
393 frame_info_.width, // y stride
394 frame_info_.width / 2, // v stride
395 frame_info_.width / 2, // u stride
396 yplane,
397 uplane,
398 vplane,
399 base::TimeDelta(),
400 base::Bind(&base::DoNothing)));
401
402 const int kYPlane = media::VideoFrame::kYPlane;
403 const int kUPlane = media::VideoFrame::kUPlane;
404 const int kVPlane = media::VideoFrame::kVPlane;
405 const int kRGBPlane = media::VideoFrame::kRGBPlane;
406
407 // Do color conversion from the camera format to I420.
408 switch (frame->format()) {
409 case media::VideoFrame::EMPTY:
410 case media::VideoFrame::INVALID: // Color format not set.
411 case media::VideoFrame::NATIVE_TEXTURE:
412 // These types will never work.
413 break;
414 case media::VideoFrame::I420:
415 case media::VideoFrame::YV12: {
416 DCHECK(!chopped_width_ && !chopped_height_);
417 media::CopyYPlane(frame->data(kYPlane),
418 frame->stride(kYPlane),
419 frame->rows(kYPlane),
420 target_as_frame);
421 media::CopyUPlane(frame->data(kUPlane),
422 frame->stride(kUPlane),
423 frame->rows(kUPlane),
424 target_as_frame);
425 media::CopyVPlane(frame->data(kVPlane),
426 frame->stride(kVPlane),
427 frame->rows(kVPlane),
428 target_as_frame);
429 break;
430 }
431 case media::VideoFrame::RGB32: {
432 media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
433 target_as_frame->data(kYPlane),
434 target_as_frame->data(kUPlane),
435 target_as_frame->data(kVPlane),
436 target_size.width(),
437 target_size.height(),
438 frame->stride(kRGBPlane),
439 target_as_frame->stride(kYPlane),
440 target_as_frame->stride(kUPlane));
441 break;
442 }
443 default:
444 NOTREACHED();
445 }
446
447 target_as_frame = NULL; // Wrapper was for temporary use only.
wjia(left Chromium) 2013/02/04 23:48:40 this is not needed.
ncarter (slow) 2013/02/05 17:36:08 Done.
448
449 BrowserThread::PostTask(BrowserThread::IO,
450 FROM_HERE,
451 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
452 this, buffer_id, timestamp));
453 }
454
362 void VideoCaptureController::OnError() { 455 void VideoCaptureController::OnError() {
363 BrowserThread::PostTask(BrowserThread::IO, 456 BrowserThread::PostTask(BrowserThread::IO,
364 FROM_HERE, 457 FROM_HERE,
365 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); 458 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this));
366 } 459 }
367 460
368 void VideoCaptureController::OnFrameInfo( 461 void VideoCaptureController::OnFrameInfo(
369 const media::VideoCaptureCapability& info) { 462 const media::VideoCaptureCapability& info) {
370 frame_info_= info; 463 frame_info_= info;
371 // Handle cases when |info| has odd numbers for width/height. 464 // 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_); 686 base::AutoLock lock(lock_);
594 for (DIBMap::iterator dib_it = owned_dibs_.begin(); 687 for (DIBMap::iterator dib_it = owned_dibs_.begin();
595 dib_it != owned_dibs_.end(); dib_it++) { 688 dib_it != owned_dibs_.end(); dib_it++) {
596 if (dib_it->second->references > 0) 689 if (dib_it->second->references > 0)
597 return true; 690 return true;
598 } 691 }
599 return false; 692 return false;
600 } 693 }
601 694
602 } // namespace content 695 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698