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

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

Issue 2370453003: 12-bit vp9 video support (Closed)
Patch Set: 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 namespace {
296
297 // Values are expected to be in [0.0..1.0]
298 void MakeHalfFloat(uint16_t* dst, const uint16_t* src, float mult, size_t num) {
299 // TODO(hubbe): Make AVX and neon versions of this code.
300 for (size_t i = 0; i < num; i++) {
301 if (src[i] == 0) {
302 dst[i] = 0;
303 } else {
304 float value = src[i] * mult;
305 uint32_t f = *(uint32_t*)&value;
306 dst[i] = ((f >> 16) & 0x8000) |
307 ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) |
308 ((f >> 13) & 0x03ff);
309 }
310 }
311 }
312
313 } // namespace
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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 513 // Note that the current method of converting integers to half-floats
486 // stops working if you have more than 10 bits of data. 514 // 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) { 515 } else if (bits_per_channel > 8) {
489 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to 516 // 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. 517 // shift the data down and create an 8-bit texture.
491 needs_conversion = true; 518 needs_conversion = true;
492 shift = bits_per_channel - 8; 519 shift = bits_per_channel - 8;
493 } 520 }
494 const uint8_t* pixels; 521 const uint8_t* pixels;
495 if (static_cast<int>(upload_image_stride) == video_stride_bytes && 522 if (static_cast<int>(upload_image_stride) == video_stride_bytes &&
496 !needs_conversion) { 523 !needs_conversion) {
497 pixels = video_frame->data(i); 524 pixels = video_frame->data(i);
498 } else { 525 } else {
499 // Avoid malloc for each frame/plane if possible. 526 // Avoid malloc for each frame/plane if possible.
500 size_t needed_size = 527 size_t needed_size =
501 upload_image_stride * resource_size_pixels.height(); 528 upload_image_stride * resource_size_pixels.height();
502 if (upload_pixels_.size() < needed_size) 529 if (upload_pixels_.size() < needed_size)
503 upload_pixels_.resize(needed_size); 530 upload_pixels_.resize(needed_size);
504 531
505 for (int row = 0; row < resource_size_pixels.height(); ++row) { 532 for (int row = 0; row < resource_size_pixels.height(); ++row) {
506 if (plane_resource.resource_format() == LUMINANCE_F16) { 533 if (plane_resource.resource_format() == LUMINANCE_F16) {
507 uint16_t* dst = reinterpret_cast<uint16_t*>( 534 uint16_t* dst = reinterpret_cast<uint16_t*>(
508 &upload_pixels_[upload_image_stride * row]); 535 &upload_pixels_[upload_image_stride * row]);
509 const uint16_t* src = reinterpret_cast<uint16_t*>( 536 const uint16_t* src = reinterpret_cast<uint16_t*>(
510 video_frame->data(i) + (video_stride_bytes * row)); 537 video_frame->data(i) + (video_stride_bytes * row));
511 // Micro-benchmarking indicates that the compiler does 538 if (bits_per_channel <= 10) {
512 // a good enough job of optimizing this loop that trying 539 // Micro-benchmarking indicates that the compiler does
513 // to manually operate on one uint64 at a time is not 540 // a good enough job of optimizing this loop that trying
514 // actually helpful. 541 // to manually operate on one uint64 at a time is not
515 // Note to future optimizers: Benchmark your optimizations! 542 // actually helpful.
516 for (size_t i = 0; i < bytes_per_row / 2; i++) 543 // Note to future optimizers: Benchmark your optimizations!
517 dst[i] = src[i] | 0x3800; 544 for (size_t i = 0; i < bytes_per_row / 2; i++)
545 dst[i] = src[i] | 0x3800;
546 } else {
547 MakeHalfFloat(dst, src, 1.0f / ((1 << bits_per_channel) - 1),
548 bytes_per_row / 2);
549 }
518 } else if (shift != 0) { 550 } else if (shift != 0) {
519 // We have more-than-8-bit input which we need to shift 551 // We have more-than-8-bit input which we need to shift
520 // down to fit it into an 8-bit texture. 552 // down to fit it into an 8-bit texture.
521 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 553 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
522 const uint16_t* src = reinterpret_cast<uint16_t*>( 554 const uint16_t* src = reinterpret_cast<uint16_t*>(
523 video_frame->data(i) + (video_stride_bytes * row)); 555 video_frame->data(i) + (video_stride_bytes * row));
524 for (size_t i = 0; i < bytes_per_row; i++) 556 for (size_t i = 0; i < bytes_per_row; i++)
525 dst[i] = src[i] >> shift; 557 dst[i] = src[i] >> shift;
526 } else { 558 } else {
527 // Input and output are the same size and format, but 559 // Input and output are the same size and format, but
528 // differ in stride, copy one row at a time. 560 // differ in stride, copy one row at a time.
529 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 561 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
530 const uint8_t* src = 562 const uint8_t* src =
531 video_frame->data(i) + (video_stride_bytes * row); 563 video_frame->data(i) + (video_stride_bytes * row);
532 memcpy(dst, src, bytes_per_row); 564 memcpy(dst, src, bytes_per_row);
533 } 565 }
534 } 566 }
535 pixels = &upload_pixels_[0]; 567 pixels = &upload_pixels_[0];
536 } 568 }
537 569
538 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels, 570 resource_provider_->CopyToResource(plane_resource.resource_id(), pixels,
539 resource_size_pixels); 571 resource_size_pixels);
540 plane_resource.SetUniqueId(video_frame->unique_id(), i); 572 plane_resource.SetUniqueId(video_frame->unique_id(), i);
541 } 573 }
542 574
543 if (plane_resource.resource_format() == LUMINANCE_F16) { 575 if (plane_resource.resource_format() == LUMINANCE_F16 &&
576 bits_per_channel <= 10) {
544 // By OR-ing with 0x3800, 10-bit numbers become half-floats in the 577 // 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). 578 // range [0.5..1) and 9-bit numbers get the range [0.5..0.75).
546 // 579 //
547 // Half-floats are evaluated as: 580 // Half-floats are evaluated as:
548 // float value = pow(2.0, exponent - 25) * (0x400 + fraction); 581 // float value = pow(2.0, exponent - 25) * (0x400 + fraction);
549 // 582 //
550 // In our case the exponent is 14 (since we or with 0x3800) and 583 // 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 584 // 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 585 // pow(2.0, 14-25) * fraction is [0..0.49951171875] for 10-bit and
553 // [0..0.24951171875] for 9-bit. 586 // [0..0.24951171875] for 9-bit.
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 if (lost_resource) { 755 if (lost_resource) {
723 resource_it->clear_refs(); 756 resource_it->clear_refs();
724 updater->DeleteResource(resource_it); 757 updater->DeleteResource(resource_it);
725 return; 758 return;
726 } 759 }
727 760
728 resource_it->remove_ref(); 761 resource_it->remove_ref();
729 } 762 }
730 763
731 } // namespace cc 764 } // namespace cc
OLDNEW
« no previous file with comments | « no previous file | content/browser/media/media_browsertest.cc » ('j') | media/renderers/skcanvas_video_renderer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698