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

Side by Side Diff: cc/resources/video_resource_updater.cc

Issue 2370453003: 12-bit vp9 video support (Closed)
Patch Set: comments addressed + comment added Created 4 years, 2 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 unified diff | Download patch
OLDNEW
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>
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 case media::PIXEL_FORMAT_RGB24: 77 case media::PIXEL_FORMAT_RGB24:
78 case media::PIXEL_FORMAT_RGB32: 78 case media::PIXEL_FORMAT_RGB32:
79 case media::PIXEL_FORMAT_MJPEG: 79 case media::PIXEL_FORMAT_MJPEG:
80 case media::PIXEL_FORMAT_MT21: 80 case media::PIXEL_FORMAT_MT21:
81 case media::PIXEL_FORMAT_YUV420P9: 81 case media::PIXEL_FORMAT_YUV420P9:
82 case media::PIXEL_FORMAT_YUV422P9: 82 case media::PIXEL_FORMAT_YUV422P9:
83 case media::PIXEL_FORMAT_YUV444P9: 83 case media::PIXEL_FORMAT_YUV444P9:
84 case media::PIXEL_FORMAT_YUV420P10: 84 case media::PIXEL_FORMAT_YUV420P10:
85 case media::PIXEL_FORMAT_YUV422P10: 85 case media::PIXEL_FORMAT_YUV422P10:
86 case media::PIXEL_FORMAT_YUV444P10: 86 case media::PIXEL_FORMAT_YUV444P10:
87 case media::PIXEL_FORMAT_YUV420P12:
88 case media::PIXEL_FORMAT_YUV422P12:
89 case media::PIXEL_FORMAT_YUV444P12:
87 case media::PIXEL_FORMAT_UNKNOWN: 90 case media::PIXEL_FORMAT_UNKNOWN:
88 break; 91 break;
89 } 92 }
90 return VideoFrameExternalResources::NONE; 93 return VideoFrameExternalResources::NONE;
91 } 94 }
92 95
93 class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient { 96 class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient {
94 public: 97 public:
95 SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl, 98 SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl,
96 const gpu::SyncToken& sync_token) 99 const gpu::SyncToken& sync_token)
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 if (software_compositor) 285 if (software_compositor)
283 return coded_size; 286 return coded_size;
284 287
285 int plane_width = media::VideoFrame::Columns( 288 int plane_width = media::VideoFrame::Columns(
286 plane_index, input_frame->format(), coded_size.width()); 289 plane_index, input_frame->format(), coded_size.width());
287 int plane_height = media::VideoFrame::Rows(plane_index, input_frame->format(), 290 int plane_height = media::VideoFrame::Rows(plane_index, input_frame->format(),
288 coded_size.height()); 291 coded_size.height());
289 return gfx::Size(plane_width, plane_height); 292 return gfx::Size(plane_width, plane_height);
290 } 293 }
291 294
295 // Values are expected to be in [0.0..1.0]
296 void VideoResourceUpdater::MakeHalfFloats(const uint16_t* src,
danakj 2016/09/26 22:10:39 Maybe MultiplyHalfFloats would be a more accurate/
hubbe 2016/09/27 00:03:24 I think I did a terrible job of explaining what th
297 float mult,
298 size_t num,
299 uint16_t* dst) {
300 // TODO(hubbe): Make AVX and neon versions of this code.
301
302 // This magic constant is 2^-112. Multiplying by this
303 // is the same as subtracting 112 from the exponent, which
304 // is he difference in exponent bias between 32-bit and
danakj 2016/09/26 22:10:39 is the
hubbe 2016/09/27 00:03:24 Done.
305 // 16-bit floats. Once we've done this subtraction, we can
306 // simply extract the low bits of the exponent and the high
307 // bits of the mantissa from our float and we're done.
308 mult *= 1.9259299444e-34f;
309 for (size_t i = 0; i < num; i++) {
310 float value = src[i] * mult;
311 dst[i] = (*(uint32_t*)&value) >> 13;
312 }
313 }
314
292 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( 315 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
293 scoped_refptr<media::VideoFrame> video_frame) { 316 scoped_refptr<media::VideoFrame> video_frame) {
294 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); 317 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes");
295 const media::VideoPixelFormat input_frame_format = video_frame->format(); 318 const media::VideoPixelFormat input_frame_format = video_frame->format();
296 319
297 // TODO(hubbe): Make this a video frame method. 320 // TODO(hubbe): Make this a video frame method.
298 int bits_per_channel = 0; 321 int bits_per_channel = 0;
299 switch (input_frame_format) { 322 switch (input_frame_format) {
300 case media::PIXEL_FORMAT_UNKNOWN: 323 case media::PIXEL_FORMAT_UNKNOWN:
301 NOTREACHED(); 324 NOTREACHED();
(...skipping 18 matching lines...) Expand all
320 case media::PIXEL_FORMAT_YUV420P9: 343 case media::PIXEL_FORMAT_YUV420P9:
321 case media::PIXEL_FORMAT_YUV422P9: 344 case media::PIXEL_FORMAT_YUV422P9:
322 case media::PIXEL_FORMAT_YUV444P9: 345 case media::PIXEL_FORMAT_YUV444P9:
323 bits_per_channel = 9; 346 bits_per_channel = 9;
324 break; 347 break;
325 case media::PIXEL_FORMAT_YUV420P10: 348 case media::PIXEL_FORMAT_YUV420P10:
326 case media::PIXEL_FORMAT_YUV422P10: 349 case media::PIXEL_FORMAT_YUV422P10:
327 case media::PIXEL_FORMAT_YUV444P10: 350 case media::PIXEL_FORMAT_YUV444P10:
328 bits_per_channel = 10; 351 bits_per_channel = 10;
329 break; 352 break;
353 case media::PIXEL_FORMAT_YUV420P12:
354 case media::PIXEL_FORMAT_YUV422P12:
355 case media::PIXEL_FORMAT_YUV444P12:
356 bits_per_channel = 12;
357 break;
330 } 358 }
331 359
332 // Only YUV software video frames are supported. 360 // Only YUV software video frames are supported.
333 if (!media::IsYuvPlanar(input_frame_format)) { 361 if (!media::IsYuvPlanar(input_frame_format)) {
334 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); 362 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format);
335 return VideoFrameExternalResources(); 363 return VideoFrameExternalResources();
336 } 364 }
337 365
338 const bool software_compositor = context_provider_ == NULL; 366 const bool software_compositor = context_provider_ == NULL;
339 367
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. 503 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default.
476 size_t upload_image_stride = 504 size_t upload_image_stride =
477 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); 505 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u);
478 506
479 bool needs_conversion = false; 507 bool needs_conversion = false;
480 int shift = 0; 508 int shift = 0;
481 509
482 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. 510 // LUMINANCE_F16 uses half-floats, so we always need a conversion step.
483 if (plane_resource.resource_format() == LUMINANCE_F16) { 511 if (plane_resource.resource_format() == LUMINANCE_F16) {
484 needs_conversion = true; 512 needs_conversion = true;
485 // Note that the current method of converting integers to half-floats
486 // stops working if you have more than 10 bits of data.
487 DCHECK_LE(bits_per_channel, 10);
488 } else if (bits_per_channel > 8) { 513 } else if (bits_per_channel > 8) {
489 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to 514 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to
490 // shift the data down and create an 8-bit texture. 515 // shift the data down and create an 8-bit texture.
491 needs_conversion = true; 516 needs_conversion = true;
492 shift = bits_per_channel - 8; 517 shift = bits_per_channel - 8;
493 } 518 }
494 const uint8_t* pixels; 519 const uint8_t* pixels;
495 if (static_cast<int>(upload_image_stride) == video_stride_bytes && 520 if (static_cast<int>(upload_image_stride) == video_stride_bytes &&
496 !needs_conversion) { 521 !needs_conversion) {
497 pixels = video_frame->data(i); 522 pixels = video_frame->data(i);
498 } else { 523 } else {
499 // Avoid malloc for each frame/plane if possible. 524 // Avoid malloc for each frame/plane if possible.
500 size_t needed_size = 525 size_t needed_size =
501 upload_image_stride * resource_size_pixels.height(); 526 upload_image_stride * resource_size_pixels.height();
502 if (upload_pixels_.size() < needed_size) 527 if (upload_pixels_.size() < needed_size)
503 upload_pixels_.resize(needed_size); 528 upload_pixels_.resize(needed_size);
504 529
505 for (int row = 0; row < resource_size_pixels.height(); ++row) { 530 for (int row = 0; row < resource_size_pixels.height(); ++row) {
506 if (plane_resource.resource_format() == LUMINANCE_F16) { 531 if (plane_resource.resource_format() == LUMINANCE_F16) {
507 uint16_t* dst = reinterpret_cast<uint16_t*>( 532 uint16_t* dst = reinterpret_cast<uint16_t*>(
508 &upload_pixels_[upload_image_stride * row]); 533 &upload_pixels_[upload_image_stride * row]);
509 const uint16_t* src = reinterpret_cast<uint16_t*>( 534 const uint16_t* src = reinterpret_cast<uint16_t*>(
510 video_frame->data(i) + (video_stride_bytes * row)); 535 video_frame->data(i) + (video_stride_bytes * row));
511 // Micro-benchmarking indicates that the compiler does 536 if (bits_per_channel <= 10) {
512 // a good enough job of optimizing this loop that trying 537 // Micro-benchmarking indicates that the compiler does
513 // to manually operate on one uint64 at a time is not 538 // a good enough job of optimizing this loop that trying
514 // actually helpful. 539 // to manually operate on one uint64 at a time is not
515 // Note to future optimizers: Benchmark your optimizations! 540 // actually helpful.
516 for (size_t i = 0; i < bytes_per_row / 2; i++) 541 // Note to future optimizers: Benchmark your optimizations!
517 dst[i] = src[i] | 0x3800; 542 for (size_t i = 0; i < bytes_per_row / 2; i++)
543 dst[i] = src[i] | 0x3800;
544 } else {
545 MakeHalfFloats(src, 1.0f / ((1 << bits_per_channel) - 1),
546 bytes_per_row / 2, dst);
547 }
518 } else if (shift != 0) { 548 } else if (shift != 0) {
519 // We have more-than-8-bit input which we need to shift 549 // We have more-than-8-bit input which we need to shift
520 // down to fit it into an 8-bit texture. 550 // down to fit it into an 8-bit texture.
521 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 551 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
522 const uint16_t* src = reinterpret_cast<uint16_t*>( 552 const uint16_t* src = reinterpret_cast<uint16_t*>(
523 video_frame->data(i) + (video_stride_bytes * row)); 553 video_frame->data(i) + (video_stride_bytes * row));
524 for (size_t i = 0; i < bytes_per_row; i++) 554 for (size_t i = 0; i < bytes_per_row; i++)
525 dst[i] = src[i] >> shift; 555 dst[i] = src[i] >> shift;
526 } else { 556 } else {
527 // Input and output are the same size and format, but 557 // Input and output are the same size and format, but
528 // differ in stride, copy one row at a time. 558 // differ in stride, copy one row at a time.
529 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 559 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
530 const uint8_t* src = 560 const uint8_t* src =
531 video_frame->data(i) + (video_stride_bytes * row); 561 video_frame->data(i) + (video_stride_bytes * row);
532 memcpy(dst, src, bytes_per_row); 562 memcpy(dst, src, bytes_per_row);
533 } 563 }
534 } 564 }
535 pixels = &upload_pixels_[0]; 565 pixels = &upload_pixels_[0];
536 } 566 }
537 567
538 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, 568 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels,
539 resource_size_pixels); 569 resource_size_pixels);
540 plane_resource.SetUniqueId(video_frame->unique_id(), i); 570 plane_resource.SetUniqueId(video_frame->unique_id(), i);
541 } 571 }
542 572
543 if (plane_resource.resource_format() == LUMINANCE_F16) { 573 if (plane_resource.resource_format() == LUMINANCE_F16 &&
574 bits_per_channel <= 10) {
544 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the 575 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the
545 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75). 576 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75).
546 // 577 //
547 // Half-floats are evaluated as: 578 // Half-floats are evaluated as:
548 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); 579 // float value = pow(2.0, exponent - 25) * (0x400 + fraction);
549 // 580 //
550 // In our case the exponent is 14 (since we or with 0x3800) and 581 // In our case the exponent is 14 (since we or with 0x3800) and
551 // pow(2.0, 14-25) * 0x400 evaluates to 0.5 (our offset) and 582 // pow(2.0, 14-25) * 0x400 evaluates to 0.5 (our offset) and
552 // pow(2.0, 14-25) * fraction is [0..0.49951171875] for 10-bit and 583 // pow(2.0, 14-25) * fraction is [0..0.49951171875] for 10-bit and
553 // [0..0.24951171875] for 9-bit. 584 // [0..0.24951171875] for 9-bit.
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 if (lost_resource) { 753 if (lost_resource) {
723 resource_it->clear_refs(); 754 resource_it->clear_refs();
724 updater->DeleteResource(resource_it); 755 updater->DeleteResource(resource_it);
725 return; 756 return;
726 } 757 }
727 758
728 resource_it->remove_ref(); 759 resource_it->remove_ref();
729 } 760 }
730 761
731 } // namespace cc 762 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698