1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "common_video/include/i420_buffer_pool.h"
12
13 #include <stdint.h>
14 #include <string.h>
15
16 #include "api/scoped_refptr.h"
17 #include "api/video/i420_buffer.h"
18 #include "api/video/video_frame_buffer.h"
19 #include "test/gtest.h"
20
21 namespace webrtc {
22
TEST(TestI420BufferPool,SimpleFrameReuse)23 TEST(TestI420BufferPool, SimpleFrameReuse) {
24 I420BufferPool pool;
25 auto buffer = pool.CreateBuffer(16, 16);
26 EXPECT_EQ(16, buffer->width());
27 EXPECT_EQ(16, buffer->height());
28 // Extract non-refcounted pointers for testing.
29 const uint8_t* y_ptr = buffer->DataY();
30 const uint8_t* u_ptr = buffer->DataU();
31 const uint8_t* v_ptr = buffer->DataV();
32 // Release buffer so that it is returned to the pool.
33 buffer = nullptr;
34 // Check that the memory is resued.
35 buffer = pool.CreateBuffer(16, 16);
36 EXPECT_EQ(y_ptr, buffer->DataY());
37 EXPECT_EQ(u_ptr, buffer->DataU());
38 EXPECT_EQ(v_ptr, buffer->DataV());
39 }
40
TEST(TestI420BufferPool,FrameReuseWithDefaultThenExplicitStride)41 TEST(TestI420BufferPool, FrameReuseWithDefaultThenExplicitStride) {
42 I420BufferPool pool;
43 auto buffer = pool.CreateBuffer(15, 16);
44 EXPECT_EQ(15, buffer->width());
45 EXPECT_EQ(16, buffer->height());
46 // The default Y stride is width and UV stride is halfwidth (rounded up).
47 ASSERT_EQ(15, buffer->StrideY());
48 ASSERT_EQ(8, buffer->StrideU());
49 ASSERT_EQ(8, buffer->StrideV());
50 // Extract non-refcounted pointers for testing.
51 const uint8_t* y_ptr = buffer->DataY();
52 const uint8_t* u_ptr = buffer->DataU();
53 const uint8_t* v_ptr = buffer->DataV();
54 // Release buffer so that it is returned to the pool.
55 buffer = nullptr;
56 // Check that the memory is resued with explicit strides if they match the
57 // assumed default above.
58 buffer = pool.CreateBuffer(15, 16, 15, 8, 8);
59 EXPECT_EQ(y_ptr, buffer->DataY());
60 EXPECT_EQ(u_ptr, buffer->DataU());
61 EXPECT_EQ(v_ptr, buffer->DataV());
62 EXPECT_EQ(15, buffer->width());
63 EXPECT_EQ(16, buffer->height());
64 EXPECT_EQ(15, buffer->StrideY());
65 EXPECT_EQ(8, buffer->StrideU());
66 EXPECT_EQ(8, buffer->StrideV());
67 }
68
TEST(TestI420BufferPool,FailToReuseWrongSize)69 TEST(TestI420BufferPool, FailToReuseWrongSize) {
70 // Set max frames to 1, just to make sure the first buffer is being released.
71 I420BufferPool pool(/*zero_initialize=*/false, 1);
72 auto buffer = pool.CreateBuffer(16, 16);
73 EXPECT_EQ(16, buffer->width());
74 EXPECT_EQ(16, buffer->height());
75 // Release buffer so that it is returned to the pool.
76 buffer = nullptr;
77 // Check that the pool doesn't try to reuse buffers of incorrect size.
78 buffer = pool.CreateBuffer(32, 16);
79 ASSERT_TRUE(buffer);
80 EXPECT_EQ(32, buffer->width());
81 EXPECT_EQ(16, buffer->height());
82 }
83
TEST(TestI420BufferPool,FailToReuseWrongStride)84 TEST(TestI420BufferPool, FailToReuseWrongStride) {
85 // Set max frames to 1, just to make sure the first buffer is being released.
86 I420BufferPool pool(/*zero_initialize=*/false, 1);
87 auto buffer = pool.CreateBuffer(32, 32, 32, 16, 16);
88 // Make sure the stride was read correctly, for the rest of the test.
89 ASSERT_EQ(16, buffer->StrideU());
90 ASSERT_EQ(16, buffer->StrideV());
91 buffer = pool.CreateBuffer(32, 32, 32, 20, 20);
92 ASSERT_TRUE(buffer);
93 EXPECT_EQ(32, buffer->StrideY());
94 EXPECT_EQ(20, buffer->StrideU());
95 EXPECT_EQ(20, buffer->StrideV());
96 }
97
TEST(TestI420BufferPool,FrameValidAfterPoolDestruction)98 TEST(TestI420BufferPool, FrameValidAfterPoolDestruction) {
99 rtc::scoped_refptr<I420Buffer> buffer;
100 {
101 I420BufferPool pool;
102 buffer = pool.CreateBuffer(16, 16);
103 }
104 EXPECT_EQ(16, buffer->width());
105 EXPECT_EQ(16, buffer->height());
106 // Try to trigger use-after-free errors by writing to y-plane.
107 memset(buffer->MutableDataY(), 0xA5, 16 * buffer->StrideY());
108 }
109
TEST(TestI420BufferPool,MaxNumberOfBuffers)110 TEST(TestI420BufferPool, MaxNumberOfBuffers) {
111 I420BufferPool pool(false, 1);
112 auto buffer1 = pool.CreateBuffer(16, 16);
113 EXPECT_NE(nullptr, buffer1.get());
114 EXPECT_EQ(nullptr, pool.CreateBuffer(16, 16).get());
115 }
116
117 } // namespace webrtc
118