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