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 |