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

Side by Side Diff: content/browser/renderer_host/media/video_capture_device_client.cc

Issue 2121043002: 16 bpp video stream capture, render and WebGL usage - Realsense R200 & SR300 support. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tests: cc, skcanvas_video_renderer, wrtcrecorder... Fake capture supports Y16. 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 "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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698