summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_output_controller_unittest.cc
diff options
context:
space:
mode:
authorenal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-13 16:18:05 +0000
committerenal@chromium.org <enal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-13 16:18:05 +0000
commit7b2d3f50076df1dd611fbd6de785dd24f70acbe3 (patch)
treebf950cc927aaef10d667c1a713bcdc376022db16 /media/audio/audio_output_controller_unittest.cc
parentf08b3f7a500276d72585b932ba44e03567f94d27 (diff)
downloadchromium_src-7b2d3f50076df1dd611fbd6de785dd24f70acbe3.zip
chromium_src-7b2d3f50076df1dd611fbd6de785dd24f70acbe3.tar.gz
chromium_src-7b2d3f50076df1dd611fbd6de785dd24f70acbe3.tar.bz2
Fix problem when we did not play beginning of HTML5 audio stream in low latency mode.
Problem manifested itself on Mac because Mac code is especially sensitive to timing, and because Mac code ignores length of data in buffer -- it assumes buffer is always full, and gives to OS the entire buffer (zeroed out in that case). Fix consists of 2 parts: * When starting audio stream, send request for the data -- previously code depended on data length in the buffer being 0, so it assumed no data would be played, and data would be returned starting from 2nd request. * Implement polling "is data ready?" when starting new stream. Start physical stream only after first chunk data is available (or after ~9ms had passed, to correctly handle "old" clients not writing metadata into buffer). Polling is not continuous, it is done by task delayed by 3ms. Fix is definitely not necessary on Windows, where we have mechanism that handles "bad" timing when requesting new data, but I decided it is better to implement it on all platforms. Added test. BUG=98674 TEST=Go to http://www.jimmysparkle.me/dump/chrome-bug/ and listen to the audio stream. Review URL: http://codereview.chromium.org/8229013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105311 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/audio_output_controller_unittest.cc')
-rw-r--r--media/audio/audio_output_controller_unittest.cc54
1 files changed, 54 insertions, 0 deletions
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index cab9929..f6917a7 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -14,6 +14,7 @@
using ::testing::_;
using ::testing::AtLeast;
+using ::testing::DoAll;
using ::testing::Exactly;
using ::testing::InvokeWithoutArgs;
using ::testing::NotNull;
@@ -54,6 +55,7 @@ class MockAudioOutputControllerSyncReader
MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes));
MOCK_METHOD2(Read, uint32(void* data, uint32 size));
MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(DataReady, bool());
private:
DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
@@ -150,6 +152,58 @@ TEST(AudioOutputControllerTest, PlayAndClose) {
CloseAudioController(controller);
}
+TEST(AudioOutputControllerTest, PlayAndCloseLowLatency) {
+ if (!HasAudioOutputDevices() || IsRunningHeadless())
+ return;
+
+ MockAudioOutputControllerEventHandler event_handler;
+ base::WaitableEvent event(false, false);
+
+ // If OnCreated is called then signal the event.
+ EXPECT_CALL(event_handler, OnCreated(NotNull()))
+ .WillOnce(SignalEvent(&event));
+
+ // OnPlaying() will be called only once.
+ EXPECT_CALL(event_handler, OnPlaying(NotNull()))
+ .Times(Exactly(1));
+
+ MockAudioOutputControllerSyncReader sync_reader;
+ EXPECT_CALL(sync_reader, UpdatePendingBytes(_))
+ .Times(AtLeast(10));
+ EXPECT_CALL(sync_reader, DataReady())
+ .WillOnce(Return(false))
+ .WillOnce(Return(false))
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(sync_reader, Read(_, kHardwareBufferSize))
+ .Times(AtLeast(10))
+ .WillRepeatedly(DoAll(SignalEvent(&event),
+ Return(1)));
+ EXPECT_CALL(sync_reader, Close());
+
+ AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
+ kSampleRate, kBitsPerSample, kSamplesPerPacket);
+ scoped_refptr<AudioOutputController> controller =
+ AudioOutputController::CreateLowLatency(&event_handler,
+ params,
+ &sync_reader);
+ ASSERT_TRUE(controller.get());
+
+ // Wait for OnCreated() to be called.
+ event.Wait();
+
+ controller->Play();
+
+ // Wait until the date is requested at least 10 times.
+ for (int i = 0; i < 10; i++) {
+ event.Wait();
+ uint8 buf[1];
+ controller->EnqueueData(buf, 0);
+ }
+
+ // Now stop the controller.
+ CloseAudioController(controller);
+}
+
TEST(AudioOutputControllerTest, PlayPauseClose) {
if (!HasAudioOutputDevices() || IsRunningHeadless())
return;