• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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