| 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 |