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

Side by Side Diff: media/renderers/skcanvas_video_renderer_unittest.cc

Issue 2476693002: WebGL & 16-bit video stream: upload to FLOAT texture. (Closed)
Patch Set: Lossless access to 16-bit video stream using WebGL GL_FLOAT texture. Created 4 years, 1 month 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <stdint.h> 5 #include <stdint.h>
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/memory/aligned_memory.h" 8 #include "base/memory/aligned_memory.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "gpu/GLES2/gl2extchromium.h" 10 #include "gpu/GLES2/gl2extchromium.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 return 0; 43 return 0;
44 if (!canvas->readPixels(&bitmap, x, y)) 44 if (!canvas->readPixels(&bitmap, x, y))
45 return 0; 45 return 0;
46 return bitmap.getColor(0, 0); 46 return bitmap.getColor(0, 0);
47 } 47 }
48 48
49 SkColor GetColor(SkCanvas* canvas) { 49 SkColor GetColor(SkCanvas* canvas) {
50 return GetColorAt(canvas, 0, 0); 50 return GetColorAt(canvas, 0, 0);
51 } 51 }
52 52
53 // Generate frame pixels to provided |external_memory| and wrap it as frame.
54 scoped_refptr<VideoFrame> CreateTestY16Frame(const gfx::Size& coded_size,
55 const gfx::Rect& visible_rect,
56 void* external_memory,
57 base::TimeDelta timestamp) {
58 const int offset_x = visible_rect.x();
59 const int offset_y = visible_rect.y();
60 const int stride = coded_size.width();
61 const size_t byte_size = stride * coded_size.height() * 2;
62
63 // In the visible rect, fill upper byte with [0-255] and lower with [255-0].
64 uint16_t* data = static_cast<uint16_t*>(external_memory);
65 for (int j = 0; j < visible_rect.height(); j++) {
66 for (int i = 0; i < visible_rect.width(); i++) {
67 const int value = i + j * visible_rect.width();
68 data[(stride * (j + offset_y)) + i + offset_x] =
69 ((value & 0xFF) << 8) | (~value & 0xFF);
70 }
71 }
72
73 return media::VideoFrame::WrapExternalData(
74 media::PIXEL_FORMAT_Y16, coded_size, visible_rect, visible_rect.size(),
75 static_cast<uint8_t*>(external_memory), byte_size, timestamp);
76 }
77
53 class SkCanvasVideoRendererTest : public testing::Test { 78 class SkCanvasVideoRendererTest : public testing::Test {
54 public: 79 public:
55 enum Color { 80 enum Color {
56 kNone, 81 kNone,
57 kRed, 82 kRed,
58 kGreen, 83 kGreen,
59 kBlue, 84 kBlue,
60 }; 85 };
61 86
62 SkCanvasVideoRendererTest(); 87 SkCanvasVideoRendererTest();
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 bitmap.allocPixels(SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType)); 543 bitmap.allocPixels(SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType));
519 544
520 // |offset_x| and |offset_y| define visible rect's offset to coded rect. 545 // |offset_x| and |offset_y| define visible rect's offset to coded rect.
521 const int offset_x = 3; 546 const int offset_x = 3;
522 const int offset_y = 5; 547 const int offset_y = 5;
523 const int stride = bitmap.width() + offset_x; 548 const int stride = bitmap.width() + offset_x;
524 const size_t byte_size = stride * (bitmap.height() + offset_y) * 2; 549 const size_t byte_size = stride * (bitmap.height() + offset_y) * 2;
525 std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory( 550 std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
526 static_cast<unsigned char*>(base::AlignedAlloc( 551 static_cast<unsigned char*>(base::AlignedAlloc(
527 byte_size, media::VideoFrame::kFrameAddressAlignment))); 552 byte_size, media::VideoFrame::kFrameAddressAlignment)));
528
529 // In the visible rect, fill upper byte with [0-255] and lower with [255-0].
530 uint16_t* data = reinterpret_cast<uint16_t*>(memory.get());
531 for (int j = 0; j < bitmap.height(); j++) {
532 for (int i = 0; i < bitmap.width(); i++) {
533 const int value = i + j * bitmap.width();
534 data[(stride * (j + offset_y)) + i + offset_x] =
535 ((value & 0xFF) << 8) | (~value & 0xFF);
536 }
537 }
538 const gfx::Rect rect(offset_x, offset_y, bitmap.width(), bitmap.height()); 553 const gfx::Rect rect(offset_x, offset_y, bitmap.width(), bitmap.height());
539 scoped_refptr<media::VideoFrame> video_frame = 554 scoped_refptr<media::VideoFrame> video_frame =
540 media::VideoFrame::WrapExternalData( 555 CreateTestY16Frame(gfx::Size(stride, offset_y + bitmap.height()), rect,
541 media::PIXEL_FORMAT_Y16, 556 memory.get(), cropped_frame()->timestamp());
542 gfx::Size(stride, offset_y + bitmap.height()), rect, rect.size(),
543 memory.get(), byte_size, cropped_frame()->timestamp());
544 557
545 SkCanvas canvas(bitmap); 558 SkCanvas canvas(bitmap);
546 SkPaint paint; 559 SkPaint paint;
547 paint.setFilterQuality(kNone_SkFilterQuality); 560 paint.setFilterQuality(kNone_SkFilterQuality);
548 renderer_.Paint(video_frame, &canvas, 561 renderer_.Paint(video_frame, &canvas,
549 gfx::RectF(bitmap.width(), bitmap.height()), paint, 562 gfx::RectF(bitmap.width(), bitmap.height()), paint,
550 VIDEO_ROTATION_0, Context3D()); 563 VIDEO_ROTATION_0, Context3D());
551 SkAutoLockPixels lock(bitmap); 564 SkAutoLockPixels lock(bitmap);
552 for (int j = 0; j < bitmap.height(); j++) { 565 for (int j = 0; j < bitmap.height(); j++) {
553 for (int i = 0; i < bitmap.width(); i++) { 566 for (int i = 0; i < bitmap.width(); i++) {
554 const int value = i + j * bitmap.width(); 567 const int value = i + j * bitmap.width();
555 EXPECT_EQ(SkColorSetRGB(value, value, value), bitmap.getColor(i, j)); 568 EXPECT_EQ(SkColorSetRGB(value, value, value), bitmap.getColor(i, j));
556 } 569 }
557 } 570 }
558 } 571 }
559 572
560 namespace { 573 namespace {
561 class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub { 574 class TestGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
562 public: 575 public:
563 void GenTextures(GLsizei n, GLuint* textures) override { 576 void GenTextures(GLsizei n, GLuint* textures) override {
564 DCHECK_EQ(1, n); 577 DCHECK_EQ(1, n);
565 *textures = 1; 578 *textures = 1;
566 } 579 }
580
581 void TexImage2D(GLenum target,
582 GLint level,
583 GLint internalformat,
584 GLsizei width,
585 GLsizei height,
586 GLint border,
587 GLenum format,
588 GLenum type,
589 const void* pixels) override {
590 if (!teximage2d_callback_.is_null()) {
591 teximage2d_callback_.Run(target, level, internalformat, width, height,
592 border, format, type, pixels);
593 }
594 }
595
596 base::Callback<void(GLenum target,
597 GLint level,
598 GLint internalformat,
599 GLsizei width,
600 GLsizei height,
601 GLint border,
602 GLenum format,
603 GLenum type,
604 const void* pixels)>
605 teximage2d_callback_;
567 }; 606 };
568 void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {} 607 void MailboxHoldersReleased(const gpu::SyncToken& sync_token) {}
569 } // namespace 608 } // namespace
570 609
571 // Test that SkCanvasVideoRendererTest::Paint doesn't crash when GrContext is 610 // Test that SkCanvasVideoRendererTest::Paint doesn't crash when GrContext is
572 // abandoned. 611 // abandoned.
573 TEST_F(SkCanvasVideoRendererTest, ContextLost) { 612 TEST_F(SkCanvasVideoRendererTest, ContextLost) {
574 sk_sp<const GrGLInterface> null_interface(GrGLCreateNullInterface()); 613 sk_sp<const GrGLInterface> null_interface(GrGLCreateNullInterface());
575 sk_sp<GrContext> gr_context(GrContext::Create( 614 sk_sp<GrContext> gr_context(GrContext::Create(
576 kOpenGL_GrBackend, 615 kOpenGL_GrBackend,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 667
629 gfx::RectF visible_rect(visible_size.width(), visible_size.height()); 668 gfx::RectF visible_rect(visible_size.width(), visible_size.height());
630 SkPaint paint; 669 SkPaint paint;
631 renderer_.Paint(video_frame, canvas, visible_rect, paint, VIDEO_ROTATION_0, 670 renderer_.Paint(video_frame, canvas, visible_rect, paint, VIDEO_ROTATION_0,
632 context_3d); 671 context_3d);
633 672
634 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width()); 673 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width());
635 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height()); 674 EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height());
636 } 675 }
637 676
677 TEST_F(SkCanvasVideoRendererTest, TexImageImplY16) {
678 // Create test frame.
679 // |offset_x| and |offset_y| define visible rect's offset to coded rect.
680 const int offset_x = 3;
681 const int offset_y = 5;
682 const int width = 16;
683 const int height = 16;
684 const int stride = width + offset_x;
685 const size_t byte_size = stride * (height + offset_y) * 2;
686 std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
687 static_cast<unsigned char*>(base::AlignedAlloc(
688 byte_size, media::VideoFrame::kFrameAddressAlignment)));
689 const gfx::Rect rect(offset_x, offset_y, width, height);
690 scoped_refptr<media::VideoFrame> video_frame =
691 CreateTestY16Frame(gfx::Size(stride, offset_y + height), rect,
692 memory.get(), cropped_frame()->timestamp());
693
694 // Create GL context.
695 sk_sp<const GrGLInterface> null_interface(GrGLCreateNullInterface());
696 sk_sp<GrContext> gr_context(GrContext::Create(
697 kOpenGL_GrBackend,
698 reinterpret_cast<GrBackendContext>(null_interface.get())));
699 TestGLES2Interface gles2;
700 Context3D context_3d(&gles2, gr_context.get());
701
702 // Bind the texImage2D callback to verify the uint16 to float32 conversion.
703 gles2.teximage2d_callback_ =
704 base::Bind([](GLenum target, GLint level, GLint internalformat,
705 GLsizei width, GLsizei height, GLint border, GLenum format,
706 GLenum type, const void* pixels) {
707 EXPECT_EQ(static_cast<unsigned>(GL_FLOAT), type);
708 EXPECT_EQ(static_cast<unsigned>(GL_RGBA), format);
709 EXPECT_EQ(GL_RGBA, internalformat);
710 EXPECT_EQ(0, border);
711 EXPECT_EQ(16, width);
712 EXPECT_EQ(16, height);
713 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
714 const float* data = static_cast<const float*>(pixels);
715 for (int j = 0; j < height; j++) {
716 for (int i = 0; i < width; i++) {
717 const int value = i + (height - j - 1) * width; // flip_y is true.
718 float expected_value =
719 (((value & 0xFF) << 8) | (~value & 0xFF)) / 65535.f;
720 EXPECT_EQ(expected_value, data[(i + j * width) * 4]);
721 EXPECT_EQ(expected_value, data[(i + j * width) * 4 + 1]);
722 EXPECT_EQ(expected_value, data[(i + j * width) * 4 + 2]);
723 EXPECT_EQ(1.0f, data[(i + j * width) * 4 + 3]);
724 }
725 }
726 });
727 SkCanvasVideoRenderer::TexImageImpl("texImage2D", GL_TEXTURE_2D, &gles2,
728 video_frame.get(), 0, GL_RGBA, GL_RGBA,
729 GL_FLOAT, 0, 0, 0, true /*flip_y*/, true);
730 }
731
638 } // namespace media 732 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698