Chromium Code Reviews| Index: cc/resources/video_resource_updater.cc |
| diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc |
| index 2584e0b3a83308af23ac83893c244a9badc04111..794ed7bc2a64110a0f8b758289d345dedce93aeb 100644 |
| --- a/cc/resources/video_resource_updater.cc |
| +++ b/cc/resources/video_resource_updater.cc |
| @@ -84,6 +84,9 @@ VideoFrameExternalResources::ResourceType ResourceTypeForVideoFrame( |
| case media::PIXEL_FORMAT_YUV420P10: |
| case media::PIXEL_FORMAT_YUV422P10: |
| case media::PIXEL_FORMAT_YUV444P10: |
| + case media::PIXEL_FORMAT_YUV420P12: |
| + case media::PIXEL_FORMAT_YUV422P12: |
| + case media::PIXEL_FORMAT_YUV444P12: |
| case media::PIXEL_FORMAT_UNKNOWN: |
| break; |
| } |
| @@ -289,6 +292,25 @@ static gfx::Size SoftwarePlaneDimension(media::VideoFrame* input_frame, |
| return gfx::Size(plane_width, plane_height); |
| } |
| +void VideoResourceUpdater::MakeHalfFloats(const uint16_t* src, |
| + int bits_per_channel, |
| + size_t num, |
| + uint16_t* dst) { |
| + // TODO(hubbe): Make AVX and neon versions of this code. |
| + |
| + // This magic constant is 2^-112. Multiplying by this |
| + // is the same as subtracting 112 from the exponent, which |
| + // is the difference in exponent bias between 32-bit and |
| + // 16-bit floats. Once we've done this subtraction, we can |
| + // simply extract the low bits of the exponent and the high |
| + // bits of the mantissa from our float and we're done. |
| + float mult = 1.9259299444e-34f / ((1 << bits_per_channel) - 1); |
| + for (size_t i = 0; i < num; i++) { |
| + float value = src[i] * mult; |
| + dst[i] = (*(uint32_t*)&value) >> 13; |
| + } |
| +} |
| + |
| VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| scoped_refptr<media::VideoFrame> video_frame) { |
| TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); |
| @@ -327,6 +349,11 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| case media::PIXEL_FORMAT_YUV444P10: |
| bits_per_channel = 10; |
| break; |
| + case media::PIXEL_FORMAT_YUV420P12: |
| + case media::PIXEL_FORMAT_YUV422P12: |
| + case media::PIXEL_FORMAT_YUV444P12: |
| + bits_per_channel = 12; |
| + break; |
| } |
| // Only YUV software video frames are supported. |
| @@ -482,9 +509,6 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| // LUMINANCE_F16 uses half-floats, so we always need a conversion step. |
| if (plane_resource.resource_format() == LUMINANCE_F16) { |
| needs_conversion = true; |
| - // Note that the current method of converting integers to half-floats |
| - // stops working if you have more than 10 bits of data. |
| - DCHECK_LE(bits_per_channel, 10); |
| } else if (bits_per_channel > 8) { |
| // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to |
| // shift the data down and create an 8-bit texture. |
| @@ -508,13 +532,17 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| &upload_pixels_[upload_image_stride * row]); |
| const uint16_t* src = reinterpret_cast<uint16_t*>( |
| video_frame->data(i) + (video_stride_bytes * row)); |
| - // Micro-benchmarking indicates that the compiler does |
| - // a good enough job of optimizing this loop that trying |
| - // to manually operate on one uint64 at a time is not |
| - // actually helpful. |
| - // Note to future optimizers: Benchmark your optimizations! |
| - for (size_t i = 0; i < bytes_per_row / 2; i++) |
| - dst[i] = src[i] | 0x3800; |
| + if (bits_per_channel <= 10) { |
| + // Micro-benchmarking indicates that the compiler does |
| + // a good enough job of optimizing this loop that trying |
| + // to manually operate on one uint64 at a time is not |
| + // actually helpful. |
| + // Note to future optimizers: Benchmark your optimizations! |
| + for (size_t i = 0; i < bytes_per_row / 2; i++) |
| + dst[i] = src[i] | 0x3800; |
| + } else { |
| + MakeHalfFloats(src, bits_per_channel, bytes_per_row / 2, dst); |
| + } |
| } else if (shift != 0) { |
| // We have more-than-8-bit input which we need to shift |
| // down to fit it into an 8-bit texture. |
| @@ -540,7 +568,13 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| plane_resource.SetUniqueId(video_frame->unique_id(), i); |
| } |
| - if (plane_resource.resource_format() == LUMINANCE_F16) { |
| + // If the input data was 9 or 10 bit, and we output to half-floats, |
| + // then we used the OR path above, which means that we need to |
| + // adjust the resource offset and multiplier accordingly. If the |
| + // input data uses more than 10 bits, it will already be normalized |
| + // to 0.0..1.0, so there is no need to do anything. |
| + if (plane_resource.resource_format() == LUMINANCE_F16 && |
|
danakj
2016/09/27 20:49:11
One more thought, we're doing this if thing twice
hubbe
2016/09/27 22:27:36
I don't really want to set a bool in every row, bu
danakj
2016/09/27 22:37:51
That's cool too if you agree it's more clear
|
| + bits_per_channel <= 10) { |
| // By OR-ing with 0x3800, 10-bit numbers become half-floats in the |
| // range [0.5..1) and 9-bit numbers get the range [0.5..0.75). |
| // |
| @@ -554,7 +588,6 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| // |
| // (https://en.wikipedia.org/wiki/Half-precision_floating-point_format) |
| // |
| - // PLEASE NOTE: This doesn't work if bits_per_channel is > 10. |
| // PLEASE NOTE: All planes are assumed to use the same multiplier/offset. |
| external_resources.offset = 0.5f; |
| // Max value from input data. |