| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "cc/resources/video_resource_updater.h" | 5 #include "cc/resources/video_resource_updater.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bit_cast.h" | 13 #include "base/bit_cast.h" |
| 14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 15 #include "cc/base/math_util.h" | 15 #include "cc/base/math_util.h" |
| 16 #include "cc/output/gl_renderer.h" | 16 #include "cc/output/gl_renderer.h" |
| 17 #include "cc/resources/resource_provider.h" | 17 #include "cc/resources/resource_provider.h" |
| 18 #include "cc/resources/resource_util.h" | 18 #include "cc/resources/resource_util.h" |
| 19 #include "gpu/GLES2/gl2extchromium.h" | 19 #include "gpu/GLES2/gl2extchromium.h" |
| 20 #include "gpu/command_buffer/client/gles2_interface.h" | 20 #include "gpu/command_buffer/client/gles2_interface.h" |
| 21 #include "media/base/media_switches.h" |
| 21 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
| 22 #include "media/renderers/skcanvas_video_renderer.h" | 23 #include "media/renderers/skcanvas_video_renderer.h" |
| 23 #include "third_party/khronos/GLES2/gl2.h" | 24 #include "third_party/khronos/GLES2/gl2.h" |
| 24 #include "third_party/khronos/GLES2/gl2ext.h" | 25 #include "third_party/khronos/GLES2/gl2ext.h" |
| 25 #include "third_party/libyuv/include/libyuv.h" | 26 #include "third_party/libyuv/include/libyuv.h" |
| 26 #include "third_party/skia/include/core/SkCanvas.h" | 27 #include "third_party/skia/include/core/SkCanvas.h" |
| 27 #include "ui/gfx/geometry/size_conversions.h" | 28 #include "ui/gfx/geometry/size_conversions.h" |
| 28 | 29 |
| 29 namespace cc { | 30 namespace cc { |
| 30 | 31 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 void VideoResourceUpdater::PlaneResource::SetUniqueId(int unique_frame_id, | 151 void VideoResourceUpdater::PlaneResource::SetUniqueId(int unique_frame_id, |
| 151 size_t plane_index) { | 152 size_t plane_index) { |
| 152 DCHECK_EQ(ref_count_, 1); | 153 DCHECK_EQ(ref_count_, 1); |
| 153 plane_index_ = plane_index; | 154 plane_index_ = plane_index; |
| 154 unique_frame_id_ = unique_frame_id; | 155 unique_frame_id_ = unique_frame_id; |
| 155 has_unique_frame_id_and_plane_index_ = true; | 156 has_unique_frame_id_and_plane_index_ = true; |
| 156 } | 157 } |
| 157 | 158 |
| 158 VideoFrameExternalResources::VideoFrameExternalResources() | 159 VideoFrameExternalResources::VideoFrameExternalResources() |
| 159 : type(NONE), | 160 : type(NONE), |
| 161 format(RGBA_8888), |
| 160 read_lock_fences_enabled(false), | 162 read_lock_fences_enabled(false), |
| 161 offset(0.0f), | 163 offset(0.0f), |
| 162 multiplier(1.0f), | 164 multiplier(1.0f), |
| 163 bits_per_channel(8) {} | 165 bits_per_channel(8) {} |
| 164 | 166 |
| 165 VideoFrameExternalResources::VideoFrameExternalResources( | 167 VideoFrameExternalResources::VideoFrameExternalResources( |
| 166 const VideoFrameExternalResources& other) = default; | 168 const VideoFrameExternalResources& other) = default; |
| 167 | 169 |
| 168 VideoFrameExternalResources::~VideoFrameExternalResources() {} | 170 VideoFrameExternalResources::~VideoFrameExternalResources() {} |
| 169 | 171 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 uint16_t* dst) { | 303 uint16_t* dst) { |
| 302 // Source and dest stride can be zero since we're only copying | 304 // Source and dest stride can be zero since we're only copying |
| 303 // one row at a time. | 305 // one row at a time. |
| 304 int stride = 0; | 306 int stride = 0; |
| 305 // Maximum value used in |src|. | 307 // Maximum value used in |src|. |
| 306 int max_value = (1 << bits_per_channel) - 1; | 308 int max_value = (1 << bits_per_channel) - 1; |
| 307 int rows = 1; | 309 int rows = 1; |
| 308 libyuv::HalfFloatPlane(src, stride, dst, stride, 1.0f / max_value, num, rows); | 310 libyuv::HalfFloatPlane(src, stride, dst, stride, 1.0f / max_value, num, rows); |
| 309 } | 311 } |
| 310 | 312 |
| 313 ResourceFormat VideoResourceUpdater::YuvResourceFormat(int bits) const { |
| 314 if (!context_provider_) |
| 315 return LUMINANCE_8; |
| 316 |
| 317 const auto caps = context_provider_->ContextCapabilities(); |
| 318 if (caps.disable_one_component_textures) |
| 319 return RGBA_8888; |
| 320 |
| 321 ResourceFormat yuv_resource_format = caps.texture_rg ? RED_8 : LUMINANCE_8; |
| 322 if (bits <= 8) |
| 323 return yuv_resource_format; |
| 324 |
| 325 if (caps.texture_half_float_linear) |
| 326 return LUMINANCE_F16; |
| 327 |
| 328 if (base::FeatureList::IsEnabled(media::kUseRGTexture) || use_rg_for_testing_) |
| 329 return caps.texture_rg ? RG_88 : RGBA_8888; |
| 330 |
| 331 return yuv_resource_format; |
| 332 } |
| 333 |
| 311 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( | 334 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| 312 scoped_refptr<media::VideoFrame> video_frame) { | 335 scoped_refptr<media::VideoFrame> video_frame) { |
| 313 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); | 336 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); |
| 314 const media::VideoPixelFormat input_frame_format = video_frame->format(); | 337 const media::VideoPixelFormat input_frame_format = video_frame->format(); |
| 315 | 338 |
| 316 // TODO(hubbe): Make this a video frame method. | 339 // TODO(hubbe): Make this a video frame method. |
| 340 // TODO(dshwang): handle YUV4XXPX by GMBs pool code. crbug.com/445071 |
| 317 int bits_per_channel = 0; | 341 int bits_per_channel = 0; |
| 318 switch (input_frame_format) { | 342 switch (input_frame_format) { |
| 319 case media::PIXEL_FORMAT_UNKNOWN: | 343 case media::PIXEL_FORMAT_UNKNOWN: |
| 320 NOTREACHED(); | 344 NOTREACHED(); |
| 321 // Fall through! | 345 // Fall through! |
| 322 case media::PIXEL_FORMAT_I420: | 346 case media::PIXEL_FORMAT_I420: |
| 323 case media::PIXEL_FORMAT_YV12: | 347 case media::PIXEL_FORMAT_YV12: |
| 324 case media::PIXEL_FORMAT_YV16: | 348 case media::PIXEL_FORMAT_YV16: |
| 325 case media::PIXEL_FORMAT_YV12A: | 349 case media::PIXEL_FORMAT_YV12A: |
| 326 case media::PIXEL_FORMAT_YV24: | 350 case media::PIXEL_FORMAT_YV24: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 350 case media::PIXEL_FORMAT_YUV420P12: | 374 case media::PIXEL_FORMAT_YUV420P12: |
| 351 case media::PIXEL_FORMAT_YUV422P12: | 375 case media::PIXEL_FORMAT_YUV422P12: |
| 352 case media::PIXEL_FORMAT_YUV444P12: | 376 case media::PIXEL_FORMAT_YUV444P12: |
| 353 bits_per_channel = 12; | 377 bits_per_channel = 12; |
| 354 break; | 378 break; |
| 355 case media::PIXEL_FORMAT_Y16: | 379 case media::PIXEL_FORMAT_Y16: |
| 356 bits_per_channel = 16; | 380 bits_per_channel = 16; |
| 357 break; | 381 break; |
| 358 } | 382 } |
| 359 | 383 |
| 360 // TODO(dshwang): support PIXEL_FORMAT_Y16. crbug.com/624436 | |
| 361 DCHECK_NE(bits_per_channel, 16); | |
| 362 | |
| 363 // Only YUV software video frames are supported. | 384 // Only YUV software video frames are supported. |
| 364 if (!media::IsYuvPlanar(input_frame_format)) { | 385 if (!media::IsYuvPlanar(input_frame_format)) { |
| 365 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); | 386 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); |
| 366 return VideoFrameExternalResources(); | 387 return VideoFrameExternalResources(); |
| 367 } | 388 } |
| 368 | 389 |
| 369 const bool software_compositor = context_provider_ == NULL; | 390 const bool software_compositor = context_provider_ == nullptr; |
| 391 bool disable_one_component_textures = true; |
| 392 if (!software_compositor) { |
| 393 const auto caps = context_provider_->ContextCapabilities(); |
| 394 disable_one_component_textures = caps.disable_one_component_textures; |
| 395 } |
| 370 | 396 |
| 371 ResourceFormat output_resource_format = | 397 ResourceFormat output_resource_format = YuvResourceFormat(bits_per_channel); |
| 372 resource_provider_->YuvResourceFormat(bits_per_channel); | |
| 373 | 398 |
| 374 // If GPU compositing is enabled, but the output resource format | 399 // If GPU compositing is enabled, but the output resource format |
| 375 // returned by the resource provider is RGBA_8888, then a GPU driver | 400 // returned by the resource provider is RGBA_8888, then a GPU driver |
| 376 // bug workaround requires that YUV frames must be converted to RGB | 401 // bug workaround requires that YUV frames must be converted to RGB |
| 377 // before texture upload. | 402 // before texture upload. |
| 378 bool texture_needs_rgb_conversion = | 403 bool texture_needs_rgb_conversion = |
| 379 !software_compositor && | 404 !software_compositor && disable_one_component_textures; |
| 380 output_resource_format == ResourceFormat::RGBA_8888; | |
| 381 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 405 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
| 382 | 406 |
| 383 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 407 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
| 384 // conversion here. That involves an extra copy of each frame to a bitmap. | 408 // conversion here. That involves an extra copy of each frame to a bitmap. |
| 385 // Obviously, this is suboptimal and should be addressed once ubercompositor | 409 // Obviously, this is suboptimal and should be addressed once ubercompositor |
| 386 // starts shaping up. | 410 // starts shaping up. |
| 387 if (software_compositor || texture_needs_rgb_conversion) { | 411 if (software_compositor || texture_needs_rgb_conversion) { |
| 388 output_resource_format = kRGBResourceFormat; | 412 output_resource_format = kRGBResourceFormat; |
| 389 output_plane_count = 1; | 413 output_plane_count = 1; |
| 390 bits_per_channel = 8; | 414 bits_per_channel = 8; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 417 ResourceList::iterator resource_it = RecycleOrAllocateResource( | 441 ResourceList::iterator resource_it = RecycleOrAllocateResource( |
| 418 output_plane_resource_size, output_resource_format, | 442 output_plane_resource_size, output_resource_format, |
| 419 video_frame->ColorSpace(), software_compositor, is_immutable, | 443 video_frame->ColorSpace(), software_compositor, is_immutable, |
| 420 video_frame->unique_id(), i); | 444 video_frame->unique_id(), i); |
| 421 | 445 |
| 422 resource_it->add_ref(); | 446 resource_it->add_ref(); |
| 423 plane_resources.push_back(resource_it); | 447 plane_resources.push_back(resource_it); |
| 424 } | 448 } |
| 425 | 449 |
| 426 VideoFrameExternalResources external_resources; | 450 VideoFrameExternalResources external_resources; |
| 427 | |
| 428 external_resources.bits_per_channel = bits_per_channel; | 451 external_resources.bits_per_channel = bits_per_channel; |
| 452 external_resources.format = output_resource_format; |
| 429 | 453 |
| 430 if (software_compositor || texture_needs_rgb_conversion) { | 454 if (software_compositor || texture_needs_rgb_conversion) { |
| 431 DCHECK_EQ(plane_resources.size(), 1u); | 455 DCHECK_EQ(plane_resources.size(), 1u); |
| 432 PlaneResource& plane_resource = *plane_resources[0]; | 456 PlaneResource& plane_resource = *plane_resources[0]; |
| 433 DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat); | 457 DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat); |
| 434 DCHECK_EQ(software_compositor, plane_resource.mailbox().IsZero()); | 458 DCHECK_EQ(software_compositor, plane_resource.mailbox().IsZero()); |
| 435 | 459 |
| 436 if (!plane_resource.Matches(video_frame->unique_id(), 0)) { | 460 if (!plane_resource.Matches(video_frame->unique_id(), 0)) { |
| 437 // We need to transfer data from |video_frame| to the plane resource. | 461 // We need to transfer data from |video_frame| to the plane resource. |
| 438 if (software_compositor) { | 462 if (software_compositor) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 plane_resource.resource_id())); | 500 plane_resource.resource_id())); |
| 477 mailbox.set_color_space(video_frame->ColorSpace()); | 501 mailbox.set_color_space(video_frame->ColorSpace()); |
| 478 external_resources.mailboxes.push_back(mailbox); | 502 external_resources.mailboxes.push_back(mailbox); |
| 479 external_resources.release_callbacks.push_back(base::Bind( | 503 external_resources.release_callbacks.push_back(base::Bind( |
| 480 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); | 504 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); |
| 481 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; | 505 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; |
| 482 } | 506 } |
| 483 return external_resources; | 507 return external_resources; |
| 484 } | 508 } |
| 485 | 509 |
| 486 for (size_t i = 0; i < plane_resources.size(); ++i) { | 510 const bool highbit_rg_rgba_fallback = |
| 487 PlaneResource& plane_resource = *plane_resources[i]; | 511 bits_per_channel > 8 && output_resource_format == RGBA_8888; |
| 512 bool needs_conversion = false; |
| 513 int shift = 0; |
| 514 if (output_resource_format == LUMINANCE_F16) { |
| 515 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. |
| 516 needs_conversion = true; |
| 517 } else if (output_resource_format == RG_88) { |
| 518 // RG_88 can represent 16bit int, so we don't need a conversion step. |
| 519 needs_conversion = false; |
| 520 } else if (highbit_rg_rgba_fallback) { |
| 521 // RG channels is used to represent 16bit int. |
| 522 needs_conversion = true; |
| 523 } else if (bits_per_channel > 8) { |
| 524 // If bits_per_channel > 8 and we can't use RG_88, we need to |
| 525 // shift the data down and create an 8-bit texture. |
| 526 needs_conversion = true; |
| 527 shift = bits_per_channel - 8; |
| 528 external_resources.bits_per_channel = 8; |
| 529 } |
| 530 |
| 531 for (size_t plane = 0; plane < plane_resources.size(); ++plane) { |
| 532 PlaneResource& plane_resource = *plane_resources[plane]; |
| 488 // Update each plane's resource id with its content. | 533 // Update each plane's resource id with its content. |
| 489 DCHECK_EQ(plane_resource.resource_format(), | 534 DCHECK_EQ(plane_resource.resource_format(), output_resource_format); |
| 490 resource_provider_->YuvResourceFormat(bits_per_channel)); | |
| 491 | 535 |
| 492 if (!plane_resource.Matches(video_frame->unique_id(), i)) { | 536 if (!plane_resource.Matches(video_frame->unique_id(), plane)) { |
| 493 // TODO(hubbe): Move all conversion (and upload?) code to media/. | 537 // TODO(hubbe): Move all conversion (and upload?) code to media/. |
| 494 // We need to transfer data from |video_frame| to the plane resource. | 538 // We need to transfer data from |video_frame| to the plane resource. |
| 495 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. | 539 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. |
| 496 | 540 |
| 497 // The |resource_size_pixels| is the size of the resource we want to | 541 // The |resource_size_pixels| is the size of the resource we want to |
| 498 // upload to. | 542 // upload to. |
| 499 gfx::Size resource_size_pixels = plane_resource.resource_size(); | 543 gfx::Size resource_size_pixels = plane_resource.resource_size(); |
| 500 // The |video_stride_bytes| is the width of the video frame we are | 544 // The |video_stride_bytes| is the width of the video frame we are |
| 501 // uploading (including non-frame data to fill in the stride). | 545 // uploading (including non-frame data to fill in the stride). |
| 502 int video_stride_bytes = video_frame->stride(i); | 546 int video_stride_bytes = video_frame->stride(plane); |
| 503 | 547 |
| 504 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( | 548 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
| 505 resource_size_pixels.width(), plane_resource.resource_format()); | 549 resource_size_pixels.width(), output_resource_format); |
| 506 // Use 4-byte row alignment (OpenGL default) for upload performance. | 550 // Use 4-byte row alignment (OpenGL default) for upload performance. |
| 507 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. | 551 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. |
| 508 size_t upload_image_stride = | 552 size_t upload_image_stride = |
| 509 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); | 553 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); |
| 510 | 554 |
| 511 bool needs_conversion = false; | |
| 512 int shift = 0; | |
| 513 | |
| 514 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. | |
| 515 if (plane_resource.resource_format() == LUMINANCE_F16) { | |
| 516 needs_conversion = true; | |
| 517 } else if (bits_per_channel > 8) { | |
| 518 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to | |
| 519 // shift the data down and create an 8-bit texture. | |
| 520 needs_conversion = true; | |
| 521 shift = bits_per_channel - 8; | |
| 522 } | |
| 523 const uint8_t* pixels; | 555 const uint8_t* pixels; |
| 524 if (static_cast<int>(upload_image_stride) == video_stride_bytes && | 556 if (static_cast<int>(upload_image_stride) == video_stride_bytes && |
| 525 !needs_conversion) { | 557 !needs_conversion) { |
| 526 pixels = video_frame->data(i); | 558 pixels = video_frame->data(plane); |
| 527 } else { | 559 } else { |
| 528 // Avoid malloc for each frame/plane if possible. | 560 // Avoid malloc for each frame/plane if possible. |
| 529 size_t needed_size = | 561 size_t needed_size = |
| 530 upload_image_stride * resource_size_pixels.height(); | 562 upload_image_stride * resource_size_pixels.height(); |
| 531 if (upload_pixels_.size() < needed_size) | 563 if (upload_pixels_.size() < needed_size) |
| 532 upload_pixels_.resize(needed_size); | 564 upload_pixels_.resize(needed_size); |
| 533 | 565 |
| 534 for (int row = 0; row < resource_size_pixels.height(); ++row) { | 566 for (int row = 0; row < resource_size_pixels.height(); ++row) { |
| 535 if (plane_resource.resource_format() == LUMINANCE_F16) { | 567 if (output_resource_format == LUMINANCE_F16) { |
| 536 uint16_t* dst = reinterpret_cast<uint16_t*>( | 568 uint16_t* dst = reinterpret_cast<uint16_t*>( |
| 537 &upload_pixels_[upload_image_stride * row]); | 569 &upload_pixels_[upload_image_stride * row]); |
| 538 const uint16_t* src = reinterpret_cast<uint16_t*>( | 570 const uint16_t* src = reinterpret_cast<uint16_t*>( |
| 539 video_frame->data(i) + (video_stride_bytes * row)); | 571 video_frame->data(plane) + (video_stride_bytes * row)); |
| 540 if (bits_per_channel <= 10) { | 572 if (bits_per_channel <= 10) { |
| 541 // Micro-benchmarking indicates that the compiler does | 573 // Micro-benchmarking indicates that the compiler does |
| 542 // a good enough job of optimizing this loop that trying | 574 // a good enough job of optimizing this loop that trying |
| 543 // to manually operate on one uint64 at a time is not | 575 // to manually operate on one uint64 at a time is not |
| 544 // actually helpful. | 576 // actually helpful. |
| 545 // Note to future optimizers: Benchmark your optimizations! | 577 // Note to future optimizers: Benchmark your optimizations! |
| 546 for (size_t i = 0; i < bytes_per_row / 2; i++) | 578 for (size_t i = 0; i < bytes_per_row / 2; i++) |
| 547 dst[i] = src[i] | 0x3800; | 579 dst[i] = src[i] | 0x3800; |
| 548 } else { | 580 } else { |
| 549 MakeHalfFloats(src, bits_per_channel, bytes_per_row / 2, dst); | 581 MakeHalfFloats(src, bits_per_channel, bytes_per_row / 2, dst); |
| 550 } | 582 } |
| 583 } else if (highbit_rg_rgba_fallback) { |
| 584 uint32_t* dst = reinterpret_cast<uint32_t*>( |
| 585 &upload_pixels_[upload_image_stride * row]); |
| 586 const uint16_t* src = reinterpret_cast<uint16_t*>( |
| 587 video_frame->data(plane) + (video_stride_bytes * row)); |
| 588 for (int i = 0; i < resource_size_pixels.width(); i++) |
| 589 dst[i] = src[i]; |
| 551 } else if (shift != 0) { | 590 } else if (shift != 0) { |
| 552 // We have more-than-8-bit input which we need to shift | 591 // We have more-than-8-bit input which we need to shift |
| 553 // down to fit it into an 8-bit texture. | 592 // down to fit it into an 8-bit texture. |
| 554 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; | 593 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; |
| 555 const uint16_t* src = reinterpret_cast<uint16_t*>( | 594 const uint16_t* src = reinterpret_cast<uint16_t*>( |
| 556 video_frame->data(i) + (video_stride_bytes * row)); | 595 video_frame->data(plane) + (video_stride_bytes * row)); |
| 557 for (size_t i = 0; i < bytes_per_row; i++) | 596 for (size_t i = 0; i < bytes_per_row; i++) |
| 558 dst[i] = src[i] >> shift; | 597 dst[i] = src[i] >> shift; |
| 559 } else { | 598 } else { |
| 560 // Input and output are the same size and format, but | 599 // Input and output are the same size and format, but |
| 561 // differ in stride, copy one row at a time. | 600 // differ in stride, copy one row at a time. |
| 562 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; | 601 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; |
| 563 const uint8_t* src = | 602 const uint8_t* src = |
| 564 video_frame->data(i) + (video_stride_bytes * row); | 603 video_frame->data(plane) + (video_stride_bytes * row); |
| 565 memcpy(dst, src, bytes_per_row); | 604 memcpy(dst, src, bytes_per_row); |
| 566 } | 605 } |
| 567 } | 606 } |
| 568 pixels = &upload_pixels_[0]; | 607 pixels = &upload_pixels_[0]; |
| 569 } | 608 } |
| 570 | 609 |
| 571 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, | 610 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, |
| 572 resource_size_pixels); | 611 resource_size_pixels); |
| 573 plane_resource.SetUniqueId(video_frame->unique_id(), i); | 612 plane_resource.SetUniqueId(video_frame->unique_id(), plane); |
| 574 } | 613 } |
| 575 | 614 |
| 576 if (plane_resource.resource_format() == LUMINANCE_F16) { | 615 if (plane_resource.resource_format() == LUMINANCE_F16) { |
| 577 // If the input data was 9 or 10 bit, and we output to half-floats, | 616 // If the input data was 9 or 10 bit, and we output to half-floats, |
| 578 // then we used the OR path above, which means that we need to | 617 // then we used the OR path above, which means that we need to |
| 579 // adjust the resource offset and multiplier accordingly. If the | 618 // adjust the resource offset and multiplier accordingly. If the |
| 580 // input data uses more than 10 bits, it will already be normalized | 619 // input data uses more than 10 bits, it will already be normalized |
| 581 // to 0.0..1.0, so there is no need to do anything. | 620 // to 0.0..1.0, so there is no need to do anything. |
| 582 if (bits_per_channel <= 10) { | 621 if (bits_per_channel <= 10) { |
| 583 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the | 622 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 if (lost_resource) { | 801 if (lost_resource) { |
| 763 resource_it->clear_refs(); | 802 resource_it->clear_refs(); |
| 764 updater->DeleteResource(resource_it); | 803 updater->DeleteResource(resource_it); |
| 765 return; | 804 return; |
| 766 } | 805 } |
| 767 | 806 |
| 768 resource_it->remove_ref(); | 807 resource_it->remove_ref(); |
| 769 } | 808 } |
| 770 | 809 |
| 771 } // namespace cc | 810 } // namespace cc |
| OLD | NEW |