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 10 matching lines...) Expand all Loading... |
21 #include "media/capture/video/video_capture_buffer_handle.h" | 21 #include "media/capture/video/video_capture_buffer_handle.h" |
22 #include "media/capture/video/video_capture_buffer_pool.h" | 22 #include "media/capture/video/video_capture_buffer_pool.h" |
23 #include "media/capture/video/video_capture_jpeg_decoder.h" | 23 #include "media/capture/video/video_capture_jpeg_decoder.h" |
24 #include "media/capture/video/video_frame_receiver.h" | 24 #include "media/capture/video/video_frame_receiver.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 and Y16 pixel formats are supported. |
| 35 return (pixel_format == media::PIXEL_FORMAT_I420 || |
| 36 pixel_format == media::PIXEL_FORMAT_Y16); |
| 37 } |
| 38 } |
| 39 |
31 namespace media { | 40 namespace media { |
32 | 41 |
33 // Class combining a Client::Buffer interface implementation and a pool buffer | 42 // Class combining a Client::Buffer interface implementation and a pool buffer |
34 // implementation to guarantee proper cleanup on destruction on our side. | 43 // implementation to guarantee proper cleanup on destruction on our side. |
35 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { | 44 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { |
36 public: | 45 public: |
37 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, | 46 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, |
38 int buffer_id) | 47 int buffer_id) |
39 : id_(buffer_id), | 48 : id_(buffer_id), |
40 pool_(pool), | 49 pool_(pool), |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 !external_jpeg_decoder_initialized_) { | 108 !external_jpeg_decoder_initialized_) { |
100 external_jpeg_decoder_initialized_ = true; | 109 external_jpeg_decoder_initialized_ = true; |
101 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); | 110 external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); |
102 external_jpeg_decoder_->Initialize(); | 111 external_jpeg_decoder_->Initialize(); |
103 } | 112 } |
104 } | 113 } |
105 | 114 |
106 if (!frame_format.IsValid()) | 115 if (!frame_format.IsValid()) |
107 return; | 116 return; |
108 | 117 |
| 118 // The input |length| can be greater than the required buffer size because of |
| 119 // paddings and/or alignments, but it cannot be smaller. |
| 120 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); |
| 121 |
| 122 const bool useFullSize = frame_format.pixel_format == media::PIXEL_FORMAT_Y16; |
| 123 |
109 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest | 124 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest |
110 // bit decomposition of {width, height}, grabbing the odd and even parts. | 125 // bit decomposition of {width, height}, grabbing the odd and even parts. |
111 const int chopped_width = frame_format.frame_size.width() & 1; | 126 const int chopped_width = frame_format.frame_size.width() & 1; |
112 const int chopped_height = frame_format.frame_size.height() & 1; | 127 const int chopped_height = frame_format.frame_size.height() & 1; |
113 const int new_unrotated_width = frame_format.frame_size.width() & ~1; | 128 const int new_unrotated_width = (useFullSize) |
114 const int new_unrotated_height = frame_format.frame_size.height() & ~1; | 129 ? frame_format.frame_size.width() |
| 130 : (frame_format.frame_size.width() & ~1); |
| 131 const int new_unrotated_height = |
| 132 (useFullSize) ? frame_format.frame_size.height() |
| 133 : (frame_format.frame_size.height() & ~1); |
115 | 134 |
116 int destination_width = new_unrotated_width; | 135 int destination_width = new_unrotated_width; |
117 int destination_height = new_unrotated_height; | 136 int destination_height = new_unrotated_height; |
118 if (rotation == 90 || rotation == 270) | 137 if (rotation == 90 || rotation == 270) |
119 std::swap(destination_width, destination_height); | 138 std::swap(destination_width, destination_height); |
120 | 139 |
121 DCHECK_EQ(0, rotation % 90) << " Rotation must be a multiple of 90, now: " | 140 DCHECK_EQ(0, rotation % 90) << " Rotation must be a multiple of 90, now: " |
122 << rotation; | 141 << rotation; |
123 libyuv::RotationMode rotation_mode = libyuv::kRotate0; | 142 libyuv::RotationMode rotation_mode = libyuv::kRotate0; |
124 if (rotation == 90) | 143 if (rotation == 90) |
125 rotation_mode = libyuv::kRotate90; | 144 rotation_mode = libyuv::kRotate90; |
126 else if (rotation == 180) | 145 else if (rotation == 180) |
127 rotation_mode = libyuv::kRotate180; | 146 rotation_mode = libyuv::kRotate180; |
128 else if (rotation == 270) | 147 else if (rotation == 270) |
129 rotation_mode = libyuv::kRotate270; | 148 rotation_mode = libyuv::kRotate270; |
130 | 149 |
131 const gfx::Size dimensions(destination_width, destination_height); | 150 const gfx::Size dimensions(destination_width, destination_height); |
132 const media::VideoPixelStorage output_pixel_storage = | 151 const media::VideoPixelStorage output_pixel_storage = |
133 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER | 152 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER |
134 : media::PIXEL_STORAGE_CPU; | 153 : media::PIXEL_STORAGE_CPU; |
135 uint8_t *y_plane_data, *u_plane_data, *v_plane_data; | 154 uint8_t* y_plane_data = 0; |
| 155 uint8_t* u_plane_data = 0; |
| 156 uint8_t* v_plane_data = 0; |
| 157 |
136 std::unique_ptr<Buffer> buffer( | 158 std::unique_ptr<Buffer> buffer( |
137 ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data, | 159 (frame_format.pixel_format == media::PIXEL_FORMAT_Y16) |
138 &u_plane_data, &v_plane_data)); | 160 ? ReserveOutputBuffer(dimensions, frame_format.pixel_format, |
| 161 output_pixel_storage) |
| 162 : ReserveI420OutputBuffer(dimensions, output_pixel_storage, |
| 163 &y_plane_data, &u_plane_data, |
| 164 &v_plane_data)); |
139 #if DCHECK_IS_ON() | 165 #if DCHECK_IS_ON() |
140 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; | 166 dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; |
141 if (dropped_frame_counter_ >= kMaxDroppedFrames) | 167 if (dropped_frame_counter_ >= kMaxDroppedFrames) |
142 OnError(FROM_HERE, "Too many frames dropped"); | 168 OnError(FROM_HERE, "Too many frames dropped"); |
143 #endif | 169 #endif |
144 // Failed to reserve I420 output buffer, so drop the frame. | 170 // Failed to reserve output buffer, so drop the frame. |
145 if (!buffer.get()) | 171 if (!buffer.get()) |
146 return; | 172 return; |
147 | 173 |
| 174 if (frame_format.pixel_format == media::PIXEL_FORMAT_Y16) { |
| 175 memcpy(buffer->data(), data, length); |
| 176 const VideoCaptureFormat output_format = |
| 177 VideoCaptureFormat(dimensions, frame_format.frame_rate, |
| 178 frame_format.pixel_format, output_pixel_storage); |
| 179 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, |
| 180 timestamp); |
| 181 return; |
| 182 } |
| 183 |
148 const int yplane_stride = dimensions.width(); | 184 const int yplane_stride = dimensions.width(); |
149 const int uv_plane_stride = yplane_stride / 2; | 185 const int uv_plane_stride = yplane_stride / 2; |
150 int crop_x = 0; | 186 int crop_x = 0; |
151 int crop_y = 0; | 187 int crop_y = 0; |
152 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; | 188 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; |
153 | 189 |
154 bool flip = false; | 190 bool flip = false; |
155 switch (frame_format.pixel_format) { | 191 switch (frame_format.pixel_format) { |
156 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. | 192 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. |
157 break; | 193 break; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 timestamp); | 289 timestamp); |
254 } | 290 } |
255 | 291 |
256 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> | 292 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> |
257 VideoCaptureDeviceClient::ReserveOutputBuffer( | 293 VideoCaptureDeviceClient::ReserveOutputBuffer( |
258 const gfx::Size& frame_size, | 294 const gfx::Size& frame_size, |
259 media::VideoPixelFormat pixel_format, | 295 media::VideoPixelFormat pixel_format, |
260 media::VideoPixelStorage pixel_storage) { | 296 media::VideoPixelStorage pixel_storage) { |
261 DCHECK_GT(frame_size.width(), 0); | 297 DCHECK_GT(frame_size.width(), 0); |
262 DCHECK_GT(frame_size.height(), 0); | 298 DCHECK_GT(frame_size.height(), 0); |
263 // Currently, only I420 pixel format is supported. | 299 DCHECK(isFormatSupported(pixel_format)); |
264 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format); | |
265 | 300 |
266 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if | 301 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if |
267 // it's a ShMem GMB or a DmaBuf GMB. | 302 // it's a ShMem GMB or a DmaBuf GMB. |
268 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; | 303 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; |
269 const int buffer_id = buffer_pool_->ReserveForProducer( | 304 const int buffer_id = buffer_pool_->ReserveForProducer( |
270 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); | 305 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); |
271 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) | 306 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) |
272 receiver_->OnBufferDestroyed(buffer_id_to_drop); | 307 receiver_->OnBufferDestroyed(buffer_id_to_drop); |
273 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 308 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
274 return nullptr; | 309 return nullptr; |
275 return base::WrapUnique<Buffer>( | 310 return base::WrapUnique<Buffer>( |
276 new AutoReleaseBuffer(buffer_pool_, buffer_id)); | 311 new AutoReleaseBuffer(buffer_pool_, buffer_id)); |
277 } | 312 } |
278 | 313 |
279 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( | 314 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( |
280 std::unique_ptr<Buffer> buffer, | 315 std::unique_ptr<Buffer> buffer, |
281 const VideoCaptureFormat& frame_format, | 316 const VideoCaptureFormat& frame_format, |
282 base::TimeTicks reference_time, | 317 base::TimeTicks reference_time, |
283 base::TimeDelta timestamp) { | 318 base::TimeDelta timestamp) { |
284 // Currently, only I420 pixel format is supported. | 319 DCHECK(isFormatSupported(frame_format.pixel_format)); |
285 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format); | |
286 | 320 |
287 scoped_refptr<VideoFrame> frame; | 321 scoped_refptr<VideoFrame> frame; |
288 switch (frame_format.pixel_storage) { | 322 switch (frame_format.pixel_storage) { |
289 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { | 323 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { |
| 324 DCHECK(isFormatSupported(frame_format.pixel_format)); |
290 // Create a VideoFrame to set the correct storage_type and pixel_format. | 325 // Create a VideoFrame to set the correct storage_type and pixel_format. |
291 gfx::GpuMemoryBufferHandle handle; | 326 gfx::GpuMemoryBufferHandle handle; |
292 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers( | 327 frame = |
293 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 328 (frame_format.pixel_format == media::PIXEL_FORMAT_I420) |
294 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0, | 329 ? VideoFrame::WrapExternalYuvGpuMemoryBuffers( |
295 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kYPlane)), | 330 media::PIXEL_FORMAT_I420, frame_format.frame_size, |
296 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kUPlane)), | 331 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
297 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kVPlane)), | 332 0, 0, 0, reinterpret_cast<uint8_t*>( |
298 handle, handle, handle, timestamp); | 333 buffer->data(media::VideoFrame::kYPlane)), |
| 334 reinterpret_cast<uint8_t*>( |
| 335 buffer->data(media::VideoFrame::kUPlane)), |
| 336 reinterpret_cast<uint8_t*>( |
| 337 buffer->data(media::VideoFrame::kVPlane)), |
| 338 handle, handle, handle, timestamp) |
| 339 : VideoFrame::WrapExternalGpuMemoryBuffer( |
| 340 frame_format.pixel_format, frame_format.frame_size, |
| 341 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
| 342 reinterpret_cast<uint8_t*>(buffer->data()), handle, |
| 343 timestamp); |
299 break; | 344 break; |
300 } | 345 } |
301 case media::PIXEL_STORAGE_CPU: | 346 case media::PIXEL_STORAGE_CPU: |
302 frame = VideoFrame::WrapExternalSharedMemory( | 347 frame = VideoFrame::WrapExternalSharedMemory( |
303 media::PIXEL_FORMAT_I420, frame_format.frame_size, | 348 frame_format.pixel_format, frame_format.frame_size, |
304 gfx::Rect(frame_format.frame_size), frame_format.frame_size, | 349 gfx::Rect(frame_format.frame_size), frame_format.frame_size, |
305 reinterpret_cast<uint8_t*>(buffer->data()), | 350 reinterpret_cast<uint8_t*>(buffer->data()), |
306 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, | 351 VideoFrame::AllocationSize(frame_format.pixel_format, |
307 frame_format.frame_size), | 352 frame_format.frame_size), |
308 base::SharedMemory::NULLHandle(), 0u, timestamp); | 353 base::SharedMemory::NULLHandle(), 0u, timestamp); |
309 break; | 354 break; |
310 } | 355 } |
311 if (!frame) | 356 if (!frame) |
312 return; | 357 return; |
313 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 358 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
314 frame_format.frame_rate); | 359 frame_format.frame_rate); |
315 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, | 360 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, |
316 reference_time); | 361 reference_time); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); | 441 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); |
397 *v_plane_data = | 442 *v_plane_data = |
398 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); | 443 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); |
399 return buffer; | 444 return buffer; |
400 } | 445 } |
401 NOTREACHED(); | 446 NOTREACHED(); |
402 return std::unique_ptr<Buffer>(); | 447 return std::unique_ptr<Buffer>(); |
403 } | 448 } |
404 | 449 |
405 } // namespace media | 450 } // namespace media |
OLD | NEW |