1 /*
2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef COMMON_VIDEO_INCLUDE_I420_BUFFER_POOL_H_
12 #define COMMON_VIDEO_INCLUDE_I420_BUFFER_POOL_H_
13 
14 #include <stddef.h>
15 
16 #include <list>
17 
18 #include "api/scoped_refptr.h"
19 #include "api/video/i420_buffer.h"
20 #include "rtc_base/race_checker.h"
21 #include "rtc_base/ref_counted_object.h"
22 
23 namespace webrtc {
24 
25 // Simple buffer pool to avoid unnecessary allocations of I420Buffer objects.
26 // The pool manages the memory of the I420Buffer returned from CreateBuffer.
27 // When the I420Buffer is destructed, the memory is returned to the pool for use
28 // by subsequent calls to CreateBuffer. If the resolution passed to CreateBuffer
29 // changes, old buffers will be purged from the pool.
30 // Note that CreateBuffer will crash if more than kMaxNumberOfFramesBeforeCrash
31 // are created. This is to prevent memory leaks where frames are not returned.
32 class I420BufferPool {
33  public:
34   I420BufferPool();
35   explicit I420BufferPool(bool zero_initialize);
36   I420BufferPool(bool zero_initialze, size_t max_number_of_buffers);
37   ~I420BufferPool();
38 
39   // Returns a buffer from the pool. If no suitable buffer exist in the pool
40   // and there are less than |max_number_of_buffers| pending, a buffer is
41   // created. Returns null otherwise.
42   rtc::scoped_refptr<I420Buffer> CreateBuffer(int width, int height);
43 
44   // Returns a buffer from the pool with the explicitly specified stride.
45   rtc::scoped_refptr<I420Buffer> CreateBuffer(int width,
46                                               int height,
47                                               int stride_y,
48                                               int stride_u,
49                                               int stride_v);
50 
51   // Changes the max amount of buffers in the pool to the new value.
52   // Returns true if change was successful and false if the amount of already
53   // allocated buffers is bigger than new value.
54   bool Resize(size_t max_number_of_buffers);
55 
56   // Clears buffers_ and detaches the thread checker so that it can be reused
57   // later from another thread.
58   void Release();
59 
60  private:
61   // Explicitly use a RefCountedObject to get access to HasOneRef,
62   // needed by the pool to check exclusive access.
63   using PooledI420Buffer = rtc::RefCountedObject<I420Buffer>;
64 
65   rtc::RaceChecker race_checker_;
66   std::list<rtc::scoped_refptr<PooledI420Buffer>> buffers_;
67   // If true, newly allocated buffers are zero-initialized. Note that recycled
68   // buffers are not zero'd before reuse. This is required of buffers used by
69   // FFmpeg according to http://crbug.com/390941, which only requires it for the
70   // initial allocation (as shown by FFmpeg's own buffer allocation code). It
71   // has to do with "Use-of-uninitialized-value" on "Linux_msan_chrome".
72   const bool zero_initialize_;
73   // Max number of buffers this pool can have pending.
74   size_t max_number_of_buffers_;
75 };
76 
77 }  // namespace webrtc
78 
79 #endif  // COMMON_VIDEO_INCLUDE_I420_BUFFER_POOL_H_
80