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/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 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 // output size is |kBytesPerCopyTarget| bytes and run in parallel. | 154 // output size is |kBytesPerCopyTarget| bytes and run in parallel. |
155 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB | 155 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB |
156 | 156 |
157 // Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat | 157 // Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat |
158 // and plane. | 158 // and plane. |
159 gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) { | 159 gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) { |
160 switch (format) { | 160 switch (format) { |
161 case PIXEL_FORMAT_I420: | 161 case PIXEL_FORMAT_I420: |
162 DCHECK_LE(plane, 2u); | 162 DCHECK_LE(plane, 2u); |
163 return gfx::BufferFormat::R_8; | 163 return gfx::BufferFormat::R_8; |
| 164 case PIXEL_FORMAT_NV12: |
| 165 DCHECK_LE(plane, 1u); |
| 166 return gfx::BufferFormat::YUV_420_BIPLANAR; |
164 case PIXEL_FORMAT_UYVY: | 167 case PIXEL_FORMAT_UYVY: |
165 DCHECK_EQ(0u, plane); | 168 DCHECK_EQ(0u, plane); |
166 return gfx::BufferFormat::UYVY_422; | 169 return gfx::BufferFormat::UYVY_422; |
167 default: | 170 default: |
168 NOTREACHED(); | 171 NOTREACHED(); |
169 return gfx::BufferFormat::BGRA_8888; | 172 return gfx::BufferFormat::BGRA_8888; |
170 } | 173 } |
171 } | 174 } |
172 | 175 |
173 unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) { | 176 unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) { |
174 switch (format) { | 177 switch (format) { |
175 case PIXEL_FORMAT_I420: | 178 case PIXEL_FORMAT_I420: |
176 DCHECK_LE(plane, 2u); | 179 DCHECK_LE(plane, 2u); |
177 return GL_R8_EXT; | 180 return GL_R8_EXT; |
| 181 case PIXEL_FORMAT_NV12: |
| 182 DCHECK_LE(plane, 1u); |
| 183 DLOG(WARNING) << "NV12 format not supported yet"; |
| 184 return 0; // TODO(andresantoso): Implement extension for NV12. |
178 case PIXEL_FORMAT_UYVY: | 185 case PIXEL_FORMAT_UYVY: |
179 DCHECK_EQ(0u, plane); | 186 DCHECK_EQ(0u, plane); |
180 return GL_RGB_YCBCR_422_CHROMIUM; | 187 return GL_RGB_YCBCR_422_CHROMIUM; |
181 default: | 188 default: |
182 NOTREACHED(); | 189 NOTREACHED(); |
183 return 0; | 190 return 0; |
184 } | 191 } |
185 } | 192 } |
186 | 193 |
| 194 // The number of output planes to be copied in each iteration. |
| 195 size_t PlanesPerCopy(VideoPixelFormat format) { |
| 196 switch (format) { |
| 197 case PIXEL_FORMAT_I420: |
| 198 case PIXEL_FORMAT_UYVY: |
| 199 return 1; |
| 200 case PIXEL_FORMAT_NV12: |
| 201 return 2; |
| 202 default: |
| 203 NOTREACHED(); |
| 204 return 0; |
| 205 } |
| 206 } |
| 207 |
| 208 // The number of output rows to be copied in each iteration. |
| 209 int RowsPerCopy(size_t plane, VideoPixelFormat format, int width) { |
| 210 int bytes_per_row = VideoFrame::RowBytes(plane, format, width); |
| 211 if (format == PIXEL_FORMAT_NV12) { |
| 212 DCHECK_EQ(0u, plane); |
| 213 bytes_per_row += VideoFrame::RowBytes(1, format, width); |
| 214 } |
| 215 // Copy an even number of lines, and at least one. |
| 216 return std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1); |
| 217 } |
| 218 |
187 void CopyRowsToI420Buffer(int first_row, | 219 void CopyRowsToI420Buffer(int first_row, |
188 int rows, | 220 int rows, |
189 int bytes_per_row, | 221 int bytes_per_row, |
190 const uint8* source, | 222 const uint8* source, |
191 int source_stride, | 223 int source_stride, |
192 uint8* output, | 224 uint8* output, |
193 int dest_stride, | 225 int dest_stride, |
194 const base::Closure& done) { | 226 const base::Closure& done) { |
195 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, | 227 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, |
196 "rows", rows); | 228 "rows", rows); |
197 DCHECK_NE(dest_stride, 0); | 229 DCHECK_NE(dest_stride, 0); |
198 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); | 230 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); |
199 DCHECK_LE(bytes_per_row, source_stride); | 231 DCHECK_LE(bytes_per_row, source_stride); |
200 for (int row = first_row; row < first_row + rows; ++row) { | 232 for (int row = first_row; row < first_row + rows; ++row) { |
201 memcpy(output + dest_stride * row, source + source_stride * row, | 233 memcpy(output + dest_stride * row, source + source_stride * row, |
202 bytes_per_row); | 234 bytes_per_row); |
203 } | 235 } |
204 done.Run(); | 236 done.Run(); |
205 } | 237 } |
206 | 238 |
| 239 void CopyRowsToNV12Buffer(int first_row, |
| 240 int rows, |
| 241 int bytes_per_row, |
| 242 const scoped_refptr<VideoFrame>& source_frame, |
| 243 uint8* dest_y, |
| 244 int dest_stride_y, |
| 245 uint8* dest_uv, |
| 246 int dest_stride_uv, |
| 247 const base::Closure& done) { |
| 248 TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "bytes_per_row", bytes_per_row, |
| 249 "rows", rows); |
| 250 DCHECK_NE(dest_stride_y, 0); |
| 251 DCHECK_NE(dest_stride_uv, 0); |
| 252 DCHECK_LE(bytes_per_row, std::abs(dest_stride_y)); |
| 253 DCHECK_LE(bytes_per_row, std::abs(dest_stride_uv)); |
| 254 DCHECK_EQ(0, first_row % 2); |
| 255 libyuv::I420ToNV12( |
| 256 source_frame->data(VideoFrame::kYPlane) + |
| 257 first_row * source_frame->stride(VideoFrame::kYPlane), |
| 258 source_frame->stride(VideoFrame::kYPlane), |
| 259 source_frame->data(VideoFrame::kUPlane) + |
| 260 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), |
| 261 source_frame->stride(VideoFrame::kUPlane), |
| 262 source_frame->data(VideoFrame::kVPlane) + |
| 263 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), |
| 264 source_frame->stride(VideoFrame::kVPlane), |
| 265 dest_y + first_row * dest_stride_y, dest_stride_y, |
| 266 dest_uv + first_row / 2 * dest_stride_uv, dest_stride_uv, |
| 267 bytes_per_row, rows); |
| 268 done.Run(); |
| 269 } |
| 270 |
207 void CopyRowsToUYVYBuffer(int first_row, | 271 void CopyRowsToUYVYBuffer(int first_row, |
208 int rows, | 272 int rows, |
209 int width, | 273 int width, |
210 const scoped_refptr<VideoFrame>& source_frame, | 274 const scoped_refptr<VideoFrame>& source_frame, |
211 uint8* output, | 275 uint8* output, |
212 int dest_stride, | 276 int dest_stride, |
213 const base::Closure& done) { | 277 const base::Closure& done) { |
214 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2, | 278 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2, |
215 "rows", rows); | 279 "rows", rows); |
216 DCHECK_NE(dest_stride, 0); | 280 DCHECK_NE(dest_stride, 0); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 | 355 |
292 worker_task_runner_->PostTask( | 356 worker_task_runner_->PostTask( |
293 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, | 357 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, |
294 video_frame, frame_resources, frame_ready_cb)); | 358 video_frame, frame_resources, frame_ready_cb)); |
295 } | 359 } |
296 | 360 |
297 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( | 361 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( |
298 const scoped_refptr<VideoFrame>& video_frame, | 362 const scoped_refptr<VideoFrame>& video_frame, |
299 FrameResources* frame_resources, | 363 FrameResources* frame_resources, |
300 const FrameReadyCB& frame_ready_cb) { | 364 const FrameReadyCB& frame_ready_cb) { |
301 const size_t planes = VideoFrame::NumPlanes(output_format_); | 365 for (const auto& plane_resource : frame_resources->plane_resources) { |
302 for (size_t i = 0; i < planes; ++i) { | 366 if (plane_resource.gpu_memory_buffer) |
303 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap(); | 367 plane_resource.gpu_memory_buffer->Unmap(); |
304 } | 368 } |
305 | 369 |
306 media_task_runner_->PostTask( | 370 media_task_runner_->PostTask( |
307 FROM_HERE, | 371 FROM_HERE, |
308 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this, | 372 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this, |
309 video_frame, frame_resources, frame_ready_cb)); | 373 video_frame, frame_resources, frame_ready_cb)); |
310 } | 374 } |
311 | 375 |
312 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks | 376 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks |
313 // that will be synchronized by a barrier. | 377 // that will be synchronized by a barrier. |
314 // After the barrier is passed OnCopiesDone will be called. | 378 // After the barrier is passed OnCopiesDone will be called. |
315 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( | 379 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( |
316 const scoped_refptr<VideoFrame>& video_frame, | 380 const scoped_refptr<VideoFrame>& video_frame, |
317 FrameResources* frame_resources, | 381 FrameResources* frame_resources, |
318 const FrameReadyCB& frame_ready_cb) { | 382 const FrameReadyCB& frame_ready_cb) { |
319 // Compute the number of tasks to post and create the barrier. | 383 // Compute the number of tasks to post and create the barrier. |
320 const size_t dest_planes = VideoFrame::NumPlanes(output_format_); | 384 const size_t num_planes = VideoFrame::NumPlanes(output_format_); |
| 385 const size_t planes_per_copy = PlanesPerCopy(output_format_); |
321 gfx::Size size = video_frame->visible_rect().size(); | 386 gfx::Size size = video_frame->visible_rect().size(); |
322 size_t copies = 0; | 387 size_t copies = 0; |
323 for (size_t i = 0; i < dest_planes; ++i) { | 388 for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
324 int rows = VideoFrame::Rows(i, output_format_, size.height()); | 389 const int rows = VideoFrame::Rows(i, output_format_, size.height()); |
325 int bytes_per_row = VideoFrame::RowBytes(i, output_format_, size.width()); | 390 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); |
326 // Copy a even number of lines, and at least one. | |
327 int rows_per_copy = | |
328 std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1); | |
329 copies += rows / rows_per_copy; | 391 copies += rows / rows_per_copy; |
330 if (rows % rows_per_copy) | 392 if (rows % rows_per_copy) |
331 ++copies; | 393 ++copies; |
332 } | 394 } |
333 base::Closure copies_done = | 395 base::Closure copies_done = |
334 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, | 396 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, |
335 frame_ready_cb); | 397 frame_ready_cb); |
336 base::Closure barrier = base::BarrierClosure(copies, copies_done); | 398 base::Closure barrier = base::BarrierClosure(copies, copies_done); |
| 399 |
337 // Post all the async tasks. | 400 // Post all the async tasks. |
338 for (size_t i = 0; i < dest_planes; ++i) { | 401 for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
339 int rows = VideoFrame::Rows(i, output_format_, size.height()); | 402 gfx::GpuMemoryBuffer* buffer = |
340 int bytes_per_row = VideoFrame::RowBytes(i, output_format_, size.width()); | 403 frame_resources->plane_resources[i].gpu_memory_buffer.get(); |
341 int rows_per_copy = | 404 DCHECK(buffer); |
342 std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1); | 405 DCHECK_EQ(planes_per_copy, |
| 406 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); |
| 407 uint8* dest_buffers[VideoFrame::kMaxPlanes]; |
| 408 int dest_strides[VideoFrame::kMaxPlanes]; |
| 409 bool rv = buffer->Map(reinterpret_cast<void**>(dest_buffers)); |
| 410 DCHECK(rv); |
| 411 buffer->GetStride(dest_strides); |
343 | 412 |
344 void* data = nullptr; | 413 const int rows = VideoFrame::Rows(i, output_format_, size.height()); |
345 DCHECK_EQ(1u, gfx::NumberOfPlanesForBufferFormat( | 414 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); |
346 GpuMemoryBufferFormat(output_format_, i))); | |
347 bool rv = frame_resources->plane_resources[i].gpu_memory_buffer->Map(&data); | |
348 DCHECK(rv); | |
349 uint8* mapped_buffer = static_cast<uint8*>(data); | |
350 | |
351 int dest_stride = 0; | |
352 frame_resources->plane_resources[i].gpu_memory_buffer->GetStride( | |
353 &dest_stride); | |
354 | 415 |
355 for (int row = 0; row < rows; row += rows_per_copy) { | 416 for (int row = 0; row < rows; row += rows_per_copy) { |
| 417 const int rows_to_copy = std::min(rows_per_copy, rows - row); |
356 switch (output_format_) { | 418 switch (output_format_) { |
357 case PIXEL_FORMAT_I420: | 419 case PIXEL_FORMAT_I420: { |
| 420 const int bytes_per_row = |
| 421 VideoFrame::RowBytes(i, output_format_, size.width()); |
358 worker_task_runner_->PostTask( | 422 worker_task_runner_->PostTask( |
359 FROM_HERE, | 423 FROM_HERE, |
360 base::Bind(&CopyRowsToI420Buffer, row, | 424 base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy, |
361 std::min(rows_per_copy, rows - row), bytes_per_row, | 425 bytes_per_row, video_frame->data(i), |
362 video_frame->data(i), video_frame->stride(i), | 426 video_frame->stride(i), dest_buffers[0], |
363 mapped_buffer, dest_stride, barrier)); | 427 dest_strides[0], barrier)); |
| 428 break; |
| 429 } |
| 430 case PIXEL_FORMAT_NV12: |
| 431 worker_task_runner_->PostTask( |
| 432 FROM_HERE, |
| 433 base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, |
| 434 size.width(), video_frame, dest_buffers[0], |
| 435 dest_strides[0], dest_buffers[1], dest_strides[1], |
| 436 barrier)); |
364 break; | 437 break; |
365 case PIXEL_FORMAT_UYVY: | 438 case PIXEL_FORMAT_UYVY: |
366 worker_task_runner_->PostTask( | 439 worker_task_runner_->PostTask( |
367 FROM_HERE, | 440 FROM_HERE, |
368 base::Bind(&CopyRowsToUYVYBuffer, row, | 441 base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, size.width(), |
369 std::min(rows_per_copy, rows - row), size.width(), | 442 video_frame, dest_buffers[0], dest_strides[0], |
370 video_frame, mapped_buffer, dest_stride, barrier)); | 443 barrier)); |
371 break; | 444 break; |
372 default: | 445 default: |
373 NOTREACHED(); | 446 NOTREACHED(); |
374 } | 447 } |
375 } | 448 } |
376 } | 449 } |
377 } | 450 } |
378 | 451 |
379 void GpuMemoryBufferVideoFramePool::PoolImpl:: | 452 void GpuMemoryBufferVideoFramePool::PoolImpl:: |
380 BindAndCreateMailboxesHardwareFrameResources( | 453 BindAndCreateMailboxesHardwareFrameResources( |
381 const scoped_refptr<VideoFrame>& video_frame, | 454 const scoped_refptr<VideoFrame>& video_frame, |
382 FrameResources* frame_resources, | 455 FrameResources* frame_resources, |
383 const FrameReadyCB& frame_ready_cb) { | 456 const FrameReadyCB& frame_ready_cb) { |
384 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); | 457 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); |
385 if (!gles2) { | 458 if (!gles2) { |
386 frame_ready_cb.Run(video_frame); | 459 frame_ready_cb.Run(video_frame); |
387 return; | 460 return; |
388 } | 461 } |
389 | 462 |
390 const size_t planes = VideoFrame::NumPlanes(output_format_); | 463 const size_t num_planes = VideoFrame::NumPlanes(output_format_); |
| 464 const size_t planes_per_copy = PlanesPerCopy(output_format_); |
391 const gfx::Size size = video_frame->visible_rect().size(); | 465 const gfx::Size size = video_frame->visible_rect().size(); |
392 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; | 466 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; |
393 // Set up the planes creating the mailboxes needed to refer to the textures. | 467 // Set up the planes creating the mailboxes needed to refer to the textures. |
394 for (size_t i = 0; i < planes; ++i) { | 468 for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
395 PlaneResource& plane_resource = frame_resources->plane_resources[i]; | 469 PlaneResource& plane_resource = frame_resources->plane_resources[i]; |
| 470 DCHECK(plane_resource.gpu_memory_buffer); |
396 // Bind the texture and create or rebind the image. | 471 // Bind the texture and create or rebind the image. |
397 gles2->BindTexture(texture_target_, plane_resource.texture_id); | 472 gles2->BindTexture(texture_target_, plane_resource.texture_id); |
398 | 473 |
399 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { | 474 if (!plane_resource.image_id) { |
400 const size_t width = VideoFrame::Columns(i, output_format_, size.width()); | 475 const size_t width = VideoFrame::Columns(i, output_format_, size.width()); |
401 const size_t height = VideoFrame::Rows(i, output_format_, size.height()); | 476 const size_t height = VideoFrame::Rows(i, output_format_, size.height()); |
402 plane_resource.image_id = gles2->CreateImageCHROMIUM( | 477 plane_resource.image_id = gles2->CreateImageCHROMIUM( |
403 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, | 478 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, |
404 ImageInternalFormat(output_format_, i)); | 479 ImageInternalFormat(output_format_, i)); |
405 } else { | 480 } else { |
406 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, | 481 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, |
407 plane_resource.image_id); | 482 plane_resource.image_id); |
408 } | 483 } |
409 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); | 484 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); |
410 mailbox_holders[i] = | 485 mailbox_holders[i] = |
411 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); | 486 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); |
412 } | 487 } |
413 | 488 |
414 // Insert a sync_point, this is needed to make sure that the textures the | 489 // Insert a sync_point, this is needed to make sure that the textures the |
415 // mailboxes refer to will be used only after all the previous commands posted | 490 // mailboxes refer to will be used only after all the previous commands posted |
416 // in the command buffer have been processed. | 491 // in the command buffer have been processed. |
417 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); | 492 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); |
418 for (size_t i = 0; i < planes; ++i) { | 493 for (size_t i = 0; i < num_planes; i += planes_per_copy) |
419 mailbox_holders[i].sync_point = sync_point; | 494 mailbox_holders[i].sync_point = sync_point; |
420 } | |
421 | 495 |
422 scoped_refptr<VideoFrame> frame; | 496 scoped_refptr<VideoFrame> frame; |
423 // Create the VideoFrame backed by native textures. | 497 // Create the VideoFrame backed by native textures. |
424 switch (output_format_) { | 498 switch (output_format_) { |
425 case PIXEL_FORMAT_I420: | 499 case PIXEL_FORMAT_I420: |
426 frame = VideoFrame::WrapYUV420NativeTextures( | 500 frame = VideoFrame::WrapYUV420NativeTextures( |
427 mailbox_holders[VideoFrame::kYPlane], | 501 mailbox_holders[VideoFrame::kYPlane], |
428 mailbox_holders[VideoFrame::kUPlane], | 502 mailbox_holders[VideoFrame::kUPlane], |
429 mailbox_holders[VideoFrame::kVPlane], | 503 mailbox_holders[VideoFrame::kVPlane], |
430 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), | 504 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), |
431 size, video_frame->visible_rect(), video_frame->natural_size(), | 505 size, video_frame->visible_rect(), video_frame->natural_size(), |
432 video_frame->timestamp()); | 506 video_frame->timestamp()); |
433 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) | 507 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) |
434 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); | 508 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); |
435 break; | 509 break; |
| 510 case PIXEL_FORMAT_NV12: |
436 case PIXEL_FORMAT_UYVY: | 511 case PIXEL_FORMAT_UYVY: |
437 frame = VideoFrame::WrapNativeTexture( | 512 frame = VideoFrame::WrapNativeTexture( |
438 PIXEL_FORMAT_UYVY, mailbox_holders[VideoFrame::kYPlane], | 513 output_format_, mailbox_holders[VideoFrame::kYPlane], |
439 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), | 514 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), |
440 size, video_frame->visible_rect(), video_frame->natural_size(), | 515 size, video_frame->visible_rect(), video_frame->natural_size(), |
441 video_frame->timestamp()); | 516 video_frame->timestamp()); |
442 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); | 517 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); |
443 break; | 518 break; |
444 default: | 519 default: |
445 NOTREACHED(); | 520 NOTREACHED(); |
446 } | 521 } |
447 frame_ready_cb.Run(frame); | 522 frame_ready_cb.Run(frame); |
448 } | 523 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 } else { | 556 } else { |
482 it++; | 557 it++; |
483 } | 558 } |
484 } | 559 } |
485 | 560 |
486 // Create the resources. | 561 // Create the resources. |
487 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); | 562 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); |
488 if (!gles2) | 563 if (!gles2) |
489 return nullptr; | 564 return nullptr; |
490 gles2->ActiveTexture(GL_TEXTURE0); | 565 gles2->ActiveTexture(GL_TEXTURE0); |
491 size_t planes = VideoFrame::NumPlanes(format); | 566 size_t num_planes = VideoFrame::NumPlanes(format); |
492 FrameResources* frame_resources = new FrameResources(size); | 567 FrameResources* frame_resources = new FrameResources(size); |
493 resources_pool_.push_back(frame_resources); | 568 resources_pool_.push_back(frame_resources); |
494 for (size_t i = 0; i < planes; ++i) { | 569 for (size_t i = 0; i < num_planes; i += PlanesPerCopy(format)) { |
495 PlaneResource& plane_resource = frame_resources->plane_resources[i]; | 570 PlaneResource& plane_resource = frame_resources->plane_resources[i]; |
496 const size_t width = VideoFrame::Columns(i, format, size.width()); | 571 const size_t width = VideoFrame::Columns(i, format, size.width()); |
497 const size_t height = VideoFrame::Rows(i, format, size.height()); | 572 const size_t height = VideoFrame::Rows(i, format, size.height()); |
498 const gfx::Size plane_size(width, height); | 573 const gfx::Size plane_size(width, height); |
499 | 574 |
| 575 const gfx::BufferFormat buffer_format = GpuMemoryBufferFormat(format, i); |
500 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( | 576 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( |
501 plane_size, GpuMemoryBufferFormat(format, i), gfx::BufferUsage::MAP); | 577 plane_size, buffer_format, gfx::BufferUsage::MAP); |
502 | 578 |
503 gles2->GenTextures(1, &plane_resource.texture_id); | 579 gles2->GenTextures(1, &plane_resource.texture_id); |
504 gles2->BindTexture(texture_target_, plane_resource.texture_id); | 580 gles2->BindTexture(texture_target_, plane_resource.texture_id); |
505 gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 581 gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
506 gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 582 gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
507 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 583 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
508 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 584 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
509 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name); | 585 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name); |
510 gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name); | 586 gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name); |
511 } | 587 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 } | 644 } |
569 | 645 |
570 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( | 646 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( |
571 const scoped_refptr<VideoFrame>& video_frame, | 647 const scoped_refptr<VideoFrame>& video_frame, |
572 const FrameReadyCB& frame_ready_cb) { | 648 const FrameReadyCB& frame_ready_cb) { |
573 DCHECK(video_frame); | 649 DCHECK(video_frame); |
574 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); | 650 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); |
575 } | 651 } |
576 | 652 |
577 } // namespace media | 653 } // namespace media |
OLD | NEW |