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" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
67 ~AutoReleaseBuffer() override { pool_->RelinquishProducerReservation(id_); } | 67 ~AutoReleaseBuffer() override { pool_->RelinquishProducerReservation(id_); } |
68 | 68 |
69 const int id_; | 69 const int id_; |
70 const scoped_refptr<VideoCaptureBufferPool> pool_; | 70 const scoped_refptr<VideoCaptureBufferPool> pool_; |
71 const std::unique_ptr<VideoCaptureBufferHandle> buffer_handle_; | 71 const std::unique_ptr<VideoCaptureBufferHandle> buffer_handle_; |
72 }; | 72 }; |
73 | 73 |
74 VideoCaptureDeviceClient::VideoCaptureDeviceClient( | 74 VideoCaptureDeviceClient::VideoCaptureDeviceClient( |
75 std::unique_ptr<VideoFrameReceiver> receiver, | 75 std::unique_ptr<VideoFrameReceiver> receiver, |
76 scoped_refptr<VideoCaptureBufferPool> buffer_pool, | 76 scoped_refptr<VideoCaptureBufferPool> buffer_pool, |
77 const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory) | 77 const VideoCaptureJpegDecoderFactoryCB& jpeg_decoder_factory, |
78 scoped_refptr<base::SingleThreadTaskRunner> | |
79 utilization_reporting_task_runner) | |
78 : receiver_(std::move(receiver)), | 80 : receiver_(std::move(receiver)), |
79 jpeg_decoder_factory_callback_(jpeg_decoder_factory), | 81 jpeg_decoder_factory_callback_(jpeg_decoder_factory), |
80 external_jpeg_decoder_initialized_(false), | 82 external_jpeg_decoder_initialized_(false), |
81 buffer_pool_(std::move(buffer_pool)), | 83 buffer_pool_(std::move(buffer_pool)), |
84 optional_load_observer_(nullptr), | |
85 utilization_reporting_task_runner_( | |
86 std::move(utilization_reporting_task_runner)), | |
82 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} | 87 last_captured_pixel_format_(media::PIXEL_FORMAT_UNKNOWN) {} |
83 | 88 |
84 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { | 89 VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { |
85 // This should be on the platform auxiliary thread since | 90 // This should be on the platform auxiliary thread since |
86 // |external_jpeg_decoder_| need to be destructed on the same thread as | 91 // |external_jpeg_decoder_| need to be destructed on the same thread as |
87 // OnIncomingCapturedData. | 92 // OnIncomingCapturedData. |
88 } | 93 } |
89 | 94 |
95 void VideoCaptureDeviceClient::SetConsumerLoadObserver( | |
96 ConsumerLoadObserver* load_observer) { | |
97 optional_load_observer_ = load_observer; | |
98 } | |
99 | |
90 void VideoCaptureDeviceClient::OnIncomingCapturedData( | 100 void VideoCaptureDeviceClient::OnIncomingCapturedData( |
91 const uint8_t* data, | 101 const uint8_t* data, |
92 int length, | 102 int length, |
93 const VideoCaptureFormat& frame_format, | 103 const VideoCaptureFormat& frame_format, |
94 int rotation, | 104 int rotation, |
95 base::TimeTicks reference_time, | 105 base::TimeTicks reference_time, |
96 base::TimeDelta timestamp) { | 106 base::TimeDelta timestamp, |
107 int frame_id) { | |
97 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); | 108 TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); |
98 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); | 109 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); |
99 | 110 |
100 if (last_captured_pixel_format_ != frame_format.pixel_format) { | 111 if (last_captured_pixel_format_ != frame_format.pixel_format) { |
101 OnLog("Pixel format: " + | 112 OnLog("Pixel format: " + |
102 media::VideoPixelFormatToString(frame_format.pixel_format)); | 113 media::VideoPixelFormatToString(frame_format.pixel_format)); |
103 last_captured_pixel_format_ = frame_format.pixel_format; | 114 last_captured_pixel_format_ = frame_format.pixel_format; |
104 | 115 |
105 if (frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && | 116 if (frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && |
106 !external_jpeg_decoder_initialized_) { | 117 !external_jpeg_decoder_initialized_) { |
107 external_jpeg_decoder_initialized_ = true; | 118 external_jpeg_decoder_initialized_ = true; |
108 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); | 119 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); |
109 external_jpeg_decoder_->Initialize(); | 120 external_jpeg_decoder_->Initialize(); |
110 } | 121 } |
111 } | 122 } |
112 | 123 |
113 if (!frame_format.IsValid()) | 124 if (!frame_format.IsValid()) |
114 return; | 125 return; |
115 | 126 |
116 if (frame_format.pixel_format == media::PIXEL_FORMAT_Y16) { | 127 if (frame_format.pixel_format == media::PIXEL_FORMAT_Y16) { |
117 return OnIncomingCapturedY16Data(data, length, frame_format, reference_time, | 128 return OnIncomingCapturedY16Data(data, length, frame_format, reference_time, |
118 timestamp); | 129 timestamp, frame_id); |
119 } | 130 } |
120 | 131 |
121 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 132 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
122 // bit decomposition of {width, height}, grabbing the odd and even parts. | 133 // bit decomposition of {width, height}, grabbing the odd and even parts. |
123 const int chopped_width = frame_format.frame_size.width() & 1; | 134 const int chopped_width = frame_format.frame_size.width() & 1; |
124 const int chopped_height = frame_format.frame_size.height() & 1; | 135 const int chopped_height = frame_format.frame_size.height() & 1; |
125 const int new_unrotated_width = frame_format.frame_size.width() & ~1; | 136 const int new_unrotated_width = frame_format.frame_size.width() & ~1; |
126 const int new_unrotated_height = frame_format.frame_size.height() & ~1; | 137 const int new_unrotated_height = frame_format.frame_size.height() & ~1; |
127 | 138 |
128 int destination_width = new_unrotated_width; | 139 int destination_width = new_unrotated_width; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 rotation_mode, origin_colorspace) != 0) { | 263 rotation_mode, origin_colorspace) != 0) { |
253 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " | 264 DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " |
254 << media::VideoPixelFormatToString(frame_format.pixel_format); | 265 << media::VideoPixelFormatToString(frame_format.pixel_format); |
255 return; | 266 return; |
256 } | 267 } |
257 | 268 |
258 const VideoCaptureFormat output_format = | 269 const VideoCaptureFormat output_format = |
259 VideoCaptureFormat(dimensions, frame_format.frame_rate, | 270 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
260 media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU); | 271 media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU); |
261 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | 272 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
262 timestamp); | 273 timestamp, frame_id); |
263 } | 274 } |
264 | 275 |
265 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 276 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
266 VideoCaptureDeviceClient::ReserveOutputBuffer( | 277 VideoCaptureDeviceClient::ReserveOutputBuffer( |
267 const gfx::Size& frame_size, | 278 const gfx::Size& frame_size, |
268 media::VideoPixelFormat pixel_format, | 279 media::VideoPixelFormat pixel_format, |
269 media::VideoPixelStorage pixel_storage) { | 280 media::VideoPixelStorage pixel_storage) { |
270 DCHECK_GT(frame_size.width(), 0); | 281 DCHECK_GT(frame_size.width(), 0); |
271 DCHECK_GT(frame_size.height(), 0); | 282 DCHECK_GT(frame_size.height(), 0); |
272 DCHECK(IsFormatSupported(pixel_format)); | 283 DCHECK(IsFormatSupported(pixel_format)); |
273 | 284 |
274 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if | 285 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
275 // it's a ShMem GMB or a DmaBuf GMB. | 286 // it's a ShMem GMB or a DmaBuf GMB. |
276 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 287 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
277 const int buffer_id = buffer_pool_->ReserveForProducer( | 288 const int buffer_id = buffer_pool_->ReserveForProducer( |
278 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); | 289 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); |
279 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) | 290 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
280 receiver_->OnBufferDestroyed(buffer_id_to_drop); | 291 receiver_->OnBufferDestroyed(buffer_id_to_drop); |
292 EraseEntryFromBufferIdToFrameIdMap(buffer_id_to_drop); | |
293 } | |
281 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 294 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
282 return nullptr; | 295 return nullptr; |
283 return base::WrapUnique<Buffer>( | 296 return base::WrapUnique<Buffer>( |
284 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 297 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
285 } | 298 } |
286 | 299 |
287 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 300 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
288 std::unique_ptr<Buffer> buffer, | 301 std::unique_ptr<Buffer> buffer, |
289 const VideoCaptureFormat& frame_format, | 302 const VideoCaptureFormat& frame_format, |
290 base::TimeTicks reference_time, | 303 base::TimeTicks reference_time, |
291 base::TimeDelta timestamp) { | 304 base::TimeDelta timestamp, |
305 int frame_id) { | |
292 DCHECK(IsFormatSupported(frame_format.pixel_format)); | 306 DCHECK(IsFormatSupported(frame_format.pixel_format)); |
293 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); | 307 DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); |
294 | 308 |
295 scoped_refptr<VideoFrame> frame; | 309 scoped_refptr<VideoFrame> frame; |
296 if (buffer->IsBackedByVideoFrame()) { | 310 if (buffer->IsBackedByVideoFrame()) { |
297 frame = buffer->GetVideoFrame(); | 311 frame = buffer->GetVideoFrame(); |
298 frame->set_timestamp(timestamp); | 312 frame->set_timestamp(timestamp); |
299 } else { | 313 } else { |
300 frame = VideoFrame::WrapExternalSharedMemory( | 314 frame = VideoFrame::WrapExternalSharedMemory( |
301 frame_format.pixel_format, frame_format.frame_size, | 315 frame_format.pixel_format, frame_format.frame_size, |
302 gfx::Rect(frame_format.frame_size), frame_format.frame_size, | 316 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
303 reinterpret_cast<uint8_t*>(buffer->data()), | 317 reinterpret_cast<uint8_t*>(buffer->data()), |
304 VideoFrame::AllocationSize(frame_format.pixel_format, | 318 VideoFrame::AllocationSize(frame_format.pixel_format, |
305 frame_format.frame_size), | 319 frame_format.frame_size), |
306 base::SharedMemory::NULLHandle(), 0u, timestamp); | 320 base::SharedMemory::NULLHandle(), 0u, timestamp); |
307 } | 321 } |
308 if (!frame) | 322 if (!frame) |
309 return; | 323 return; |
310 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 324 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
311 frame_format.frame_rate); | 325 frame_format.frame_rate); |
312 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 326 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
313 reference_time); | 327 reference_time); |
314 OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); | 328 OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame), frame_id); |
315 } | 329 } |
316 | 330 |
317 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( | 331 void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( |
318 std::unique_ptr<Buffer> buffer, | 332 std::unique_ptr<Buffer> buffer, |
319 scoped_refptr<VideoFrame> frame) { | 333 scoped_refptr<VideoFrame> frame, |
334 int frame_id) { | |
335 AddEntryToBufferIdToFrameIdMap(buffer->id(), frame_id); | |
320 receiver_->OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); | 336 receiver_->OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); |
321 } | 337 } |
322 | 338 |
323 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 339 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
324 VideoCaptureDeviceClient::ResurrectLastOutputBuffer( | 340 VideoCaptureDeviceClient::ResurrectLastOutputBuffer( |
325 const gfx::Size& dimensions, | 341 const gfx::Size& dimensions, |
326 media::VideoPixelFormat format, | 342 media::VideoPixelFormat format, |
327 media::VideoPixelStorage storage) { | 343 media::VideoPixelStorage storage) { |
328 const int buffer_id = | 344 const int buffer_id = |
329 buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); | 345 buffer_pool_->ResurrectLastForProducer(dimensions, format, storage); |
(...skipping 17 matching lines...) Expand all Loading... | |
347 } | 363 } |
348 | 364 |
349 void VideoCaptureDeviceClient::OnLog(const std::string& message) { | 365 void VideoCaptureDeviceClient::OnLog(const std::string& message) { |
350 receiver_->OnLog(message); | 366 receiver_->OnLog(message); |
351 } | 367 } |
352 | 368 |
353 double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { | 369 double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { |
354 return buffer_pool_->GetBufferPoolUtilization(); | 370 return buffer_pool_->GetBufferPoolUtilization(); |
355 } | 371 } |
356 | 372 |
373 void VideoCaptureDeviceClient::OnReceiverReportingUtilization( | |
374 int buffer_id, | |
375 double utilization) { | |
376 DCHECK(utilization_reporting_task_runner_->BelongsToCurrentThread()); | |
377 if (optional_load_observer_ == nullptr) | |
378 return; | |
379 optional_load_observer_->OnConsumerReportingUtilization( | |
380 buffer_id_to_frame_id_map_[buffer_id], utilization); | |
381 } | |
382 | |
357 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 383 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
358 VideoCaptureDeviceClient::ReserveI420OutputBuffer( | 384 VideoCaptureDeviceClient::ReserveI420OutputBuffer( |
359 const gfx::Size& dimensions, | 385 const gfx::Size& dimensions, |
360 media::VideoPixelStorage storage, | 386 media::VideoPixelStorage storage, |
361 uint8_t** y_plane_data, | 387 uint8_t** y_plane_data, |
362 uint8_t** u_plane_data, | 388 uint8_t** u_plane_data, |
363 uint8_t** v_plane_data) { | 389 uint8_t** v_plane_data) { |
364 DCHECK(storage == media::PIXEL_STORAGE_CPU); | 390 DCHECK(storage == media::PIXEL_STORAGE_CPU); |
365 DCHECK(dimensions.height()); | 391 DCHECK(dimensions.height()); |
366 DCHECK(dimensions.width()); | 392 DCHECK(dimensions.width()); |
(...skipping 13 matching lines...) Expand all Loading... | |
380 *u_plane_data + | 406 *u_plane_data + |
381 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions).GetArea(); | 407 VideoFrame::PlaneSize(format, VideoFrame::kUPlane, dimensions).GetArea(); |
382 return buffer; | 408 return buffer; |
383 } | 409 } |
384 | 410 |
385 void VideoCaptureDeviceClient::OnIncomingCapturedY16Data( | 411 void VideoCaptureDeviceClient::OnIncomingCapturedY16Data( |
386 const uint8_t* data, | 412 const uint8_t* data, |
387 int length, | 413 int length, |
388 const VideoCaptureFormat& frame_format, | 414 const VideoCaptureFormat& frame_format, |
389 base::TimeTicks reference_time, | 415 base::TimeTicks reference_time, |
390 base::TimeDelta timestamp) { | 416 base::TimeDelta timestamp, |
417 int frame_id) { | |
391 std::unique_ptr<Buffer> buffer(ReserveOutputBuffer(frame_format.frame_size, | 418 std::unique_ptr<Buffer> buffer(ReserveOutputBuffer(frame_format.frame_size, |
392 media::PIXEL_FORMAT_Y16, | 419 media::PIXEL_FORMAT_Y16, |
393 media::PIXEL_STORAGE_CPU)); | 420 media::PIXEL_STORAGE_CPU)); |
394 // The input |length| can be greater than the required buffer size because of | 421 // The input |length| can be greater than the required buffer size because of |
395 // paddings and/or alignments, but it cannot be smaller. | 422 // paddings and/or alignments, but it cannot be smaller. |
396 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); | 423 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); |
397 #if DCHECK_IS_ON() | 424 #if DCHECK_IS_ON() |
398 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; | 425 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; |
399 if (dropped_frame_counter_ >= kMaxDroppedFrames) | 426 if (dropped_frame_counter_ >= kMaxDroppedFrames) |
400 OnError(FROM_HERE, "Too many frames dropped"); | 427 OnError(FROM_HERE, "Too many frames dropped"); |
401 #endif | 428 #endif |
402 // Failed to reserve output buffer, so drop the frame. | 429 // Failed to reserve output buffer, so drop the frame. |
403 if (!buffer.get()) | 430 if (!buffer.get()) |
404 return; | 431 return; |
405 memcpy(buffer->data(), data, length); | 432 memcpy(buffer->data(), data, length); |
406 const VideoCaptureFormat output_format = | 433 const VideoCaptureFormat output_format = |
407 VideoCaptureFormat(frame_format.frame_size, frame_format.frame_rate, | 434 VideoCaptureFormat(frame_format.frame_size, frame_format.frame_rate, |
408 media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); | 435 media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); |
409 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, | 436 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
410 timestamp); | 437 timestamp, frame_id); |
438 } | |
439 | |
440 void VideoCaptureDeviceClient::AddEntryToBufferIdToFrameIdMap(int buffer_id, | |
441 int frame_id) { | |
442 if (utilization_reporting_task_runner_->BelongsToCurrentThread()) { | |
miu
2016/12/01 05:25:18
The threading in these two new methods feels a bit
chfremer
2016/12/02 01:28:29
Luckily, we were able to eliminate the need for al
| |
443 buffer_id_to_frame_id_map_[buffer_id] = frame_id; | |
444 return; | |
445 } | |
446 utilization_reporting_task_runner_->PostTask( | |
447 FROM_HERE, | |
448 base::Bind(&VideoCaptureDeviceClient::AddEntryToBufferIdToFrameIdMap, | |
449 base::Unretained(this), buffer_id, frame_id)); | |
450 } | |
451 | |
452 void VideoCaptureDeviceClient::EraseEntryFromBufferIdToFrameIdMap( | |
453 int buffer_id_to_drop) { | |
454 if (utilization_reporting_task_runner_->BelongsToCurrentThread()) { | |
455 if (buffer_id_to_frame_id_map_.find(buffer_id_to_drop) != | |
456 buffer_id_to_frame_id_map_.end()) | |
457 buffer_id_to_frame_id_map_.erase(buffer_id_to_drop); | |
458 return; | |
459 } | |
460 utilization_reporting_task_runner_->PostTask( | |
461 FROM_HERE, | |
462 base::Bind(&VideoCaptureDeviceClient::EraseEntryFromBufferIdToFrameIdMap, | |
463 base::Unretained(this), buffer_id_to_drop)); | |
411 } | 464 } |
412 | 465 |
413 } // namespace media | 466 } // namespace media |
OLD | NEW |