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

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: 8 bpp support added. R200 camera supported. Created 4 years, 5 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 }
41
31 namespace content { 42 namespace content {
32 43
33 // Class combining a Client::Buffer interface implementation and a pool buffer 44 // Class combining a Client::Buffer interface implementation and a pool buffer
34 // implementation to guarantee proper cleanup on destruction on our side. 45 // implementation to guarantee proper cleanup on destruction on our side.
35 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer { 46 class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer {
36 public: 47 public:
37 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, 48 AutoReleaseBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool,
38 int buffer_id) 49 int buffer_id)
39 : id_(buffer_id), 50 : id_(buffer_id),
40 pool_(pool), 51 pool_(pool),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 external_jpeg_decoder_.reset(new VideoCaptureGpuJpegDecoder(base::Bind( 112 external_jpeg_decoder_.reset(new VideoCaptureGpuJpegDecoder(base::Bind(
102 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread, 113 &VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread,
103 controller_))); 114 controller_)));
104 external_jpeg_decoder_->Initialize(); 115 external_jpeg_decoder_->Initialize();
105 } 116 }
106 } 117 }
107 118
108 if (!frame_format.IsValid()) 119 if (!frame_format.IsValid())
109 return; 120 return;
110 121
122 // The input |length| can be greater than the required buffer size because of
123 // paddings and/or alignments, but it cannot be smaller.
124 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize());
125
126 const bool useFullSize =
127 frame_format.pixel_format == media::PIXEL_FORMAT_Y8 ||
128 frame_format.pixel_format == media::PIXEL_FORMAT_Y16;
129
111 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest 130 // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest
112 // bit decomposition of {width, height}, grabbing the odd and even parts. 131 // bit decomposition of {width, height}, grabbing the odd and even parts.
113 const int chopped_width = frame_format.frame_size.width() & 1; 132 const int chopped_width = frame_format.frame_size.width() & 1;
114 const int chopped_height = frame_format.frame_size.height() & 1; 133 const int chopped_height = frame_format.frame_size.height() & 1;
115 const int new_unrotated_width = frame_format.frame_size.width() & ~1; 134 const int new_unrotated_width = (useFullSize)
116 const int new_unrotated_height = frame_format.frame_size.height() & ~1; 135 ? frame_format.frame_size.width()
136 : (frame_format.frame_size.width() & ~1);
137 const int new_unrotated_height = (useFullSize)
138 ? frame_format.frame_size.height()
139 : (frame_format.frame_size.height() & ~1);
117 140
118 int destination_width = new_unrotated_width; 141 int destination_width = new_unrotated_width;
119 int destination_height = new_unrotated_height; 142 int destination_height = new_unrotated_height;
120 if (rotation == 90 || rotation == 270) 143 if (rotation == 90 || rotation == 270)
121 std::swap(destination_width, destination_height); 144 std::swap(destination_width, destination_height);
122 145
123 DCHECK_EQ(0, rotation % 90) 146 DCHECK_EQ(0, rotation % 90)
124 << " Rotation must be a multiple of 90, now: " << rotation; 147 << " Rotation must be a multiple of 90, now: " << rotation;
125 libyuv::RotationMode rotation_mode = libyuv::kRotate0; 148 libyuv::RotationMode rotation_mode = libyuv::kRotate0;
126 if (rotation == 90) 149 if (rotation == 90)
127 rotation_mode = libyuv::kRotate90; 150 rotation_mode = libyuv::kRotate90;
128 else if (rotation == 180) 151 else if (rotation == 180)
129 rotation_mode = libyuv::kRotate180; 152 rotation_mode = libyuv::kRotate180;
130 else if (rotation == 270) 153 else if (rotation == 270)
131 rotation_mode = libyuv::kRotate270; 154 rotation_mode = libyuv::kRotate270;
132 155
133 const gfx::Size dimensions(destination_width, destination_height); 156 const gfx::Size dimensions(destination_width, destination_height);
134 const media::VideoPixelStorage output_pixel_storage = 157 const media::VideoPixelStorage output_pixel_storage =
135 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER 158 use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER
136 : media::PIXEL_STORAGE_CPU; 159 : media::PIXEL_STORAGE_CPU;
137 uint8_t *y_plane_data, *u_plane_data, *v_plane_data; 160 uint8_t *y_plane_data, *u_plane_data, *v_plane_data;
138 std::unique_ptr<Buffer> buffer( 161
139 ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data, 162 if (frame_format.pixel_format == media::PIXEL_FORMAT_Y8 ||
140 &u_plane_data, &v_plane_data)); 163 frame_format.pixel_format == media::PIXEL_FORMAT_Y16) {
164 std::unique_ptr<Buffer> buffer(ReserveOutputBuffer(dimensions,
165 frame_format.pixel_format, output_pixel_storage));
166 if (!buffer.get()) {
167 DLOG(WARNING)
168 << "Failed to reserve output buffer:"
169 << media::VideoPixelFormatToString(frame_format.pixel_format);
170 return;
171 }
172 memcpy(buffer->data(), data, length);
aleksandar.stojiljkovic 2016/07/11 22:15:14 normalized unsigned short -| half_float conversion
173 const VideoCaptureFormat output_format = VideoCaptureFormat(
174 dimensions, frame_format.frame_rate,
175 frame_format.pixel_format, output_pixel_storage);
176 OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time,
177 timestamp);
178 return;
179 }
180
181 std::unique_ptr<Buffer> buffer(ReserveI420OutputBuffer(dimensions,
182 output_pixel_storage, &y_plane_data, &u_plane_data, &v_plane_data));
141 if (!buffer.get()) { 183 if (!buffer.get()) {
142 DLOG(WARNING) << "Failed to reserve I420 output buffer."; 184 DLOG(WARNING) << "Failed to reserve I420 output buffer.";
143 return; 185 return;
144 } 186 }
145 187
146 const int yplane_stride = dimensions.width(); 188 const int yplane_stride = dimensions.width();
147 const int uv_plane_stride = yplane_stride / 2; 189 const int uv_plane_stride = yplane_stride / 2;
148 int crop_x = 0; 190 int crop_x = 0;
149 int crop_y = 0; 191 int crop_y = 0;
150 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; 192 libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 case media::PIXEL_FORMAT_ARGB: 248 case media::PIXEL_FORMAT_ARGB:
207 origin_colorspace = libyuv::FOURCC_ARGB; 249 origin_colorspace = libyuv::FOURCC_ARGB;
208 break; 250 break;
209 case media::PIXEL_FORMAT_MJPEG: 251 case media::PIXEL_FORMAT_MJPEG:
210 origin_colorspace = libyuv::FOURCC_MJPG; 252 origin_colorspace = libyuv::FOURCC_MJPG;
211 break; 253 break;
212 default: 254 default:
213 NOTREACHED(); 255 NOTREACHED();
214 } 256 }
215 257
216 // The input |length| can be greater than the required buffer size because of
217 // paddings and/or alignments, but it cannot be smaller.
218 DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize());
219
220 if (external_jpeg_decoder_) { 258 if (external_jpeg_decoder_) {
221 const VideoCaptureGpuJpegDecoder::STATUS status = 259 const VideoCaptureGpuJpegDecoder::STATUS status =
222 external_jpeg_decoder_->GetStatus(); 260 external_jpeg_decoder_->GetStatus();
223 if (status == VideoCaptureGpuJpegDecoder::FAILED) { 261 if (status == VideoCaptureGpuJpegDecoder::FAILED) {
224 external_jpeg_decoder_.reset(); 262 external_jpeg_decoder_.reset();
225 } else if (status == VideoCaptureGpuJpegDecoder::INIT_PASSED && 263 } else if (status == VideoCaptureGpuJpegDecoder::INIT_PASSED &&
226 frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && 264 frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG &&
227 rotation == 0 && !flip) { 265 rotation == 0 && !flip) {
228 external_jpeg_decoder_->DecodeCapturedData(data, length, frame_format, 266 external_jpeg_decoder_->DecodeCapturedData(data, length, frame_format,
229 reference_time, timestamp, 267 reference_time, timestamp,
(...skipping 30 matching lines...) Expand all
260 timestamp); 298 timestamp);
261 } 299 }
262 300
263 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> 301 std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
264 VideoCaptureDeviceClient::ReserveOutputBuffer( 302 VideoCaptureDeviceClient::ReserveOutputBuffer(
265 const gfx::Size& frame_size, 303 const gfx::Size& frame_size,
266 media::VideoPixelFormat pixel_format, 304 media::VideoPixelFormat pixel_format,
267 media::VideoPixelStorage pixel_storage) { 305 media::VideoPixelStorage pixel_storage) {
268 DCHECK_GT(frame_size.width(), 0); 306 DCHECK_GT(frame_size.width(), 0);
269 DCHECK_GT(frame_size.height(), 0); 307 DCHECK_GT(frame_size.height(), 0);
270 // Currently, only I420 pixel format is supported. 308 DCHECK(isFormatSupported(pixel_format));
271 DCHECK_EQ(media::PIXEL_FORMAT_I420, pixel_format);
272 309
273 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if 310 // TODO(mcasas): For PIXEL_STORAGE_GPUMEMORYBUFFER, find a way to indicate if
274 // it's a ShMem GMB or a DmaBuf GMB. 311 // it's a ShMem GMB or a DmaBuf GMB.
275 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; 312 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
276 const int buffer_id = buffer_pool_->ReserveForProducer( 313 const int buffer_id = buffer_pool_->ReserveForProducer(
277 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop); 314 frame_size, pixel_format, pixel_storage, &buffer_id_to_drop);
278 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { 315 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
279 BrowserThread::PostTask(BrowserThread::IO, 316 BrowserThread::PostTask(BrowserThread::IO,
280 FROM_HERE, 317 FROM_HERE,
281 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread, 318 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
282 controller_, buffer_id_to_drop)); 319 controller_, buffer_id_to_drop));
283 } 320 }
284 if (buffer_id == VideoCaptureBufferPool::kInvalidId) 321 if (buffer_id == VideoCaptureBufferPool::kInvalidId)
285 return nullptr; 322 return nullptr;
286 return base::WrapUnique<Buffer>( 323 return base::WrapUnique<Buffer>(
287 new AutoReleaseBuffer(buffer_pool_, buffer_id)); 324 new AutoReleaseBuffer(buffer_pool_, buffer_id));
288 } 325 }
289 326
290 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( 327 void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
291 std::unique_ptr<Buffer> buffer, 328 std::unique_ptr<Buffer> buffer,
292 const VideoCaptureFormat& frame_format, 329 const VideoCaptureFormat& frame_format,
293 base::TimeTicks reference_time, 330 base::TimeTicks reference_time,
294 base::TimeDelta timestamp) { 331 base::TimeDelta timestamp) {
295 // Currently, only I420 pixel format is supported. 332 DCHECK(isFormatSupported(frame_format.pixel_format));
296 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format);
297 333
298 scoped_refptr<VideoFrame> frame; 334 scoped_refptr<VideoFrame> frame;
299 switch (frame_format.pixel_storage) { 335 switch (frame_format.pixel_storage) {
300 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: { 336 case media::PIXEL_STORAGE_GPUMEMORYBUFFER: {
337 // TODO(astojilj) Check Y8 and Y16 support.
338 DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format);
301 // Create a VideoFrame to set the correct storage_type and pixel_format. 339 // Create a VideoFrame to set the correct storage_type and pixel_format.
302 gfx::GpuMemoryBufferHandle handle; 340 gfx::GpuMemoryBufferHandle handle;
303 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers( 341 frame = VideoFrame::WrapExternalYuvGpuMemoryBuffers(
304 media::PIXEL_FORMAT_I420, frame_format.frame_size, 342 media::PIXEL_FORMAT_I420, frame_format.frame_size,
305 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0, 343 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 0, 0, 0,
306 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kYPlane)), 344 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kYPlane)),
307 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kUPlane)), 345 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kUPlane)),
308 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kVPlane)), 346 reinterpret_cast<uint8_t*>(buffer->data(media::VideoFrame::kVPlane)),
309 handle, handle, handle, timestamp); 347 handle, handle, handle, timestamp);
310 break; 348 break;
311 } 349 }
312 case media::PIXEL_STORAGE_CPU: 350 case media::PIXEL_STORAGE_CPU:
313 frame = VideoFrame::WrapExternalSharedMemory( 351 frame = VideoFrame::WrapExternalSharedMemory(
314 media::PIXEL_FORMAT_I420, frame_format.frame_size, 352 frame_format.pixel_format, frame_format.frame_size,
315 gfx::Rect(frame_format.frame_size), frame_format.frame_size, 353 gfx::Rect(frame_format.frame_size), frame_format.frame_size,
316 reinterpret_cast<uint8_t*>(buffer->data()), 354 reinterpret_cast<uint8_t*>(buffer->data()),
317 VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, 355 VideoFrame::AllocationSize(frame_format.pixel_format,
318 frame_format.frame_size), 356 frame_format.frame_size),
319 base::SharedMemory::NULLHandle(), 0u, timestamp); 357 base::SharedMemory::NULLHandle(), 0u, timestamp);
320 break; 358 break;
321 } 359 }
322 if (!frame) 360 if (!frame)
323 return; 361 return;
324 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, 362 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
325 frame_format.frame_rate); 363 frame_format.frame_rate);
326 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, 364 frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
327 reference_time); 365 reference_time);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane)); 455 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kUPlane));
418 *v_plane_data = 456 *v_plane_data =
419 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane)); 457 reinterpret_cast<uint8_t*>(buffer->data(VideoFrame::kVPlane));
420 return buffer; 458 return buffer;
421 } 459 }
422 NOTREACHED(); 460 NOTREACHED();
423 return std::unique_ptr<Buffer>(); 461 return std::unique_ptr<Buffer>();
424 } 462 }
425 463
426 } // namespace content 464 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698