Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: media/capture/video/video_capture_device_client.cc

Issue 2398463003: 16 bit capture and GPU&CPU memory buffer support.
Patch Set: fixes. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/capture/video/linux/v4l2_capture_delegate.cc ('k') | media/capture/video/video_capture_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698