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