Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_buffer_pool_unittest.cc
blob39fd9857b3ee4da108bd71fedd1616bdc1fa975c
1 // Copyright (c) 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 // Unit test for VideoCaptureBufferPool.
7 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
9 #include "base/bind.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "content/browser/renderer_host/media/video_capture_controller.h"
13 #include "media/base/video_frame.h"
14 #include "media/base/video_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace content {
19 class VideoCaptureBufferPoolTest : public testing::Test {
20 protected:
21 class Buffer {
22 public:
23 Buffer(const scoped_refptr<VideoCaptureBufferPool> pool,
24 int id,
25 void* data,
26 size_t size)
27 : pool_(pool), id_(id), data_(data), size_(size) {}
28 ~Buffer() { pool_->RelinquishProducerReservation(id()); }
29 int id() const { return id_; }
30 void* data() const { return data_; }
31 size_t size() const { return size_; }
33 private:
34 const scoped_refptr<VideoCaptureBufferPool> pool_;
35 const int id_;
36 void* const data_;
37 const size_t size_;
39 VideoCaptureBufferPoolTest()
40 : expected_dropped_id_(0),
41 pool_(new VideoCaptureBufferPool(3)) {}
43 void ExpectDroppedId(int expected_dropped_id) {
44 expected_dropped_id_ = expected_dropped_id;
47 scoped_ptr<Buffer> ReserveI420Buffer(const gfx::Size& dimensions) {
48 const size_t frame_bytes =
49 media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions);
50 // To verify that ReserveI420Buffer always sets |buffer_id_to_drop|,
51 // initialize it to something different than the expected value.
52 int buffer_id_to_drop = ~expected_dropped_id_;
53 int buffer_id = pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop);
54 if (buffer_id == VideoCaptureBufferPool::kInvalidId)
55 return scoped_ptr<Buffer>();
57 void* memory;
58 size_t size;
59 pool_->GetBufferInfo(buffer_id, &memory, &size);
60 EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop);
61 return scoped_ptr<Buffer>(new Buffer(pool_, buffer_id, memory, size));
64 int expected_dropped_id_;
65 scoped_refptr<VideoCaptureBufferPool> pool_;
67 private:
68 DISALLOW_COPY_AND_ASSIGN(VideoCaptureBufferPoolTest);
71 TEST_F(VideoCaptureBufferPoolTest, BufferPool) {
72 const gfx::Size size_lo = gfx::Size(640, 480);
73 const gfx::Size size_hi = gfx::Size(1024, 768);
74 scoped_refptr<media::VideoFrame> non_pool_frame =
75 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_lo,
76 gfx::Rect(size_lo), size_lo,
77 base::TimeDelta());
79 // Reallocation won't happen for the first part of the test.
80 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
82 scoped_ptr<Buffer> buffer1 = ReserveI420Buffer(size_lo);
83 ASSERT_TRUE(NULL != buffer1.get());
84 ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
85 buffer1->size());
86 scoped_ptr<Buffer> buffer2 = ReserveI420Buffer(size_lo);
87 ASSERT_TRUE(NULL != buffer2.get());
88 ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
89 buffer2->size());
90 scoped_ptr<Buffer> buffer3 = ReserveI420Buffer(size_lo);
91 ASSERT_TRUE(NULL != buffer3.get());
92 ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
93 buffer3->size());
95 // Touch the memory.
96 memset(buffer1->data(), 0x11, buffer1->size());
97 memset(buffer2->data(), 0x44, buffer2->size());
98 memset(buffer3->data(), 0x77, buffer3->size());
100 // Fourth buffer should fail.
101 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
103 // Release 1st buffer and retry; this should succeed.
104 buffer1.reset();
105 scoped_ptr<Buffer> buffer4 = ReserveI420Buffer(size_lo);
106 ASSERT_TRUE(NULL != buffer4.get());
108 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
109 ASSERT_FALSE(ReserveI420Buffer(size_hi)) << "Pool should be empty";
111 // Validate the IDs
112 int buffer_id2 = buffer2->id();
113 ASSERT_EQ(1, buffer_id2);
114 int buffer_id3 = buffer3->id();
115 ASSERT_EQ(2, buffer_id3);
116 void* const memory_pointer3 = buffer3->data();
117 int buffer_id4 = buffer4->id();
118 ASSERT_EQ(0, buffer_id4);
120 // Deliver a buffer.
121 pool_->HoldForConsumers(buffer_id3, 2);
123 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
125 buffer3.reset(); // Old producer releases buffer. Should be a noop.
126 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
127 ASSERT_FALSE(ReserveI420Buffer(size_hi)) << "Pool should be empty";
129 buffer2.reset(); // Active producer releases buffer. Should free a buffer.
131 buffer1 = ReserveI420Buffer(size_lo);
132 ASSERT_TRUE(NULL != buffer1.get());
133 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
135 // First consumer finishes.
136 pool_->RelinquishConsumerHold(buffer_id3, 1);
137 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
139 // Second consumer finishes. This should free that buffer.
140 pool_->RelinquishConsumerHold(buffer_id3, 1);
141 buffer3 = ReserveI420Buffer(size_lo);
142 ASSERT_TRUE(NULL != buffer3.get());
143 ASSERT_EQ(buffer_id3, buffer3->id()) << "Buffer ID should be reused.";
144 ASSERT_EQ(memory_pointer3, buffer3->data());
145 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
147 // Now deliver & consume buffer1, but don't release the buffer.
148 int buffer_id1 = buffer1->id();
149 ASSERT_EQ(1, buffer_id1);
150 pool_->HoldForConsumers(buffer_id1, 5);
151 pool_->RelinquishConsumerHold(buffer_id1, 5);
153 // Even though the consumer is done with the buffer at |buffer_id1|, it cannot
154 // be re-allocated to the producer, because |buffer1| still references it. But
155 // when |buffer1| goes away, we should be able to re-reserve the buffer (and
156 // the ID ought to be the same).
157 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
158 buffer1.reset(); // Should free the buffer.
159 buffer2 = ReserveI420Buffer(size_lo);
160 ASSERT_TRUE(NULL != buffer2.get());
161 ASSERT_EQ(buffer_id1, buffer2->id());
162 buffer_id2 = buffer_id1;
163 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
165 // Now try reallocation with different resolutions. We expect reallocation
166 // to occur only when the old buffer is too small.
167 buffer2.reset();
168 ExpectDroppedId(buffer_id2);
169 buffer2 = ReserveI420Buffer(size_hi);
170 ASSERT_TRUE(NULL != buffer2.get());
171 ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_hi),
172 buffer2->size());
173 ASSERT_EQ(3, buffer2->id());
174 void* const memory_pointer_hi = buffer2->data();
175 buffer2.reset(); // Frees it.
176 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
177 buffer2 = ReserveI420Buffer(size_lo);
178 void* const memory_pointer_lo = buffer2->data();
179 ASSERT_EQ(memory_pointer_hi, memory_pointer_lo)
180 << "Decrease in resolution should not reallocate buffer";
181 ASSERT_TRUE(NULL != buffer2.get());
182 ASSERT_EQ(3, buffer2->id());
183 ASSERT_LE(media::VideoFrame::AllocationSize(media::VideoFrame::I420, size_lo),
184 buffer2->size());
185 ASSERT_FALSE(ReserveI420Buffer(size_lo)) << "Pool should be empty";
187 // Tear down the pool_, writing into the buffers. The buffer should preserve
188 // the lifetime of the underlying memory.
189 buffer3.reset();
190 pool_ = NULL;
192 // Touch the memory.
193 memset(buffer2->data(), 0x22, buffer2->size());
194 memset(buffer4->data(), 0x55, buffer4->size());
196 buffer2.reset();
198 memset(buffer4->data(), 0x77, buffer4->size());
199 buffer4.reset();
202 } // namespace content