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

Side by Side Diff: media/video/gpu_memory_buffer_video_frame_pool.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: gpu memory buffers, reinterpret RG8->R32F on GPU, Linux and ChromeOS support added. Created 4 years, 3 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/video/gpu_memory_buffer_video_frame_pool.h" 5 #include "media/video/gpu_memory_buffer_video_frame_pool.h"
6 6
7 #include <GLES2/gl2.h> 7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h> 8 #include <GLES2/gl2ext.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <stdint.h> 10 #include <stdint.h>
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 struct PlaneResource { 77 struct PlaneResource {
78 gfx::Size size; 78 gfx::Size size;
79 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; 79 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
80 unsigned texture_id = 0u; 80 unsigned texture_id = 0u;
81 unsigned image_id = 0u; 81 unsigned image_id = 0u;
82 gpu::Mailbox mailbox; 82 gpu::Mailbox mailbox;
83 }; 83 };
84 84
85 // All the resources needed to compose a frame. 85 // All the resources needed to compose a frame.
86 struct FrameResources { 86 struct FrameResources {
87 explicit FrameResources(const gfx::Size& size) : size(size) {} 87 explicit FrameResources(const gfx::Size& size, VideoPixelFormat format)
88 : size(size), format(format) {}
88 void SetIsInUse(bool in_use) { in_use_ = in_use; } 89 void SetIsInUse(bool in_use) { in_use_ = in_use; }
89 bool IsInUse() const { return in_use_; } 90 bool IsInUse() const { return in_use_; }
90 91
91 const gfx::Size size; 92 const gfx::Size size;
93 VideoPixelFormat format;
92 PlaneResource plane_resources[VideoFrame::kMaxPlanes]; 94 PlaneResource plane_resources[VideoFrame::kMaxPlanes];
93 95
94 private: 96 private:
95 bool in_use_ = true; 97 bool in_use_ = true;
96 }; 98 };
97 99
98 // Copy |video_frame| data into |frame_resouces| 100 // Copy |video_frame| data into |frame_resouces|
99 // and calls |done| when done. 101 // and calls |done| when done.
100 void CopyVideoFrameToGpuMemoryBuffers( 102 void CopyVideoFrameToGpuMemoryBuffers(
101 const scoped_refptr<VideoFrame>& video_frame, 103 const scoped_refptr<VideoFrame>& video_frame,
(...skipping 10 matching lines...) Expand all
112 // This has to be run on |media_task_runner_| where |frame_ready_cb| will also 114 // This has to be run on |media_task_runner_| where |frame_ready_cb| will also
113 // be run. 115 // be run.
114 void BindAndCreateMailboxesHardwareFrameResources( 116 void BindAndCreateMailboxesHardwareFrameResources(
115 const scoped_refptr<VideoFrame>& video_frame, 117 const scoped_refptr<VideoFrame>& video_frame,
116 FrameResources* frame_resources, 118 FrameResources* frame_resources,
117 const FrameReadyCB& frame_ready_cb); 119 const FrameReadyCB& frame_ready_cb);
118 120
119 // Return true if |resources| can be used to represent a frame for 121 // Return true if |resources| can be used to represent a frame for
120 // specific |format| and |size|. 122 // specific |format| and |size|.
121 static bool AreFrameResourcesCompatible(const FrameResources* resources, 123 static bool AreFrameResourcesCompatible(const FrameResources* resources,
122 const gfx::Size& size) { 124 const gfx::Size& size,
123 return size == resources->size; 125 VideoPixelFormat format) {
126 return size == resources->size && format == resources->format;
124 } 127 }
125 128
126 // Get the resources needed for a frame out of the pool, or create them if 129 // Get the resources needed for a frame out of the pool, or create them if
127 // necessary. 130 // necessary.
128 // This also drops the LRU resources that can't be reuse for this frame. 131 // This also drops the LRU resources that can't be reuse for this frame.
129 FrameResources* GetOrCreateFrameResources(const gfx::Size& size, 132 FrameResources* GetOrCreateFrameResources(const gfx::Size& size,
130 VideoPixelFormat format); 133 VideoPixelFormat format);
131 134
132 // Callback called when a VideoFrame generated with GetFrameResources is no 135 // Callback called when a VideoFrame generated with GetFrameResources is no
133 // longer referenced. 136 // longer referenced.
(...skipping 12 matching lines...) Expand all
146 scoped_refptr<base::TaskRunner> worker_task_runner_; 149 scoped_refptr<base::TaskRunner> worker_task_runner_;
147 150
148 // Interface to GPU related operations. 151 // Interface to GPU related operations.
149 GpuVideoAcceleratorFactories* gpu_factories_; 152 GpuVideoAcceleratorFactories* gpu_factories_;
150 153
151 // Pool of resources. 154 // Pool of resources.
152 std::list<FrameResources*> resources_pool_; 155 std::list<FrameResources*> resources_pool_;
153 156
154 // TODO(dcastagna): change the following type from VideoPixelFormat to 157 // TODO(dcastagna): change the following type from VideoPixelFormat to
155 // BufferFormat. 158 // BufferFormat.
159 // Pixel format of the hardware video frames for I420 and YV12 video.
156 VideoPixelFormat output_format_; 160 VideoPixelFormat output_format_;
157 161
162 // If texture_rg is supported, gpu memory buffers can be used for R8 and RG8.
163 bool texture_rg_available_ = false;
164 bool texture_rg_available_initialized_ = false;
165
158 DISALLOW_COPY_AND_ASSIGN(PoolImpl); 166 DISALLOW_COPY_AND_ASSIGN(PoolImpl);
159 }; 167 };
160 168
161 namespace { 169 namespace {
162 170
163 // VideoFrame copies to GpuMemoryBuffers will be split in copies where the 171 // VideoFrame copies to GpuMemoryBuffers will be split in copies where the
164 // output size is |kBytesPerCopyTarget| bytes and run in parallel. 172 // output size is |kBytesPerCopyTarget| bytes and run in parallel.
165 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB 173 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB
166 174
167 // Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat
168 // and plane.
169 gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) {
170 switch (format) {
171 case PIXEL_FORMAT_I420:
172 DCHECK_LE(plane, 2u);
173 return gfx::BufferFormat::R_8;
174 case PIXEL_FORMAT_NV12:
175 DCHECK_LE(plane, 1u);
176 return gfx::BufferFormat::YUV_420_BIPLANAR;
177 case PIXEL_FORMAT_UYVY:
178 DCHECK_EQ(0u, plane);
179 return gfx::BufferFormat::UYVY_422;
180 default:
181 NOTREACHED();
182 return gfx::BufferFormat::BGRA_8888;
183 }
184 }
185
186 unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) { 175 unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) {
187 switch (format) { 176 switch (format) {
188 case PIXEL_FORMAT_I420: 177 case PIXEL_FORMAT_I420:
189 DCHECK_LE(plane, 2u); 178 DCHECK_LE(plane, 2u);
190 return GL_RED_EXT; 179 return GL_RED_EXT;
191 case PIXEL_FORMAT_NV12: 180 case PIXEL_FORMAT_NV12:
192 DCHECK_LE(plane, 1u); 181 DCHECK_LE(plane, 1u);
193 return GL_RGB_YCBCR_420V_CHROMIUM; 182 return GL_RGB_YCBCR_420V_CHROMIUM;
194 case PIXEL_FORMAT_UYVY: 183 case PIXEL_FORMAT_UYVY:
195 DCHECK_EQ(0u, plane); 184 DCHECK_EQ(0u, plane);
196 return GL_RGB_YCBCR_422_CHROMIUM; 185 return GL_RGB_YCBCR_422_CHROMIUM;
186 case PIXEL_FORMAT_Y8:
187 DCHECK_EQ(0u, plane);
188 return GL_RED_EXT;
189 case PIXEL_FORMAT_Y16:
190 DCHECK_EQ(0u, plane);
191 return GL_RG_EXT;
197 default: 192 default:
198 NOTREACHED(); 193 NOTREACHED();
199 return 0; 194 return 0;
200 } 195 }
201 } 196 }
202 197
203 // The number of output planes to be copied in each iteration. 198 // The number of output planes to be copied in each iteration.
204 size_t PlanesPerCopy(VideoPixelFormat format) { 199 size_t PlanesPerCopy(VideoPixelFormat format) {
205 switch (format) { 200 switch (format) {
206 case PIXEL_FORMAT_I420: 201 case PIXEL_FORMAT_I420:
207 case PIXEL_FORMAT_UYVY: 202 case PIXEL_FORMAT_UYVY:
203 case PIXEL_FORMAT_Y8:
204 case PIXEL_FORMAT_Y16:
208 return 1; 205 return 1;
209 case PIXEL_FORMAT_NV12: 206 case PIXEL_FORMAT_NV12:
210 return 2; 207 return 2;
211 default: 208 default:
212 NOTREACHED(); 209 NOTREACHED();
213 return 0; 210 return 0;
214 } 211 }
215 } 212 }
216 213
217 // The number of output rows to be copied in each iteration. 214 // The number of output rows to be copied in each iteration.
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), 300 first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
304 source_frame->stride(VideoFrame::kUPlane), 301 source_frame->stride(VideoFrame::kUPlane),
305 source_frame->visible_data(VideoFrame::kVPlane) + 302 source_frame->visible_data(VideoFrame::kVPlane) +
306 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), 303 first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
307 source_frame->stride(VideoFrame::kVPlane), 304 source_frame->stride(VideoFrame::kVPlane),
308 output + first_row * dest_stride, dest_stride, width, rows); 305 output + first_row * dest_stride, dest_stride, width, rows);
309 } 306 }
310 done.Run(); 307 done.Run();
311 } 308 }
312 309
310 void CopyRowsToGPUBuffer(int first_row,
311 int rows,
312 int width,
313 const scoped_refptr<VideoFrame>& source_frame,
314 uint8_t* output,
315 int dest_stride,
316 const base::Closure& done) {
317 int row_bytes = VideoFrame::RowBytes(0, source_frame->format(), width);
318 TRACE_EVENT2("media", "CopyRowsToGPUBuffer", "bytes_per_row", row_bytes,
319 "rows", rows);
320 if (output) {
321 DCHECK_NE(dest_stride, 0);
322 DCHECK_LE(row_bytes, std::abs(dest_stride));
323 const int source_stride = source_frame->stride(0);
324 const uint8_t* source =
325 source_frame->visible_data(0) + first_row * source_stride;
326 uint8_t* dest = output + first_row * dest_stride;
327 for (int i = 0; i < rows; ++i)
328 memcpy(dest + i * dest_stride, source + i * source_stride, row_bytes);
329 }
330 done.Run();
331 }
332
313 gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame, 333 gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame,
314 VideoPixelFormat output_format) { 334 VideoPixelFormat output_format) {
315 DCHECK(gfx::Rect(video_frame->coded_size()) 335 DCHECK(gfx::Rect(video_frame->coded_size())
316 .Contains(video_frame->visible_rect())); 336 .Contains(video_frame->visible_rect()));
317 DCHECK((video_frame->visible_rect().x() & 1) == 0); 337 DCHECK((video_frame->visible_rect().x() & 1) == 0);
318 gfx::Size output; 338 gfx::Size output;
319 switch (output_format) { 339 switch (output_format) {
320 case PIXEL_FORMAT_I420: 340 case PIXEL_FORMAT_I420:
321 case PIXEL_FORMAT_NV12: 341 case PIXEL_FORMAT_NV12:
322 DCHECK((video_frame->visible_rect().y() & 1) == 0); 342 DCHECK((video_frame->visible_rect().y() & 1) == 0);
323 output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, 343 output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1,
324 (video_frame->visible_rect().height() + 1) & ~1); 344 (video_frame->visible_rect().height() + 1) & ~1);
325 break; 345 break;
326 case PIXEL_FORMAT_UYVY: 346 case PIXEL_FORMAT_UYVY:
327 output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, 347 output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1,
328 video_frame->visible_rect().height()); 348 video_frame->visible_rect().height());
329 break; 349 break;
350 case PIXEL_FORMAT_Y8:
351 case PIXEL_FORMAT_Y16:
352 output = video_frame->visible_rect().size();
353 break;
330 default: 354 default:
331 NOTREACHED(); 355 NOTREACHED();
332 } 356 }
333 DCHECK(gfx::Rect(video_frame->coded_size()).Contains(gfx::Rect(output))); 357 DCHECK(gfx::Rect(video_frame->coded_size()).Contains(gfx::Rect(output)));
334 return output; 358 return output;
335 } 359 }
336 } // unnamed namespace 360 } // unnamed namespace
337 361
338 // Creates a VideoFrame backed by native textures starting from a software 362 // Creates a VideoFrame backed by native textures starting from a software
339 // VideoFrame. 363 // VideoFrame.
340 // The data contained in |video_frame| is copied into the VideoFrame passed to 364 // The data contained in |video_frame| is copied into the VideoFrame passed to
341 // |frame_ready_cb|. 365 // |frame_ready_cb|.
342 // This has to be called on the thread where |media_task_runner_| is current. 366 // This has to be called on the thread where |media_task_runner_| is current.
343 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( 367 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
344 const scoped_refptr<VideoFrame>& video_frame, 368 const scoped_refptr<VideoFrame>& video_frame,
345 const FrameReadyCB& frame_ready_cb) { 369 const FrameReadyCB& frame_ready_cb) {
346 DCHECK(media_task_runner_->BelongsToCurrentThread()); 370 DCHECK(media_task_runner_->BelongsToCurrentThread());
347 // Lazily initialize output_format_ since VideoFrameOutputFormat() has to be 371 media::VideoPixelFormat output_format = PIXEL_FORMAT_UNKNOWN;
348 // called on the media_thread while this object might be instantiated on any.
349 if (output_format_ == PIXEL_FORMAT_UNKNOWN)
350 output_format_ = gpu_factories_->VideoFrameOutputFormat();
351
352 if (output_format_ == PIXEL_FORMAT_UNKNOWN) {
353 frame_ready_cb.Run(video_frame);
354 return;
355 }
356 switch (video_frame->format()) { 372 switch (video_frame->format()) {
357 // Supported cases. 373 // Supported cases.
358 case PIXEL_FORMAT_YV12: 374 case PIXEL_FORMAT_YV12:
359 case PIXEL_FORMAT_I420: 375 case PIXEL_FORMAT_I420: {
376 // Lazily initialize output_format_ since VideoFrameOutputFormat() has to
377 // be called on the media_thread while this object might be instantiated
378 // on any.
379 if (output_format_ == PIXEL_FORMAT_UNKNOWN) {
380 output_format_ =
381 gpu_factories_->VideoFrameOutputFormat(PIXEL_FORMAT_I420);
382 }
383 output_format = output_format_;
384 break;
385 }
386 case PIXEL_FORMAT_Y8:
387 case PIXEL_FORMAT_Y16:
388 // Lazily initialize texture_rg_available_.
389 if (!texture_rg_available_initialized_) {
390 texture_rg_available_initialized_ = true;
391 texture_rg_available_ = gpu_factories_->VideoFrameOutputFormat(
392 PIXEL_FORMAT_Y16) == PIXEL_FORMAT_Y16;
393 }
394 output_format =
395 texture_rg_available_ ? video_frame->format() : PIXEL_FORMAT_UNKNOWN;
360 break; 396 break;
361 // Unsupported cases. 397 // Unsupported cases.
362 case PIXEL_FORMAT_YV12A: 398 case PIXEL_FORMAT_YV12A:
363 case PIXEL_FORMAT_YV16: 399 case PIXEL_FORMAT_YV16:
364 case PIXEL_FORMAT_YV24: 400 case PIXEL_FORMAT_YV24:
365 case PIXEL_FORMAT_NV12: 401 case PIXEL_FORMAT_NV12:
366 case PIXEL_FORMAT_NV21: 402 case PIXEL_FORMAT_NV21:
367 case PIXEL_FORMAT_UYVY: 403 case PIXEL_FORMAT_UYVY:
368 case PIXEL_FORMAT_YUY2: 404 case PIXEL_FORMAT_YUY2:
369 case PIXEL_FORMAT_ARGB: 405 case PIXEL_FORMAT_ARGB:
370 case PIXEL_FORMAT_XRGB: 406 case PIXEL_FORMAT_XRGB:
371 case PIXEL_FORMAT_RGB24: 407 case PIXEL_FORMAT_RGB24:
372 case PIXEL_FORMAT_RGB32: 408 case PIXEL_FORMAT_RGB32:
373 case PIXEL_FORMAT_MJPEG: 409 case PIXEL_FORMAT_MJPEG:
374 case PIXEL_FORMAT_MT21: 410 case PIXEL_FORMAT_MT21:
375 case PIXEL_FORMAT_YUV420P9: 411 case PIXEL_FORMAT_YUV420P9:
376 case PIXEL_FORMAT_YUV422P9: 412 case PIXEL_FORMAT_YUV422P9:
377 case PIXEL_FORMAT_YUV444P9: 413 case PIXEL_FORMAT_YUV444P9:
378 case PIXEL_FORMAT_YUV420P10: 414 case PIXEL_FORMAT_YUV420P10:
379 case PIXEL_FORMAT_YUV422P10: 415 case PIXEL_FORMAT_YUV422P10:
380 case PIXEL_FORMAT_YUV444P10: 416 case PIXEL_FORMAT_YUV444P10:
381 case PIXEL_FORMAT_UNKNOWN: 417 case PIXEL_FORMAT_UNKNOWN:
382 frame_ready_cb.Run(video_frame); 418 break;
383 return; 419 }
420 if (output_format == PIXEL_FORMAT_UNKNOWN) {
421 frame_ready_cb.Run(video_frame);
422 return;
384 } 423 }
385 424
386 const gfx::Size coded_size = CodedSize(video_frame, output_format_); 425 const gfx::Size coded_size = CodedSize(video_frame, output_format);
387 // Acquire resources. Incompatible ones will be dropped from the pool. 426 // Acquire resources. Incompatible ones will be dropped from the pool.
388 FrameResources* frame_resources = 427 FrameResources* frame_resources =
389 GetOrCreateFrameResources(coded_size, output_format_); 428 GetOrCreateFrameResources(coded_size, output_format);
390 if (!frame_resources) { 429 if (!frame_resources) {
391 frame_ready_cb.Run(video_frame); 430 frame_ready_cb.Run(video_frame);
392 return; 431 return;
393 } 432 }
394 433
395 worker_task_runner_->PostTask( 434 worker_task_runner_->PostTask(
396 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, 435 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this,
397 video_frame, frame_resources, frame_ready_cb)); 436 video_frame, frame_resources, frame_ready_cb));
398 } 437 }
399 438
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 } 491 }
453 492
454 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks 493 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks
455 // that will be synchronized by a barrier. 494 // that will be synchronized by a barrier.
456 // After the barrier is passed OnCopiesDone will be called. 495 // After the barrier is passed OnCopiesDone will be called.
457 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( 496 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
458 const scoped_refptr<VideoFrame>& video_frame, 497 const scoped_refptr<VideoFrame>& video_frame,
459 FrameResources* frame_resources, 498 FrameResources* frame_resources,
460 const FrameReadyCB& frame_ready_cb) { 499 const FrameReadyCB& frame_ready_cb) {
461 // Compute the number of tasks to post and create the barrier. 500 // Compute the number of tasks to post and create the barrier.
462 const size_t num_planes = VideoFrame::NumPlanes(output_format_); 501 const size_t num_planes = VideoFrame::NumPlanes(frame_resources->format);
463 const size_t planes_per_copy = PlanesPerCopy(output_format_); 502 const size_t planes_per_copy = PlanesPerCopy(frame_resources->format);
464 const gfx::Size coded_size = CodedSize(video_frame, output_format_); 503 const gfx::Size coded_size = CodedSize(video_frame, frame_resources->format);
465 size_t copies = 0; 504 size_t copies = 0;
466 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 505 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
467 const int rows = VideoFrame::Rows(i, output_format_, coded_size.height()); 506 const int rows =
507 VideoFrame::Rows(i, frame_resources->format, coded_size.height());
468 const int rows_per_copy = 508 const int rows_per_copy =
469 RowsPerCopy(i, output_format_, coded_size.width()); 509 RowsPerCopy(i, frame_resources->format, coded_size.width());
470 copies += rows / rows_per_copy; 510 copies += rows / rows_per_copy;
471 if (rows % rows_per_copy) 511 if (rows % rows_per_copy)
472 ++copies; 512 ++copies;
473 } 513 }
474 const base::Closure copies_done = 514 const base::Closure copies_done =
475 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, 515 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources,
476 frame_ready_cb); 516 frame_ready_cb);
477 const base::Closure barrier = base::BarrierClosure(copies, copies_done); 517 const base::Closure barrier = base::BarrierClosure(copies, copies_done);
478 518
479 // Post all the async tasks. 519 // Post all the async tasks.
480 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 520 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
481 gfx::GpuMemoryBuffer* buffer = 521 gfx::GpuMemoryBuffer* buffer =
482 frame_resources->plane_resources[i].gpu_memory_buffer.get(); 522 frame_resources->plane_resources[i].gpu_memory_buffer.get();
483 523
484 if (!buffer || !buffer->Map()) { 524 if (!buffer || !buffer->Map()) {
485 DLOG(ERROR) << "Could not get or Map() buffer"; 525 DLOG(ERROR) << "Could not get or Map() buffer";
486 return; 526 return;
487 } 527 }
488 DCHECK_EQ(planes_per_copy, 528 DCHECK_EQ(planes_per_copy,
489 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); 529 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat()));
490 530
491 const int rows = VideoFrame::Rows(i, output_format_, coded_size.height()); 531 const int rows =
532 VideoFrame::Rows(i, frame_resources->format, coded_size.height());
492 const int rows_per_copy = 533 const int rows_per_copy =
493 RowsPerCopy(i, output_format_, coded_size.width()); 534 RowsPerCopy(i, frame_resources->format, coded_size.width());
494 535
495 for (int row = 0; row < rows; row += rows_per_copy) { 536 for (int row = 0; row < rows; row += rows_per_copy) {
496 const int rows_to_copy = std::min(rows_per_copy, rows - row); 537 const int rows_to_copy = std::min(rows_per_copy, rows - row);
497 switch (output_format_) { 538 switch (frame_resources->format) {
498 case PIXEL_FORMAT_I420: { 539 case PIXEL_FORMAT_I420: {
499 const int bytes_per_row = 540 const int bytes_per_row = VideoFrame::RowBytes(
500 VideoFrame::RowBytes(i, output_format_, coded_size.width()); 541 i, frame_resources->format, coded_size.width());
501 worker_task_runner_->PostTask( 542 worker_task_runner_->PostTask(
502 FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy, 543 FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy,
503 bytes_per_row, video_frame->visible_data(i), 544 bytes_per_row, video_frame->visible_data(i),
504 video_frame->stride(i), 545 video_frame->stride(i),
505 static_cast<uint8_t*>(buffer->memory(0)), 546 static_cast<uint8_t*>(buffer->memory(0)),
506 buffer->stride(0), barrier)); 547 buffer->stride(0), barrier));
507 break; 548 break;
508 } 549 }
509 case PIXEL_FORMAT_NV12: 550 case PIXEL_FORMAT_NV12:
510 worker_task_runner_->PostTask( 551 worker_task_runner_->PostTask(
511 FROM_HERE, base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, 552 FROM_HERE, base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy,
512 coded_size.width(), video_frame, 553 coded_size.width(), video_frame,
513 static_cast<uint8_t*>(buffer->memory(0)), 554 static_cast<uint8_t*>(buffer->memory(0)),
514 buffer->stride(0), 555 buffer->stride(0),
515 static_cast<uint8_t*>(buffer->memory(1)), 556 static_cast<uint8_t*>(buffer->memory(1)),
516 buffer->stride(1), barrier)); 557 buffer->stride(1), barrier));
517 break; 558 break;
518 case PIXEL_FORMAT_UYVY: 559 case PIXEL_FORMAT_UYVY:
519 worker_task_runner_->PostTask( 560 worker_task_runner_->PostTask(
520 FROM_HERE, base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, 561 FROM_HERE, base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy,
521 coded_size.width(), video_frame, 562 coded_size.width(), video_frame,
522 static_cast<uint8_t*>(buffer->memory(0)), 563 static_cast<uint8_t*>(buffer->memory(0)),
523 buffer->stride(0), barrier)); 564 buffer->stride(0), barrier));
524 break; 565 break;
566 case PIXEL_FORMAT_Y8:
567 case PIXEL_FORMAT_Y16:
568 worker_task_runner_->PostTask(
569 FROM_HERE, base::Bind(&CopyRowsToGPUBuffer, row, rows_to_copy,
570 coded_size.width(), video_frame,
571 static_cast<uint8_t*>(buffer->memory(0)),
572 buffer->stride(0), barrier));
573 break;
525 default: 574 default:
526 NOTREACHED(); 575 NOTREACHED();
527 } 576 }
528 } 577 }
529 } 578 }
530 } 579 }
531 580
532 void GpuMemoryBufferVideoFramePool::PoolImpl:: 581 void GpuMemoryBufferVideoFramePool::PoolImpl::
533 BindAndCreateMailboxesHardwareFrameResources( 582 BindAndCreateMailboxesHardwareFrameResources(
534 const scoped_refptr<VideoFrame>& video_frame, 583 const scoped_refptr<VideoFrame>& video_frame,
535 FrameResources* frame_resources, 584 FrameResources* frame_resources,
536 const FrameReadyCB& frame_ready_cb) { 585 const FrameReadyCB& frame_ready_cb) {
537 std::unique_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> lock( 586 std::unique_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> lock(
538 gpu_factories_->GetGLContextLock()); 587 gpu_factories_->GetGLContextLock());
539 if (!lock) { 588 if (!lock) {
540 frame_ready_cb.Run(video_frame); 589 frame_ready_cb.Run(video_frame);
541 return; 590 return;
542 } 591 }
543 gpu::gles2::GLES2Interface* gles2 = lock->ContextGL(); 592 gpu::gles2::GLES2Interface* gles2 = lock->ContextGL();
544 593
545 const size_t num_planes = VideoFrame::NumPlanes(output_format_); 594 const size_t num_planes = VideoFrame::NumPlanes(frame_resources->format);
546 const size_t planes_per_copy = PlanesPerCopy(output_format_); 595 const size_t planes_per_copy = PlanesPerCopy(frame_resources->format);
547 const gfx::Size coded_size = CodedSize(video_frame, output_format_); 596 const gfx::Size coded_size = CodedSize(video_frame, frame_resources->format);
548 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; 597 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
549 // Set up the planes creating the mailboxes needed to refer to the textures. 598 // Set up the planes creating the mailboxes needed to refer to the textures.
550 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 599 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
551 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 600 PlaneResource& plane_resource = frame_resources->plane_resources[i];
552 const gfx::BufferFormat buffer_format = 601 const gfx::BufferFormat buffer_format =
553 GpuMemoryBufferFormat(output_format_, i); 602 VideoFrame::BufferFormat(frame_resources->format);
554 unsigned texture_target = gpu_factories_->ImageTextureTarget(buffer_format); 603 unsigned texture_target = gpu_factories_->ImageTextureTarget(buffer_format);
555 // Bind the texture and create or rebind the image. 604 // Bind the texture and create or rebind the image.
556 gles2->BindTexture(texture_target, plane_resource.texture_id); 605 gles2->BindTexture(texture_target, plane_resource.texture_id);
557 606
558 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { 607 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) {
559 const size_t width = 608 const size_t width =
560 VideoFrame::Columns(i, output_format_, coded_size.width()); 609 VideoFrame::Columns(i, frame_resources->format, coded_size.width());
561 const size_t height = 610 const size_t height =
562 VideoFrame::Rows(i, output_format_, coded_size.height()); 611 VideoFrame::Rows(i, frame_resources->format, coded_size.height());
563 plane_resource.image_id = gles2->CreateImageCHROMIUM( 612 plane_resource.image_id = gles2->CreateImageCHROMIUM(
564 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, 613 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height,
565 ImageInternalFormat(output_format_, i)); 614 ImageInternalFormat(frame_resources->format, i));
566 } else if (plane_resource.image_id) { 615 } else if (plane_resource.image_id) {
567 gles2->ReleaseTexImage2DCHROMIUM(texture_target, plane_resource.image_id); 616 gles2->ReleaseTexImage2DCHROMIUM(texture_target, plane_resource.image_id);
568 } 617 }
569 if (plane_resource.image_id) 618 if (plane_resource.image_id)
570 gles2->BindTexImage2DCHROMIUM(texture_target, plane_resource.image_id); 619 gles2->BindTexImage2DCHROMIUM(texture_target, plane_resource.image_id);
571 mailbox_holders[i] = gpu::MailboxHolder(plane_resource.mailbox, 620 mailbox_holders[i] = gpu::MailboxHolder(plane_resource.mailbox,
572 gpu::SyncToken(), texture_target); 621 gpu::SyncToken(), texture_target);
573 } 622 }
574 623
575 // Insert a sync_token, this is needed to make sure that the textures the 624 // Insert a sync_token, this is needed to make sure that the textures the
576 // mailboxes refer to will be used only after all the previous commands posted 625 // mailboxes refer to will be used only after all the previous commands posted
577 // in the command buffer have been processed. 626 // in the command buffer have been processed.
578 const GLuint64 fence_sync = gles2->InsertFenceSyncCHROMIUM(); 627 const GLuint64 fence_sync = gles2->InsertFenceSyncCHROMIUM();
579 gles2->OrderingBarrierCHROMIUM(); 628 gles2->OrderingBarrierCHROMIUM();
580 629
581 gpu::SyncToken sync_token; 630 gpu::SyncToken sync_token;
582 gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); 631 gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
583 for (size_t i = 0; i < num_planes; i += planes_per_copy) 632 for (size_t i = 0; i < num_planes; i += planes_per_copy)
584 mailbox_holders[i].sync_token = sync_token; 633 mailbox_holders[i].sync_token = sync_token;
585 634
586 635
587 auto release_mailbox_callback = BindToCurrentLoop( 636 auto release_mailbox_callback = BindToCurrentLoop(
588 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources)); 637 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources));
589 638
590 // Consumers should sample from NV12 textures as if they're XRGB. 639 // Consumers should sample from NV12 textures as if they're XRGB.
591 VideoPixelFormat frame_format = 640 VideoPixelFormat frame_format = (frame_resources->format == PIXEL_FORMAT_NV12)
592 output_format_ == PIXEL_FORMAT_NV12 ? PIXEL_FORMAT_XRGB : output_format_; 641 ? PIXEL_FORMAT_XRGB
642 : frame_resources->format;
593 DCHECK_EQ(VideoFrame::NumPlanes(frame_format) * planes_per_copy, num_planes); 643 DCHECK_EQ(VideoFrame::NumPlanes(frame_format) * planes_per_copy, num_planes);
594 644
595 // Create the VideoFrame backed by native textures. 645 // Create the VideoFrame backed by native textures.
596 gfx::Size visible_size = video_frame->visible_rect().size(); 646 gfx::Size visible_size = video_frame->visible_rect().size();
597 scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures( 647 scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
598 frame_format, mailbox_holders, release_mailbox_callback, coded_size, 648 frame_format, mailbox_holders, release_mailbox_callback, coded_size,
599 gfx::Rect(visible_size), video_frame->natural_size(), 649 gfx::Rect(visible_size), video_frame->natural_size(),
600 video_frame->timestamp()); 650 video_frame->timestamp());
601 651
602 if (!frame) { 652 if (!frame) {
603 release_mailbox_callback.Run(gpu::SyncToken()); 653 release_mailbox_callback.Run(gpu::SyncToken());
604 frame_ready_cb.Run(video_frame); 654 frame_ready_cb.Run(video_frame);
605 return; 655 return;
606 } 656 }
607 657
608 frame->set_color_space(video_frame->ColorSpace()); 658 frame->set_color_space(video_frame->ColorSpace());
609 659
610 bool allow_overlay = false; 660 bool allow_overlay = false;
611 switch (output_format_) { 661 switch (frame_resources->format) {
612 case PIXEL_FORMAT_I420: 662 case PIXEL_FORMAT_I420:
613 allow_overlay = 663 allow_overlay =
614 video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY); 664 video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY);
615 break; 665 break;
616 case PIXEL_FORMAT_NV12: 666 case PIXEL_FORMAT_NV12:
617 case PIXEL_FORMAT_UYVY: 667 case PIXEL_FORMAT_UYVY:
668 case PIXEL_FORMAT_Y8:
669 case PIXEL_FORMAT_Y16:
618 allow_overlay = true; 670 allow_overlay = true;
619 break; 671 break;
620 default: 672 default:
621 break; 673 break;
622 } 674 }
623 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, 675 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY,
624 allow_overlay); 676 allow_overlay);
625 677
626 base::TimeTicks render_time; 678 base::TimeTicks render_time;
627 if (video_frame->metadata()->GetTimeTicks(VideoFrameMetadata::REFERENCE_TIME, 679 if (video_frame->metadata()->GetTimeTicks(VideoFrameMetadata::REFERENCE_TIME,
(...skipping 24 matching lines...) Expand all
652 // Tries to find the resources in the pool or create them. 704 // Tries to find the resources in the pool or create them.
653 // Incompatible resources will be dropped. 705 // Incompatible resources will be dropped.
654 GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources* 706 GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources*
655 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources( 707 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources(
656 const gfx::Size& size, 708 const gfx::Size& size,
657 VideoPixelFormat format) { 709 VideoPixelFormat format) {
658 auto it = resources_pool_.begin(); 710 auto it = resources_pool_.begin();
659 while (it != resources_pool_.end()) { 711 while (it != resources_pool_.end()) {
660 FrameResources* frame_resources = *it; 712 FrameResources* frame_resources = *it;
661 if (!frame_resources->IsInUse()) { 713 if (!frame_resources->IsInUse()) {
662 if (AreFrameResourcesCompatible(frame_resources, size)) { 714 if (AreFrameResourcesCompatible(frame_resources, size, format)) {
663 frame_resources->SetIsInUse(true); 715 frame_resources->SetIsInUse(true);
664 return frame_resources; 716 return frame_resources;
665 } else { 717 } else {
666 resources_pool_.erase(it++); 718 resources_pool_.erase(it++);
667 DeleteFrameResources(gpu_factories_, frame_resources); 719 DeleteFrameResources(gpu_factories_, frame_resources);
668 delete frame_resources; 720 delete frame_resources;
669 } 721 }
670 } else { 722 } else {
671 it++; 723 it++;
672 } 724 }
673 } 725 }
674 726
675 // Create the resources. 727 // Create the resources.
676 std::unique_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> lock( 728 std::unique_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> lock(
677 gpu_factories_->GetGLContextLock()); 729 gpu_factories_->GetGLContextLock());
678 if (!lock) 730 if (!lock)
679 return nullptr; 731 return nullptr;
680 732
681 gpu::gles2::GLES2Interface* gles2 = lock->ContextGL(); 733 gpu::gles2::GLES2Interface* gles2 = lock->ContextGL();
682 gles2->ActiveTexture(GL_TEXTURE0); 734 gles2->ActiveTexture(GL_TEXTURE0);
683 size_t num_planes = VideoFrame::NumPlanes(format); 735 size_t num_planes = VideoFrame::NumPlanes(format);
684 FrameResources* frame_resources = new FrameResources(size); 736 FrameResources* frame_resources = new FrameResources(size, format);
685 resources_pool_.push_back(frame_resources); 737 resources_pool_.push_back(frame_resources);
686 for (size_t i = 0; i < num_planes; i += PlanesPerCopy(format)) { 738 for (size_t i = 0; i < num_planes; i += PlanesPerCopy(format)) {
687 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 739 PlaneResource& plane_resource = frame_resources->plane_resources[i];
688 const size_t width = VideoFrame::Columns(i, format, size.width()); 740 const size_t width = VideoFrame::Columns(i, format, size.width());
689 const size_t height = VideoFrame::Rows(i, format, size.height()); 741 const size_t height = VideoFrame::Rows(i, format, size.height());
690 plane_resource.size = gfx::Size(width, height); 742 plane_resource.size = gfx::Size(width, height);
691 743
692 const gfx::BufferFormat buffer_format = GpuMemoryBufferFormat(format, i); 744 const gfx::BufferFormat buffer_format = VideoFrame::BufferFormat(format);
693 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( 745 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer(
694 plane_resource.size, buffer_format, 746 plane_resource.size, buffer_format,
695 gfx::BufferUsage::GPU_READ_CPU_READ_WRITE); 747 gfx::BufferUsage::GPU_READ_CPU_READ_WRITE);
696 748
697 unsigned texture_target = gpu_factories_->ImageTextureTarget(buffer_format); 749 unsigned texture_target = gpu_factories_->ImageTextureTarget(buffer_format);
698 gles2->GenTextures(1, &plane_resource.texture_id); 750 gles2->GenTextures(1, &plane_resource.texture_id);
699 gles2->BindTexture(texture_target, plane_resource.texture_id); 751 gles2->BindTexture(texture_target, plane_resource.texture_id);
700 gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 752 if (format == PIXEL_FORMAT_Y16) {
701 gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 753 gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
754 gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
755 } else {
756 gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
757 gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
758 }
702 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 759 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
703 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 760 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
704 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name); 761 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name);
705 gles2->ProduceTextureCHROMIUM(texture_target, plane_resource.mailbox.name); 762 gles2->ProduceTextureCHROMIUM(texture_target, plane_resource.mailbox.name);
706 } 763 }
707 return frame_resources; 764 return frame_resources;
708 } 765 }
709 766
710 // static 767 // static
711 void GpuMemoryBufferVideoFramePool::PoolImpl::DeleteFrameResources( 768 void GpuMemoryBufferVideoFramePool::PoolImpl::DeleteFrameResources(
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 } 820 }
764 821
765 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( 822 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
766 const scoped_refptr<VideoFrame>& video_frame, 823 const scoped_refptr<VideoFrame>& video_frame,
767 const FrameReadyCB& frame_ready_cb) { 824 const FrameReadyCB& frame_ready_cb) {
768 DCHECK(video_frame); 825 DCHECK(video_frame);
769 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); 826 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb);
770 } 827 }
771 828
772 } // namespace media 829 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698