OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_ | 5 #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_ |
6 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_ | 6 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_ |
7 | 7 |
| 8 #include <map> |
| 9 |
8 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
9 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
10 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
11 #include "base/memory/shared_memory.h" | 13 #include "base/memory/shared_memory.h" |
12 #include "base/process/process.h" | 14 #include "base/process/process.h" |
13 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
14 #include "content/common/content_export.h" | 16 #include "content/common/content_export.h" |
15 #include "ui/gfx/size.h" | 17 #include "ui/gfx/size.h" |
16 | 18 |
17 namespace media { | 19 namespace media { |
18 | 20 |
19 class VideoFrame; | 21 class VideoFrame; |
20 | 22 |
21 } // namespace media | 23 } // namespace media |
22 | 24 |
23 namespace content { | 25 namespace content { |
24 | 26 |
25 // A thread-safe class that does the bookkeeping and lifetime management for a | 27 // A thread-safe class that does the bookkeeping and lifetime management for a |
26 // pool of shared-memory pixel buffers cycled between an in-process producer | 28 // pool of shared-memory pixel buffers cycled between an in-process producer |
27 // (e.g. a VideoCaptureDevice) and a set of out-of-process consumers. The pool | 29 // (e.g. a VideoCaptureDevice) and a set of out-of-process consumers. The pool |
28 // is intended to be allocated and orchestrated by a VideoCaptureController, but | 30 // is intended to be orchestrated by a VideoCaptureController, but is designed |
29 // is designed to outlive the controller if necessary. | 31 // to outlive the controller if necessary. |
30 // | 32 // |
31 // Buffers are identified by an int value called |buffer_id|. Callers may depend | 33 // Producers get a buffer by calling ReserveForProducer(), and may pass on their |
32 // on the buffer IDs being dense in the range [0, count()), so long as the | 34 // ownership to the consumer by calling HoldForConsumers(), or drop the buffer |
33 // Allocate() step succeeded. -1 is never a valid ID, and is returned by some | 35 // (without further processing) by calling RelinquishProducerReservation(). |
34 // methods to indicate failure. Producers get a buffer by calling | 36 // Consumers signal that they are done with the buffer by calling |
35 // ReserveForProducer(), and may pass on their ownership to the consumer by | 37 // RelinquishConsumerHold(). |
36 // calling HoldForConsumers(), or drop the buffer (without further processing) | 38 // |
37 // by calling ReserveForProducer(). Consumers signal that they are done with the | 39 // Buffers are allocated on demand, but there will never be more than |count| |
38 // buffer by calling RelinquishConsumerHold(). | 40 // buffers in existence at any time. Buffers are identified by an int value |
| 41 // called |buffer_id|. -1 (kInvalidId) is never a valid ID, and is returned by |
| 42 // some methods to indicate failure. The active set of buffer ids may change |
| 43 // over the lifetime of the buffer pool, as existing buffers are freed and |
| 44 // reallocated at larger size. When reallocation occurs, new buffer IDs will |
| 45 // circulate. |
39 class CONTENT_EXPORT VideoCaptureBufferPool | 46 class CONTENT_EXPORT VideoCaptureBufferPool |
40 : public base::RefCountedThreadSafe<VideoCaptureBufferPool> { | 47 : public base::RefCountedThreadSafe<VideoCaptureBufferPool> { |
41 public: | 48 public: |
42 VideoCaptureBufferPool(size_t size, int count); | 49 static const int kInvalidId; |
43 | 50 VideoCaptureBufferPool(int count); |
44 // One-time initialization to allocate the shared memory buffers. Returns true | |
45 // on success. | |
46 bool Allocate(); | |
47 | 51 |
48 // One-time (per client/per-buffer) initialization to share a particular | 52 // One-time (per client/per-buffer) initialization to share a particular |
49 // buffer to a process. | 53 // buffer to a process. The size of the allocation is returned as |
| 54 // |memory_size|. |
50 base::SharedMemoryHandle ShareToProcess(int buffer_id, | 55 base::SharedMemoryHandle ShareToProcess(int buffer_id, |
51 base::ProcessHandle process_handle); | 56 base::ProcessHandle process_handle, |
| 57 size_t* memory_size); |
52 | 58 |
53 // Get the shared memory handle for a particular buffer index. | 59 // Locate or allocate a buffer that's not in use by the producer or consumers, |
54 base::SharedMemoryHandle GetHandle(int buffer_id); | 60 // reserve it, and return its id. If no such buffer exists, returns |
55 | 61 // kInvalidId. The reserved buffer remains reserved (and writable by the |
56 // Get the mapped buffer memory for a particular buffer index. | |
57 void* GetMemory(int buffer_id); | |
58 | |
59 // Locate the index of a buffer (if any) that's not in use by the producer or | |
60 // consumers, and reserve it. The buffer remains reserved (and writable by the | |
61 // producer) until ownership is transferred either to the consumer via | 62 // producer) until ownership is transferred either to the consumer via |
62 // HoldForConsumers(), or back to the pool with | 63 // HoldForConsumers(), or back to the pool with |
63 // RelinquishProducerReservation(). | 64 // RelinquishProducerReservation(). |
64 int ReserveForProducer(); | 65 // |
| 66 // On occasion, this call will decide to free an old buffer to make room for a |
| 67 // new allocation at a larger size. If so, the ID of the destroyed buffer is |
| 68 // returned via |buffer_id_to_drop|. |
| 69 int ReserveForProducer(size_t size, int* buffer_id_to_drop); |
65 | 70 |
66 // Indicate that a buffer held for the producer should be returned back to the | 71 // Indicate that a buffer held for the producer should be returned back to the |
67 // pool without passing on to the consumer. This effectively is the opposite | 72 // pool without passing on to the consumer. This effectively is the opposite |
68 // of ReserveForProducer(). | 73 // of ReserveForProducer(). |
69 void RelinquishProducerReservation(int buffer_id); | 74 void RelinquishProducerReservation(int buffer_id); |
70 | 75 |
71 // Transfer a buffer from producer to consumer ownership. | 76 // Transfer a buffer from producer to consumer ownership. |
72 // |buffer_id| must be a buffer index previously returned by | 77 // |buffer_id| must be a buffer index previously returned by |
73 // ReserveForProducer(), and not already passed to HoldForConsumers(). | 78 // ReserveForProducer(), and not already passed to HoldForConsumers(). |
74 void HoldForConsumers(int buffer_id, int num_clients); | 79 void HoldForConsumers(int buffer_id, int num_clients); |
75 | 80 |
76 // Indicate that one or more consumers are done with a particular buffer. This | 81 // Indicate that one or more consumers are done with a particular buffer. This |
77 // effectively is the opposite of HoldForConsumers(). Once the consumers are | 82 // effectively is the opposite of HoldForConsumers(). Once the consumers are |
78 // done, a buffer is returned to the pool for reuse. | 83 // done, a buffer is returned to the pool for reuse. |
79 void RelinquishConsumerHold(int buffer_id, int num_clients); | 84 void RelinquishConsumerHold(int buffer_id, int num_clients); |
80 | 85 |
81 // Detect whether a particular SharedMemoryHandle is exported by a buffer that | 86 // Detect whether a particular SharedMemoryHandle is exported by a buffer that |
82 // belongs to this pool -- that is, whether it was allocated by an earlier | 87 // belongs to this pool -- that is, whether it was reserved by an earlier call |
83 // call to ReserveForProducer(). If so, return its buffer_id (a value on the | 88 // to ReserveForProducer(). If so, return its buffer_id. If not, return |
84 // range [0, count())). If not, return -1, indicating the buffer is not | 89 // kInvalidId, indicating the buffer is not recognized (it may be a valid |
85 // recognized (it may be a valid frame, but we didn't allocate it). | 90 // frame, but we didn't allocate it). |
86 int RecognizeReservedBuffer(base::SharedMemoryHandle maybe_belongs_to_pool); | 91 int RecognizeReservedBuffer(base::SharedMemoryHandle maybe_belongs_to_pool); |
87 | 92 |
88 // Utility functions to return a buffer wrapped in a useful type. | 93 // Return a buffer wrapped in a useful type. If a reallocation occurred, the |
89 scoped_refptr<media::VideoFrame> ReserveI420VideoFrame(const gfx::Size& size, | 94 // ID of the destroyed buffer is returned via |buffer_id_to_drop|. |
90 int rotation); | 95 scoped_refptr<media::VideoFrame> ReserveI420VideoFrame( |
| 96 const gfx::Size& size, |
| 97 int rotation, |
| 98 int* buffer_id_to_drop); |
91 | 99 |
92 int count() const { return count_; } | 100 int count() const { return count_; } |
93 size_t GetMemorySize() const; | |
94 bool IsAnyBufferHeldForConsumers(); | |
95 | 101 |
96 private: | 102 private: |
97 friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>; | 103 friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>; |
98 | 104 |
99 // Per-buffer state. | 105 // Per-buffer state. |
100 struct Buffer { | 106 struct Buffer { |
101 Buffer(); | 107 Buffer(); |
102 | 108 |
103 // The memory created to be shared with renderer processes. | 109 // The memory created to be shared with renderer processes. |
104 base::SharedMemory shared_memory; | 110 base::SharedMemory shared_memory; |
105 | 111 |
106 // Rotation in degrees of the buffer. | 112 // Rotation in degrees of the buffer. |
| 113 // |
| 114 // TODO(jiayl): Move this out of this class. Clients can track rotation |
| 115 // state themselves by means of a map keyed by buffer_id. |
107 int rotation; | 116 int rotation; |
108 | 117 |
109 // Tracks whether this buffer is currently referenced by the producer. | 118 // Tracks whether this buffer is currently referenced by the producer. |
110 bool held_by_producer; | 119 bool held_by_producer; |
111 | 120 |
112 // Number of consumer processes which hold this shared memory. | 121 // Number of consumer processes which hold this shared memory. |
113 int consumer_hold_count; | 122 int consumer_hold_count; |
114 }; | 123 }; |
115 | 124 |
| 125 typedef std::map<int, Buffer*> BufferMap; |
| 126 |
116 virtual ~VideoCaptureBufferPool(); | 127 virtual ~VideoCaptureBufferPool(); |
117 | 128 |
118 int ReserveForProducerInternal(); | 129 int ReserveForProducerInternal(size_t size, int* buffer_id_to_drop); |
119 | 130 |
120 bool IsAllocated() const; | 131 Buffer* GetBuffer(int buffer_id); |
121 | 132 |
122 // Protects |buffers_| and contents thereof. | 133 // Protects the mutable members of this class. |
123 base::Lock lock_; | 134 base::Lock lock_; |
124 | 135 |
125 // The buffers, indexed by |buffer_id|. Element 0 is always NULL. | 136 // The ID of the next buffer. |
126 ScopedVector<Buffer> buffers_; | 137 int next_buffer_id_; |
127 | 138 |
128 const size_t size_; | 139 // The buffers, indexed by |buffer_id|. |
| 140 BufferMap buffers_; |
| 141 |
| 142 // The max number of buffers that the pool is allowed to have at any moment. |
129 const int count_; | 143 const int count_; |
130 | 144 |
131 DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureBufferPool); | 145 DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureBufferPool); |
132 }; | 146 }; |
133 | 147 |
134 } // namespace content | 148 } // namespace content |
135 | 149 |
136 #endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_ | 150 #endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_BUFFER_POOL_H_ |
OLD | NEW |