OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_device_client.h" | 5 #include "content/browser/renderer_host/media/video_capture_device_client.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 | 209 |
210 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} | 210 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} |
211 | 211 |
212 void VideoCaptureDeviceClient::OnIncomingCapturedData( | 212 void VideoCaptureDeviceClient::OnIncomingCapturedData( |
213 const uint8* data, | 213 const uint8* data, |
214 int length, | 214 int length, |
215 const VideoCaptureFormat& frame_format, | 215 const VideoCaptureFormat& frame_format, |
216 int rotation, | 216 int rotation, |
217 const base::TimeTicks& timestamp) { | 217 const base::TimeTicks& timestamp) { |
218 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); | 218 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); |
219 DCHECK_EQ(frame_format.pixel_storage, media::PIXEL_STORAGE_CPU); | |
mcasas
2015/06/24 21:23:23
dcheng@: Same comment: this should be DCHECK_EQ(ac
| |
219 | 220 |
220 if (last_captured_pixel_format_ != frame_format.pixel_format) { | 221 if (last_captured_pixel_format_ != frame_format.pixel_format) { |
221 OnLog("Pixel format: " + media::VideoCaptureFormat::PixelFormatToString( | 222 OnLog("Pixel format: " + |
222 frame_format.pixel_format)); | 223 VideoCaptureFormat::PixelFormatToString(frame_format.pixel_format)); |
223 last_captured_pixel_format_ = frame_format.pixel_format; | 224 last_captured_pixel_format_ = frame_format.pixel_format; |
224 } | 225 } |
225 | 226 |
226 if (!frame_format.IsValid()) | 227 if (!frame_format.IsValid()) |
227 return; | 228 return; |
228 | 229 |
229 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 230 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
230 // bit decomposition of {width, height}, grabbing the odd and even parts. | 231 // bit decomposition of {width, height}, grabbing the odd and even parts. |
231 const int chopped_width = frame_format.frame_size.width() & 1; | 232 const int chopped_width = frame_format.frame_size.width() & 1; |
232 const int chopped_height = frame_format.frame_size.height() & 1; | 233 const int chopped_height = frame_format.frame_size.height() & 1; |
(...skipping 17 matching lines...) Expand all Loading... | |
250 | 251 |
251 const gfx::Size dimensions(destination_width, destination_height); | 252 const gfx::Size dimensions(destination_width, destination_height); |
252 if (!VideoFrame::IsValidConfig(VideoFrame::I420, | 253 if (!VideoFrame::IsValidConfig(VideoFrame::I420, |
253 VideoFrame::STORAGE_UNKNOWN, | 254 VideoFrame::STORAGE_UNKNOWN, |
254 dimensions, | 255 dimensions, |
255 gfx::Rect(dimensions), | 256 gfx::Rect(dimensions), |
256 dimensions)) { | 257 dimensions)) { |
257 return; | 258 return; |
258 } | 259 } |
259 | 260 |
260 scoped_ptr<Buffer> buffer( | 261 scoped_ptr<Buffer> buffer(ReserveOutputBuffer( |
261 ReserveOutputBuffer(media::PIXEL_FORMAT_I420, dimensions)); | 262 dimensions, media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU)); |
262 if (!buffer.get()) | 263 if (!buffer.get()) |
263 return; | 264 return; |
264 | 265 |
265 const size_t y_plane_size = VideoFrame::PlaneSize( | 266 const size_t y_plane_size = VideoFrame::PlaneSize( |
266 VideoFrame::I420, VideoFrame::kYPlane, dimensions).GetArea(); | 267 VideoFrame::I420, VideoFrame::kYPlane, dimensions).GetArea(); |
267 const size_t u_plane_size = VideoFrame::PlaneSize( | 268 const size_t u_plane_size = VideoFrame::PlaneSize( |
268 VideoFrame::I420, VideoFrame::kUPlane, dimensions).GetArea(); | 269 VideoFrame::I420, VideoFrame::kUPlane, dimensions).GetArea(); |
269 uint8* const yplane = reinterpret_cast<uint8*>(buffer->data()); | 270 uint8* const yplane = reinterpret_cast<uint8*>(buffer->data()); |
270 uint8* const uplane = yplane + y_plane_size; | 271 uint8* const uplane = yplane + y_plane_size; |
271 uint8* const vplane = uplane + u_plane_size; | 272 uint8* const vplane = uplane + u_plane_size; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
343 uv_plane_stride, | 344 uv_plane_stride, |
344 crop_x, | 345 crop_x, |
345 crop_y, | 346 crop_y, |
346 frame_format.frame_size.width(), | 347 frame_format.frame_size.width(), |
347 (flip ? -1 : 1) * frame_format.frame_size.height(), | 348 (flip ? -1 : 1) * frame_format.frame_size.height(), |
348 new_unrotated_width, | 349 new_unrotated_width, |
349 new_unrotated_height, | 350 new_unrotated_height, |
350 rotation_mode, | 351 rotation_mode, |
351 origin_colorspace) != 0) { | 352 origin_colorspace) != 0) { |
352 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " | 353 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " |
353 << media::VideoCaptureFormat::PixelFormatToString( | 354 << VideoCaptureFormat::PixelFormatToString( |
354 frame_format.pixel_format); | 355 frame_format.pixel_format); |
355 return; | 356 return; |
356 } | 357 } |
357 | 358 |
358 OnIncomingCapturedBuffer(buffer.Pass(), | 359 const VideoCaptureFormat output_format = |
359 media::VideoCaptureFormat(dimensions, | 360 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
360 frame_format.frame_rate, | 361 media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU); |
361 media::PIXEL_FORMAT_I420), | 362 OnIncomingCapturedBuffer(buffer.Pass(), output_format, timestamp); |
362 timestamp); | |
363 } | 363 } |
364 | 364 |
365 void | 365 void |
366 VideoCaptureDeviceClient::OnIncomingCapturedYuvData( | 366 VideoCaptureDeviceClient::OnIncomingCapturedYuvData( |
367 const uint8* y_data, | 367 const uint8* y_data, |
368 const uint8* u_data, | 368 const uint8* u_data, |
369 const uint8* v_data, | 369 const uint8* v_data, |
370 size_t y_stride, | 370 size_t y_stride, |
371 size_t u_stride, | 371 size_t u_stride, |
372 size_t v_stride, | 372 size_t v_stride, |
373 const VideoCaptureFormat& frame_format, | 373 const VideoCaptureFormat& frame_format, |
374 int clockwise_rotation, | 374 int clockwise_rotation, |
375 const base::TimeTicks& timestamp) { | 375 const base::TimeTicks& timestamp) { |
376 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedYuvData"); | 376 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedYuvData"); |
377 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_I420); | 377 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_I420); |
378 DCHECK_EQ(frame_format.pixel_storage, media::PIXEL_STORAGE_CPU); | |
378 DCHECK_EQ(clockwise_rotation, 0) << "Rotation not supported"; | 379 DCHECK_EQ(clockwise_rotation, 0) << "Rotation not supported"; |
379 | 380 |
380 scoped_ptr<Buffer> buffer( | 381 scoped_ptr<Buffer> buffer(ReserveOutputBuffer(frame_format.frame_size, |
381 ReserveOutputBuffer(frame_format.pixel_format, frame_format.frame_size)); | 382 frame_format.pixel_format, |
383 frame_format.pixel_storage)); | |
382 if (!buffer.get()) | 384 if (!buffer.get()) |
383 return; | 385 return; |
384 | 386 |
385 // Blit (copy) here from y,u,v into buffer.data()). Needed so we can return | 387 // Blit (copy) here from y,u,v into buffer.data()). Needed so we can return |
386 // the parameter buffer synchronously to the driver. | 388 // the parameter buffer synchronously to the driver. |
387 const size_t y_plane_size = VideoFrame::PlaneSize( | 389 const size_t y_plane_size = VideoFrame::PlaneSize( |
388 VideoFrame::I420, VideoFrame::kYPlane, frame_format.frame_size).GetArea(); | 390 VideoFrame::I420, VideoFrame::kYPlane, frame_format.frame_size).GetArea(); |
389 const size_t u_plane_size = VideoFrame::PlaneSize( | 391 const size_t u_plane_size = VideoFrame::PlaneSize( |
390 VideoFrame::I420, VideoFrame::kUPlane, frame_format.frame_size).GetArea(); | 392 VideoFrame::I420, VideoFrame::kUPlane, frame_format.frame_size).GetArea(); |
391 uint8* const dst_y = reinterpret_cast<uint8*>(buffer->data()); | 393 uint8* const dst_y = reinterpret_cast<uint8*>(buffer->data()); |
(...skipping 19 matching lines...) Expand all Loading... | |
411 frame_format.frame_size.width(), | 413 frame_format.frame_size.width(), |
412 frame_format.frame_size.height())) { | 414 frame_format.frame_size.height())) { |
413 DLOG(WARNING) << "Failed to copy buffer"; | 415 DLOG(WARNING) << "Failed to copy buffer"; |
414 return; | 416 return; |
415 } | 417 } |
416 | 418 |
417 OnIncomingCapturedBuffer(buffer.Pass(), frame_format, timestamp); | 419 OnIncomingCapturedBuffer(buffer.Pass(), frame_format, timestamp); |
418 }; | 420 }; |
419 | 421 |
420 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> | 422 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> |
421 VideoCaptureDeviceClient::ReserveOutputBuffer(media::VideoPixelFormat format, | 423 VideoCaptureDeviceClient::ReserveOutputBuffer( |
422 const gfx::Size& dimensions) { | 424 const gfx::Size& frame_size, |
423 DCHECK(format == media::PIXEL_FORMAT_I420 || | 425 media::VideoPixelFormat pixel_format, |
424 format == media::PIXEL_FORMAT_TEXTURE || | 426 media::VideoPixelStorage pixel_storage) { |
425 format == media::PIXEL_FORMAT_GPUMEMORYBUFFER); | 427 DCHECK(pixel_format == media::PIXEL_FORMAT_I420 || |
426 DCHECK_GT(dimensions.width(), 0); | 428 pixel_format == media::PIXEL_FORMAT_ARGB); |
427 DCHECK_GT(dimensions.height(), 0); | 429 DCHECK_GT(frame_size.width(), 0); |
430 DCHECK_GT(frame_size.height(), 0); | |
428 | 431 |
429 if (format == media::PIXEL_FORMAT_GPUMEMORYBUFFER && !texture_wrap_helper_) { | 432 if (pixel_storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER && |
433 !texture_wrap_helper_) { | |
430 texture_wrap_helper_ = | 434 texture_wrap_helper_ = |
431 new TextureWrapHelper(controller_, capture_task_runner_); | 435 new TextureWrapHelper(controller_, capture_task_runner_); |
432 } | 436 } |
433 | 437 |
438 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if | |
439 // it's a ShMem GMB or a DmaBuf GMB. | |
434 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 440 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
435 const int buffer_id = | 441 const int buffer_id = buffer_pool_->ReserveForProducer( |
436 buffer_pool_->ReserveForProducer(format, dimensions, &buffer_id_to_drop); | 442 pixel_format, pixel_storage, frame_size, &buffer_id_to_drop); |
437 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 443 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
438 return NULL; | 444 return NULL; |
439 | 445 |
440 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( | 446 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( |
441 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 447 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
442 | 448 |
443 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { | 449 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
444 BrowserThread::PostTask(BrowserThread::IO, | 450 BrowserThread::PostTask(BrowserThread::IO, |
445 FROM_HERE, | 451 FROM_HERE, |
446 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, | 452 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, |
447 controller_, buffer_id_to_drop)); | 453 controller_, buffer_id_to_drop)); |
448 } | 454 } |
449 | 455 |
450 return output_buffer.Pass(); | 456 return output_buffer.Pass(); |
451 } | 457 } |
452 | 458 |
453 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 459 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
454 scoped_ptr<Buffer> buffer, | 460 scoped_ptr<Buffer> buffer, |
455 const media::VideoCaptureFormat& frame_format, | 461 const VideoCaptureFormat& frame_format, |
456 const base::TimeTicks& timestamp) { | 462 const base::TimeTicks& timestamp) { |
457 if (frame_format.pixel_format == media::PIXEL_FORMAT_GPUMEMORYBUFFER) { | 463 if (frame_format.pixel_storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER) { |
458 capture_task_runner_->PostTask( | 464 capture_task_runner_->PostTask( |
459 FROM_HERE, | 465 FROM_HERE, |
460 base::Bind(&TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer, | 466 base::Bind(&TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer, |
461 texture_wrap_helper_, | 467 texture_wrap_helper_, |
462 base::Passed(&buffer), | 468 base::Passed(&buffer), |
463 frame_format, | 469 frame_format, |
464 timestamp)); | 470 timestamp)); |
465 } else { | 471 } else { |
466 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_I420); | 472 DCHECK(frame_format.pixel_format == media::PIXEL_FORMAT_I420 || |
473 frame_format.pixel_format == media::PIXEL_FORMAT_ARGB); | |
467 scoped_refptr<VideoFrame> video_frame = | 474 scoped_refptr<VideoFrame> video_frame = |
468 VideoFrame::WrapExternalData( | 475 VideoFrame::WrapExternalData( |
469 VideoFrame::I420, | 476 VideoFrame::I420, |
470 frame_format.frame_size, | 477 frame_format.frame_size, |
471 gfx::Rect(frame_format.frame_size), | 478 gfx::Rect(frame_format.frame_size), |
472 frame_format.frame_size, | 479 frame_format.frame_size, |
473 reinterpret_cast<uint8*>(buffer->data()), | 480 reinterpret_cast<uint8*>(buffer->data()), |
474 VideoFrame::AllocationSize(VideoFrame::I420, | 481 VideoFrame::AllocationSize(VideoFrame::I420, |
475 frame_format.frame_size), | 482 frame_format.frame_size), |
476 base::TimeDelta()); | 483 base::TimeDelta()); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
530 capture_task_runner_->PostTask(FROM_HERE, | 537 capture_task_runner_->PostTask(FROM_HERE, |
531 base::Bind(&TextureWrapHelper::Init, this)); | 538 base::Bind(&TextureWrapHelper::Init, this)); |
532 } | 539 } |
533 | 540 |
534 void | 541 void |
535 VideoCaptureDeviceClient::TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer( | 542 VideoCaptureDeviceClient::TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer( |
536 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, | 543 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
537 const media::VideoCaptureFormat& frame_format, | 544 const media::VideoCaptureFormat& frame_format, |
538 const base::TimeTicks& timestamp) { | 545 const base::TimeTicks& timestamp) { |
539 DCHECK(capture_task_runner_->BelongsToCurrentThread()); | 546 DCHECK(capture_task_runner_->BelongsToCurrentThread()); |
540 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_GPUMEMORYBUFFER); | 547 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_ARGB); |
548 DCHECK_EQ(frame_format.pixel_storage, media::PIXEL_STORAGE_GPUMEMORYBUFFER); | |
541 if (!gl_helper_) { | 549 if (!gl_helper_) { |
542 // |gl_helper_| might not exist due to asynchronous initialization not | 550 // |gl_helper_| might not exist due to asynchronous initialization not |
543 // finished or due to termination in process after a context loss. | 551 // finished or due to termination in process after a context loss. |
544 DVLOG(1) << " Skipping ingress frame, no GL context."; | 552 DVLOG(1) << " Skipping ingress frame, no GL context."; |
545 return; | 553 return; |
546 } | 554 } |
547 | 555 |
548 gpu::gles2::GLES2Interface* gl = capture_thread_context_->ContextGL(); | 556 gpu::gles2::GLES2Interface* gl = capture_thread_context_->ContextGL(); |
549 GLuint image_id = gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), | 557 GLuint image_id = gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), |
550 frame_format.frame_size.width(), | 558 frame_format.frame_size.width(), |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 void VideoCaptureDeviceClient::TextureWrapHelper::OnError( | 693 void VideoCaptureDeviceClient::TextureWrapHelper::OnError( |
686 const std::string& message) { | 694 const std::string& message) { |
687 DCHECK(capture_task_runner_->BelongsToCurrentThread()); | 695 DCHECK(capture_task_runner_->BelongsToCurrentThread()); |
688 DLOG(ERROR) << message; | 696 DLOG(ERROR) << message; |
689 BrowserThread::PostTask( | 697 BrowserThread::PostTask( |
690 BrowserThread::IO, FROM_HERE, | 698 BrowserThread::IO, FROM_HERE, |
691 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); | 699 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); |
692 } | 700 } |
693 | 701 |
694 } // namespace content | 702 } // namespace content |
OLD | NEW |