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

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

Issue 2370453003: 12-bit vp9 video support (Closed)
Patch Set: merged 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,
297 float mult,
298 size_t num,
299 uint16_t* dst) {
300 // TODO(hubbe): Make AVX and neon versions of this code.
301 mult *= 1.9259299444e-34f; // Magic conversion value.
302 for (size_t i = 0; i < num; i++) {
303 if (src[i] == 0) {
304 dst[i] = 0;
305 } else {
306 float value = src[i] * mult;
307 dst[i] = (*(uint32_t*)&value) >> 13;
308 }
309 }
310 }
311
292 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( 312 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
293 scoped_refptr<media::VideoFrame> video_frame) { 313 scoped_refptr<media::VideoFrame> video_frame) {
294 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); 314 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes");
295 const media::VideoPixelFormat input_frame_format = video_frame->format(); 315 const media::VideoPixelFormat input_frame_format = video_frame->format();
296 316
297 // TODO(hubbe): Make this a video frame method. 317 // TODO(hubbe): Make this a video frame method.
298 int bits_per_channel = 0; 318 int bits_per_channel = 0;
299 switch (input_frame_format) { 319 switch (input_frame_format) {
300 case media::PIXEL_FORMAT_UNKNOWN: 320 case media::PIXEL_FORMAT_UNKNOWN:
301 NOTREACHED(); 321 NOTREACHED();
(...skipping 18 matching lines...) Expand all
320 case media::PIXEL_FORMAT_YUV420P9: 340 case media::PIXEL_FORMAT_YUV420P9:
321 case media::PIXEL_FORMAT_YUV422P9: 341 case media::PIXEL_FORMAT_YUV422P9:
322 case media::PIXEL_FORMAT_YUV444P9: 342 case media::PIXEL_FORMAT_YUV444P9:
323 bits_per_channel = 9; 343 bits_per_channel = 9;
324 break; 344 break;
325 case media::PIXEL_FORMAT_YUV420P10: 345 case media::PIXEL_FORMAT_YUV420P10:
326 case media::PIXEL_FORMAT_YUV422P10: 346 case media::PIXEL_FORMAT_YUV422P10:
327 case media::PIXEL_FORMAT_YUV444P10: 347 case media::PIXEL_FORMAT_YUV444P10:
328 bits_per_channel = 10; 348 bits_per_channel = 10;
329 break; 349 break;
350 case media::PIXEL_FORMAT_YUV420P12:
351 case media::PIXEL_FORMAT_YUV422P12:
352 case media::PIXEL_FORMAT_YUV444P12:
353 bits_per_channel = 12;
354 break;
330 } 355 }
331 356
332 // Only YUV software video frames are supported. 357 // Only YUV software video frames are supported.
333 if (!media::IsYuvPlanar(input_frame_format)) { 358 if (!media::IsYuvPlanar(input_frame_format)) {
334 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); 359 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format);
335 return VideoFrameExternalResources(); 360 return VideoFrameExternalResources();
336 } 361 }
337 362
338 const bool software_compositor = context_provider_ == NULL; 363 const bool software_compositor = context_provider_ == NULL;
339 364
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. 500 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default.
476 size_t upload_image_stride = 501 size_t upload_image_stride =
477 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); 502 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u);
478 503
479 bool needs_conversion = false; 504 bool needs_conversion = false;
480 int shift = 0; 505 int shift = 0;
481 506
482 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. 507 // LUMINANCE_F16 uses half-floats, so we always need a conversion step.
483 if (plane_resource.resource_format() == LUMINANCE_F16) { 508 if (plane_resource.resource_format() == LUMINANCE_F16) {
484 needs_conversion = true; 509 needs_conversion = true;
485 // Note that the current method of converting integers to half-floats 510 // Note that the current method of converting integers to half-floats
danakj 2016/09/26 20:35:04 What about this comment?
hubbe 2016/09/26 21:19:36 Removed.
486 // stops working if you have more than 10 bits of data. 511 // 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) { 512 } else if (bits_per_channel > 8) {
489 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to 513 // 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. 514 // shift the data down and create an 8-bit texture.
491 needs_conversion = true; 515 needs_conversion = true;
492 shift = bits_per_channel - 8; 516 shift = bits_per_channel - 8;
493 } 517 }
494 const uint8_t* pixels; 518 const uint8_t* pixels;
495 if (static_cast<int>(upload_image_stride) == video_stride_bytes && 519 if (static_cast<int>(upload_image_stride) == video_stride_bytes &&
496 !needs_conversion) { 520 !needs_conversion) {
497 pixels = video_frame->data(i); 521 pixels = video_frame->data(i);
498 } else { 522 } else {
499 // Avoid malloc for each frame/plane if possible. 523 // Avoid malloc for each frame/plane if possible.
500 size_t needed_size = 524 size_t needed_size =
501 upload_image_stride * resource_size_pixels.height(); 525 upload_image_stride * resource_size_pixels.height();
502 if (upload_pixels_.size() < needed_size) 526 if (upload_pixels_.size() < needed_size)
503 upload_pixels_.resize(needed_size); 527 upload_pixels_.resize(needed_size);
504 528
505 for (int row = 0; row < resource_size_pixels.height(); ++row) { 529 for (int row = 0; row < resource_size_pixels.height(); ++row) {
506 if (plane_resource.resource_format() == LUMINANCE_F16) { 530 if (plane_resource.resource_format() == LUMINANCE_F16) {
507 uint16_t* dst = reinterpret_cast<uint16_t*>( 531 uint16_t* dst = reinterpret_cast<uint16_t*>(
508 &upload_pixels_[upload_image_stride * row]); 532 &upload_pixels_[upload_image_stride * row]);
509 const uint16_t* src = reinterpret_cast<uint16_t*>( 533 const uint16_t* src = reinterpret_cast<uint16_t*>(
510 video_frame->data(i) + (video_stride_bytes * row)); 534 video_frame->data(i) + (video_stride_bytes * row));
511 // Micro-benchmarking indicates that the compiler does 535 if (bits_per_channel <= 10) {
512 // a good enough job of optimizing this loop that trying 536 // Micro-benchmarking indicates that the compiler does
513 // to manually operate on one uint64 at a time is not 537 // a good enough job of optimizing this loop that trying
514 // actually helpful. 538 // to manually operate on one uint64 at a time is not
515 // Note to future optimizers: Benchmark your optimizations! 539 // actually helpful.
516 for (size_t i = 0; i < bytes_per_row / 2; i++) 540 // Note to future optimizers: Benchmark your optimizations!
517 dst[i] = src[i] | 0x3800; 541 for (size_t i = 0; i < bytes_per_row / 2; i++)
542 dst[i] = src[i] | 0x3800;
543 } else {
544 MakeHalfFloats(src, 1.0f / ((1 << bits_per_channel) - 1),
545 bytes_per_row / 2, dst);
546 }
518 } else if (shift != 0) { 547 } else if (shift != 0) {
519 // We have more-than-8-bit input which we need to shift 548 // We have more-than-8-bit input which we need to shift
520 // down to fit it into an 8-bit texture. 549 // down to fit it into an 8-bit texture.
521 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 550 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
522 const uint16_t* src = reinterpret_cast<uint16_t*>( 551 const uint16_t* src = reinterpret_cast<uint16_t*>(
523 video_frame->data(i) + (video_stride_bytes * row)); 552 video_frame->data(i) + (video_stride_bytes * row));
524 for (size_t i = 0; i < bytes_per_row; i++) 553 for (size_t i = 0; i < bytes_per_row; i++)
525 dst[i] = src[i] >> shift; 554 dst[i] = src[i] >> shift;
526 } else { 555 } else {
527 // Input and output are the same size and format, but 556 // Input and output are the same size and format, but
528 // differ in stride, copy one row at a time. 557 // differ in stride, copy one row at a time.
529 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 558 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
530 const uint8_t* src = 559 const uint8_t* src =
531 video_frame->data(i) + (video_stride_bytes * row); 560 video_frame->data(i) + (video_stride_bytes * row);
532 memcpy(dst, src, bytes_per_row); 561 memcpy(dst, src, bytes_per_row);
533 } 562 }
534 } 563 }
535 pixels = &upload_pixels_[0]; 564 pixels = &upload_pixels_[0];
536 } 565 }
537 566
538 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, 567 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels,
539 resource_size_pixels); 568 resource_size_pixels);
540 plane_resource.SetUniqueId(video_frame->unique_id(), i); 569 plane_resource.SetUniqueId(video_frame->unique_id(), i);
541 } 570 }
542 571
543 if (plane_resource.resource_format() == LUMINANCE_F16) { 572 if (plane_resource.resource_format() == LUMINANCE_F16 &&
573 bits_per_channel <= 10) {
danakj 2016/09/26 20:35:04 what if bits > 10?
hubbe 2016/09/26 21:19:36 Then offset and multiplier should have their defau
danakj 2016/09/26 22:10:39 Can you explain in a comment too?
hubbe 2016/09/27 00:03:24 Done.
544 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the 574 // 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). 575 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75).
546 // 576 //
547 // Half-floats are evaluated as: 577 // Half-floats are evaluated as:
548 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); 578 // float value = pow(2.0, exponent - 25) * (0x400 + fraction);
549 // 579 //
550 // In our case the exponent is 14 (since we or with 0x3800) and 580 // 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 581 // 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 582 // pow(2.0, 14-25) * fraction is [0..0.49951171875] for 10-bit and
553 // [0..0.24951171875] for 9-bit. 583 // [0..0.24951171875] for 9-bit.
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 if (lost_resource) { 752 if (lost_resource) {
723 resource_it->clear_refs(); 753 resource_it->clear_refs();
724 updater->DeleteResource(resource_it); 754 updater->DeleteResource(resource_it);
725 return; 755 return;
726 } 756 }
727 757
728 resource_it->remove_ref(); 758 resource_it->remove_ref();
729 } 759 }
730 760
731 } // namespace cc 761 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698