OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ | 5 #ifndef CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ |
6 #define CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ | 6 #define CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <list> | 11 #include <list> |
| 12 #include <memory> |
12 | 13 |
13 #include "base/atomicops.h" | 14 #include "base/atomicops.h" |
14 #include "base/callback.h" | 15 #include "base/callback.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/macros.h" | 17 #include "base/macros.h" |
17 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
18 #include "base/memory/scoped_ptr.h" | |
19 #include "base/memory/weak_ptr.h" | 19 #include "base/memory/weak_ptr.h" |
20 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
21 | 21 |
22 namespace chromecast { | 22 namespace chromecast { |
23 namespace media { | 23 namespace media { |
24 class MediaMemoryChunk; | 24 class MediaMemoryChunk; |
25 class MediaMessage; | 25 class MediaMessage; |
26 class MediaMessageFlag; | 26 class MediaMessageFlag; |
27 | 27 |
28 // MediaMessageFifo is a lock free fifo implementation | 28 // MediaMessageFifo is a lock free fifo implementation |
29 // to pass audio/video data from one thread to another or from one process | 29 // to pass audio/video data from one thread to another or from one process |
30 // to another one (in that case using shared memory). | 30 // to another one (in that case using shared memory). |
31 // | 31 // |
32 // Assuming the feeder and the consumer have a common block of shared memory | 32 // Assuming the feeder and the consumer have a common block of shared memory |
33 // (representing the serialized structure of the fifo), | 33 // (representing the serialized structure of the fifo), |
34 // the feeder (which must be running on a single thread) instantiates its own | 34 // the feeder (which must be running on a single thread) instantiates its own |
35 // instance of MediaMessageFifo, same applies to the consumer. | 35 // instance of MediaMessageFifo, same applies to the consumer. |
36 // | 36 // |
37 // Example: assuming the block of shared memory is given by |mem|, a typical | 37 // Example: assuming the block of shared memory is given by |mem|, a typical |
38 // feeder (using MediaMessageFifo instance fifo_feeder) will push messages | 38 // feeder (using MediaMessageFifo instance fifo_feeder) will push messages |
39 // in the following way: | 39 // in the following way: |
40 // // Create a dummy message to calculate the size of the serialized message. | 40 // // Create a dummy message to calculate the size of the serialized message. |
41 // scoped_ptr<MediaMessage> dummy_msg( | 41 // std::unique_ptr<MediaMessage> dummy_msg( |
42 // MediaMessage::CreateDummyMessage(msg_type)); | 42 // MediaMessage::CreateDummyMessage(msg_type)); |
43 // // ... | 43 // // ... |
44 // // Write all the fields to the dummy message. | 44 // // Write all the fields to the dummy message. |
45 // // ... | 45 // // ... |
46 // | 46 // |
47 // // Create the real message, once the size of the serialized message | 47 // // Create the real message, once the size of the serialized message |
48 // // is known. | 48 // // is known. |
49 // scoped_ptr<MediaMessage> msg( | 49 // std::unique_ptr<MediaMessage> msg( |
50 // MediaMessage::CreateMessage( | 50 // MediaMessage::CreateMessage( |
51 // msg_type, | 51 // msg_type, |
52 // base::Bind(&MediaMessageFifo::ReserveMemory, | 52 // base::Bind(&MediaMessageFifo::ReserveMemory, |
53 // base::Unretained(fifo_feeder.get())), | 53 // base::Unretained(fifo_feeder.get())), |
54 // dummy_msg->content_size())); | 54 // dummy_msg->content_size())); |
55 // if (!msg) { | 55 // if (!msg) { |
56 // // Not enough space for the message: | 56 // // Not enough space for the message: |
57 // // retry later (e.g. when receiving a read activity event, meaning | 57 // // retry later (e.g. when receiving a read activity event, meaning |
58 // // some enough space might have been release). | 58 // // some enough space might have been release). |
59 // return; | 59 // return; |
60 // } | 60 // } |
61 // // ... | 61 // // ... |
62 // // Write all the fields to the real message | 62 // // Write all the fields to the real message |
63 // // in exactly the same way it was done for the dummy message. | 63 // // in exactly the same way it was done for the dummy message. |
64 // // ... | 64 // // ... |
65 // // Once message |msg| is going out of scope, then MediaMessageFifo | 65 // // Once message |msg| is going out of scope, then MediaMessageFifo |
66 // // fifo_feeder is informed that the message is not needed anymore | 66 // // fifo_feeder is informed that the message is not needed anymore |
67 // // (i.e. it was fully written), and fifo_feeder can then update | 67 // // (i.e. it was fully written), and fifo_feeder can then update |
68 // // the external write pointer of the fifo so that the consumer | 68 // // the external write pointer of the fifo so that the consumer |
69 // // can start consuming this message. | 69 // // can start consuming this message. |
70 // | 70 // |
71 // A typical consumer (using MediaMessageFifo instance fifo_consumer) | 71 // A typical consumer (using MediaMessageFifo instance fifo_consumer) |
72 // will retrive messages in the following way: | 72 // will retrive messages in the following way: |
73 // scoped_ptr<MediaMessage> msg(fifo_consumer->Pop()); | 73 // std::unique_ptr<MediaMessage> msg(fifo_consumer->Pop()); |
74 // if (!msg) { | 74 // if (!msg) { |
75 // // The fifo is empty, i.e. no message left. | 75 // // The fifo is empty, i.e. no message left. |
76 // // Try reading again later (e.g. after receiving a write activity event. | 76 // // Try reading again later (e.g. after receiving a write activity event. |
77 // return; | 77 // return; |
78 // } | 78 // } |
79 // // Parse the message using Read functions of MediaMessage: | 79 // // Parse the message using Read functions of MediaMessage: |
80 // // ... | 80 // // ... |
81 // // Once the message is going out of scope, MediaMessageFifo will receive | 81 // // Once the message is going out of scope, MediaMessageFifo will receive |
82 // // a notification that the underlying memory can be released | 82 // // a notification that the underlying memory can be released |
83 // // (i.e. the external read pointer can be updated). | 83 // // (i.e. the external read pointer can be updated). |
84 // | 84 // |
85 // | 85 // |
86 class MediaMessageFifo { | 86 class MediaMessageFifo { |
87 private: | 87 private: |
88 struct Descriptor { | 88 struct Descriptor { |
89 size_t size; | 89 size_t size; |
90 size_t rd_offset; | 90 size_t rd_offset; |
91 size_t wr_offset; | 91 size_t wr_offset; |
92 | 92 |
93 // Ensure the first item has the same alignment as an int64_t. | 93 // Ensure the first item has the same alignment as an int64_t. |
94 int64_t first_item; | 94 int64_t first_item; |
95 }; | 95 }; |
96 | 96 |
97 public: | 97 public: |
98 static const int kDescriptorSize = sizeof(Descriptor); | 98 static const int kDescriptorSize = sizeof(Descriptor); |
99 | 99 |
100 // Creates a media message fifo using |mem| as the underlying serialized | 100 // Creates a media message fifo using |mem| as the underlying serialized |
101 // structure. | 101 // structure. |
102 // If |init| is true, the underlying fifo structure is initialized. | 102 // If |init| is true, the underlying fifo structure is initialized. |
103 MediaMessageFifo(scoped_ptr<MediaMemoryChunk> mem, bool init); | 103 MediaMessageFifo(std::unique_ptr<MediaMemoryChunk> mem, bool init); |
104 ~MediaMessageFifo(); | 104 ~MediaMessageFifo(); |
105 | 105 |
106 // When the consumer and the feeder are living in two different processes, | 106 // When the consumer and the feeder are living in two different processes, |
107 // we might want to convey some messages between these two processes to notify | 107 // we might want to convey some messages between these two processes to notify |
108 // about some fifo activity. | 108 // about some fifo activity. |
109 void ObserveReadActivity(const base::Closure& read_event_cb); | 109 void ObserveReadActivity(const base::Closure& read_event_cb); |
110 void ObserveWriteActivity(const base::Closure& write_event_cb); | 110 void ObserveWriteActivity(const base::Closure& write_event_cb); |
111 | 111 |
112 // Reserves a writeable block of memory at the back of the fifo, | 112 // Reserves a writeable block of memory at the back of the fifo, |
113 // corresponding to the serialized structure of the message. | 113 // corresponding to the serialized structure of the message. |
114 // Returns NULL if the required size cannot be allocated. | 114 // Returns NULL if the required size cannot be allocated. |
115 scoped_ptr<MediaMemoryChunk> ReserveMemory(size_t size); | 115 std::unique_ptr<MediaMemoryChunk> ReserveMemory(size_t size); |
116 | 116 |
117 // Pop a message from the queue. | 117 // Pop a message from the queue. |
118 // Returns a null pointer if there is no message left. | 118 // Returns a null pointer if there is no message left. |
119 scoped_ptr<MediaMessage> Pop(); | 119 std::unique_ptr<MediaMessage> Pop(); |
120 | 120 |
121 // Flush the fifo. | 121 // Flush the fifo. |
122 void Flush(); | 122 void Flush(); |
123 | 123 |
124 private: | 124 private: |
125 // Add some accessors to ensure security on the browser process side. | 125 // Add some accessors to ensure security on the browser process side. |
126 size_t current_rd_offset() const; | 126 size_t current_rd_offset() const; |
127 size_t current_wr_offset() const; | 127 size_t current_wr_offset() const; |
128 size_t internal_rd_offset() const { | 128 size_t internal_rd_offset() const { |
129 DCHECK_LT(internal_rd_offset_, size_); | 129 DCHECK_LT(internal_rd_offset_, size_); |
130 return internal_rd_offset_; | 130 return internal_rd_offset_; |
131 } | 131 } |
132 size_t internal_wr_offset() const { | 132 size_t internal_wr_offset() const { |
133 DCHECK_LT(internal_wr_offset_, size_); | 133 DCHECK_LT(internal_wr_offset_, size_); |
134 return internal_wr_offset_; | 134 return internal_wr_offset_; |
135 } | 135 } |
136 | 136 |
137 // Reserve a block of free memory without doing any check on the available | 137 // Reserve a block of free memory without doing any check on the available |
138 // space. Invoke this function only when all the checks have been done. | 138 // space. Invoke this function only when all the checks have been done. |
139 scoped_ptr<MediaMemoryChunk> ReserveMemoryNoCheck(size_t size); | 139 std::unique_ptr<MediaMemoryChunk> ReserveMemoryNoCheck(size_t size); |
140 | 140 |
141 // Invoked each time there is a memory region in the free space of the fifo | 141 // Invoked each time there is a memory region in the free space of the fifo |
142 // that has possibly been written. | 142 // that has possibly been written. |
143 void OnWrMemoryReleased(); | 143 void OnWrMemoryReleased(); |
144 | 144 |
145 // Invoked each time there is a memory region in the allocated space | 145 // Invoked each time there is a memory region in the allocated space |
146 // of the fifo that has possibly been released. | 146 // of the fifo that has possibly been released. |
147 void OnRdMemoryReleased(); | 147 void OnRdMemoryReleased(); |
148 | 148 |
149 // Functions to modify the internal/external read/write pointers. | 149 // Functions to modify the internal/external read/write pointers. |
150 void CommitRead(size_t new_rd_offset); | 150 void CommitRead(size_t new_rd_offset); |
151 void CommitWrite(size_t new_wr_offset); | 151 void CommitWrite(size_t new_wr_offset); |
152 void CommitInternalRead(size_t new_rd_offset); | 152 void CommitInternalRead(size_t new_rd_offset); |
153 void CommitInternalWrite(size_t new_wr_offset); | 153 void CommitInternalWrite(size_t new_wr_offset); |
154 | 154 |
155 // An instance of MediaMessageFifo must be running on a single thread. | 155 // An instance of MediaMessageFifo must be running on a single thread. |
156 // If the fifo feeder and consumer are living on 2 different threads | 156 // If the fifo feeder and consumer are living on 2 different threads |
157 // or 2 different processes, they must create their own instance | 157 // or 2 different processes, they must create their own instance |
158 // of MediaMessageFifo using the same underlying block of (shared) memory | 158 // of MediaMessageFifo using the same underlying block of (shared) memory |
159 // in the constructor. | 159 // in the constructor. |
160 base::ThreadChecker thread_checker_; | 160 base::ThreadChecker thread_checker_; |
161 | 161 |
162 // Callbacks invoked to notify either of some read or write activity on the | 162 // Callbacks invoked to notify either of some read or write activity on the |
163 // fifo. This is especially useful when the feeder and consumer are living in | 163 // fifo. This is especially useful when the feeder and consumer are living in |
164 // two different processes. | 164 // two different processes. |
165 base::Closure read_event_cb_; | 165 base::Closure read_event_cb_; |
166 base::Closure write_event_cb_; | 166 base::Closure write_event_cb_; |
167 | 167 |
168 // The serialized structure of the fifo. | 168 // The serialized structure of the fifo. |
169 scoped_ptr<MediaMemoryChunk> mem_; | 169 std::unique_ptr<MediaMemoryChunk> mem_; |
170 | 170 |
171 // The size in bytes of the fifo is cached locally for security purpose. | 171 // The size in bytes of the fifo is cached locally for security purpose. |
172 // (the renderer process cannot modify the size and make the browser process | 172 // (the renderer process cannot modify the size and make the browser process |
173 // access out of range addresses). | 173 // access out of range addresses). |
174 size_t size_; | 174 size_t size_; |
175 | 175 |
176 // TODO(damienv): This is a work-around since atomicops.h does not define | 176 // TODO(damienv): This is a work-around since atomicops.h does not define |
177 // an atomic size_t type. | 177 // an atomic size_t type. |
178 #if SIZE_MAX == UINT32_MAX | 178 #if SIZE_MAX == UINT32_MAX |
179 typedef base::subtle::Atomic32 AtomicSize; | 179 typedef base::subtle::Atomic32 AtomicSize; |
(...skipping 24 matching lines...) Expand all Loading... |
204 base::WeakPtr<MediaMessageFifo> weak_this_; | 204 base::WeakPtr<MediaMessageFifo> weak_this_; |
205 base::WeakPtrFactory<MediaMessageFifo> weak_factory_; | 205 base::WeakPtrFactory<MediaMessageFifo> weak_factory_; |
206 | 206 |
207 DISALLOW_COPY_AND_ASSIGN(MediaMessageFifo); | 207 DISALLOW_COPY_AND_ASSIGN(MediaMessageFifo); |
208 }; | 208 }; |
209 | 209 |
210 } // namespace media | 210 } // namespace media |
211 } // namespace chromecast | 211 } // namespace chromecast |
212 | 212 |
213 #endif // CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ | 213 #endif // CHROMECAST_MEDIA_CMA_IPC_MEDIA_MESSAGE_FIFO_H_ |
OLD | NEW |