alsa_output_unittest.cc 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. // Copyright 2013 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. #include <stdint.h>
  5. #include <memory>
  6. #include "base/logging.h"
  7. #include "base/run_loop.h"
  8. #include "base/strings/stringprintf.h"
  9. #include "base/test/simple_test_tick_clock.h"
  10. #include "base/test/test_message_loop.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "base/time/time.h"
  13. #include "media/audio/alsa/alsa_output.h"
  14. #include "media/audio/alsa/alsa_wrapper.h"
  15. #include "media/audio/alsa/audio_manager_alsa.h"
  16. #include "media/audio/alsa/mock_alsa_wrapper.h"
  17. #include "media/audio/fake_audio_log_factory.h"
  18. #include "media/audio/mock_audio_source_callback.h"
  19. #include "media/audio/test_audio_thread.h"
  20. #include "media/base/audio_timestamp_helper.h"
  21. #include "media/base/data_buffer.h"
  22. #include "media/base/seekable_buffer.h"
  23. #include "testing/gmock/include/gmock/gmock.h"
  24. #include "testing/gtest/include/gtest/gtest.h"
  25. using testing::_;
  26. using testing::AllOf;
  27. using testing::AtLeast;
  28. using testing::DoAll;
  29. using testing::Field;
  30. using testing::InSequence;
  31. using testing::Invoke;
  32. using testing::InvokeWithoutArgs;
  33. using testing::Mock;
  34. using testing::MockFunction;
  35. using testing::Return;
  36. using testing::SetArgPointee;
  37. using testing::StrictMock;
  38. using testing::StrEq;
  39. using testing::Unused;
  40. namespace media {
  41. class MockAudioManagerAlsa : public AudioManagerAlsa {
  42. public:
  43. MockAudioManagerAlsa()
  44. : AudioManagerAlsa(std::make_unique<TestAudioThread>(),
  45. &fake_audio_log_factory_) {}
  46. MOCK_METHOD0(Init, void());
  47. MOCK_METHOD0(HasAudioOutputDevices, bool());
  48. MOCK_METHOD0(HasAudioInputDevices, bool());
  49. MOCK_METHOD2(MakeLinearOutputStream,
  50. AudioOutputStream*(const AudioParameters& params,
  51. const LogCallback& log_callback));
  52. MOCK_METHOD3(MakeLowLatencyOutputStream,
  53. AudioOutputStream*(const AudioParameters& params,
  54. const std::string& device_id,
  55. const LogCallback& log_callback));
  56. MOCK_METHOD3(MakeLowLatencyInputStream,
  57. AudioInputStream*(const AudioParameters& params,
  58. const std::string& device_id,
  59. const LogCallback& log_callback));
  60. // We need to override this function in order to skip the checking the number
  61. // of active output streams. It is because the number of active streams
  62. // is managed inside MakeAudioOutputStream, and we don't use
  63. // MakeAudioOutputStream to create the stream in the tests.
  64. void ReleaseOutputStream(AudioOutputStream* stream) override {
  65. DCHECK(stream);
  66. delete stream;
  67. }
  68. private:
  69. FakeAudioLogFactory fake_audio_log_factory_;
  70. };
  71. class AlsaPcmOutputStreamTest : public testing::Test {
  72. public:
  73. AlsaPcmOutputStreamTest(const AlsaPcmOutputStreamTest&) = delete;
  74. AlsaPcmOutputStreamTest& operator=(const AlsaPcmOutputStreamTest&) = delete;
  75. protected:
  76. AlsaPcmOutputStreamTest() {
  77. mock_manager_ = std::make_unique<StrictMock<MockAudioManagerAlsa>>();
  78. }
  79. ~AlsaPcmOutputStreamTest() override { mock_manager_->Shutdown(); }
  80. AlsaPcmOutputStream* CreateStream(ChannelLayout layout) {
  81. return CreateStream(layout, kTestFramesPerPacket);
  82. }
  83. AlsaPcmOutputStream* CreateStream(ChannelLayout layout,
  84. int32_t samples_per_packet) {
  85. AudioParameters params(kTestFormat, layout, kTestSampleRate,
  86. samples_per_packet);
  87. return new AlsaPcmOutputStream(kTestDeviceName,
  88. params,
  89. &mock_alsa_wrapper_,
  90. mock_manager_.get());
  91. }
  92. // Helper function to malloc the string returned by DeviceNameHint for NAME.
  93. static char* EchoHint(const void* name, Unused) {
  94. return strdup(static_cast<const char*>(name));
  95. }
  96. // Helper function to malloc the string returned by DeviceNameHint for IOID.
  97. static char* OutputHint(Unused, Unused) {
  98. return strdup("Output");
  99. }
  100. // Helper function to initialize |test_stream->buffer_|. Must be called
  101. // in all tests that use buffer_ without opening the stream.
  102. void InitBuffer(AlsaPcmOutputStream* test_stream) {
  103. DCHECK(test_stream);
  104. packet_ = new DataBuffer(kTestPacketSize);
  105. packet_->set_data_size(kTestPacketSize);
  106. test_stream->buffer_ = std::make_unique<SeekableBuffer>(0, kTestPacketSize);
  107. test_stream->buffer_->Append(packet_.get());
  108. }
  109. static const ChannelLayout kTestChannelLayout;
  110. static const int kTestSampleRate;
  111. static const int kTestBitsPerSample;
  112. static const int kTestBytesPerFrame;
  113. static const AudioParameters::Format kTestFormat;
  114. static const char kTestDeviceName[];
  115. static const char kDummyMessage[];
  116. static const uint32_t kTestFramesPerPacket;
  117. static const int kTestPacketSize;
  118. static const int kTestFailedErrno;
  119. static snd_pcm_t* const kFakeHandle;
  120. // Used to simulate DeviceNameHint.
  121. static char kSurround40[];
  122. static char kSurround41[];
  123. static char kSurround50[];
  124. static char kSurround51[];
  125. static char kSurround70[];
  126. static char kSurround71[];
  127. static void* kFakeHints[];
  128. static char kGenericSurround50[];
  129. base::TestMessageLoop message_loop_;
  130. StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
  131. std::unique_ptr<StrictMock<MockAudioManagerAlsa>> mock_manager_;
  132. scoped_refptr<DataBuffer> packet_;
  133. };
  134. const ChannelLayout AlsaPcmOutputStreamTest::kTestChannelLayout =
  135. CHANNEL_LAYOUT_STEREO;
  136. const int AlsaPcmOutputStreamTest::kTestSampleRate =
  137. AudioParameters::kAudioCDSampleRate;
  138. const int AlsaPcmOutputStreamTest::kTestBitsPerSample = 16;
  139. const int AlsaPcmOutputStreamTest::kTestBytesPerFrame =
  140. AlsaPcmOutputStreamTest::kTestBitsPerSample / 8 *
  141. ChannelLayoutToChannelCount(AlsaPcmOutputStreamTest::kTestChannelLayout);
  142. const AudioParameters::Format AlsaPcmOutputStreamTest::kTestFormat =
  143. AudioParameters::AUDIO_PCM_LINEAR;
  144. const char AlsaPcmOutputStreamTest::kTestDeviceName[] = "TestDevice";
  145. const char AlsaPcmOutputStreamTest::kDummyMessage[] = "dummy";
  146. const uint32_t AlsaPcmOutputStreamTest::kTestFramesPerPacket = 1000;
  147. const int AlsaPcmOutputStreamTest::kTestPacketSize =
  148. AlsaPcmOutputStreamTest::kTestFramesPerPacket *
  149. AlsaPcmOutputStreamTest::kTestBytesPerFrame;
  150. const int AlsaPcmOutputStreamTest::kTestFailedErrno = -EACCES;
  151. snd_pcm_t* const AlsaPcmOutputStreamTest::kFakeHandle =
  152. reinterpret_cast<snd_pcm_t*>(1);
  153. char AlsaPcmOutputStreamTest::kSurround40[] = "surround40:CARD=foo,DEV=0";
  154. char AlsaPcmOutputStreamTest::kSurround41[] = "surround41:CARD=foo,DEV=0";
  155. char AlsaPcmOutputStreamTest::kSurround50[] = "surround50:CARD=foo,DEV=0";
  156. char AlsaPcmOutputStreamTest::kSurround51[] = "surround51:CARD=foo,DEV=0";
  157. char AlsaPcmOutputStreamTest::kSurround70[] = "surround70:CARD=foo,DEV=0";
  158. char AlsaPcmOutputStreamTest::kSurround71[] = "surround71:CARD=foo,DEV=0";
  159. void* AlsaPcmOutputStreamTest::kFakeHints[] = {
  160. kSurround40, kSurround41, kSurround50, kSurround51,
  161. kSurround70, kSurround71, nullptr};
  162. char AlsaPcmOutputStreamTest::kGenericSurround50[] = "surround50";
  163. // Custom action to clear a memory buffer.
  164. ACTION(ClearBuffer) {
  165. arg3->Zero();
  166. }
  167. TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
  168. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  169. EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
  170. test_stream->Close();
  171. // Should support mono.
  172. test_stream = CreateStream(CHANNEL_LAYOUT_MONO);
  173. EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
  174. test_stream->Close();
  175. // Should support multi-channel.
  176. test_stream = CreateStream(CHANNEL_LAYOUT_SURROUND);
  177. EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
  178. test_stream->Close();
  179. }
  180. TEST_F(AlsaPcmOutputStreamTest, LatencyFloor) {
  181. const double kMicrosPerFrame =
  182. static_cast<double>(1000000) / kTestSampleRate;
  183. const double kPacketFramesInMinLatency =
  184. AlsaPcmOutputStream::kMinLatencyMicros / kMicrosPerFrame / 2.0;
  185. // Test that packets which would cause a latency under less than
  186. // AlsaPcmOutputStream::kMinLatencyMicros will get clipped to
  187. // AlsaPcmOutputStream::kMinLatencyMicros,
  188. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  189. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  190. EXPECT_CALL(mock_alsa_wrapper_,
  191. PcmSetParams(_, _, _, _, _, _,
  192. AlsaPcmOutputStream::kMinLatencyMicros))
  193. .WillOnce(Return(0));
  194. EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
  195. .WillOnce(DoAll(SetArgPointee<1>(kTestFramesPerPacket),
  196. SetArgPointee<2>(kTestFramesPerPacket / 2), Return(0)));
  197. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout,
  198. kPacketFramesInMinLatency);
  199. ASSERT_TRUE(test_stream->Open());
  200. // Now close it and test that everything was released.
  201. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle)).WillOnce(Return(0));
  202. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  203. .WillOnce(Return(kTestDeviceName));
  204. test_stream->Close();
  205. Mock::VerifyAndClear(&mock_alsa_wrapper_);
  206. Mock::VerifyAndClear(mock_manager_.get());
  207. // Test that having more packets ends up with a latency based on packet size.
  208. const int kOverMinLatencyPacketSize = kPacketFramesInMinLatency + 1;
  209. int64_t expected_micros = AudioTimestampHelper::FramesToTime(
  210. kOverMinLatencyPacketSize * 2, kTestSampleRate)
  211. .InMicroseconds();
  212. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  213. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  214. EXPECT_CALL(mock_alsa_wrapper_,
  215. PcmSetParams(_, _, _, _, _, _, expected_micros))
  216. .WillOnce(Return(0));
  217. EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
  218. .WillOnce(DoAll(SetArgPointee<1>(kTestFramesPerPacket),
  219. SetArgPointee<2>(kTestFramesPerPacket / 2), Return(0)));
  220. test_stream = CreateStream(kTestChannelLayout,
  221. kOverMinLatencyPacketSize);
  222. ASSERT_TRUE(test_stream->Open());
  223. // Now close it and test that everything was released.
  224. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
  225. .WillOnce(Return(0));
  226. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  227. .WillOnce(Return(kTestDeviceName));
  228. test_stream->Close();
  229. Mock::VerifyAndClear(&mock_alsa_wrapper_);
  230. Mock::VerifyAndClear(mock_manager_.get());
  231. }
  232. TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
  233. int64_t expected_micros = AudioTimestampHelper::FramesToTime(
  234. 2 * kTestFramesPerPacket, kTestSampleRate)
  235. .InMicroseconds();
  236. // Open() call opens the playback device, sets the parameters, posts a task
  237. // with the resulting configuration data, and transitions the object state to
  238. // kIsOpened.
  239. EXPECT_CALL(mock_alsa_wrapper_,
  240. PcmOpen(_, StrEq(kTestDeviceName), SND_PCM_STREAM_PLAYBACK,
  241. SND_PCM_NONBLOCK))
  242. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  243. EXPECT_CALL(mock_alsa_wrapper_,
  244. PcmSetParams(kFakeHandle, SND_PCM_FORMAT_S16_LE,
  245. SND_PCM_ACCESS_RW_INTERLEAVED,
  246. ChannelLayoutToChannelCount(kTestChannelLayout),
  247. kTestSampleRate, 1, expected_micros))
  248. .WillOnce(Return(0));
  249. EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(kFakeHandle, _, _))
  250. .WillOnce(DoAll(SetArgPointee<1>(kTestFramesPerPacket),
  251. SetArgPointee<2>(kTestFramesPerPacket / 2), Return(0)));
  252. // Open the stream.
  253. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  254. ASSERT_TRUE(test_stream->Open());
  255. EXPECT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream->state());
  256. EXPECT_EQ(kFakeHandle, test_stream->playback_handle_);
  257. EXPECT_EQ(kTestFramesPerPacket, test_stream->frames_per_packet_);
  258. EXPECT_TRUE(test_stream->buffer_.get());
  259. EXPECT_FALSE(test_stream->stop_stream_);
  260. // Now close it and test that everything was released.
  261. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
  262. .WillOnce(Return(0));
  263. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  264. .WillOnce(Return(kTestDeviceName));
  265. test_stream->Close();
  266. }
  267. TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) {
  268. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  269. .WillOnce(Return(kTestFailedErrno));
  270. EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
  271. .WillOnce(Return(kDummyMessage));
  272. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  273. ASSERT_FALSE(test_stream->Open());
  274. ASSERT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
  275. // Ensure internal state is set for a no-op stream if PcmOpen() failes.
  276. EXPECT_TRUE(test_stream->stop_stream_);
  277. EXPECT_FALSE(test_stream->playback_handle_);
  278. EXPECT_FALSE(test_stream->buffer_.get());
  279. // Close the stream since we opened it to make destruction happy.
  280. test_stream->Close();
  281. }
  282. TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) {
  283. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  284. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  285. EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
  286. .WillOnce(Return(kTestFailedErrno));
  287. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
  288. .WillOnce(Return(0));
  289. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  290. .WillOnce(Return(kTestDeviceName));
  291. EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
  292. .WillOnce(Return(kDummyMessage));
  293. // If open fails, the stream stays in kCreated because it has effectively had
  294. // no changes.
  295. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  296. ASSERT_FALSE(test_stream->Open());
  297. EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
  298. // Ensure internal state is set for a no-op stream if PcmSetParams() failes.
  299. EXPECT_TRUE(test_stream->stop_stream_);
  300. EXPECT_FALSE(test_stream->playback_handle_);
  301. EXPECT_FALSE(test_stream->buffer_.get());
  302. // Close the stream since we opened it to make destruction happy.
  303. test_stream->Close();
  304. }
  305. TEST_F(AlsaPcmOutputStreamTest, StartStop) {
  306. // Open() call opens the playback device, sets the parameters, posts a task
  307. // with the resulting configuration data, and transitions the object state to
  308. // kIsOpened.
  309. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  310. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  311. EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
  312. .WillOnce(Return(0));
  313. EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
  314. .WillOnce(DoAll(SetArgPointee<1>(kTestFramesPerPacket),
  315. SetArgPointee<2>(kTestFramesPerPacket / 2), Return(0)));
  316. // Open the stream.
  317. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  318. ASSERT_TRUE(test_stream->Open());
  319. base::SimpleTestTickClock tick_clock;
  320. tick_clock.SetNowTicks(base::TimeTicks::Now());
  321. test_stream->SetTickClockForTesting(&tick_clock);
  322. // Expect Device setup.
  323. EXPECT_CALL(mock_alsa_wrapper_, PcmDrop(kFakeHandle))
  324. .WillOnce(Return(0));
  325. EXPECT_CALL(mock_alsa_wrapper_, PcmPrepare(kFakeHandle))
  326. .WillOnce(Return(0));
  327. // Expect the pre-roll.
  328. MockAudioSourceCallback mock_callback;
  329. EXPECT_CALL(mock_alsa_wrapper_, PcmState(kFakeHandle))
  330. .WillRepeatedly(Return(SND_PCM_STATE_RUNNING));
  331. EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(kFakeHandle, _))
  332. .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(0)));
  333. EXPECT_CALL(mock_callback,
  334. OnMoreData(base::TimeDelta(), tick_clock.NowTicks(), 0, _))
  335. .WillRepeatedly(DoAll(ClearBuffer(), Return(kTestFramesPerPacket)));
  336. EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
  337. .WillRepeatedly(Return(kTestFramesPerPacket));
  338. // Expect scheduling.
  339. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
  340. .Times(AtLeast(2))
  341. .WillRepeatedly(Return(kTestFramesPerPacket));
  342. test_stream->Start(&mock_callback);
  343. // Start() will issue a WriteTask() directly and then schedule the next one,
  344. // call Stop() immediately after to ensure we don't run the message loop
  345. // forever.
  346. test_stream->Stop();
  347. base::RunLoop().RunUntilIdle();
  348. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
  349. .WillOnce(Return(0));
  350. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  351. .WillOnce(Return(kTestDeviceName));
  352. test_stream->Close();
  353. }
  354. TEST_F(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket) {
  355. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  356. InitBuffer(test_stream);
  357. test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
  358. test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
  359. // Nothing should happen. Don't set any expectations and Our strict mocks
  360. // should verify most of this.
  361. // Test empty buffer.
  362. test_stream->buffer_->Clear();
  363. test_stream->WritePacket();
  364. test_stream->Close();
  365. }
  366. TEST_F(AlsaPcmOutputStreamTest, WritePacket_NormalPacket) {
  367. // We need to open the stream before writing data to ALSA.
  368. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  369. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  370. EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
  371. .WillOnce(Return(0));
  372. EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
  373. .WillOnce(DoAll(SetArgPointee<1>(kTestFramesPerPacket),
  374. SetArgPointee<2>(kTestFramesPerPacket / 2), Return(0)));
  375. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  376. ASSERT_TRUE(test_stream->Open());
  377. InitBuffer(test_stream);
  378. test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
  379. // Write a little less than half the data.
  380. int written = packet_->data_size() / kTestBytesPerFrame / 2 - 1;
  381. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
  382. .WillOnce(Return(written));
  383. EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, packet_->data(), _))
  384. .WillOnce(Return(written));
  385. test_stream->WritePacket();
  386. ASSERT_EQ(test_stream->buffer_->forward_bytes(),
  387. packet_->data_size() - written * kTestBytesPerFrame);
  388. // Write the rest.
  389. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
  390. .WillOnce(Return(kTestFramesPerPacket - written));
  391. EXPECT_CALL(mock_alsa_wrapper_,
  392. PcmWritei(kFakeHandle,
  393. packet_->data() + written * kTestBytesPerFrame,
  394. _))
  395. .WillOnce(Return(packet_->data_size() / kTestBytesPerFrame - written));
  396. test_stream->WritePacket();
  397. EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
  398. // Now close it and test that everything was released.
  399. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
  400. .WillOnce(Return(0));
  401. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  402. .WillOnce(Return(kTestDeviceName));
  403. test_stream->Close();
  404. }
  405. TEST_F(AlsaPcmOutputStreamTest, WritePacket_WriteFails) {
  406. // We need to open the stream before writing data to ALSA.
  407. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
  408. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  409. EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
  410. .WillOnce(Return(0));
  411. EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
  412. .WillOnce(DoAll(SetArgPointee<1>(kTestFramesPerPacket),
  413. SetArgPointee<2>(kTestFramesPerPacket / 2), Return(0)));
  414. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  415. ASSERT_TRUE(test_stream->Open());
  416. InitBuffer(test_stream);
  417. test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
  418. // Fail due to a recoverable error and see that PcmRecover code path
  419. // continues normally.
  420. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
  421. .WillOnce(Return(kTestFramesPerPacket));
  422. EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
  423. .WillOnce(Return(-EINTR));
  424. EXPECT_CALL(mock_alsa_wrapper_, PcmRecover(kFakeHandle, _, _))
  425. .WillOnce(Return(0));
  426. test_stream->WritePacket();
  427. ASSERT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
  428. // Fail the next write, and see that stop_stream_ is set.
  429. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
  430. .WillOnce(Return(kTestFramesPerPacket));
  431. EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
  432. .WillOnce(Return(kTestFailedErrno));
  433. EXPECT_CALL(mock_alsa_wrapper_, PcmRecover(kFakeHandle, _, _))
  434. .WillOnce(Return(kTestFailedErrno));
  435. EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
  436. .WillOnce(Return(kDummyMessage));
  437. test_stream->WritePacket();
  438. EXPECT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
  439. EXPECT_TRUE(test_stream->stop_stream_);
  440. // Now close it and test that everything was released.
  441. EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
  442. .WillOnce(Return(0));
  443. EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
  444. .WillOnce(Return(kTestDeviceName));
  445. test_stream->Close();
  446. }
  447. TEST_F(AlsaPcmOutputStreamTest, WritePacket_StopStream) {
  448. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  449. InitBuffer(test_stream);
  450. test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
  451. test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
  452. // No expectations set on the strict mock because nothing should be called.
  453. test_stream->stop_stream_ = true;
  454. test_stream->WritePacket();
  455. EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
  456. test_stream->Close();
  457. }
  458. TEST_F(AlsaPcmOutputStreamTest, BufferPacket) {
  459. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  460. base::SimpleTestTickClock tick_clock;
  461. tick_clock.SetNowTicks(base::TimeTicks::Now());
  462. test_stream->SetTickClockForTesting(&tick_clock);
  463. InitBuffer(test_stream);
  464. test_stream->buffer_->Clear();
  465. MockAudioSourceCallback mock_callback;
  466. EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
  467. .WillOnce(Return(SND_PCM_STATE_RUNNING));
  468. EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _))
  469. .WillOnce(DoAll(SetArgPointee<1>(1), Return(0)));
  470. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
  471. .WillRepeatedly(Return(0)); // Buffer is full.
  472. // Return a partially filled packet.
  473. EXPECT_CALL(mock_callback,
  474. OnMoreData(base::TimeDelta(), tick_clock.NowTicks(), 0, _))
  475. .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
  476. bool source_exhausted;
  477. test_stream->set_source_callback(&mock_callback);
  478. test_stream->packet_size_ = kTestPacketSize;
  479. test_stream->BufferPacket(&source_exhausted);
  480. EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
  481. EXPECT_FALSE(source_exhausted);
  482. test_stream->Close();
  483. }
  484. TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Negative) {
  485. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  486. base::SimpleTestTickClock tick_clock;
  487. tick_clock.SetNowTicks(base::TimeTicks::Now());
  488. test_stream->SetTickClockForTesting(&tick_clock);
  489. InitBuffer(test_stream);
  490. test_stream->buffer_->Clear();
  491. // Simulate where the underrun has occurred right after checking the delay.
  492. MockAudioSourceCallback mock_callback;
  493. EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
  494. .WillOnce(Return(SND_PCM_STATE_RUNNING));
  495. EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _))
  496. .WillOnce(DoAll(SetArgPointee<1>(-1), Return(0)));
  497. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
  498. .WillRepeatedly(Return(0)); // Buffer is full.
  499. EXPECT_CALL(mock_callback,
  500. OnMoreData(base::TimeDelta(), tick_clock.NowTicks(), 0, _))
  501. .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
  502. bool source_exhausted;
  503. test_stream->set_source_callback(&mock_callback);
  504. test_stream->packet_size_ = kTestPacketSize;
  505. test_stream->BufferPacket(&source_exhausted);
  506. EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
  507. EXPECT_FALSE(source_exhausted);
  508. test_stream->Close();
  509. }
  510. TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Underrun) {
  511. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  512. base::SimpleTestTickClock tick_clock;
  513. tick_clock.SetNowTicks(base::TimeTicks::Now());
  514. test_stream->SetTickClockForTesting(&tick_clock);
  515. InitBuffer(test_stream);
  516. test_stream->buffer_->Clear();
  517. // If ALSA has underrun then we should assume a delay of zero.
  518. MockAudioSourceCallback mock_callback;
  519. EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
  520. .WillOnce(Return(SND_PCM_STATE_XRUN));
  521. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
  522. .WillRepeatedly(Return(0)); // Buffer is full.
  523. EXPECT_CALL(mock_callback,
  524. OnMoreData(base::TimeDelta(), tick_clock.NowTicks(), 0, _))
  525. .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
  526. bool source_exhausted;
  527. test_stream->set_source_callback(&mock_callback);
  528. test_stream->packet_size_ = kTestPacketSize;
  529. test_stream->BufferPacket(&source_exhausted);
  530. EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
  531. EXPECT_FALSE(source_exhausted);
  532. test_stream->Close();
  533. }
  534. TEST_F(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer) {
  535. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  536. InitBuffer(test_stream);
  537. // No expectations set on the strict mock because nothing should be called.
  538. bool source_exhausted;
  539. test_stream->packet_size_ = kTestPacketSize;
  540. test_stream->BufferPacket(&source_exhausted);
  541. EXPECT_EQ(kTestPacketSize, test_stream->buffer_->forward_bytes());
  542. EXPECT_FALSE(source_exhausted);
  543. test_stream->Close();
  544. }
  545. TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect) {
  546. // Try channels from 1 -> 9. and see that we get the more specific surroundXX
  547. // device opened for channels 4-8. For all other channels, the device should
  548. // default to |AlsaPcmOutputStream::kDefaultDevice|. We should also not
  549. // downmix any channel in this case because downmixing is only defined for
  550. // channels 4-8, which we are guaranteeing to work.
  551. //
  552. // Note that the loop starts at "1", so the first parameter is ignored in
  553. // these arrays.
  554. const char* kExpectedDeviceName[] = {nullptr,
  555. AlsaPcmOutputStream::kDefaultDevice,
  556. AlsaPcmOutputStream::kDefaultDevice,
  557. AlsaPcmOutputStream::kDefaultDevice,
  558. kSurround40,
  559. kSurround50,
  560. kSurround51,
  561. kSurround70,
  562. kSurround71,
  563. AlsaPcmOutputStream::kDefaultDevice};
  564. bool kExpectedDownmix[] = { false, false, false, false, false, true,
  565. false, false, false, false };
  566. ChannelLayout kExpectedLayouts[] = { CHANNEL_LAYOUT_NONE,
  567. CHANNEL_LAYOUT_MONO,
  568. CHANNEL_LAYOUT_STEREO,
  569. CHANNEL_LAYOUT_SURROUND,
  570. CHANNEL_LAYOUT_4_0,
  571. CHANNEL_LAYOUT_5_0,
  572. CHANNEL_LAYOUT_5_1,
  573. CHANNEL_LAYOUT_7_0,
  574. CHANNEL_LAYOUT_7_1 };
  575. for (int i = 1; i < 9; ++i) {
  576. if (i == 3 || i == 4 || i == 5) // invalid number of channels
  577. continue;
  578. SCOPED_TRACE(base::StringPrintf("Attempting %d Channel", i));
  579. // Hints will only be grabbed for channel numbers that have non-default
  580. // devices associated with them.
  581. if (kExpectedDeviceName[i] != AlsaPcmOutputStream::kDefaultDevice) {
  582. // The DeviceNameHint and DeviceNameFreeHint need to be paired to avoid a
  583. // memory leak.
  584. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
  585. .WillOnce(DoAll(SetArgPointee<2>(&kFakeHints[0]), Return(0)));
  586. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
  587. .Times(1);
  588. }
  589. EXPECT_CALL(mock_alsa_wrapper_,
  590. PcmOpen(_, StrEq(kExpectedDeviceName[i]), _, _))
  591. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  592. EXPECT_CALL(mock_alsa_wrapper_,
  593. PcmSetParams(kFakeHandle, _, _, i, _, _, _))
  594. .WillOnce(Return(0));
  595. // The parameters are specified by ALSA documentation, and are in constants
  596. // in the implementation files.
  597. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
  598. .WillRepeatedly(Invoke(OutputHint));
  599. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
  600. .WillRepeatedly(Invoke(EchoHint));
  601. AlsaPcmOutputStream* test_stream = CreateStream(kExpectedLayouts[i]);
  602. EXPECT_TRUE(test_stream->AutoSelectDevice(i));
  603. EXPECT_EQ(kExpectedDownmix[i],
  604. static_cast<bool>(test_stream->channel_mixer_));
  605. Mock::VerifyAndClearExpectations(&mock_alsa_wrapper_);
  606. Mock::VerifyAndClearExpectations(mock_manager_.get());
  607. test_stream->Close();
  608. }
  609. }
  610. TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices) {
  611. using std::string;
  612. // If there are problems opening a multi-channel device, it the fallbacks
  613. // operations should be as follows. Assume the multi-channel device name is
  614. // surround50:
  615. //
  616. // 1) Try open "surround50:CARD=foo,DEV=0"
  617. // 2) Try open "plug:surround50:CARD=foo,DEV=0".
  618. // 3) Try open "plug:surround50".
  619. // 4) Try open "default".
  620. // 5) Try open "plug:default".
  621. // 6) Give up trying to open.
  622. //
  623. const string first_try = kSurround50;
  624. const string second_try = string(AlsaPcmOutputStream::kPlugPrefix) +
  625. kSurround50;
  626. const string third_try = string(AlsaPcmOutputStream::kPlugPrefix) +
  627. kGenericSurround50;
  628. const string fourth_try = AlsaPcmOutputStream::kDefaultDevice;
  629. const string fifth_try = string(AlsaPcmOutputStream::kPlugPrefix) +
  630. AlsaPcmOutputStream::kDefaultDevice;
  631. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
  632. .WillOnce(DoAll(SetArgPointee<2>(&kFakeHints[0]), Return(0)));
  633. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
  634. .Times(1);
  635. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
  636. .WillRepeatedly(Invoke(OutputHint));
  637. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
  638. .WillRepeatedly(Invoke(EchoHint));
  639. EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
  640. .WillRepeatedly(Return(kDummyMessage));
  641. InSequence s;
  642. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(first_try.c_str()), _, _))
  643. .WillOnce(Return(kTestFailedErrno));
  644. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(second_try.c_str()), _, _))
  645. .WillOnce(Return(kTestFailedErrno));
  646. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(third_try.c_str()), _, _))
  647. .WillOnce(Return(kTestFailedErrno));
  648. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(fourth_try.c_str()), _, _))
  649. .WillOnce(Return(kTestFailedErrno));
  650. EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(fifth_try.c_str()), _, _))
  651. .WillOnce(Return(kTestFailedErrno));
  652. AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
  653. EXPECT_FALSE(test_stream->AutoSelectDevice(5));
  654. test_stream->Close();
  655. }
  656. TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail) {
  657. // Should get |kDefaultDevice|, and force a 2-channel downmix on a failure to
  658. // enumerate devices.
  659. EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
  660. .WillRepeatedly(Return(kTestFailedErrno));
  661. EXPECT_CALL(mock_alsa_wrapper_,
  662. PcmOpen(_, StrEq(AlsaPcmOutputStream::kDefaultDevice), _, _))
  663. .WillOnce(DoAll(SetArgPointee<0>(kFakeHandle), Return(0)));
  664. EXPECT_CALL(mock_alsa_wrapper_,
  665. PcmSetParams(kFakeHandle, _, _, 2, _, _, _))
  666. .WillOnce(Return(0));
  667. EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
  668. .WillOnce(Return(kDummyMessage));
  669. AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
  670. EXPECT_TRUE(test_stream->AutoSelectDevice(5));
  671. EXPECT_TRUE(test_stream->channel_mixer_);
  672. test_stream->Close();
  673. }
  674. TEST_F(AlsaPcmOutputStreamTest, BufferPacket_StopStream) {
  675. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  676. InitBuffer(test_stream);
  677. test_stream->stop_stream_ = true;
  678. bool source_exhausted;
  679. test_stream->BufferPacket(&source_exhausted);
  680. EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
  681. EXPECT_TRUE(source_exhausted);
  682. test_stream->Close();
  683. }
  684. TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite) {
  685. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  686. test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
  687. test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
  688. InitBuffer(test_stream);
  689. DVLOG(1) << test_stream->state();
  690. EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
  691. .WillOnce(Return(10));
  692. test_stream->ScheduleNextWrite(false);
  693. DVLOG(1) << test_stream->state();
  694. // TODO(sergeyu): Figure out how to check that the task has been added to the
  695. // message loop.
  696. // Cleanup the message queue. Currently ~MessageQueue() doesn't free pending
  697. // tasks unless running on valgrind. The code below is needed to keep
  698. // heapcheck happy.
  699. test_stream->stop_stream_ = true;
  700. DVLOG(1) << test_stream->state();
  701. test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
  702. DVLOG(1) << test_stream->state();
  703. test_stream->Close();
  704. }
  705. TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite_StopStream) {
  706. AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
  707. test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
  708. test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
  709. InitBuffer(test_stream);
  710. test_stream->stop_stream_ = true;
  711. test_stream->ScheduleNextWrite(true);
  712. // TODO(ajwong): Find a way to test whether or not another task has been
  713. // posted so we can verify that the Alsa code will indeed break the task
  714. // posting loop.
  715. test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
  716. test_stream->Close();
  717. }
  718. } // namespace media