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 #include "chromecast/media/cma/ipc/media_message_fifo.h" |
| 6 |
5 #include <stddef.h> | 7 #include <stddef.h> |
6 #include <stdint.h> | 8 #include <stdint.h> |
7 | 9 |
| 10 #include <memory> |
| 11 |
8 #include "base/bind.h" | 12 #include "base/bind.h" |
9 #include "base/macros.h" | 13 #include "base/macros.h" |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
12 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
13 #include "chromecast/media/cma/ipc/media_memory_chunk.h" | 16 #include "chromecast/media/cma/ipc/media_memory_chunk.h" |
14 #include "chromecast/media/cma/ipc/media_message.h" | 17 #include "chromecast/media/cma/ipc/media_message.h" |
15 #include "chromecast/media/cma/ipc/media_message_fifo.h" | |
16 #include "chromecast/media/cma/ipc/media_message_type.h" | 18 #include "chromecast/media/cma/ipc/media_message_type.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
18 | 20 |
19 namespace chromecast { | 21 namespace chromecast { |
20 namespace media { | 22 namespace media { |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
24 class FifoMemoryChunk : public MediaMemoryChunk { | 26 class FifoMemoryChunk : public MediaMemoryChunk { |
25 public: | 27 public: |
26 FifoMemoryChunk(void* mem, size_t size) | 28 FifoMemoryChunk(void* mem, size_t size) |
27 : mem_(mem), size_(size) {} | 29 : mem_(mem), size_(size) {} |
28 ~FifoMemoryChunk() override {} | 30 ~FifoMemoryChunk() override {} |
29 | 31 |
30 void* data() const override { return mem_; } | 32 void* data() const override { return mem_; } |
31 size_t size() const override { return size_; } | 33 size_t size() const override { return size_; } |
32 bool valid() const override { return true; } | 34 bool valid() const override { return true; } |
33 | 35 |
34 private: | 36 private: |
35 void* mem_; | 37 void* mem_; |
36 size_t size_; | 38 size_t size_; |
37 | 39 |
38 DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk); | 40 DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk); |
39 }; | 41 }; |
40 | 42 |
41 void MsgProducer(scoped_ptr<MediaMessageFifo> fifo, | 43 void MsgProducer(std::unique_ptr<MediaMessageFifo> fifo, |
42 int msg_count, | 44 int msg_count, |
43 base::WaitableEvent* event) { | 45 base::WaitableEvent* event) { |
44 | |
45 for (int k = 0; k < msg_count; k++) { | 46 for (int k = 0; k < msg_count; k++) { |
46 uint32_t msg_type = 0x2 + (k % 5); | 47 uint32_t msg_type = 0x2 + (k % 5); |
47 uint32_t max_msg_content_size = k % 64; | 48 uint32_t max_msg_content_size = k % 64; |
48 do { | 49 do { |
49 scoped_ptr<MediaMessage> msg1( | 50 std::unique_ptr<MediaMessage> msg1(MediaMessage::CreateMessage( |
50 MediaMessage::CreateMessage( | 51 msg_type, base::Bind(&MediaMessageFifo::ReserveMemory, |
51 msg_type, | 52 base::Unretained(fifo.get())), |
52 base::Bind(&MediaMessageFifo::ReserveMemory, | 53 max_msg_content_size)); |
53 base::Unretained(fifo.get())), | |
54 max_msg_content_size)); | |
55 if (msg1) | 54 if (msg1) |
56 break; | 55 break; |
57 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | 56 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); |
58 } while(true); | 57 } while(true); |
59 } | 58 } |
60 | 59 |
61 fifo.reset(); | 60 fifo.reset(); |
62 | 61 |
63 event->Signal(); | 62 event->Signal(); |
64 } | 63 } |
65 | 64 |
66 void MsgConsumer(scoped_ptr<MediaMessageFifo> fifo, | 65 void MsgConsumer(std::unique_ptr<MediaMessageFifo> fifo, |
67 int msg_count, | 66 int msg_count, |
68 base::WaitableEvent* event) { | 67 base::WaitableEvent* event) { |
69 | |
70 int k = 0; | 68 int k = 0; |
71 while (k < msg_count) { | 69 while (k < msg_count) { |
72 uint32_t msg_type = 0x2 + (k % 5); | 70 uint32_t msg_type = 0x2 + (k % 5); |
73 do { | 71 do { |
74 scoped_ptr<MediaMessage> msg2(fifo->Pop()); | 72 std::unique_ptr<MediaMessage> msg2(fifo->Pop()); |
75 if (msg2) { | 73 if (msg2) { |
76 if (msg2->type() != PaddingMediaMsg) { | 74 if (msg2->type() != PaddingMediaMsg) { |
77 EXPECT_EQ(msg2->type(), msg_type); | 75 EXPECT_EQ(msg2->type(), msg_type); |
78 k++; | 76 k++; |
79 } | 77 } |
80 break; | 78 break; |
81 } | 79 } |
82 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); | 80 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); |
83 } while(true); | 81 } while(true); |
84 } | 82 } |
85 | 83 |
86 fifo.reset(); | 84 fifo.reset(); |
87 | 85 |
88 event->Signal(); | 86 event->Signal(); |
89 } | 87 } |
90 | 88 |
91 void MsgProducerConsumer( | 89 void MsgProducerConsumer(std::unique_ptr<MediaMessageFifo> producer_fifo, |
92 scoped_ptr<MediaMessageFifo> producer_fifo, | 90 std::unique_ptr<MediaMessageFifo> consumer_fifo, |
93 scoped_ptr<MediaMessageFifo> consumer_fifo, | 91 base::WaitableEvent* event) { |
94 base::WaitableEvent* event) { | |
95 for (int k = 0; k < 2048; k++) { | 92 for (int k = 0; k < 2048; k++) { |
96 // Should have enough space to create a message. | 93 // Should have enough space to create a message. |
97 uint32_t msg_type = 0x2 + (k % 5); | 94 uint32_t msg_type = 0x2 + (k % 5); |
98 uint32_t max_msg_content_size = k % 64; | 95 uint32_t max_msg_content_size = k % 64; |
99 scoped_ptr<MediaMessage> msg1( | 96 std::unique_ptr<MediaMessage> msg1(MediaMessage::CreateMessage( |
100 MediaMessage::CreateMessage( | 97 msg_type, base::Bind(&MediaMessageFifo::ReserveMemory, |
101 msg_type, | 98 base::Unretained(producer_fifo.get())), |
102 base::Bind(&MediaMessageFifo::ReserveMemory, | 99 max_msg_content_size)); |
103 base::Unretained(producer_fifo.get())), | |
104 max_msg_content_size)); | |
105 EXPECT_TRUE(msg1); | 100 EXPECT_TRUE(msg1); |
106 | 101 |
107 // Make sure the message is commited. | 102 // Make sure the message is commited. |
108 msg1.reset(); | 103 msg1.reset(); |
109 | 104 |
110 // At this point, we should have a message to read. | 105 // At this point, we should have a message to read. |
111 scoped_ptr<MediaMessage> msg2(consumer_fifo->Pop()); | 106 std::unique_ptr<MediaMessage> msg2(consumer_fifo->Pop()); |
112 EXPECT_TRUE(msg2); | 107 EXPECT_TRUE(msg2); |
113 } | 108 } |
114 | 109 |
115 producer_fifo.reset(); | 110 producer_fifo.reset(); |
116 consumer_fifo.reset(); | 111 consumer_fifo.reset(); |
117 | 112 |
118 event->Signal(); | 113 event->Signal(); |
119 } | 114 } |
120 | 115 |
121 } // namespace | 116 } // namespace |
122 | 117 |
123 TEST(MediaMessageFifoTest, AlternateWriteRead) { | 118 TEST(MediaMessageFifoTest, AlternateWriteRead) { |
124 size_t buffer_size = 64 * 1024; | 119 size_t buffer_size = 64 * 1024; |
125 scoped_ptr<uint64_t[]> buffer(new uint64_t[buffer_size / sizeof(uint64_t)]); | 120 std::unique_ptr<uint64_t[]> buffer( |
| 121 new uint64_t[buffer_size / sizeof(uint64_t)]); |
126 | 122 |
127 scoped_ptr<base::Thread> thread( | 123 std::unique_ptr<base::Thread> thread( |
128 new base::Thread("FeederConsumerThread")); | 124 new base::Thread("FeederConsumerThread")); |
129 thread->Start(); | 125 thread->Start(); |
130 | 126 |
131 scoped_ptr<MediaMessageFifo> producer_fifo(new MediaMessageFifo( | 127 std::unique_ptr<MediaMessageFifo> producer_fifo( |
132 scoped_ptr<MediaMemoryChunk>( | 128 new MediaMessageFifo(std::unique_ptr<MediaMemoryChunk>( |
133 new FifoMemoryChunk(&buffer[0], buffer_size)), | 129 new FifoMemoryChunk(&buffer[0], buffer_size)), |
134 true)); | 130 true)); |
135 scoped_ptr<MediaMessageFifo> consumer_fifo(new MediaMessageFifo( | 131 std::unique_ptr<MediaMessageFifo> consumer_fifo( |
136 scoped_ptr<MediaMemoryChunk>( | 132 new MediaMessageFifo(std::unique_ptr<MediaMemoryChunk>( |
137 new FifoMemoryChunk(&buffer[0], buffer_size)), | 133 new FifoMemoryChunk(&buffer[0], buffer_size)), |
138 false)); | 134 false)); |
139 | 135 |
140 base::WaitableEvent event(false, false); | 136 base::WaitableEvent event(false, false); |
141 thread->task_runner()->PostTask( | 137 thread->task_runner()->PostTask( |
142 FROM_HERE, base::Bind(&MsgProducerConsumer, base::Passed(&producer_fifo), | 138 FROM_HERE, base::Bind(&MsgProducerConsumer, base::Passed(&producer_fifo), |
143 base::Passed(&consumer_fifo), &event)); | 139 base::Passed(&consumer_fifo), &event)); |
144 event.Wait(); | 140 event.Wait(); |
145 | 141 |
146 thread.reset(); | 142 thread.reset(); |
147 } | 143 } |
148 | 144 |
149 TEST(MediaMessageFifoTest, MultiThreaded) { | 145 TEST(MediaMessageFifoTest, MultiThreaded) { |
150 size_t buffer_size = 64 * 1024; | 146 size_t buffer_size = 64 * 1024; |
151 scoped_ptr<uint64_t[]> buffer(new uint64_t[buffer_size / sizeof(uint64_t)]); | 147 std::unique_ptr<uint64_t[]> buffer( |
| 148 new uint64_t[buffer_size / sizeof(uint64_t)]); |
152 | 149 |
153 scoped_ptr<base::Thread> producer_thread( | 150 std::unique_ptr<base::Thread> producer_thread( |
154 new base::Thread("FeederThread")); | 151 new base::Thread("FeederThread")); |
155 scoped_ptr<base::Thread> consumer_thread( | 152 std::unique_ptr<base::Thread> consumer_thread( |
156 new base::Thread("ConsumerThread")); | 153 new base::Thread("ConsumerThread")); |
157 producer_thread->Start(); | 154 producer_thread->Start(); |
158 consumer_thread->Start(); | 155 consumer_thread->Start(); |
159 | 156 |
160 scoped_ptr<MediaMessageFifo> producer_fifo(new MediaMessageFifo( | 157 std::unique_ptr<MediaMessageFifo> producer_fifo( |
161 scoped_ptr<MediaMemoryChunk>( | 158 new MediaMessageFifo(std::unique_ptr<MediaMemoryChunk>( |
162 new FifoMemoryChunk(&buffer[0], buffer_size)), | 159 new FifoMemoryChunk(&buffer[0], buffer_size)), |
163 true)); | 160 true)); |
164 scoped_ptr<MediaMessageFifo> consumer_fifo(new MediaMessageFifo( | 161 std::unique_ptr<MediaMessageFifo> consumer_fifo( |
165 scoped_ptr<MediaMemoryChunk>( | 162 new MediaMessageFifo(std::unique_ptr<MediaMemoryChunk>( |
166 new FifoMemoryChunk(&buffer[0], buffer_size)), | 163 new FifoMemoryChunk(&buffer[0], buffer_size)), |
167 false)); | 164 false)); |
168 | 165 |
169 base::WaitableEvent producer_event_done(false, false); | 166 base::WaitableEvent producer_event_done(false, false); |
170 base::WaitableEvent consumer_event_done(false, false); | 167 base::WaitableEvent consumer_event_done(false, false); |
171 | 168 |
172 const int msg_count = 2048; | 169 const int msg_count = 2048; |
173 producer_thread->task_runner()->PostTask( | 170 producer_thread->task_runner()->PostTask( |
174 FROM_HERE, base::Bind(&MsgProducer, base::Passed(&producer_fifo), | 171 FROM_HERE, base::Bind(&MsgProducer, base::Passed(&producer_fifo), |
175 msg_count, &producer_event_done)); | 172 msg_count, &producer_event_done)); |
176 consumer_thread->task_runner()->PostTask( | 173 consumer_thread->task_runner()->PostTask( |
177 FROM_HERE, base::Bind(&MsgConsumer, base::Passed(&consumer_fifo), | 174 FROM_HERE, base::Bind(&MsgConsumer, base::Passed(&consumer_fifo), |
178 msg_count, &consumer_event_done)); | 175 msg_count, &consumer_event_done)); |
179 | 176 |
180 producer_event_done.Wait(); | 177 producer_event_done.Wait(); |
181 consumer_event_done.Wait(); | 178 consumer_event_done.Wait(); |
182 | 179 |
183 producer_thread.reset(); | 180 producer_thread.reset(); |
184 consumer_thread.reset(); | 181 consumer_thread.reset(); |
185 } | 182 } |
186 | 183 |
187 } // namespace media | 184 } // namespace media |
188 } // namespace chromecast | 185 } // namespace chromecast |
189 | 186 |
OLD | NEW |