video_capture_buffer_pool_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.
4
5// Unit test for VideoCaptureBufferPool.
6
7#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
8
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"
14
15namespace content {
16
17TEST(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);
24
25  ASSERT_EQ(460800u, pool->GetMemorySize());
26
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());
36
37  // Touch the memory.
38  media::FillYUV(frame1, 0x11, 0x22, 0x33);
39  media::FillYUV(frame2, 0x44, 0x55, 0x66);
40  media::FillYUV(frame3, 0x77, 0x88, 0x99);
41
42  // Fourth frame should fail.
43  ASSERT_EQ(NULL, pool->ReserveForProducer(0).get()) << "Pool should be empty";
44
45  // Release 1st frame and retry; this should succeed.
46  frame1 = NULL;
47  scoped_refptr<media::VideoFrame> frame4 = pool->ReserveForProducer(0);
48  ASSERT_TRUE(NULL != frame4.get());
49
50  ASSERT_EQ(NULL, pool->ReserveForProducer(0).get()) << "Pool should be empty";
51
52  // Validate the IDs
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);
61
62  ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
63
64  // Deliver a frame.
65  pool->HoldForConsumers(frame3, buffer_id3, 2);
66
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.
73  buffer_id2 = 0;
74
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());
80
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());
85
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);
91  ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers());
92  ASSERT_EQ(NULL, pool->ReserveForProducer(0).get()) << "Pool should be empty";
93
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());
101
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);
110  ASSERT_EQ(buffer_id1, pool->RecognizeReservedBuffer(frame2));
111  ASSERT_EQ(NULL, pool->ReserveForProducer(0).get()) << "Pool should be empty";
112
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.
115  frame2 = NULL;
116  frame1 = pool->ReserveForProducer(0);
117  ASSERT_TRUE(NULL != frame1);
118  ASSERT_EQ(buffer_id1, pool->RecognizeReservedBuffer(frame1));
119  ASSERT_EQ(NULL, pool->ReserveForProducer(0).get()) << "Pool should be empty";
120
121  // Tear down the pool, writing into the frames. The VideoFrame should
122  // preserve the lifetime of the underlying memory.
123  frame3 = NULL;
124  pool = NULL;
125
126  // Touch the memory.
127  media::FillYUV(frame1, 0x11, 0x22, 0x33);
128  media::FillYUV(frame4, 0x44, 0x55, 0x66);
129
130  frame1 = NULL;
131
132  media::FillYUV(frame4, 0x44, 0x55, 0x66);
133  frame4 = NULL;
134}
135
136} // namespace content
137