Chromium Code Reviews| 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 void CopyRowsToI420Buffer(int first_row, | 219 void CopyRowsToI420Buffer(int first_row, |
| 220 int rows, | 220 int rows, |
| 221 int bytes_per_row, | 221 int bytes_per_row, |
| 222 const uint8* source, | 222 const uint8* source, |
| 223 int source_stride, | 223 int source_stride, |
| 224 uint8* output, | 224 uint8* output, |
| 225 int dest_stride, | 225 int dest_stride, |
| 226 const base::Closure& done) { | 226 const base::Closure& done) { |
| 227 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, | 227 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, |
| 228 "rows", rows); | 228 "rows", rows); |
| 229 DCHECK_NE(dest_stride, 0); | 229 if (output) { |
| 230 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); | 230 DCHECK_NE(dest_stride, 0); |
| 231 DCHECK_LE(bytes_per_row, source_stride); | 231 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); |
| 232 for (int row = first_row; row < first_row + rows; ++row) { | 232 DCHECK_LE(bytes_per_row, source_stride); |
| 233 memcpy(output + dest_stride * row, source + source_stride * row, | 233 for (int row = first_row; row < first_row + rows; ++row) { |
| 234 bytes_per_row); | 234 memcpy(output + dest_stride * row, source + source_stride * row, |
| 235 bytes_per_row); | |
| 236 } | |
| 235 } | 237 } |
| 236 done.Run(); | 238 done.Run(); |
| 237 } | 239 } |
| 238 | 240 |
| 239 void CopyRowsToNV12Buffer(int first_row, | 241 void CopyRowsToNV12Buffer(int first_row, |
| 240 int rows, | 242 int rows, |
| 241 int bytes_per_row, | 243 int bytes_per_row, |
| 242 const scoped_refptr<VideoFrame>& source_frame, | 244 const scoped_refptr<VideoFrame>& source_frame, |
| 243 uint8* dest_y, | 245 uint8* dest_y, |
| 244 int dest_stride_y, | 246 int dest_stride_y, |
| 245 uint8* dest_uv, | 247 uint8* dest_uv, |
| 246 int dest_stride_uv, | 248 int dest_stride_uv, |
| 247 const base::Closure& done) { | 249 const base::Closure& done) { |
| 248 TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "bytes_per_row", bytes_per_row, | 250 TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "bytes_per_row", bytes_per_row, |
| 249 "rows", rows); | 251 "rows", rows); |
| 250 DCHECK_NE(dest_stride_y, 0); | 252 if (dest_y && dest_uv) { |
| 251 DCHECK_NE(dest_stride_uv, 0); | 253 DCHECK_NE(dest_stride_y, 0); |
| 252 DCHECK_LE(bytes_per_row, std::abs(dest_stride_y)); | 254 DCHECK_NE(dest_stride_uv, 0); |
| 253 DCHECK_LE(bytes_per_row, std::abs(dest_stride_uv)); | 255 DCHECK_LE(bytes_per_row, std::abs(dest_stride_y)); |
| 254 DCHECK_EQ(0, first_row % 2); | 256 DCHECK_LE(bytes_per_row, std::abs(dest_stride_uv)); |
| 255 libyuv::I420ToNV12( | 257 DCHECK_EQ(0, first_row % 2); |
| 256 source_frame->data(VideoFrame::kYPlane) + | 258 |
| 257 first_row * source_frame->stride(VideoFrame::kYPlane), | 259 libyuv::I420ToNV12( |
| 258 source_frame->stride(VideoFrame::kYPlane), | 260 source_frame->data(VideoFrame::kYPlane) + |
| 259 source_frame->data(VideoFrame::kUPlane) + | 261 first_row * source_frame->stride(VideoFrame::kYPlane), |
| 260 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), | 262 source_frame->stride(VideoFrame::kYPlane), |
| 261 source_frame->stride(VideoFrame::kUPlane), | 263 source_frame->data(VideoFrame::kUPlane) + |
| 262 source_frame->data(VideoFrame::kVPlane) + | 264 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), |
| 263 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), | 265 source_frame->stride(VideoFrame::kUPlane), |
| 264 source_frame->stride(VideoFrame::kVPlane), | 266 source_frame->data(VideoFrame::kVPlane) + |
| 265 dest_y + first_row * dest_stride_y, dest_stride_y, | 267 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), |
| 266 dest_uv + first_row / 2 * dest_stride_uv, dest_stride_uv, | 268 source_frame->stride(VideoFrame::kVPlane), |
| 267 bytes_per_row, rows); | 269 dest_y + first_row * dest_stride_y, dest_stride_y, |
| 270 dest_uv + first_row / 2 * dest_stride_uv, dest_stride_uv, bytes_per_row, | |
| 271 rows); | |
| 272 } | |
| 268 done.Run(); | 273 done.Run(); |
| 269 } | 274 } |
| 270 | 275 |
| 271 void CopyRowsToUYVYBuffer(int first_row, | 276 void CopyRowsToUYVYBuffer(int first_row, |
| 272 int rows, | 277 int rows, |
| 273 int width, | 278 int width, |
| 274 const scoped_refptr<VideoFrame>& source_frame, | 279 const scoped_refptr<VideoFrame>& source_frame, |
| 275 uint8* output, | 280 uint8* output, |
| 276 int dest_stride, | 281 int dest_stride, |
| 277 const base::Closure& done) { | 282 const base::Closure& done) { |
| 278 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2, | 283 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2, |
| 279 "rows", rows); | 284 "rows", rows); |
| 280 DCHECK_NE(dest_stride, 0); | 285 if (output) { |
| 281 DCHECK_LE(width, std::abs(dest_stride / 2)); | 286 DCHECK_NE(dest_stride, 0); |
| 282 DCHECK_EQ(0, first_row % 2); | 287 DCHECK_LE(width, std::abs(dest_stride / 2)); |
| 283 libyuv::I420ToUYVY( | 288 DCHECK_EQ(0, first_row % 2); |
| 284 source_frame->data(VideoFrame::kYPlane) + | 289 libyuv::I420ToUYVY( |
| 285 first_row * source_frame->stride(VideoFrame::kYPlane), | 290 source_frame->data(VideoFrame::kYPlane) + |
| 286 source_frame->stride(VideoFrame::kYPlane), | 291 first_row * source_frame->stride(VideoFrame::kYPlane), |
| 287 source_frame->data(VideoFrame::kUPlane) + | 292 source_frame->stride(VideoFrame::kYPlane), |
| 288 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), | 293 source_frame->data(VideoFrame::kUPlane) + |
| 289 source_frame->stride(VideoFrame::kUPlane), | 294 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), |
| 290 source_frame->data(VideoFrame::kVPlane) + | 295 source_frame->stride(VideoFrame::kUPlane), |
| 291 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), | 296 source_frame->data(VideoFrame::kVPlane) + |
| 292 source_frame->stride(VideoFrame::kVPlane), | 297 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), |
| 293 output + first_row * dest_stride, dest_stride, width, rows); | 298 source_frame->stride(VideoFrame::kVPlane), |
| 299 output + first_row * dest_stride, dest_stride, width, rows); | |
| 300 } | |
| 294 done.Run(); | 301 done.Run(); |
| 295 } | 302 } |
| 296 | 303 |
| 297 } // unnamed namespace | 304 } // unnamed namespace |
| 298 | 305 |
| 299 // Creates a VideoFrame backed by native textures starting from a software | 306 // Creates a VideoFrame backed by native textures starting from a software |
| 300 // VideoFrame. | 307 // VideoFrame. |
| 301 // The data contained in |video_frame| is copied into the VideoFrame passed to | 308 // The data contained in |video_frame| is copied into the VideoFrame passed to |
| 302 // |frame_ready_cb|. | 309 // |frame_ready_cb|. |
| 303 // This has to be called on the thread where |media_task_runner_| is current. | 310 // This has to be called on the thread where |media_task_runner_| is current. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 frame_ready_cb.Run(video_frame); | 348 frame_ready_cb.Run(video_frame); |
| 342 return; | 349 return; |
| 343 } | 350 } |
| 344 | 351 |
| 345 DCHECK(video_frame->visible_rect().origin().IsOrigin()); | 352 DCHECK(video_frame->visible_rect().origin().IsOrigin()); |
| 346 const gfx::Size size = video_frame->visible_rect().size(); | 353 const gfx::Size size = video_frame->visible_rect().size(); |
| 347 | 354 |
| 348 // Acquire resources. Incompatible ones will be dropped from the pool. | 355 // Acquire resources. Incompatible ones will be dropped from the pool. |
| 349 FrameResources* frame_resources = | 356 FrameResources* frame_resources = |
| 350 GetOrCreateFrameResources(size, output_format_); | 357 GetOrCreateFrameResources(size, output_format_); |
| 351 if (!frame_resources) { | 358 if (!frame_resources) { |
|
DaleCurtis
2015/09/13 18:48:47
I don't understand how this crashed before? Should
Daniele Castagna
2015/09/13 19:31:06
What I think was happening before is the frame_res
| |
| 352 frame_ready_cb.Run(video_frame); | 359 frame_ready_cb.Run(video_frame); |
| 353 return; | 360 return; |
| 354 } | 361 } |
| 355 | 362 |
| 356 worker_task_runner_->PostTask( | 363 worker_task_runner_->PostTask( |
| 357 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, | 364 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, |
| 358 video_frame, frame_resources, frame_ready_cb)); | 365 video_frame, frame_resources, frame_ready_cb)); |
| 359 } | 366 } |
| 360 | 367 |
| 361 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( | 368 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 } | 401 } |
| 395 base::Closure copies_done = | 402 base::Closure copies_done = |
| 396 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, | 403 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, |
| 397 frame_ready_cb); | 404 frame_ready_cb); |
| 398 base::Closure barrier = base::BarrierClosure(copies, copies_done); | 405 base::Closure barrier = base::BarrierClosure(copies, copies_done); |
| 399 | 406 |
| 400 // Post all the async tasks. | 407 // Post all the async tasks. |
| 401 for (size_t i = 0; i < num_planes; i += planes_per_copy) { | 408 for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
| 402 gfx::GpuMemoryBuffer* buffer = | 409 gfx::GpuMemoryBuffer* buffer = |
| 403 frame_resources->plane_resources[i].gpu_memory_buffer.get(); | 410 frame_resources->plane_resources[i].gpu_memory_buffer.get(); |
| 404 DCHECK(buffer); | 411 uint8* dest_buffers[VideoFrame::kMaxPlanes] = {0}; |
| 405 DCHECK_EQ(planes_per_copy, | 412 int dest_strides[VideoFrame::kMaxPlanes] = {0}; |
| 406 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); | 413 if (buffer) { |
| 407 uint8* dest_buffers[VideoFrame::kMaxPlanes]; | 414 DCHECK_EQ(planes_per_copy, |
| 408 int dest_strides[VideoFrame::kMaxPlanes]; | 415 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); |
| 409 bool rv = buffer->Map(reinterpret_cast<void**>(dest_buffers)); | 416 bool rv = buffer->Map(reinterpret_cast<void**>(dest_buffers)); |
| 410 DCHECK(rv); | 417 DCHECK(rv); |
| 411 buffer->GetStride(dest_strides); | 418 buffer->GetStride(dest_strides); |
| 419 } | |
| 412 | 420 |
| 413 const int rows = VideoFrame::Rows(i, output_format_, size.height()); | 421 const int rows = VideoFrame::Rows(i, output_format_, size.height()); |
| 414 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); | 422 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); |
| 415 | 423 |
| 416 for (int row = 0; row < rows; row += rows_per_copy) { | 424 for (int row = 0; row < rows; row += rows_per_copy) { |
| 417 const int rows_to_copy = std::min(rows_per_copy, rows - row); | 425 const int rows_to_copy = std::min(rows_per_copy, rows - row); |
| 418 switch (output_format_) { | 426 switch (output_format_) { |
| 419 case PIXEL_FORMAT_I420: { | 427 case PIXEL_FORMAT_I420: { |
| 420 const int bytes_per_row = | 428 const int bytes_per_row = |
| 421 VideoFrame::RowBytes(i, output_format_, size.width()); | 429 VideoFrame::RowBytes(i, output_format_, size.width()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 return; | 468 return; |
| 461 } | 469 } |
| 462 | 470 |
| 463 const size_t num_planes = VideoFrame::NumPlanes(output_format_); | 471 const size_t num_planes = VideoFrame::NumPlanes(output_format_); |
| 464 const size_t planes_per_copy = PlanesPerCopy(output_format_); | 472 const size_t planes_per_copy = PlanesPerCopy(output_format_); |
| 465 const gfx::Size size = video_frame->visible_rect().size(); | 473 const gfx::Size size = video_frame->visible_rect().size(); |
| 466 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; | 474 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; |
| 467 // Set up the planes creating the mailboxes needed to refer to the textures. | 475 // Set up the planes creating the mailboxes needed to refer to the textures. |
| 468 for (size_t i = 0; i < num_planes; i += planes_per_copy) { | 476 for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
| 469 PlaneResource& plane_resource = frame_resources->plane_resources[i]; | 477 PlaneResource& plane_resource = frame_resources->plane_resources[i]; |
| 470 DCHECK(plane_resource.gpu_memory_buffer); | |
| 471 // Bind the texture and create or rebind the image. | 478 // Bind the texture and create or rebind the image. |
| 472 gles2->BindTexture(texture_target_, plane_resource.texture_id); | 479 gles2->BindTexture(texture_target_, plane_resource.texture_id); |
| 473 | 480 |
| 474 if (!plane_resource.image_id) { | 481 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { |
| 475 const size_t width = VideoFrame::Columns(i, output_format_, size.width()); | 482 const size_t width = VideoFrame::Columns(i, output_format_, size.width()); |
| 476 const size_t height = VideoFrame::Rows(i, output_format_, size.height()); | 483 const size_t height = VideoFrame::Rows(i, output_format_, size.height()); |
| 477 plane_resource.image_id = gles2->CreateImageCHROMIUM( | 484 plane_resource.image_id = gles2->CreateImageCHROMIUM( |
| 478 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, | 485 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, |
| 479 ImageInternalFormat(output_format_, i)); | 486 ImageInternalFormat(output_format_, i)); |
| 480 } else { | 487 } else if (plane_resource.image_id) { |
| 481 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, | 488 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, |
| 482 plane_resource.image_id); | 489 plane_resource.image_id); |
| 483 } | 490 } |
| 484 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); | 491 if (plane_resource.image_id) |
| 492 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); | |
| 485 mailbox_holders[i] = | 493 mailbox_holders[i] = |
| 486 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); | 494 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); |
| 487 } | 495 } |
| 488 | 496 |
| 489 // Insert a sync_point, this is needed to make sure that the textures the | 497 // Insert a sync_point, this is needed to make sure that the textures the |
| 490 // mailboxes refer to will be used only after all the previous commands posted | 498 // mailboxes refer to will be used only after all the previous commands posted |
| 491 // in the command buffer have been processed. | 499 // in the command buffer have been processed. |
| 492 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); | 500 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); |
| 493 for (size_t i = 0; i < num_planes; i += planes_per_copy) | 501 for (size_t i = 0; i < num_planes; i += planes_per_copy) |
| 494 mailbox_holders[i].sync_point = sync_point; | 502 mailbox_holders[i].sync_point = sync_point; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 644 } | 652 } |
| 645 | 653 |
| 646 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( | 654 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( |
| 647 const scoped_refptr<VideoFrame>& video_frame, | 655 const scoped_refptr<VideoFrame>& video_frame, |
| 648 const FrameReadyCB& frame_ready_cb) { | 656 const FrameReadyCB& frame_ready_cb) { |
| 649 DCHECK(video_frame); | 657 DCHECK(video_frame); |
| 650 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); | 658 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); |
| 651 } | 659 } |
| 652 | 660 |
| 653 } // namespace media | 661 } // namespace media |
| OLD | NEW |