Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc

Issue 23551011: From Video Capture, abolish OnFrameInfo and enable resolution changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rework IPC serialization, VideoCaptureParams switch to composition, eliminate OnFrameInfo for PPAPI… Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Unit test for VideoCaptureBufferPool. 5 // Unit test for VideoCaptureBufferPool.
6 6
7 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" 7 #include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "content/browser/renderer_host/media/video_capture_controller.h" 12 #include "content/browser/renderer_host/media/video_capture_controller.h"
13 #include "media/base/video_frame.h" 13 #include "media/base/video_frame.h"
14 #include "media/base/video_util.h" 14 #include "media/base/video_util.h"
15 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
16 16
17 namespace content { 17 namespace content {
18 18
19 TEST(VideoCaptureBufferPoolTest, BufferPool) { 19 class VideoCaptureBufferPoolTest : public testing::Test {
20 const gfx::Size size = gfx::Size(640, 480); 20 protected:
21 VideoCaptureBufferPoolTest()
22 : expected_dropped_id_(0),
23 pool_(new VideoCaptureBufferPool(3)) {}
24
25 void ExpectDroppedId(int expected_dropped_id) {
sheu 2013/10/18 01:48:45 nit: according to style guide, this would be: voi
ncarter (slow) 2013/10/22 01:06:21 This is ExpectDroppedId because, from calling code
26 expected_dropped_id_ = expected_dropped_id;
27 }
28
29 scoped_refptr<media::VideoFrame> ReserveI420VideoFrame(
30 const gfx::Size& size) {
31 int buffer_id_to_drop = ~expected_dropped_id_;
32 scoped_refptr<media::VideoFrame> frame =
33 pool_->ReserveI420VideoFrame(size, 0, &buffer_id_to_drop);
34 EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop)
35 << "Unexpected buffer reallocation result.";
36 return frame;
37 }
38
39 int expected_dropped_id_;
40 scoped_refptr<VideoCaptureBufferPool> pool_;
41
42 private:
43 DISALLOW_COPY_AND_ASSIGN(VideoCaptureBufferPoolTest);
44 };
45
46 TEST_F(VideoCaptureBufferPoolTest, BufferPool) {
47 const gfx::Size size_lo = gfx::Size(640, 480);
48 const gfx::Size size_hi = gfx::Size(1024, 768);
21 scoped_refptr<media::VideoFrame> non_pool_frame = 49 scoped_refptr<media::VideoFrame> non_pool_frame =
22 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size, 50 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_lo,
23 gfx::Rect(size), size, base::TimeDelta()); 51 gfx::Rect(size_lo), size_lo,
24 scoped_refptr<VideoCaptureBufferPool> pool = new VideoCaptureBufferPool( 52 base::TimeDelta());
25 media::VideoFrame::AllocationSize(media::VideoFrame::I420, size), 3);
26 53
27 ASSERT_EQ(460800u, pool->GetMemorySize()); 54 // Reallocation won't happen for the first part of the test.
28 ASSERT_TRUE(pool->Allocate()); 55 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
29 56
30 scoped_refptr<media::VideoFrame> frame1 = 57 scoped_refptr<media::VideoFrame> frame1 = ReserveI420VideoFrame(size_lo);
31 pool->ReserveI420VideoFrame(size, 0);
32 ASSERT_TRUE(NULL != frame1.get()); 58 ASSERT_TRUE(NULL != frame1.get());
33 ASSERT_EQ(size, frame1->coded_size()); 59 ASSERT_EQ(size_lo, frame1->coded_size());
34 scoped_refptr<media::VideoFrame> frame2 = 60 scoped_refptr<media::VideoFrame> frame2 = ReserveI420VideoFrame(size_lo);
35 pool->ReserveI420VideoFrame(size, 0);
36 ASSERT_TRUE(NULL != frame2.get()); 61 ASSERT_TRUE(NULL != frame2.get());
37 ASSERT_EQ(size, frame2->coded_size()); 62 ASSERT_EQ(size_lo, frame2->coded_size());
38 scoped_refptr<media::VideoFrame> frame3 = 63 scoped_refptr<media::VideoFrame> frame3 = ReserveI420VideoFrame(size_lo);
39 pool->ReserveI420VideoFrame(size, 0);
40 ASSERT_TRUE(NULL != frame3.get()); 64 ASSERT_TRUE(NULL != frame3.get());
41 65
42 // Touch the memory. 66 // Touch the memory.
43 media::FillYUV(frame1.get(), 0x11, 0x22, 0x33); 67 media::FillYUV(frame1.get(), 0x11, 0x22, 0x33);
44 media::FillYUV(frame2.get(), 0x44, 0x55, 0x66); 68 media::FillYUV(frame2.get(), 0x44, 0x55, 0x66);
45 media::FillYUV(frame3.get(), 0x77, 0x88, 0x99); 69 media::FillYUV(frame3.get(), 0x77, 0x88, 0x99);
46 70
47 // Fourth frame should fail. 71 // Fourth frame should fail.
48 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 72 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
49 << "Pool should be empty";
50 73
51 // Release 1st frame and retry; this should succeed. 74 // Release 1st frame and retry; this should succeed.
52 frame1 = NULL; 75 frame1 = NULL;
53 scoped_refptr<media::VideoFrame> frame4 = 76 scoped_refptr<media::VideoFrame> frame4 = ReserveI420VideoFrame(size_lo);
54 pool->ReserveI420VideoFrame(size, 0);
55 ASSERT_TRUE(NULL != frame4.get()); 77 ASSERT_TRUE(NULL != frame4.get());
56 78
57 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 79 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
58 << "Pool should be empty"; 80 ASSERT_FALSE(ReserveI420VideoFrame(size_hi)) << "Pool should be empty";
59 81
60 // Validate the IDs 82 // Validate the IDs
61 int buffer_id2 = 83 int buffer_id2 =
62 pool->RecognizeReservedBuffer(frame2->shared_memory_handle()); 84 pool_->RecognizeReservedBuffer(frame2->shared_memory_handle());
63 ASSERT_LE(0, buffer_id2); 85 ASSERT_EQ(1, buffer_id2);
64 int buffer_id3 = 86 int buffer_id3 =
65 pool->RecognizeReservedBuffer(frame3->shared_memory_handle()); 87 pool_->RecognizeReservedBuffer(frame3->shared_memory_handle());
66 ASSERT_LE(0, buffer_id3); 88 base::SharedMemoryHandle memory_handle3 = frame3->shared_memory_handle();
89 ASSERT_EQ(2, buffer_id3);
67 int buffer_id4 = 90 int buffer_id4 =
68 pool->RecognizeReservedBuffer(frame4->shared_memory_handle()); 91 pool_->RecognizeReservedBuffer(frame4->shared_memory_handle());
69 ASSERT_LE(0, buffer_id4); 92 ASSERT_EQ(0, buffer_id4);
70 int buffer_id_non_pool = 93 int buffer_id_non_pool =
71 pool->RecognizeReservedBuffer(non_pool_frame->shared_memory_handle()); 94 pool_->RecognizeReservedBuffer(non_pool_frame->shared_memory_handle());
72 ASSERT_GT(0, buffer_id_non_pool); 95 ASSERT_EQ(VideoCaptureBufferPool::kInvalidId, buffer_id_non_pool);
73
74 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
75 96
76 // Deliver a frame. 97 // Deliver a frame.
77 pool->HoldForConsumers(buffer_id3, 2); 98 pool_->HoldForConsumers(buffer_id3, 2);
78 99
79 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 100 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
80 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 101
81 << "Pool should be empty";
82 frame3 = NULL; // Old producer releases frame. Should be a noop. 102 frame3 = NULL; // Old producer releases frame. Should be a noop.
83 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 103 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
84 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 104 ASSERT_FALSE(ReserveI420VideoFrame(size_hi)) << "Pool should be empty";
85 << "Pool should be empty"; 105
86 frame2 = NULL; // Active producer releases frame. Should free a frame. 106 frame2 = NULL; // Active producer releases frame. Should free a frame.
87 buffer_id2 = 0;
88 107
89 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 108 frame1 = ReserveI420VideoFrame(size_lo);
90 frame1 = pool->ReserveI420VideoFrame(size, 0);
91 ASSERT_TRUE(NULL != frame1.get()); 109 ASSERT_TRUE(NULL != frame1.get());
92 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 110 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
93 << "Pool should be empty";
94 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
95 111
96 // First consumer finishes. 112 // First consumer finishes.
97 pool->RelinquishConsumerHold(buffer_id3, 1); 113 pool_->RelinquishConsumerHold(buffer_id3, 1);
98 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 114 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
99 << "Pool should be empty";
100 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers());
101 115
102 // Second consumer finishes. This should free that frame. 116 // Second consumer finishes. This should free that frame.
103 pool->RelinquishConsumerHold(buffer_id3, 1); 117 pool_->RelinquishConsumerHold(buffer_id3, 1);
104 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers()); 118 frame3 = ReserveI420VideoFrame(size_lo);
105 frame3 = pool->ReserveI420VideoFrame(size, 0);
106 ASSERT_TRUE(NULL != frame3.get()); 119 ASSERT_TRUE(NULL != frame3.get());
107 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers()); 120 ASSERT_EQ(buffer_id3,
108 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 121 pool_->RecognizeReservedBuffer(frame3->shared_memory_handle()))
109 << "Pool should be empty"; 122 << "Buffer ID should be reused.";
123 ASSERT_EQ(memory_handle3, frame3->shared_memory_handle());
124 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
110 125
111 // Now deliver & consume frame1, but don't release the VideoFrame. 126 // Now deliver & consume frame1, but don't release the VideoFrame.
112 int buffer_id1 = 127 int buffer_id1 =
113 pool->RecognizeReservedBuffer(frame1->shared_memory_handle()); 128 pool_->RecognizeReservedBuffer(frame1->shared_memory_handle());
114 ASSERT_LE(0, buffer_id1); 129 ASSERT_EQ(1, buffer_id1);
115 pool->HoldForConsumers(buffer_id1, 5); 130 pool_->HoldForConsumers(buffer_id1, 5);
116 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 131 pool_->RelinquishConsumerHold(buffer_id1, 5);
117 pool->RelinquishConsumerHold(buffer_id1, 5);
118 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
119 132
120 // Even though the consumer is done with the buffer at |buffer_id1|, it cannot 133 // Even though the consumer is done with the buffer at |buffer_id1|, it cannot
121 // be re-allocated to the producer, because |frame1| still references it. But 134 // be re-allocated to the producer, because |frame1| still references it. But
122 // when |frame1| goes away, we should be able to re-reserve the buffer (and 135 // when |frame1| goes away, we should be able to re-reserve the buffer (and
123 // the ID ought to be the same). 136 // the ID ought to be the same).
124 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 137 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
125 << "Pool should be empty";
126 frame1 = NULL; // Should free the frame. 138 frame1 = NULL; // Should free the frame.
127 frame2 = pool->ReserveI420VideoFrame(size, 0); 139 frame2 = ReserveI420VideoFrame(size_lo);
128 ASSERT_TRUE(NULL != frame2.get()); 140 ASSERT_TRUE(NULL != frame2.get());
129 ASSERT_EQ(buffer_id1, 141 ASSERT_EQ(buffer_id1,
130 pool->RecognizeReservedBuffer(frame2->shared_memory_handle())); 142 pool_->RecognizeReservedBuffer(frame2->shared_memory_handle()));
131 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 143 buffer_id2 = buffer_id1;
132 << "Pool should be empty"; 144 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
133 145
134 // For good measure, do one more cycle of free/realloc without delivery, now 146 // Now try reallocation with different resolutions. We expect reallocation
135 // that this buffer has been through the consumer-hold cycle. 147 // to occur only when the old buffer is too small.
136 frame2 = NULL; 148 frame2 = NULL;
137 frame1 = pool->ReserveI420VideoFrame(size, 0); 149 ExpectDroppedId(buffer_id2);
138 ASSERT_TRUE(NULL != frame1.get()); 150 frame2 = ReserveI420VideoFrame(size_hi);
139 ASSERT_EQ(buffer_id1, 151 ASSERT_TRUE(NULL != frame2.get());
140 pool->RecognizeReservedBuffer(frame1->shared_memory_handle())); 152 ASSERT_TRUE(frame2->coded_size() == size_hi);
141 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 153 ASSERT_EQ(3, pool_->RecognizeReservedBuffer(frame2->shared_memory_handle()));
142 << "Pool should be empty"; 154 base::SharedMemoryHandle memory_handle_hi = frame2->shared_memory_handle();
155 frame2 = NULL; // Frees it.
156 ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
157 frame2 = ReserveI420VideoFrame(size_lo);
158 base::SharedMemoryHandle memory_handle_lo = frame2->shared_memory_handle();
159 ASSERT_EQ(memory_handle_hi, memory_handle_lo)
160 << "Decrease in resolution should not reallocate buffer";
161 ASSERT_TRUE(NULL != frame2.get());
162 ASSERT_TRUE(frame2->coded_size() == size_lo);
163 ASSERT_EQ(3, pool_->RecognizeReservedBuffer(frame2->shared_memory_handle()));
164 ASSERT_FALSE(ReserveI420VideoFrame(size_lo)) << "Pool should be empty";
143 165
144 // Tear down the pool, writing into the frames. The VideoFrame should 166 // Tear down the pool_, writing into the frames. The VideoFrame should
145 // preserve the lifetime of the underlying memory. 167 // preserve the lifetime of the underlying memory.
146 frame3 = NULL; 168 frame3 = NULL;
147 pool = NULL; 169 pool_ = NULL;
148 170
149 // Touch the memory. 171 // Touch the memory.
150 media::FillYUV(frame1.get(), 0x11, 0x22, 0x33); 172 media::FillYUV(frame2.get(), 0x11, 0x22, 0x33);
151 media::FillYUV(frame4.get(), 0x44, 0x55, 0x66); 173 media::FillYUV(frame4.get(), 0x44, 0x55, 0x66);
152 174
153 frame1 = NULL; 175 frame2 = NULL;
154 176
155 media::FillYUV(frame4.get(), 0x44, 0x55, 0x66); 177 media::FillYUV(frame4.get(), 0x44, 0x55, 0x66);
156 frame4 = NULL; 178 frame4 = NULL;
157 } 179 }
158 180
159 } // namespace content 181 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698