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 ~FifoMemoryChunk() override
{}
27 void* data() const override
{ return mem_
; }
28 size_t size() const override
{ return size_
; }
29 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
->task_runner()->PostTask(
139 FROM_HERE
, base::Bind(&MsgProducerConsumer
, base::Passed(&producer_fifo
),
140 base::Passed(&consumer_fifo
), &event
));
146 TEST(MediaMessageFifoTest
, MultiThreaded
) {
147 size_t buffer_size
= 64 * 1024;
148 scoped_ptr
<uint64
[]> buffer(new uint64
[buffer_size
/ sizeof(uint64
)]);
150 scoped_ptr
<base::Thread
> producer_thread(
151 new base::Thread("FeederThread"));
152 scoped_ptr
<base::Thread
> consumer_thread(
153 new base::Thread("ConsumerThread"));
154 producer_thread
->Start();
155 consumer_thread
->Start();
157 scoped_ptr
<MediaMessageFifo
> producer_fifo(new MediaMessageFifo(
158 scoped_ptr
<MediaMemoryChunk
>(
159 new FifoMemoryChunk(&buffer
[0], buffer_size
)),
161 scoped_ptr
<MediaMessageFifo
> consumer_fifo(new MediaMessageFifo(
162 scoped_ptr
<MediaMemoryChunk
>(
163 new FifoMemoryChunk(&buffer
[0], buffer_size
)),
166 base::WaitableEvent
producer_event_done(false, false);
167 base::WaitableEvent
consumer_event_done(false, false);
169 const int msg_count
= 2048;
170 producer_thread
->task_runner()->PostTask(
171 FROM_HERE
, base::Bind(&MsgProducer
, base::Passed(&producer_fifo
),
172 msg_count
, &producer_event_done
));
173 consumer_thread
->task_runner()->PostTask(
174 FROM_HERE
, base::Bind(&MsgConsumer
, base::Passed(&consumer_fifo
),
175 msg_count
, &consumer_event_done
));
177 producer_event_done
.Wait();
178 consumer_event_done
.Wait();
180 producer_thread
.reset();
181 consumer_thread
.reset();
185 } // namespace chromecast