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.
5 #include "base/basictypes.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "base/threading/thread.h"
10 #include "chromecast/media/cma/ipc/media_memory_chunk.h"
11 #include "chromecast/media/cma/ipc/media_message.h"
12 #include "chromecast/media/cma/ipc/media_message_fifo.h"
13 #include "chromecast/media/cma/ipc/media_message_type.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace chromecast {
21 class FifoMemoryChunk : public MediaMemoryChunk {
23 FifoMemoryChunk(void* mem, size_t size)
24 : mem_(mem), size_(size) {}
25 virtual ~FifoMemoryChunk() {}
27 virtual void* data() const OVERRIDE { return mem_; }
28 virtual size_t size() const OVERRIDE { return size_; }
29 virtual bool valid() const OVERRIDE { return true; }
35 DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk);
38 void MsgProducer(scoped_ptr<MediaMessageFifo> fifo,
40 base::WaitableEvent* event) {
42 for (int k = 0; k < msg_count; k++) {
43 uint32 msg_type = 0x2 + (k % 5);
44 uint32 max_msg_content_size = k % 64;
46 scoped_ptr<MediaMessage> msg1(
47 MediaMessage::CreateMessage(
49 base::Bind(&MediaMessageFifo::ReserveMemory,
50 base::Unretained(fifo.get())),
51 max_msg_content_size));
54 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
63 void MsgConsumer(scoped_ptr<MediaMessageFifo> fifo,
65 base::WaitableEvent* event) {
68 while (k < msg_count) {
69 uint32 msg_type = 0x2 + (k % 5);
71 scoped_ptr<MediaMessage> msg2(fifo->Pop());
73 if (msg2->type() != PaddingMediaMsg) {
74 EXPECT_EQ(msg2->type(), msg_type);
79 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
88 void MsgProducerConsumer(
89 scoped_ptr<MediaMessageFifo> producer_fifo,
90 scoped_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 msg_type = 0x2 + (k % 5);
95 uint32 max_msg_content_size = k % 64;
96 scoped_ptr<MediaMessage> msg1(
97 MediaMessage::CreateMessage(
99 base::Bind(&MediaMessageFifo::ReserveMemory,
100 base::Unretained(producer_fifo.get())),
101 max_msg_content_size));
104 // Make sure the message is commited.
107 // At this point, we should have a message to read.
108 scoped_ptr<MediaMessage> msg2(consumer_fifo->Pop());
112 producer_fifo.reset();
113 consumer_fifo.reset();
120 TEST(MediaMessageFifoTest, AlternateWriteRead) {
121 size_t buffer_size = 64 * 1024;
122 scoped_ptr<uint64[]> buffer(new uint64[buffer_size / sizeof(uint64)]);
124 scoped_ptr<base::Thread> thread(
125 new base::Thread("FeederConsumerThread"));
128 scoped_ptr<MediaMessageFifo> producer_fifo(new MediaMessageFifo(
129 scoped_ptr<MediaMemoryChunk>(
130 new FifoMemoryChunk(&buffer[0], buffer_size)),
132 scoped_ptr<MediaMessageFifo> consumer_fifo(new MediaMessageFifo(
133 scoped_ptr<MediaMemoryChunk>(
134 new FifoMemoryChunk(&buffer[0], buffer_size)),
137 base::WaitableEvent event(false, false);
138 thread->message_loop_proxy()->PostTask(
140 base::Bind(&MsgProducerConsumer,
141 base::Passed(&producer_fifo),
142 base::Passed(&consumer_fifo),
149 TEST(MediaMessageFifoTest, MultiThreaded) {
150 size_t buffer_size = 64 * 1024;
151 scoped_ptr<uint64[]> buffer(new uint64[buffer_size / sizeof(uint64)]);
153 scoped_ptr<base::Thread> producer_thread(
154 new base::Thread("FeederThread"));
155 scoped_ptr<base::Thread> consumer_thread(
156 new base::Thread("ConsumerThread"));
157 producer_thread->Start();
158 consumer_thread->Start();
160 scoped_ptr<MediaMessageFifo> producer_fifo(new MediaMessageFifo(
161 scoped_ptr<MediaMemoryChunk>(
162 new FifoMemoryChunk(&buffer[0], buffer_size)),
164 scoped_ptr<MediaMessageFifo> consumer_fifo(new MediaMessageFifo(
165 scoped_ptr<MediaMemoryChunk>(
166 new FifoMemoryChunk(&buffer[0], buffer_size)),
169 base::WaitableEvent producer_event_done(false, false);
170 base::WaitableEvent consumer_event_done(false, false);
172 const int msg_count = 2048;
173 producer_thread->message_loop_proxy()->PostTask(
175 base::Bind(&MsgProducer,
176 base::Passed(&producer_fifo),
178 &producer_event_done));
179 consumer_thread->message_loop_proxy()->PostTask(
181 base::Bind(&MsgConsumer,
182 base::Passed(&consumer_fifo),
184 &consumer_event_done));
186 producer_event_done.Wait();
187 consumer_event_done.Wait();
189 producer_thread.reset();
190 consumer_thread.reset();
194 } // namespace chromecast