| 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 "media/capture/video/video_capture_device_client.h" | 5 #include "media/capture/video/video_capture_device_client.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "media/base/bind_to_current_loop.h" | 17 #include "media/base/bind_to_current_loop.h" |
| 18 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
| 19 #include "media/capture/video/video_capture_buffer_handle.h" | 19 #include "media/capture/video/video_capture_buffer_handle.h" |
| 20 #include "media/capture/video/video_capture_buffer_pool.h" | 20 #include "media/capture/video/video_capture_buffer_pool.h" |
| 21 #include "media/capture/video/video_capture_jpeg_decoder.h" | 21 #include "media/capture/video/video_capture_jpeg_decoder.h" |
| 22 #include "media/capture/video/video_frame_receiver.h" | 22 #include "media/capture/video/video_frame_receiver.h" |
| 23 #include "media/capture/video_capture_types.h" | 23 #include "media/capture/video_capture_types.h" |
| 24 #include "mojo/public/cpp/system/platform_handle.h" | |
| 25 #include "third_party/libyuv/include/libyuv.h" | 24 #include "third_party/libyuv/include/libyuv.h" |
| 26 | 25 |
| 27 using media::VideoCaptureFormat; | 26 using media::VideoCaptureFormat; |
| 28 using media::VideoFrame; | 27 using media::VideoFrame; |
| 29 using media::VideoFrameMetadata; | 28 using media::VideoFrameMetadata; |
| 30 | 29 |
| 31 namespace { | 30 namespace { |
| 32 | 31 |
| 33 bool IsFormatSupported(media::VideoPixelFormat pixel_format) { | 32 bool IsFormatSupported(media::VideoPixelFormat pixel_format) { |
| 34 return (pixel_format == media::PIXEL_FORMAT_I420 || | 33 return (pixel_format == media::PIXEL_FORMAT_I420 || |
| (...skipping 15 matching lines...) Expand all Loading... |
| 50 | 49 |
| 51 ~BufferPoolProducerReservation() override { | 50 ~BufferPoolProducerReservation() override { |
| 52 buffer_pool_->RelinquishProducerReservation(buffer_id_); | 51 buffer_pool_->RelinquishProducerReservation(buffer_id_); |
| 53 } | 52 } |
| 54 | 53 |
| 55 private: | 54 private: |
| 56 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; | 55 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; |
| 57 const int buffer_id_; | 56 const int buffer_id_; |
| 58 }; | 57 }; |
| 59 | 58 |
| 59 class BufferPoolConsumerReservation : public Ownership { |
| 60 public: |
| 61 BufferPoolConsumerReservation( |
| 62 scoped_refptr<VideoCaptureBufferPool> buffer_pool, |
| 63 int buffer_id) |
| 64 : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) { |
| 65 // The code invoking this contstructor is supposed to have already set a |
| 66 // consumer hold on the buffer from pool. |
| 67 } |
| 68 |
| 69 ~BufferPoolConsumerReservation() override { |
| 70 buffer_pool_->RelinquishConsumerHold(buffer_id_, 1); |
| 71 } |
| 72 |
| 73 private: |
| 74 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; |
| 75 const int buffer_id_; |
| 76 }; |
| 77 |
| 60 class BufferPoolBufferHandleProvider : public BufferHandleProvider { | 78 class BufferPoolBufferHandleProvider : public BufferHandleProvider { |
| 61 public: | 79 public: |
| 62 BufferPoolBufferHandleProvider( | 80 BufferPoolBufferHandleProvider( |
| 63 scoped_refptr<VideoCaptureBufferPool> buffer_pool, | 81 scoped_refptr<VideoCaptureBufferPool> buffer_pool, |
| 64 int buffer_id) | 82 int buffer_id) |
| 65 : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) {} | 83 : buffer_pool_(std::move(buffer_pool)), buffer_id_(buffer_id) {} |
| 66 | 84 |
| 67 // Implementation of BufferHandleProvider: | 85 // Implementation of BufferHandleProvider: |
| 68 mojo::ScopedSharedBufferHandle GetHandleForInterProcessTransit() override { | 86 mojo::ScopedSharedBufferHandle GetHandleForInterProcessTransit() override { |
| 69 return buffer_pool_->GetHandleForInterProcessTransit(buffer_id_); | 87 return buffer_pool_->GetHandleForInterProcessTransit(buffer_id_); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 85 : receiver_(std::move(receiver)), | 103 : receiver_(std::move(receiver)), |
| 86 jpeg_decoder_factory_callback_(jpeg_decoder_factory), | 104 jpeg_decoder_factory_callback_(jpeg_decoder_factory), |
| 87 external_jpeg_decoder_initialized_(false), | 105 external_jpeg_decoder_initialized_(false), |
| 88 buffer_pool_(std::move(buffer_pool)), | 106 buffer_pool_(std::move(buffer_pool)), |
| 89 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} | 107 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} |
| 90 | 108 |
| 91 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { | 109 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { |
| 92 // This should be on the platform auxiliary thread since | 110 // This should be on the platform auxiliary thread since |
| 93 // |external_jpeg_decoder_| need to be destructed on the same thread as | 111 // |external_jpeg_decoder_| need to be destructed on the same thread as |
| 94 // OnIncomingCapturedData. | 112 // OnIncomingCapturedData. |
| 113 |
| 114 for (int buffer_id : buffer_ids_known_by_receiver_) { |
| 115 receiver_->OnBufferRetired(buffer_id); |
| 116 } |
| 95 } | 117 } |
| 96 | 118 |
| 97 void VideoCaptureDeviceClient::OnIncomingCapturedData( | 119 void VideoCaptureDeviceClient::OnIncomingCapturedData( |
| 98 const uint8_t* data, | 120 const uint8_t* data, |
| 99 int length, | 121 int length, |
| 100 const VideoCaptureFormat& format, | 122 const VideoCaptureFormat& format, |
| 101 int rotation, | 123 int rotation, |
| 102 base::TimeTicks reference_time, | 124 base::TimeTicks reference_time, |
| 103 base::TimeDelta timestamp, | 125 base::TimeDelta timestamp, |
| 104 int frame_feedback_id) { | 126 int frame_feedback_id) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | 293 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
| 272 timestamp); | 294 timestamp); |
| 273 } | 295 } |
| 274 | 296 |
| 275 media::VideoCaptureDevice::Client::Buffer | 297 media::VideoCaptureDevice::Client::Buffer |
| 276 VideoCaptureDeviceClient::ReserveOutputBuffer( | 298 VideoCaptureDeviceClient::ReserveOutputBuffer( |
| 277 const gfx::Size& frame_size, | 299 const gfx::Size& frame_size, |
| 278 media::VideoPixelFormat pixel_format, | 300 media::VideoPixelFormat pixel_format, |
| 279 media::VideoPixelStorage pixel_storage, | 301 media::VideoPixelStorage pixel_storage, |
| 280 int frame_feedback_id) { | 302 int frame_feedback_id) { |
| 303 DFAKE_SCOPED_RECURSIVE_LOCK(call_from_producer_); |
| 281 DCHECK_GT(frame_size.width(), 0); | 304 DCHECK_GT(frame_size.width(), 0); |
| 282 DCHECK_GT(frame_size.height(), 0); | 305 DCHECK_GT(frame_size.height(), 0); |
| 283 DCHECK(IsFormatSupported(pixel_format)); | 306 DCHECK(IsFormatSupported(pixel_format)); |
| 284 | 307 |
| 285 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 308 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
| 286 const int buffer_id = | 309 const int buffer_id = |
| 287 buffer_pool_->ReserveForProducer(frame_size, pixel_format, pixel_storage, | 310 buffer_pool_->ReserveForProducer(frame_size, pixel_format, pixel_storage, |
| 288 frame_feedback_id, &buffer_id_to_drop); | 311 frame_feedback_id, &buffer_id_to_drop); |
| 289 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) | 312 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
| 290 receiver_->OnBufferDestroyed(buffer_id_to_drop); | 313 // Buffer pool has decided to releasea buffer. Notify receiver in case |
| 314 // the buffer has already been shared with it. |
| 315 if (buffer_ids_known_by_receiver_.find(buffer_id_to_drop) != |
| 316 buffer_ids_known_by_receiver_.end()) { |
| 317 buffer_ids_known_by_receiver_.erase(buffer_id_to_drop); |
| 318 receiver_->OnBufferRetired(buffer_id_to_drop); |
| 319 } |
| 320 } |
| 291 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 321 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 292 return Buffer(); | 322 return Buffer(); |
| 293 return MakeBufferStruct(buffer_pool_, buffer_id, frame_feedback_id); | 323 return MakeBufferStruct(buffer_pool_, buffer_id, frame_feedback_id); |
| 294 } | 324 } |
| 295 | 325 |
| 296 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 326 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
| 297 Buffer buffer, | 327 Buffer buffer, |
| 298 const VideoCaptureFormat& format, | 328 const VideoCaptureFormat& format, |
| 299 base::TimeTicks reference_time, | 329 base::TimeTicks reference_time, |
| 300 base::TimeDelta timestamp) { | 330 base::TimeDelta timestamp) { |
| 331 DFAKE_SCOPED_RECURSIVE_LOCK(call_from_producer_); |
| 301 OnIncomingCapturedBufferExt(std::move(buffer), format, reference_time, | 332 OnIncomingCapturedBufferExt(std::move(buffer), format, reference_time, |
| 302 timestamp, gfx::Rect(format.frame_size), | 333 timestamp, gfx::Rect(format.frame_size), |
| 303 VideoFrameMetadata()); | 334 VideoFrameMetadata()); |
| 304 } | 335 } |
| 305 | 336 |
| 306 void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( | 337 void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( |
| 307 Buffer buffer, | 338 Buffer buffer, |
| 308 const VideoCaptureFormat& format, | 339 const VideoCaptureFormat& format, |
| 309 base::TimeTicks reference_time, | 340 base::TimeTicks reference_time, |
| 310 base::TimeDelta timestamp, | 341 base::TimeDelta timestamp, |
| 311 gfx::Rect visible_rect, | 342 gfx::Rect visible_rect, |
| 312 const VideoFrameMetadata& additional_metadata) { | 343 const VideoFrameMetadata& additional_metadata) { |
| 313 auto buffer_mojo_handle = | 344 DFAKE_SCOPED_RECURSIVE_LOCK(call_from_producer_); |
| 314 buffer_pool_->GetHandleForInterProcessTransit(buffer.id()); | |
| 315 base::SharedMemoryHandle memory_handle; | |
| 316 size_t memory_size = 0; | |
| 317 bool read_only_flag = false; | |
| 318 const MojoResult unwrap_result_code = mojo::UnwrapSharedMemoryHandle( | |
| 319 std::move(buffer_mojo_handle), &memory_handle, &memory_size, | |
| 320 &read_only_flag); | |
| 321 DCHECK_EQ(MOJO_RESULT_OK, unwrap_result_code); | |
| 322 | 345 |
| 323 auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); | 346 if (buffer_ids_known_by_receiver_.find(buffer.id()) == |
| 324 scoped_refptr<media::VideoFrame> frame = | 347 buffer_ids_known_by_receiver_.end()) { |
| 325 media::VideoFrame::WrapExternalSharedMemory( | 348 receiver_->OnNewBufferHandle(buffer.id(), |
| 326 format.pixel_format, // format | 349 std::move(buffer.handle_provider)); |
| 327 format.frame_size, // coded_size | 350 buffer_ids_known_by_receiver_.insert(buffer.id()); |
| 328 visible_rect, // visible_rect | 351 } |
| 329 format.frame_size, // natural_size | |
| 330 buffer_access->data(), // data | |
| 331 buffer_access->mapped_size(), // data_size | |
| 332 memory_handle, // handle | |
| 333 0, // shared_memory_offset | |
| 334 timestamp); // timestamp | |
| 335 frame->metadata()->MergeMetadataFrom(&additional_metadata); | |
| 336 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | |
| 337 format.frame_rate); | |
| 338 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | |
| 339 reference_time); | |
| 340 | 352 |
| 341 receiver_->OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); | 353 VideoFrameMetadata metadata; |
| 354 metadata.MergeMetadataFrom(&additional_metadata); |
| 355 metadata.SetDouble(media::VideoFrameMetadata::FRAME_RATE, format.frame_rate); |
| 356 metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
| 357 reference_time); |
| 358 |
| 359 mojom::VideoFrameInfoPtr info = mojom::VideoFrameInfo::New(); |
| 360 info->timestamp = timestamp; |
| 361 info->pixel_format = format.pixel_format; |
| 362 info->storage_type = format.pixel_storage; |
| 363 info->coded_size = format.frame_size; |
| 364 info->visible_rect = visible_rect; |
| 365 info->metadata = metadata.CopyInternalValues(); |
| 366 |
| 367 buffer_pool_->HoldForConsumers(buffer.id(), 1); |
| 368 receiver_->OnFrameReadyInBuffer( |
| 369 buffer.id(), buffer.frame_feedback_id(), |
| 370 base::MakeUnique<BufferPoolConsumerReservation>(buffer_pool_, |
| 371 buffer.id()), |
| 372 std::move(info)); |
| 342 } | 373 } |
| 343 | 374 |
| 344 media::VideoCaptureDevice::Client::Buffer | 375 media::VideoCaptureDevice::Client::Buffer |
| 345 VideoCaptureDeviceClient::ResurrectLastOutputBuffer( | 376 VideoCaptureDeviceClient::ResurrectLastOutputBuffer( |
| 346 const gfx::Size& dimensions, | 377 const gfx::Size& dimensions, |
| 347 media::VideoPixelFormat format, | 378 media::VideoPixelFormat format, |
| 348 media::VideoPixelStorage storage, | 379 media::VideoPixelStorage storage, |
| 349 int new_frame_feedback_id) { | 380 int new_frame_feedback_id) { |
| 381 DFAKE_SCOPED_RECURSIVE_LOCK(call_from_producer_); |
| 350 const int buffer_id = | 382 const int buffer_id = |
| 351 buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); | 383 buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); |
| 352 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 384 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 353 return Buffer(); | 385 return Buffer(); |
| 354 return MakeBufferStruct(buffer_pool_, buffer_id, new_frame_feedback_id); | 386 return MakeBufferStruct(buffer_pool_, buffer_id, new_frame_feedback_id); |
| 355 } | 387 } |
| 356 | 388 |
| 357 void VideoCaptureDeviceClient::OnError( | 389 void VideoCaptureDeviceClient::OnError( |
| 358 const tracked_objects::Location& from_here, | 390 const tracked_objects::Location& from_here, |
| 359 const std::string& reason) { | 391 const std::string& reason) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); | 463 auto buffer_access = buffer.handle_provider->GetHandleForInProcessAccess(); |
| 432 memcpy(buffer_access->data(), data, length); | 464 memcpy(buffer_access->data(), data, length); |
| 433 const VideoCaptureFormat output_format = | 465 const VideoCaptureFormat output_format = |
| 434 VideoCaptureFormat(format.frame_size, format.frame_rate, | 466 VideoCaptureFormat(format.frame_size, format.frame_rate, |
| 435 media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); | 467 media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); |
| 436 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | 468 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
| 437 timestamp); | 469 timestamp); |
| 438 } | 470 } |
| 439 | 471 |
| 440 } // namespace media | 472 } // namespace media |
| OLD | NEW |