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 |