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/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "media/base/video_frame.h"
12 #include "media/base/video_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 TEST(VideoCaptureBufferPoolTest
, BufferPool
) {
18 const gfx::Size size
= gfx::Size(640, 480);
19 scoped_refptr
<media::VideoFrame
> non_pool_frame
=
20 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
, size
,
21 gfx::Rect(size
), size
, base::TimeDelta());
22 scoped_refptr
<VideoCaptureBufferPool
> pool
=
23 new VideoCaptureBufferPool(size
, 3);
25 ASSERT_EQ(460800u, pool
->GetMemorySize());
27 ASSERT_TRUE(pool
->Allocate());
28 scoped_refptr
<media::VideoFrame
> frame1
= pool
->ReserveForProducer(0);
29 ASSERT_TRUE(NULL
!= frame1
.get());
30 ASSERT_EQ(size
, frame1
->coded_size());
31 scoped_refptr
<media::VideoFrame
> frame2
= pool
->ReserveForProducer(0);
32 ASSERT_TRUE(NULL
!= frame2
.get());
33 ASSERT_EQ(size
, frame2
->coded_size());
34 scoped_refptr
<media::VideoFrame
> frame3
= pool
->ReserveForProducer(0);
35 ASSERT_TRUE(NULL
!= frame3
.get());
38 media::FillYUV(frame1
.get(), 0x11, 0x22, 0x33);
39 media::FillYUV(frame2
.get(), 0x44, 0x55, 0x66);
40 media::FillYUV(frame3
.get(), 0x77, 0x88, 0x99);
42 // Fourth frame should fail.
43 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
45 // Release 1st frame and retry; this should succeed.
47 scoped_refptr
<media::VideoFrame
> frame4
= pool
->ReserveForProducer(0);
48 ASSERT_TRUE(NULL
!= frame4
.get());
50 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
53 int buffer_id2
= pool
->RecognizeReservedBuffer(frame2
);
54 ASSERT_NE(0, buffer_id2
);
55 int buffer_id3
= pool
->RecognizeReservedBuffer(frame3
);
56 ASSERT_NE(0, buffer_id3
);
57 int buffer_id4
= pool
->RecognizeReservedBuffer(frame4
);
58 ASSERT_NE(0, buffer_id4
);
59 int buffer_id_non_pool
= pool
->RecognizeReservedBuffer(non_pool_frame
);
60 ASSERT_EQ(0, buffer_id_non_pool
);
62 ASSERT_FALSE(pool
->IsAnyBufferHeldForConsumers());
65 pool
->HoldForConsumers(frame3
, buffer_id3
, 2);
67 ASSERT_TRUE(pool
->IsAnyBufferHeldForConsumers());
68 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
69 frame3
= NULL
; // Old producer releases frame. Should be a noop.
70 ASSERT_TRUE(pool
->IsAnyBufferHeldForConsumers());
71 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
72 frame2
= NULL
; // Active producer releases frame. Should free a frame.
75 ASSERT_TRUE(pool
->IsAnyBufferHeldForConsumers());
76 frame1
= pool
->ReserveForProducer(0);
77 ASSERT_TRUE(NULL
!= frame1
.get());
78 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
79 ASSERT_TRUE(pool
->IsAnyBufferHeldForConsumers());
81 // First consumer finishes.
82 pool
->RelinquishConsumerHold(buffer_id3
, 1);
83 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
84 ASSERT_TRUE(pool
->IsAnyBufferHeldForConsumers());
86 // Second consumer finishes. This should free that frame.
87 pool
->RelinquishConsumerHold(buffer_id3
, 1);
88 ASSERT_FALSE(pool
->IsAnyBufferHeldForConsumers());
89 frame3
= pool
->ReserveForProducer(0);
90 ASSERT_TRUE(NULL
!= frame3
.get());
91 ASSERT_FALSE(pool
->IsAnyBufferHeldForConsumers());
92 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
94 // Now deliver & consume frame1, but don't release the VideoFrame.
95 int buffer_id1
= pool
->RecognizeReservedBuffer(frame1
);
96 ASSERT_NE(0, buffer_id1
);
97 pool
->HoldForConsumers(frame1
, buffer_id1
, 5);
98 ASSERT_TRUE(pool
->IsAnyBufferHeldForConsumers());
99 pool
->RelinquishConsumerHold(buffer_id1
, 5);
100 ASSERT_FALSE(pool
->IsAnyBufferHeldForConsumers());
102 // Even though the consumer is done with the buffer at |buffer_id1|, it cannot
103 // be re-allocated to the producer, because |frame1| still references it. But
104 // when |frame1| goes away, we should be able to re-reserve the buffer (and
105 // the ID ought to be the same).
106 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
107 frame1
= NULL
; // Should free the frame.
108 frame2
= pool
->ReserveForProducer(0);
109 ASSERT_TRUE(NULL
!= frame2
.get());
110 ASSERT_EQ(buffer_id1
, pool
->RecognizeReservedBuffer(frame2
));
111 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
113 // For good measure, do one more cycle of free/realloc without delivery, now
114 // that this buffer has been through the consumer-hold cycle.
116 frame1
= pool
->ReserveForProducer(0);
117 ASSERT_TRUE(NULL
!= frame1
.get());
118 ASSERT_EQ(buffer_id1
, pool
->RecognizeReservedBuffer(frame1
));
119 ASSERT_EQ(NULL
, pool
->ReserveForProducer(0).get()) << "Pool should be empty";
121 // Tear down the pool, writing into the frames. The VideoFrame should
122 // preserve the lifetime of the underlying memory.
127 media::FillYUV(frame1
.get(), 0x11, 0x22, 0x33);
128 media::FillYUV(frame4
.get(), 0x44, 0x55, 0x66);
132 media::FillYUV(frame4
.get(), 0x44, 0x55, 0x66);
136 } // namespace content