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/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" 16 17 namespace content { 18 19 TEST(VideoCaptureBufferPoolTest, BufferPool) { 20 const gfx::Size size = gfx::Size(640, 480); 21 scoped_refptr<media::VideoFrame> non_pool_frame = 22 media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size, 23 gfx::Rect(size), size, base::TimeDelta()); 24 scoped_refptr<VideoCaptureBufferPool> pool = 25 new VideoCaptureBufferPool(size.GetArea() * 3 / 2, 3); 26 27 ASSERT_EQ(460800u, pool->GetMemorySize()); 28 ASSERT_TRUE(pool->Allocate()); 29 30 scoped_refptr<media::VideoFrame> frame1 = 31 pool->ReserveI420VideoFrame(size, 0); 32 ASSERT_TRUE(NULL != frame1.get()); 33 ASSERT_EQ(size, frame1->coded_size()); 34 scoped_refptr<media::VideoFrame> frame2 = 35 pool->ReserveI420VideoFrame(size, 0); 36 ASSERT_TRUE(NULL != frame2.get()); 37 ASSERT_EQ(size, frame2->coded_size()); 38 scoped_refptr<media::VideoFrame> frame3 = 39 pool->ReserveI420VideoFrame(size, 0); 40 ASSERT_TRUE(NULL != frame3.get()); 41 42 // Touch the memory. 43 media::FillYUV(frame1.get(), 0x11, 0x22, 0x33); 44 media::FillYUV(frame2.get(), 0x44, 0x55, 0x66); 45 media::FillYUV(frame3.get(), 0x77, 0x88, 0x99); 46 47 // Fourth frame should fail. 48 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 49 << "Pool should be empty"; 50 51 // Release 1st frame and retry; this should succeed. 52 frame1 = NULL; 53 scoped_refptr<media::VideoFrame> frame4 = 54 pool->ReserveI420VideoFrame(size, 0); 55 ASSERT_TRUE(NULL != frame4.get()); 56 57 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 58 << "Pool should be empty"; 59 60 // Validate the IDs 61 int buffer_id2 = 62 pool->RecognizeReservedBuffer(frame2->shared_memory_handle()); 63 ASSERT_LE(0, buffer_id2); 64 int buffer_id3 = 65 pool->RecognizeReservedBuffer(frame3->shared_memory_handle()); 66 ASSERT_LE(0, buffer_id3); 67 int buffer_id4 = 68 pool->RecognizeReservedBuffer(frame4->shared_memory_handle()); 69 ASSERT_LE(0, buffer_id4); 70 int buffer_id_non_pool = 71 pool->RecognizeReservedBuffer(non_pool_frame->shared_memory_handle()); 72 ASSERT_GT(0, buffer_id_non_pool); 73 74 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers()); 75 76 // Deliver a frame. 77 pool->HoldForConsumers(buffer_id3, 2); 78 79 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 80 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 81 << "Pool should be empty"; 82 frame3 = NULL; // Old producer releases frame. Should be a noop. 83 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 84 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 85 << "Pool should be empty"; 86 frame2 = NULL; // Active producer releases frame. Should free a frame. 87 buffer_id2 = 0; 88 89 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 90 frame1 = pool->ReserveI420VideoFrame(size, 0); 91 ASSERT_TRUE(NULL != frame1.get()); 92 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 93 << "Pool should be empty"; 94 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 95 96 // First consumer finishes. 97 pool->RelinquishConsumerHold(buffer_id3, 1); 98 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 99 << "Pool should be empty"; 100 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 101 102 // Second consumer finishes. This should free that frame. 103 pool->RelinquishConsumerHold(buffer_id3, 1); 104 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers()); 105 frame3 = pool->ReserveI420VideoFrame(size, 0); 106 ASSERT_TRUE(NULL != frame3.get()); 107 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers()); 108 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 109 << "Pool should be empty"; 110 111 // Now deliver & consume frame1, but don't release the VideoFrame. 112 int buffer_id1 = 113 pool->RecognizeReservedBuffer(frame1->shared_memory_handle()); 114 ASSERT_LE(0, buffer_id1); 115 pool->HoldForConsumers(buffer_id1, 5); 116 ASSERT_TRUE(pool->IsAnyBufferHeldForConsumers()); 117 pool->RelinquishConsumerHold(buffer_id1, 5); 118 ASSERT_FALSE(pool->IsAnyBufferHeldForConsumers()); 119 120 // 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 122 // when |frame1| goes away, we should be able to re-reserve the buffer (and 123 // the ID ought to be the same). 124 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 125 << "Pool should be empty"; 126 frame1 = NULL; // Should free the frame. 127 frame2 = pool->ReserveI420VideoFrame(size, 0); 128 ASSERT_TRUE(NULL != frame2.get()); 129 ASSERT_EQ(buffer_id1, 130 pool->RecognizeReservedBuffer(frame2->shared_memory_handle())); 131 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 132 << "Pool should be empty"; 133 134 // For good measure, do one more cycle of free/realloc without delivery, now 135 // that this buffer has been through the consumer-hold cycle. 136 frame2 = NULL; 137 frame1 = pool->ReserveI420VideoFrame(size, 0); 138 ASSERT_TRUE(NULL != frame1.get()); 139 ASSERT_EQ(buffer_id1, 140 pool->RecognizeReservedBuffer(frame1->shared_memory_handle())); 141 ASSERT_EQ(NULL, pool->ReserveI420VideoFrame(size, 0).get()) 142 << "Pool should be empty"; 143 144 // Tear down the pool, writing into the frames. The VideoFrame should 145 // preserve the lifetime of the underlying memory. 146 frame3 = NULL; 147 pool = NULL; 148 149 // Touch the memory. 150 media::FillYUV(frame1.get(), 0x11, 0x22, 0x33); 151 media::FillYUV(frame4.get(), 0x44, 0x55, 0x66); 152 153 frame1 = NULL; 154 155 media::FillYUV(frame4.get(), 0x44, 0x55, 0x66); 156 frame4 = NULL; 157 } 158 159 } // namespace content 160