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 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "media/base/bind_to_current_loop.h" | 21 #include "media/base/bind_to_current_loop.h" |
22 #include "media/base/media_switches.h" | 22 #include "media/base/media_switches.h" |
23 #include "media/base/video_capture_types.h" | 23 #include "media/base/video_capture_types.h" |
24 #include "media/base/video_frame.h" | 24 #include "media/base/video_frame.h" |
25 #include "third_party/libyuv/include/libyuv.h" | 25 #include "third_party/libyuv/include/libyuv.h" |
26 | 26 |
27 using media::VideoCaptureFormat; | 27 using media::VideoCaptureFormat; |
28 using media::VideoFrame; | 28 using media::VideoFrame; |
29 using media::VideoFrameMetadata; | 29 using media::VideoFrameMetadata; |
30 | 30 |
| 31 namespace { |
| 32 |
| 33 bool isFormatSupported(media::VideoPixelFormat pixel_format) { |
| 34 // Currently, only I420, Y8 and Y16 pixel formats are supported. |
| 35 return (pixel_format == media::PIXEL_FORMAT_I420 || |
| 36 pixel_format == media::PIXEL_FORMAT_Y8 || |
| 37 pixel_format == media::PIXEL_FORMAT_Y16); |
| 38 } |
| 39 } |
| 40 |
31 namespace content { | 41 namespace content { |
32 | 42 |
33 // Class combining a Client::Buffer interface implementation and a pool buffer | 43 // Class combining a Client::Buffer interface implementation and a pool buffer |
34 // implementation to guarantee proper cleanup on destruction on our side. | 44 // implementation to guarantee proper cleanup on destruction on our side. |
35 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { | 45 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { |
36 public: | 46 public: |
37 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, | 47 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, |
38 int buffer_id) | 48 int buffer_id) |
39 : id_(buffer_id), | 49 : id_(buffer_id), |
40 pool_(pool), | 50 pool_(pool), |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 external_jpeg_decoder_.reset(new VideoCaptureGpuJpegDecoder(base::Bind( | 111 external_jpeg_decoder_.reset(new VideoCaptureGpuJpegDecoder(base::Bind( |
102 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, | 112 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, |
103 controller_))); | 113 controller_))); |
104 external_jpeg_decoder_->Initialize(); | 114 external_jpeg_decoder_->Initialize(); |
105 } | 115 } |
106 } | 116 } |
107 | 117 |
108 if (!frame_format.IsValid()) | 118 if (!frame_format.IsValid()) |
109 return; | 119 return; |
110 | 120 |
| 121 // The input |length| can be greater than the required buffer size because of |
| 122 // paddings and/or alignments, but it cannot be smaller. |
| 123 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); |
| 124 |
| 125 const bool useFullSize = |
| 126 frame_format.pixel_format == media::PIXEL_FORMAT_Y8 || |
| 127 frame_format.pixel_format == media::PIXEL_FORMAT_Y16; |
| 128 |
111 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 129 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
112 // bit decomposition of {width, height}, grabbing the odd and even parts. | 130 // bit decomposition of {width, height}, grabbing the odd and even parts. |
113 const int chopped_width = frame_format.frame_size.width() & 1; | 131 const int chopped_width = frame_format.frame_size.width() & 1; |
114 const int chopped_height = frame_format.frame_size.height() & 1; | 132 const int chopped_height = frame_format.frame_size.height() & 1; |
115 const int new_unrotated_width = frame_format.frame_size.width() & ~1; | 133 const int new_unrotated_width = (useFullSize) |
116 const int new_unrotated_height = frame_format.frame_size.height() & ~1; | 134 ? frame_format.frame_size.width() |
| 135 : (frame_format.frame_size.width() & ~1); |
| 136 const int new_unrotated_height = |
| 137 (useFullSize) ? frame_format.frame_size.height() |
| 138 : (frame_format.frame_size.height() & ~1); |
117 | 139 |
118 int destination_width = new_unrotated_width; | 140 int destination_width = new_unrotated_width; |
119 int destination_height = new_unrotated_height; | 141 int destination_height = new_unrotated_height; |
120 if (rotation == 90 || rotation == 270) | 142 if (rotation == 90 || rotation == 270) |
121 std::swap(destination_width, destination_height); | 143 std::swap(destination_width, destination_height); |
122 | 144 |
123 DCHECK_EQ(0, rotation % 90) | 145 DCHECK_EQ(0, rotation % 90) |
124 << " Rotation must be a multiple of 90, now: " << rotation; | 146 << " Rotation must be a multiple of 90, now: " << rotation; |
125 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | 147 libyuv::RotationMode rotation_mode = libyuv::kRotate0; |
126 if (rotation == 90) | 148 if (rotation == 90) |
127 rotation_mode = libyuv::kRotate90; | 149 rotation_mode = libyuv::kRotate90; |
128 else if (rotation == 180) | 150 else if (rotation == 180) |
129 rotation_mode = libyuv::kRotate180; | 151 rotation_mode = libyuv::kRotate180; |
130 else if (rotation == 270) | 152 else if (rotation == 270) |
131 rotation_mode = libyuv::kRotate270; | 153 rotation_mode = libyuv::kRotate270; |
132 | 154 |
133 const gfx::Size dimensions(destination_width, destination_height); | 155 const gfx::Size dimensions(destination_width, destination_height); |
134 const media::VideoPixelStorage output_pixel_storage = | 156 const media::VideoPixelStorage output_pixel_storage = |
135 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER | 157 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER |
136 : media::PIXEL_STORAGE_CPU; | 158 : media::PIXEL_STORAGE_CPU; |
137 uint8_t *y_plane_data, *u_plane_data, *v_plane_data; | 159 uint8_t *y_plane_data, *u_plane_data, *v_plane_data; |
| 160 |
| 161 if (frame_format.pixel_format == media::PIXEL_FORMAT_Y8 || |
| 162 frame_format.pixel_format == media::PIXEL_FORMAT_Y16) { |
| 163 std::unique_ptr<Buffer> buffer(ReserveOutputBuffer( |
| 164 dimensions, frame_format.pixel_format, output_pixel_storage)); |
| 165 if (!buffer.get()) { |
| 166 DLOG(WARNING) << "Failed to reserve output buffer:" |
| 167 << media::VideoPixelFormatToString( |
| 168 frame_format.pixel_format); |
| 169 return; |
| 170 } |
| 171 memcpy(buffer->data(), data, length); |
| 172 const VideoCaptureFormat output_format = |
| 173 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
| 174 frame_format.pixel_format, output_pixel_storage); |
| 175 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
| 176 timestamp); |
| 177 return; |
| 178 } |
| 179 |
138 std::unique_ptr<Buffer> buffer( | 180 std::unique_ptr<Buffer> buffer( |
139 ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data, | 181 ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data, |
140 &u_plane_data, &v_plane_data)); | 182 &u_plane_data, &v_plane_data)); |
141 #if DCHECK_IS_ON() | 183 #if DCHECK_IS_ON() |
142 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; | 184 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; |
143 if (dropped_frame_counter_ >= kMaxDroppedFrames) | 185 if (dropped_frame_counter_ >= kMaxDroppedFrames) |
144 OnError(FROM_HERE, "Too many frames dropped"); | 186 OnError(FROM_HERE, "Too many frames dropped"); |
145 #endif | 187 #endif |
146 // Failed to reserve I420 output buffer, so drop the frame. | 188 // Failed to reserve I420 output buffer, so drop the frame. |
147 if (!buffer.get()) | 189 if (!buffer.get()) |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 timestamp); | 306 timestamp); |
265 } | 307 } |
266 | 308 |
267 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 309 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
268 VideoCaptureDeviceClient::ReserveOutputBuffer( | 310 VideoCaptureDeviceClient::ReserveOutputBuffer( |
269 const gfx::Size& frame_size, | 311 const gfx::Size& frame_size, |
270 media::VideoPixelFormat pixel_format, | 312 media::VideoPixelFormat pixel_format, |
271 media::VideoPixelStorage pixel_storage) { | 313 media::VideoPixelStorage pixel_storage) { |
272 DCHECK_GT(frame_size.width(), 0); | 314 DCHECK_GT(frame_size.width(), 0); |
273 DCHECK_GT(frame_size.height(), 0); | 315 DCHECK_GT(frame_size.height(), 0); |
274 // Currently, only I420 pixel format is supported. | 316 DCHECK(isFormatSupported(pixel_format)); |
275 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); | |
276 | 317 |
277 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if | 318 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
278 // it's a ShMem GMB or a DmaBuf GMB. | 319 // it's a ShMem GMB or a DmaBuf GMB. |
279 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 320 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
280 const int buffer_id = buffer_pool_->ReserveForProducer( | 321 const int buffer_id = buffer_pool_->ReserveForProducer( |
281 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); | 322 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); |
282 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { | 323 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { |
283 BrowserThread::PostTask(BrowserThread::IO, | 324 BrowserThread::PostTask(BrowserThread::IO, |
284 FROM_HERE, | 325 FROM_HERE, |
285 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, | 326 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, |
286 controller_, buffer_id_to_drop)); | 327 controller_, buffer_id_to_drop)); |
287 } | 328 } |
288 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 329 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
289 return nullptr; | 330 return nullptr; |
290 return base::WrapUnique<Buffer>( | 331 return base::WrapUnique<Buffer>( |
291 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 332 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
292 } | 333 } |
293 | 334 |
294 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 335 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
295 std::unique_ptr<Buffer> buffer, | 336 std::unique_ptr<Buffer> buffer, |
296 const VideoCaptureFormat& frame_format, | 337 const VideoCaptureFormat& frame_format, |
297 base::TimeTicks reference_time, | 338 base::TimeTicks reference_time, |
298 base::TimeDelta timestamp) { | 339 base::TimeDelta timestamp) { |
299 // Currently, only I420 pixel format is supported. | 340 DCHECK(isFormatSupported(frame_format.pixel_format)); |
300 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format); | |
301 | 341 |
302 scoped_refptr<VideoFrame> frame; | 342 scoped_refptr<VideoFrame> frame; |
303 switch (frame_format.pixel_storage) { | 343 switch (frame_format.pixel_storage) { |
304 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { | 344 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { |
| 345 DCHECK(isFormatSupported(frame_format.pixel_format)); |
305 // Create a VideoFrame to set the correct storage_type and pixel_format. | 346 // Create a VideoFrame to set the correct storage_type and pixel_format. |
306 gfx::GpuMemoryBufferHandle handle; | 347 gfx::GpuMemoryBufferHandle handle; |
307 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers( | 348 frame = |
308 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 349 (frame_format.pixel_format == media::PIXEL_FORMAT_I420) |
309 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0, | 350 ? VideoFrame::WrapExternalYuvGpuMemoryBuffers( |
310 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kYPlane)), | 351 media::PIXEL_FORMAT_I420, frame_format.frame_size, |
311 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kUPlane)), | 352 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
312 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kVPlane)), | 353 0, 0, 0, reinterpret_cast<uint8_t*>( |
313 handle, handle, handle, timestamp); | 354 buffer->data(media::VideoFrame::kYPlane)), |
| 355 reinterpret_cast<uint8_t*>( |
| 356 buffer->data(media::VideoFrame::kUPlane)), |
| 357 reinterpret_cast<uint8_t*>( |
| 358 buffer->data(media::VideoFrame::kVPlane)), |
| 359 handle, handle, handle, timestamp) |
| 360 : VideoFrame::WrapExternalGpuMemoryBuffer( |
| 361 frame_format.pixel_format, frame_format.frame_size, |
| 362 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
| 363 reinterpret_cast<uint8_t*>(buffer->data()), handle, |
| 364 timestamp); |
314 break; | 365 break; |
315 } | 366 } |
316 case media::PIXEL_STORAGE_CPU: | 367 case media::PIXEL_STORAGE_CPU: |
317 frame = VideoFrame::WrapExternalSharedMemory( | 368 frame = VideoFrame::WrapExternalSharedMemory( |
318 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 369 frame_format.pixel_format, frame_format.frame_size, |
319 gfx::Rect(frame_format.frame_size), frame_format.frame_size, | 370 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
320 reinterpret_cast<uint8_t*>(buffer->data()), | 371 reinterpret_cast<uint8_t*>(buffer->data()), |
321 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, | 372 VideoFrame::AllocationSize(frame_format.pixel_format, |
322 frame_format.frame_size), | 373 frame_format.frame_size), |
323 base::SharedMemory::NULLHandle(), 0u, timestamp); | 374 base::SharedMemory::NULLHandle(), 0u, timestamp); |
324 break; | 375 break; |
325 } | 376 } |
326 if (!frame) | 377 if (!frame) |
327 return; | 378 return; |
328 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 379 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
329 frame_format.frame_rate); | 380 frame_format.frame_rate); |
330 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 381 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
331 reference_time); | 382 reference_time); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); | 472 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); |
422 *v_plane_data = | 473 *v_plane_data = |
423 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); | 474 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); |
424 return buffer; | 475 return buffer; |
425 } | 476 } |
426 NOTREACHED(); | 477 NOTREACHED(); |
427 return std::unique_ptr<Buffer>(); | 478 return std::unique_ptr<Buffer>(); |
428 } | 479 } |
429 | 480 |
430 } // namespace content | 481 } // namespace content |
OLD | NEW |