Home | History | Annotate | Download | only in media
      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