Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(726)

Unified Diff: cc/resources/video_resource_updater.cc

Issue 2370453003: 12-bit vp9 video support (Closed)
Patch Set: build fix Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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.

Powered by Google App Engine
This is Rietveld 408576698