magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 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 | |
Jonas Olsson | a4d8737 | 2019-07-05 17:08:33 | [diff] [blame] | 11 | #include "common_video/include/i420_buffer_pool.h" |
| 12 | |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 13 | #include <stdint.h> |
| 14 | #include <string.h> |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 15 | |
Mirko Bonadei | d970807 | 2019-01-25 19:26:48 | [diff] [blame] | 16 | #include "api/scoped_refptr.h" |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 17 | #include "api/video/i420_buffer.h" |
| 18 | #include "api/video/video_frame_buffer.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 19 | #include "test/gtest.h" |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 20 | |
| 21 | namespace webrtc { |
| 22 | |
| 23 | TEST(TestI420BufferPool, SimpleFrameReuse) { |
| 24 | I420BufferPool pool; |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 25 | auto buffer = pool.CreateBuffer(16, 16); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 26 | EXPECT_EQ(16, buffer->width()); |
| 27 | EXPECT_EQ(16, buffer->height()); |
| 28 | // Extract non-refcounted pointers for testing. |
nisse | 06176e4 | 2016-04-18 12:34:40 | [diff] [blame] | 29 | const uint8_t* y_ptr = buffer->DataY(); |
| 30 | const uint8_t* u_ptr = buffer->DataU(); |
| 31 | const uint8_t* v_ptr = buffer->DataV(); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 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); |
nisse | 06176e4 | 2016-04-18 12:34:40 | [diff] [blame] | 36 | EXPECT_EQ(y_ptr, buffer->DataY()); |
| 37 | EXPECT_EQ(u_ptr, buffer->DataU()); |
| 38 | EXPECT_EQ(v_ptr, buffer->DataV()); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 39 | } |
| 40 | |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 41 | TEST(TestI420BufferPool, FrameReuseWithDefaultThenExplicitStride) { |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 42 | I420BufferPool pool; |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 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()); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 50 | // Extract non-refcounted pointers for testing. |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 51 | const uint8_t* y_ptr = buffer->DataY(); |
nisse | 06176e4 | 2016-04-18 12:34:40 | [diff] [blame] | 52 | const uint8_t* u_ptr = buffer->DataU(); |
| 53 | const uint8_t* v_ptr = buffer->DataV(); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 54 | // Release buffer so that it is returned to the pool. |
| 55 | buffer = nullptr; |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 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 | |
| 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; |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 77 | // Check that the pool doesn't try to reuse buffers of incorrect size. |
| 78 | buffer = pool.CreateBuffer(32, 16); |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 79 | ASSERT_TRUE(buffer); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 80 | EXPECT_EQ(32, buffer->width()); |
| 81 | EXPECT_EQ(16, buffer->height()); |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 82 | } |
| 83 | |
| 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()); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 96 | } |
| 97 | |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 98 | TEST(TestI420BufferPool, FrameValidAfterPoolDestruction) { |
nisse | 64ec8f8 | 2016-09-27 07:17:25 | [diff] [blame] | 99 | rtc::scoped_refptr<I420Buffer> buffer; |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 100 | { |
| 101 | I420BufferPool pool; |
| 102 | buffer = pool.CreateBuffer(16, 16); |
| 103 | } |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 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. |
nisse | 06176e4 | 2016-04-18 12:34:40 | [diff] [blame] | 107 | memset(buffer->MutableDataY(), 0xA5, 16 * buffer->StrideY()); |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 108 | } |
| 109 | |
Per | 0098357 | 2016-11-04 07:57:26 | [diff] [blame] | 110 | TEST(TestI420BufferPool, MaxNumberOfBuffers) { |
| 111 | I420BufferPool pool(false, 1); |
Noah Richards | 408a3c6 | 2019-04-01 17:14:47 | [diff] [blame] | 112 | auto buffer1 = pool.CreateBuffer(16, 16); |
Per | 0098357 | 2016-11-04 07:57:26 | [diff] [blame] | 113 | EXPECT_NE(nullptr, buffer1.get()); |
| 114 | EXPECT_EQ(nullptr, pool.CreateBuffer(16, 16).get()); |
| 115 | } |
| 116 | |
magjed@webrtc.org | 73d763e | 2015-03-17 11:40:45 | [diff] [blame] | 117 | } // namespace webrtc |