| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
| 10 #include "content/browser/compositor/image_transport_factory.h" | 10 #include "content/browser/compositor/image_transport_factory.h" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 | 208 |
| 209 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} | 209 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} |
| 210 | 210 |
| 211 void VideoCaptureDeviceClient::OnIncomingCapturedData( | 211 void VideoCaptureDeviceClient::OnIncomingCapturedData( |
| 212 const uint8* data, | 212 const uint8* data, |
| 213 int length, | 213 int length, |
| 214 const VideoCaptureFormat& frame_format, | 214 const VideoCaptureFormat& frame_format, |
| 215 int rotation, | 215 int rotation, |
| 216 const base::TimeTicks& timestamp) { | 216 const base::TimeTicks& timestamp) { |
| 217 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); | 217 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); |
| 218 DCHECK_EQ(frame_format.pixel_storage, media::PIXEL_STORAGE_CPU); |
| 218 | 219 |
| 219 if (last_captured_pixel_format_ != frame_format.pixel_format) { | 220 if (last_captured_pixel_format_ != frame_format.pixel_format) { |
| 220 OnLog("Pixel format: " + media::VideoCaptureFormat::PixelFormatToString( | 221 OnLog("Pixel format: " + |
| 221 frame_format.pixel_format)); | 222 VideoCaptureFormat::PixelFormatToString(frame_format.pixel_format)); |
| 222 last_captured_pixel_format_ = frame_format.pixel_format; | 223 last_captured_pixel_format_ = frame_format.pixel_format; |
| 223 } | 224 } |
| 224 | 225 |
| 225 if (!frame_format.IsValid()) | 226 if (!frame_format.IsValid()) |
| 226 return; | 227 return; |
| 227 | 228 |
| 228 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 229 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
| 229 // bit decomposition of {width, height}, grabbing the odd and even parts. | 230 // bit decomposition of {width, height}, grabbing the odd and even parts. |
| 230 const int chopped_width = frame_format.frame_size.width() & 1; | 231 const int chopped_width = frame_format.frame_size.width() & 1; |
| 231 const int chopped_height = frame_format.frame_size.height() & 1; | 232 const int chopped_height = frame_format.frame_size.height() & 1; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 251 | 252 |
| 252 const gfx::Size dimensions(destination_width, destination_height); | 253 const gfx::Size dimensions(destination_width, destination_height); |
| 253 if (!VideoFrame::IsValidConfig(VideoFrame::I420, | 254 if (!VideoFrame::IsValidConfig(VideoFrame::I420, |
| 254 VideoFrame::STORAGE_UNKNOWN, | 255 VideoFrame::STORAGE_UNKNOWN, |
| 255 dimensions, | 256 dimensions, |
| 256 gfx::Rect(dimensions), | 257 gfx::Rect(dimensions), |
| 257 dimensions)) { | 258 dimensions)) { |
| 258 return; | 259 return; |
| 259 } | 260 } |
| 260 | 261 |
| 261 scoped_ptr<Buffer> buffer( | 262 const VideoCaptureFormat output_format = |
| 262 ReserveOutputBuffer(media::PIXEL_FORMAT_I420, dimensions)); | 263 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
| 264 media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU); |
| 265 |
| 266 scoped_ptr<Buffer> buffer(ReserveOutputBuffer(output_format)); |
| 263 if (!buffer.get()) | 267 if (!buffer.get()) |
| 264 return; | 268 return; |
| 265 | 269 |
| 266 uint8* const yplane = reinterpret_cast<uint8*>(buffer->data()); | 270 uint8* const yplane = reinterpret_cast<uint8*>(buffer->data()); |
| 267 uint8* const uplane = | 271 uint8* const uplane = |
| 268 yplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, | 272 yplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, |
| 269 VideoFrame::kYPlane, dimensions); | 273 VideoFrame::kYPlane, dimensions); |
| 270 uint8* const vplane = | 274 uint8* const vplane = |
| 271 uplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, | 275 uplane + VideoFrame::PlaneAllocationSize(VideoFrame::I420, |
| 272 VideoFrame::kUPlane, dimensions); | 276 VideoFrame::kUPlane, dimensions); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 uv_plane_stride, | 347 uv_plane_stride, |
| 344 crop_x, | 348 crop_x, |
| 345 crop_y, | 349 crop_y, |
| 346 frame_format.frame_size.width(), | 350 frame_format.frame_size.width(), |
| 347 (flip ? -1 : 1) * frame_format.frame_size.height(), | 351 (flip ? -1 : 1) * frame_format.frame_size.height(), |
| 348 new_unrotated_width, | 352 new_unrotated_width, |
| 349 new_unrotated_height, | 353 new_unrotated_height, |
| 350 rotation_mode, | 354 rotation_mode, |
| 351 origin_colorspace) != 0) { | 355 origin_colorspace) != 0) { |
| 352 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " | 356 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " |
| 353 << media::VideoCaptureFormat::PixelFormatToString( | 357 << VideoCaptureFormat::PixelFormatToString( |
| 354 frame_format.pixel_format); | 358 frame_format.pixel_format); |
| 355 return; | 359 return; |
| 356 } | 360 } |
| 357 | 361 |
| 358 OnIncomingCapturedBuffer(buffer.Pass(), | 362 OnIncomingCapturedBuffer(buffer.Pass(), output_format, timestamp); |
| 359 media::VideoCaptureFormat(dimensions, | |
| 360 frame_format.frame_rate, | |
| 361 media::PIXEL_FORMAT_I420), | |
| 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)); |
| 381 ReserveOutputBuffer(frame_format.pixel_format, frame_format.frame_size)); | |
| 382 if (!buffer.get()) | 382 if (!buffer.get()) |
| 383 return; | 383 return; |
| 384 | 384 |
| 385 // Blit (copy) here from y,u,v into buffer.data()). Needed so we can return | 385 // Blit (copy) here from y,u,v into buffer.data()). Needed so we can return |
| 386 // the parameter buffer synchronously to the driver. | 386 // the parameter buffer synchronously to the driver. |
| 387 const size_t y_plane_size = VideoFrame::PlaneAllocationSize(VideoFrame::I420, | 387 const size_t y_plane_size = VideoFrame::PlaneAllocationSize(VideoFrame::I420, |
| 388 VideoFrame::kYPlane, frame_format.frame_size); | 388 VideoFrame::kYPlane, frame_format.frame_size); |
| 389 const size_t u_plane_size = VideoFrame::PlaneAllocationSize( | 389 const size_t u_plane_size = VideoFrame::PlaneAllocationSize( |
| 390 VideoFrame::I420, VideoFrame::kUPlane, frame_format.frame_size); | 390 VideoFrame::I420, VideoFrame::kUPlane, frame_format.frame_size); |
| 391 uint8* const dst_y = reinterpret_cast<uint8*>(buffer->data()); | 391 uint8* const dst_y = reinterpret_cast<uint8*>(buffer->data()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 411 frame_format.frame_size.width(), | 411 frame_format.frame_size.width(), |
| 412 frame_format.frame_size.height())) { | 412 frame_format.frame_size.height())) { |
| 413 DLOG(WARNING) << "Failed to copy buffer"; | 413 DLOG(WARNING) << "Failed to copy buffer"; |
| 414 return; | 414 return; |
| 415 } | 415 } |
| 416 | 416 |
| 417 OnIncomingCapturedBuffer(buffer.Pass(), frame_format, timestamp); | 417 OnIncomingCapturedBuffer(buffer.Pass(), frame_format, timestamp); |
| 418 }; | 418 }; |
| 419 | 419 |
| 420 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> | 420 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> |
| 421 VideoCaptureDeviceClient::ReserveOutputBuffer(media::VideoPixelFormat format, | 421 VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 422 const gfx::Size& dimensions) { | 422 const VideoCaptureFormat& frame_format) { |
| 423 DCHECK(format == media::PIXEL_FORMAT_I420 || | 423 DCHECK(frame_format.pixel_format == media::PIXEL_FORMAT_I420 || |
| 424 format == media::PIXEL_FORMAT_TEXTURE || | 424 frame_format.pixel_format == media::PIXEL_FORMAT_ARGB); |
| 425 format == media::PIXEL_FORMAT_GPUMEMORYBUFFER); | 425 DCHECK_GT(frame_format.frame_size.width(), 0); |
| 426 DCHECK_GT(dimensions.width(), 0); | 426 DCHECK_GT(frame_format.frame_size.height(), 0); |
| 427 DCHECK_GT(dimensions.height(), 0); | |
| 428 | 427 |
| 429 if (format == media::PIXEL_FORMAT_GPUMEMORYBUFFER && !texture_wrap_helper_) { | 428 if (frame_format.pixel_storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER && |
| 429 !texture_wrap_helper_) { |
| 430 texture_wrap_helper_ = | 430 texture_wrap_helper_ = |
| 431 new TextureWrapHelper(controller_, capture_task_runner_); | 431 new TextureWrapHelper(controller_, capture_task_runner_); |
| 432 } | 432 } |
| 433 | 433 |
| 434 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
| 435 // it's a ShMem GMB or a DmaBuf GMB. |
| 434 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 436 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
| 435 const int buffer_id = | 437 const int buffer_id = buffer_pool_->ReserveForProducer( |
| 436 buffer_pool_->ReserveForProducer(format, dimensions, &buffer_id_to_drop); | 438 frame_format.pixel_format, frame_format.pixel_storage, |
| 439 frame_format.frame_size, &buffer_id_to_drop); |
| 437 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 440 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 438 return NULL; | 441 return NULL; |
| 439 | 442 |
| 440 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( | 443 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( |
| 441 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 444 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
| 442 | 445 |
| 443 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { | 446 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
| 444 BrowserThread::PostTask(BrowserThread::IO, | 447 BrowserThread::PostTask(BrowserThread::IO, |
| 445 FROM_HERE, | 448 FROM_HERE, |
| 446 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, | 449 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, |
| 447 controller_, buffer_id_to_drop)); | 450 controller_, buffer_id_to_drop)); |
| 448 } | 451 } |
| 449 | 452 |
| 450 return output_buffer.Pass(); | 453 return output_buffer.Pass(); |
| 451 } | 454 } |
| 452 | 455 |
| 453 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 456 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 454 scoped_ptr<Buffer> buffer, | 457 scoped_ptr<Buffer> buffer, |
| 455 const media::VideoCaptureFormat& frame_format, | 458 const VideoCaptureFormat& frame_format, |
| 456 const base::TimeTicks& timestamp) { | 459 const base::TimeTicks& timestamp) { |
| 457 if (frame_format.pixel_format == media::PIXEL_FORMAT_GPUMEMORYBUFFER) { | 460 if (frame_format.pixel_storage == media::PIXEL_STORAGE_GPUMEMORYBUFFER) { |
| 458 capture_task_runner_->PostTask( | 461 capture_task_runner_->PostTask( |
| 459 FROM_HERE, | 462 FROM_HERE, |
| 460 base::Bind(&TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer, | 463 base::Bind(&TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer, |
| 461 texture_wrap_helper_, | 464 texture_wrap_helper_, |
| 462 base::Passed(&buffer), | 465 base::Passed(&buffer), |
| 463 frame_format, | 466 frame_format, |
| 464 timestamp)); | 467 timestamp)); |
| 465 } else { | 468 } else { |
| 466 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_I420); | 469 DCHECK(frame_format.pixel_format == media::PIXEL_FORMAT_I420 || |
| 470 frame_format.pixel_format == media::PIXEL_FORMAT_ARGB); |
| 467 scoped_refptr<VideoFrame> video_frame = | 471 scoped_refptr<VideoFrame> video_frame = |
| 468 VideoFrame::WrapExternalData( | 472 VideoFrame::WrapExternalData( |
| 469 VideoFrame::I420, | 473 VideoFrame::I420, |
| 470 frame_format.frame_size, | 474 frame_format.frame_size, |
| 471 gfx::Rect(frame_format.frame_size), | 475 gfx::Rect(frame_format.frame_size), |
| 472 frame_format.frame_size, | 476 frame_format.frame_size, |
| 473 reinterpret_cast<uint8*>(buffer->data()), | 477 reinterpret_cast<uint8*>(buffer->data()), |
| 474 VideoFrame::AllocationSize(VideoFrame::I420, | 478 VideoFrame::AllocationSize(VideoFrame::I420, |
| 475 frame_format.frame_size), | 479 frame_format.frame_size), |
| 476 base::TimeDelta()); | 480 base::TimeDelta()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 capture_task_runner_->PostTask(FROM_HERE, | 529 capture_task_runner_->PostTask(FROM_HERE, |
| 526 base::Bind(&TextureWrapHelper::Init, this)); | 530 base::Bind(&TextureWrapHelper::Init, this)); |
| 527 } | 531 } |
| 528 | 532 |
| 529 void | 533 void |
| 530 VideoCaptureDeviceClient::TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer( | 534 VideoCaptureDeviceClient::TextureWrapHelper::OnIncomingCapturedGpuMemoryBuffer( |
| 531 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, | 535 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
| 532 const media::VideoCaptureFormat& frame_format, | 536 const media::VideoCaptureFormat& frame_format, |
| 533 const base::TimeTicks& timestamp) { | 537 const base::TimeTicks& timestamp) { |
| 534 DCHECK(capture_task_runner_->BelongsToCurrentThread()); | 538 DCHECK(capture_task_runner_->BelongsToCurrentThread()); |
| 535 DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_GPUMEMORYBUFFER); | 539 DCHECK_EQ(frame_format.pixel_storage, media::PIXEL_STORAGE_GPUMEMORYBUFFER); |
| 536 if (!gl_helper_) { | 540 if (!gl_helper_) { |
| 537 // |gl_helper_| might not exist due to asynchronous initialization not | 541 // |gl_helper_| might not exist due to asynchronous initialization not |
| 538 // finished or due to termination in process after a context loss. | 542 // finished or due to termination in process after a context loss. |
| 539 DVLOG(1) << " Skipping ingress frame, no GL context."; | 543 DVLOG(1) << " Skipping ingress frame, no GL context."; |
| 540 return; | 544 return; |
| 541 } | 545 } |
| 542 | 546 |
| 543 gpu::gles2::GLES2Interface* gl = capture_thread_context_->ContextGL(); | 547 gpu::gles2::GLES2Interface* gl = capture_thread_context_->ContextGL(); |
| 544 GLuint image_id = gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), | 548 GLuint image_id = gl->CreateImageCHROMIUM(buffer->AsClientBuffer(), |
| 545 frame_format.frame_size.width(), | 549 frame_format.frame_size.width(), |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 void VideoCaptureDeviceClient::TextureWrapHelper::OnError( | 678 void VideoCaptureDeviceClient::TextureWrapHelper::OnError( |
| 675 const std::string& message) { | 679 const std::string& message) { |
| 676 DCHECK(capture_task_runner_->BelongsToCurrentThread()); | 680 DCHECK(capture_task_runner_->BelongsToCurrentThread()); |
| 677 DLOG(ERROR) << message; | 681 DLOG(ERROR) << message; |
| 678 BrowserThread::PostTask( | 682 BrowserThread::PostTask( |
| 679 BrowserThread::IO, FROM_HERE, | 683 BrowserThread::IO, FROM_HERE, |
| 680 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); | 684 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); |
| 681 } | 685 } |
| 682 | 686 |
| 683 } // namespace content | 687 } // namespace content |
| OLD | NEW |