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
3 // found in the LICENSE file.
5 #include "cc/resources/video_resource_updater.h"
7 #include "base/memory/shared_memory.h"
8 #include "cc/resources/resource_provider.h"
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/fake_output_surface_client.h"
11 #include "cc/test/test_shared_bitmap_manager.h"
12 #include "cc/test/test_web_graphics_context_3d.h"
13 #include "cc/trees/blocking_task_runner.h"
14 #include "media/base/video_frame.h"
15 #include "testing/gtest/include/gtest/gtest.h"
20 class WebGraphicsContext3DUploadCounter
: public TestWebGraphicsContext3D
{
22 void texSubImage2D(GLenum target
,
30 const void* pixels
) override
{
34 int UploadCount() { return upload_count_
; }
35 void ResetUploadCount() { upload_count_
= 0; }
41 class SharedBitmapManagerAllocationCounter
: public TestSharedBitmapManager
{
43 scoped_ptr
<SharedBitmap
> AllocateSharedBitmap(
44 const gfx::Size
& size
) override
{
46 return TestSharedBitmapManager::AllocateSharedBitmap(size
);
49 int AllocationCount() { return allocation_count_
; }
50 void ResetAllocationCount() { allocation_count_
= 0; }
53 int allocation_count_
;
56 class VideoResourceUpdaterTest
: public testing::Test
{
58 VideoResourceUpdaterTest() {
59 scoped_ptr
<WebGraphicsContext3DUploadCounter
> context3d(
60 new WebGraphicsContext3DUploadCounter());
62 context3d_
= context3d
.get();
65 FakeOutputSurface::Create3d(context3d
.Pass());
66 CHECK(output_surface3d_
->BindToClient(&client_
));
68 output_surface_software_
= FakeOutputSurface::CreateSoftware(
69 make_scoped_ptr(new SoftwareOutputDevice
));
70 CHECK(output_surface_software_
->BindToClient(&client_
));
72 shared_bitmap_manager_
.reset(new SharedBitmapManagerAllocationCounter());
73 resource_provider3d_
=
74 ResourceProvider::Create(output_surface3d_
.get(),
75 shared_bitmap_manager_
.get(),
82 resource_provider_software_
= ResourceProvider::Create(
83 output_surface_software_
.get(), shared_bitmap_manager_
.get(), NULL
,
87 scoped_refptr
<media::VideoFrame
> CreateTestYUVVideoFrame() {
88 const int kDimension
= 10;
89 gfx::Size
size(kDimension
, kDimension
);
90 static uint8 y_data
[kDimension
* kDimension
] = { 0 };
91 static uint8 u_data
[kDimension
* kDimension
/ 2] = { 0 };
92 static uint8 v_data
[kDimension
* kDimension
/ 2] = { 0 };
94 return media::VideoFrame::WrapExternalYuvData(
95 media::VideoFrame::YV16
, // format
97 gfx::Rect(size
), // visible_rect
99 size
.width(), // y_stride
100 size
.width() / 2, // u_stride
101 size
.width() / 2, // v_stride
105 base::TimeDelta(), // timestamp,
106 base::Closure()); // no_longer_needed_cb
109 WebGraphicsContext3DUploadCounter
* context3d_
;
110 FakeOutputSurfaceClient client_
;
111 scoped_ptr
<FakeOutputSurface
> output_surface3d_
;
112 scoped_ptr
<FakeOutputSurface
> output_surface_software_
;
113 scoped_ptr
<SharedBitmapManagerAllocationCounter
> shared_bitmap_manager_
;
114 scoped_ptr
<ResourceProvider
> resource_provider3d_
;
115 scoped_ptr
<ResourceProvider
> resource_provider_software_
;
118 TEST_F(VideoResourceUpdaterTest
, SoftwareFrame
) {
119 VideoResourceUpdater
updater(output_surface3d_
->context_provider(),
120 resource_provider3d_
.get());
121 scoped_refptr
<media::VideoFrame
> video_frame
= CreateTestYUVVideoFrame();
123 VideoFrameExternalResources resources
=
124 updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
125 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE
, resources
.type
);
128 TEST_F(VideoResourceUpdaterTest
, ReuseResource
) {
129 VideoResourceUpdater
updater(output_surface3d_
->context_provider(),
130 resource_provider3d_
.get());
131 scoped_refptr
<media::VideoFrame
> video_frame
= CreateTestYUVVideoFrame();
132 video_frame
->set_timestamp(base::TimeDelta::FromSeconds(1234));
134 // Allocate the resources for a YUV video frame.
135 context3d_
->ResetUploadCount();
136 VideoFrameExternalResources resources
=
137 updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
138 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE
, resources
.type
);
139 EXPECT_EQ(size_t(3), resources
.mailboxes
.size());
140 EXPECT_EQ(size_t(3), resources
.release_callbacks
.size());
141 EXPECT_EQ(size_t(0), resources
.software_resources
.size());
142 // Expect exactly three texture uploads, one for each plane.
143 EXPECT_EQ(3, context3d_
->UploadCount());
145 // Simulate the ResourceProvider releasing the resources back to the video
147 for (ReleaseCallbackImpl
& release_callback
: resources
.release_callbacks
)
148 release_callback
.Run(0, false, nullptr);
150 // Allocate resources for the same frame.
151 context3d_
->ResetUploadCount();
152 resources
= updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
153 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE
, resources
.type
);
154 EXPECT_EQ(size_t(3), resources
.mailboxes
.size());
155 EXPECT_EQ(size_t(3), resources
.release_callbacks
.size());
156 // The data should be reused so expect no texture uploads.
157 EXPECT_EQ(0, context3d_
->UploadCount());
160 TEST_F(VideoResourceUpdaterTest
, ReuseResourceNoDelete
) {
161 VideoResourceUpdater
updater(output_surface3d_
->context_provider(),
162 resource_provider3d_
.get());
163 scoped_refptr
<media::VideoFrame
> video_frame
= CreateTestYUVVideoFrame();
164 video_frame
->set_timestamp(base::TimeDelta::FromSeconds(1234));
166 // Allocate the resources for a YUV video frame.
167 context3d_
->ResetUploadCount();
168 VideoFrameExternalResources resources
=
169 updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
170 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE
, resources
.type
);
171 EXPECT_EQ(size_t(3), resources
.mailboxes
.size());
172 EXPECT_EQ(size_t(3), resources
.release_callbacks
.size());
173 EXPECT_EQ(size_t(0), resources
.software_resources
.size());
174 // Expect exactly three texture uploads, one for each plane.
175 EXPECT_EQ(3, context3d_
->UploadCount());
177 // Allocate resources for the same frame.
178 context3d_
->ResetUploadCount();
179 resources
= updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
180 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE
, resources
.type
);
181 EXPECT_EQ(size_t(3), resources
.mailboxes
.size());
182 EXPECT_EQ(size_t(3), resources
.release_callbacks
.size());
183 // The data should be reused so expect no texture uploads.
184 EXPECT_EQ(0, context3d_
->UploadCount());
187 TEST_F(VideoResourceUpdaterTest
, SoftwareFrameSoftwareCompositor
) {
188 VideoResourceUpdater
updater(nullptr, resource_provider_software_
.get());
189 scoped_refptr
<media::VideoFrame
> video_frame
= CreateTestYUVVideoFrame();
191 VideoFrameExternalResources resources
=
192 updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
193 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE
, resources
.type
);
196 TEST_F(VideoResourceUpdaterTest
, ReuseResourceSoftwareCompositor
) {
197 VideoResourceUpdater
updater(nullptr, resource_provider_software_
.get());
198 scoped_refptr
<media::VideoFrame
> video_frame
= CreateTestYUVVideoFrame();
199 video_frame
->set_timestamp(base::TimeDelta::FromSeconds(1234));
201 // Allocate the resources for a software video frame.
202 shared_bitmap_manager_
->ResetAllocationCount();
203 VideoFrameExternalResources resources
=
204 updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
205 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE
, resources
.type
);
206 EXPECT_EQ(size_t(0), resources
.mailboxes
.size());
207 EXPECT_EQ(size_t(0), resources
.release_callbacks
.size());
208 EXPECT_EQ(size_t(1), resources
.software_resources
.size());
209 // Expect exactly one allocated shared bitmap.
210 EXPECT_EQ(1, shared_bitmap_manager_
->AllocationCount());
212 // Simulate the ResourceProvider releasing the resource back to the video
214 resources
.software_release_callback
.Run(0, false, nullptr);
216 // Allocate resources for the same frame.
217 shared_bitmap_manager_
->ResetAllocationCount();
218 resources
= updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
219 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE
, resources
.type
);
220 EXPECT_EQ(size_t(0), resources
.mailboxes
.size());
221 EXPECT_EQ(size_t(0), resources
.release_callbacks
.size());
222 EXPECT_EQ(size_t(1), resources
.software_resources
.size());
223 // The data should be reused so expect no new allocations.
224 EXPECT_EQ(0, shared_bitmap_manager_
->AllocationCount());
227 TEST_F(VideoResourceUpdaterTest
, ReuseResourceNoDeleteSoftwareCompositor
) {
228 VideoResourceUpdater
updater(nullptr, resource_provider_software_
.get());
229 scoped_refptr
<media::VideoFrame
> video_frame
= CreateTestYUVVideoFrame();
230 video_frame
->set_timestamp(base::TimeDelta::FromSeconds(1234));
232 // Allocate the resources for a software video frame.
233 shared_bitmap_manager_
->ResetAllocationCount();
234 VideoFrameExternalResources resources
=
235 updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
236 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE
, resources
.type
);
237 EXPECT_EQ(size_t(0), resources
.mailboxes
.size());
238 EXPECT_EQ(size_t(0), resources
.release_callbacks
.size());
239 EXPECT_EQ(size_t(1), resources
.software_resources
.size());
240 // Expect exactly one allocated shared bitmap.
241 EXPECT_EQ(1, shared_bitmap_manager_
->AllocationCount());
243 // Allocate resources for the same frame.
244 shared_bitmap_manager_
->ResetAllocationCount();
245 resources
= updater
.CreateExternalResourcesFromVideoFrame(video_frame
);
246 EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE
, resources
.type
);
247 EXPECT_EQ(size_t(0), resources
.mailboxes
.size());
248 EXPECT_EQ(size_t(0), resources
.release_callbacks
.size());
249 EXPECT_EQ(size_t(1), resources
.software_resources
.size());
250 // The data should be reused so expect no new allocations.
251 EXPECT_EQ(0, shared_bitmap_manager_
->AllocationCount());