Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1397)

Side by Side Diff: media/audio/win/audio_output_win_unittest.cc

Issue 2101303004: Pass delay and timestamp to AudioSourceCallback::OnMoreData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Fix Mac CQ errors. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <windows.h> 5 #include <windows.h>
6 #include <mmsystem.h> 6 #include <mmsystem.h>
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <memory> 10 #include <memory>
11 11
12 #include "base/base_paths.h" 12 #include "base/base_paths.h"
13 #include "base/memory/aligned_memory.h" 13 #include "base/memory/aligned_memory.h"
14 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h" 15 #include "base/run_loop.h"
16 #include "base/sync_socket.h" 16 #include "base/sync_socket.h"
17 #include "base/time/time.h"
17 #include "base/win/scoped_com_initializer.h" 18 #include "base/win/scoped_com_initializer.h"
18 #include "base/win/windows_version.h" 19 #include "base/win/windows_version.h"
19 #include "media/audio/audio_io.h" 20 #include "media/audio/audio_io.h"
20 #include "media/audio/audio_manager.h" 21 #include "media/audio/audio_manager.h"
21 #include "media/audio/audio_unittest_util.h" 22 #include "media/audio/audio_unittest_util.h"
22 #include "media/audio/mock_audio_source_callback.h" 23 #include "media/audio/mock_audio_source_callback.h"
23 #include "media/audio/simple_sources.h" 24 #include "media/audio/simple_sources.h"
24 #include "media/base/limits.h" 25 #include "media/base/limits.h"
25 #include "testing/gmock/include/gmock/gmock.h" 26 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
27 28
28 using ::testing::_; 29 using ::testing::_;
29 using ::testing::AnyNumber; 30 using ::testing::AnyNumber;
30 using ::testing::DoAll; 31 using ::testing::DoAll;
31 using ::testing::Field; 32 using ::testing::Field;
32 using ::testing::Invoke; 33 using ::testing::Invoke;
33 using ::testing::InSequence; 34 using ::testing::InSequence;
34 using ::testing::NiceMock; 35 using ::testing::NiceMock;
35 using ::testing::NotNull; 36 using ::testing::NotNull;
36 using ::testing::Return; 37 using ::testing::Return;
37 38
38 namespace media { 39 namespace media {
39 40
40 static int ClearData(AudioBus* audio_bus, 41 static int ClearData(base::TimeDelta /* delay */,
41 uint32_t total_bytes_delay, 42 base::TimeTicks /* delay_timestamp */,
42 uint32_t frames_skipped) { 43 int /* prior_frames_skipped */,
43 audio_bus->Zero(); 44 AudioBus* dest) {
44 return audio_bus->frames(); 45 dest->Zero();
46 return dest->frames();
45 } 47 }
46 48
47 // This class allows to find out if the callbacks are occurring as 49 // This class allows to find out if the callbacks are occurring as
48 // expected and if any error has been reported. 50 // expected and if any error has been reported.
49 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { 51 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
50 public: 52 public:
51 TestSourceBasic() 53 TestSourceBasic()
52 : callback_count_(0), 54 : callback_count_(0),
53 had_error_(0) { 55 had_error_(0) {
54 } 56 }
55 // AudioSourceCallback::OnMoreData implementation: 57 // AudioSourceCallback::OnMoreData implementation:
56 int OnMoreData(AudioBus* audio_bus, 58 int OnMoreData(base::TimeDelta /* delay */,
57 uint32_t total_bytes_delay, 59 base::TimeTicks /* delay_timestamp */,
58 uint32_t frames_skipped) override { 60 int /* prior_frames_skipped */,
61 AudioBus* dest) override {
59 ++callback_count_; 62 ++callback_count_;
60 // Touch the channel memory value to make sure memory is good. 63 // Touch the channel memory value to make sure memory is good.
61 audio_bus->Zero(); 64 dest->Zero();
62 return audio_bus->frames(); 65 return dest->frames();
63 } 66 }
64 // AudioSourceCallback::OnError implementation: 67 // AudioSourceCallback::OnError implementation:
65 void OnError(AudioOutputStream* stream) override { ++had_error_; } 68 void OnError(AudioOutputStream* stream) override { ++had_error_; }
66 // Returns how many times OnMoreData() has been called. 69 // Returns how many times OnMoreData() has been called.
67 int callback_count() const { 70 int callback_count() const {
68 return callback_count_; 71 return callback_count_;
69 } 72 }
70 // Returns how many times the OnError callback was called. 73 // Returns how many times the OnError callback was called.
71 int had_error() const { 74 int had_error() const {
72 return had_error_; 75 return had_error_;
73 } 76 }
74 77
75 void set_error(bool error) { 78 void set_error(bool error) {
76 had_error_ += error ? 1 : 0; 79 had_error_ += error ? 1 : 0;
77 } 80 }
78 81
79 private: 82 private:
80 int callback_count_; 83 int callback_count_;
81 int had_error_; 84 int had_error_;
82 }; 85 };
83 86
84 const int kMaxNumBuffers = 3; 87 const int kMaxNumBuffers = 3;
85 // Specializes TestSourceBasic to simulate a source that blocks for some time 88 // Specializes TestSourceBasic to simulate a source that blocks for some time
86 // in the OnMoreData callback. 89 // in the OnMoreData callback.
87 class TestSourceLaggy : public TestSourceBasic { 90 class TestSourceLaggy : public TestSourceBasic {
88 public: 91 public:
89 explicit TestSourceLaggy(int lag_in_ms) 92 explicit TestSourceLaggy(int lag_in_ms)
90 : lag_in_ms_(lag_in_ms) { 93 : lag_in_ms_(lag_in_ms) {
91 } 94 }
92 int OnMoreData(AudioBus* audio_bus, 95 int OnMoreData(base::TimeDelta delay,
93 uint32_t total_bytes_delay, 96 base::TimeTicks delay_timestamp,
94 uint32_t frames_skipped) override { 97 int prior_frames_skipped,
98 AudioBus* dest) override {
95 // Call the base, which increments the callback_count_. 99 // Call the base, which increments the callback_count_.
96 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay, frames_skipped); 100 TestSourceBasic::OnMoreData(delay, delay_timestamp, prior_frames_skipped,
101 dest);
97 if (callback_count() > kMaxNumBuffers) { 102 if (callback_count() > kMaxNumBuffers) {
98 ::Sleep(lag_in_ms_); 103 ::Sleep(lag_in_ms_);
99 } 104 }
100 return audio_bus->frames(); 105 return dest->frames();
101 } 106 }
102 private: 107 private:
103 int lag_in_ms_; 108 int lag_in_ms_;
104 }; 109 };
105 110
106 // Helper class to memory map an entire file. The mapping is read-only. Don't 111 // Helper class to memory map an entire file. The mapping is read-only. Don't
107 // use for gigabyte-sized files. Attempts to write to this memory generate 112 // use for gigabyte-sized files. Attempts to write to this memory generate
108 // memory access violations. 113 // memory access violations.
109 class ReadOnlyMappedFile { 114 class ReadOnlyMappedFile {
110 public: 115 public:
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 485 uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
481 AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream( 486 AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
482 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 487 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
483 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), 488 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
484 std::string(), AudioManager::LogCallback()); 489 std::string(), AudioManager::LogCallback());
485 ASSERT_TRUE(NULL != oas); 490 ASSERT_TRUE(NULL != oas);
486 491
487 NiceMock<MockAudioSourceCallback> source; 492 NiceMock<MockAudioSourceCallback> source;
488 EXPECT_TRUE(oas->Open()); 493 EXPECT_TRUE(oas->Open());
489 494
490 uint32_t bytes_100_ms = samples_100_ms * 2; 495 const base::TimeDelta delay_100_ms = base::TimeDelta::FromMilliseconds(100);
496 const base::TimeDelta delay_200_ms = base::TimeDelta::FromMilliseconds(200);
491 497
492 // Audio output stream has either a double or triple buffer scheme. 498 // Audio output stream has either a double or triple buffer scheme. We expect
493 // We expect the amount of pending bytes will reaching up to 2 times of 499 // the delay to reach up to 200 ms depending on the number of buffers used.
494 // |bytes_100_ms| depending on number of buffers used.
495 // From that it would decrease as we are playing the data but not providing 500 // From that it would decrease as we are playing the data but not providing
496 // new one. And then we will try to provide zero data so the amount of 501 // new one. And then we will try to provide zero data so the amount of
497 // pending bytes will go down and eventually read zero. 502 // pending bytes will go down and eventually read zero.
498 InSequence s; 503 InSequence s;
499 504
500 EXPECT_CALL(source, OnMoreData(NotNull(), 0, 0)).WillOnce(Invoke(ClearData)); 505 EXPECT_CALL(source, OnMoreData(base::TimeDelta(), _, 0, NotNull()))
506 .WillOnce(Invoke(ClearData));
501 507
502 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this 508 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
503 // test is run on Vista, these expectations will fail. 509 // test is run on Vista, these expectations will fail.
504 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 0)) 510 EXPECT_CALL(source, OnMoreData(delay_100_ms, _, 0, NotNull()))
505 .WillOnce(Invoke(ClearData)); 511 .WillOnce(Invoke(ClearData));
506 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms, 0)) 512 EXPECT_CALL(source, OnMoreData(delay_200_ms, _, 0, NotNull()))
507 .WillOnce(Invoke(ClearData)); 513 .WillOnce(Invoke(ClearData));
508 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms, 0)) 514 EXPECT_CALL(source, OnMoreData(delay_200_ms, _, 0, NotNull()))
509 .Times(AnyNumber()) 515 .Times(AnyNumber())
510 .WillRepeatedly(Return(0)); 516 .WillRepeatedly(Return(0));
511 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 0)) 517 EXPECT_CALL(source, OnMoreData(delay_100_ms, _, 0, NotNull()))
512 .Times(AnyNumber()) 518 .Times(AnyNumber())
513 .WillRepeatedly(Return(0)); 519 .WillRepeatedly(Return(0));
514 EXPECT_CALL(source, OnMoreData(NotNull(), 0, 0)) 520 EXPECT_CALL(source, OnMoreData(base::TimeDelta(), _, 0, NotNull()))
515 .Times(AnyNumber()) 521 .Times(AnyNumber())
516 .WillRepeatedly(Return(0)); 522 .WillRepeatedly(Return(0));
517 523
518 oas->Start(&source); 524 oas->Start(&source);
519 ::Sleep(500); 525 ::Sleep(500);
520 oas->Stop(); 526 oas->Stop();
521 oas->Close(); 527 oas->Close();
522 } 528 }
523 529
524 // Simple source that uses a SyncSocket to retrieve the audio data 530 // Simple source that uses a SyncSocket to retrieve the audio data
525 // from a potentially remote thread. 531 // from a potentially remote thread.
526 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { 532 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
527 public: 533 public:
528 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) 534 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
529 : socket_(socket) { 535 : socket_(socket), params_(params) {
530 // Setup AudioBus wrapping data we'll receive over the sync socket. 536 // Setup AudioBus wrapping data we'll receive over the sync socket.
531 data_size_ = AudioBus::CalculateMemorySize(params); 537 data_size_ = AudioBus::CalculateMemorySize(params);
532 data_.reset(static_cast<float*>( 538 data_.reset(static_cast<float*>(
533 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); 539 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
534 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); 540 audio_bus_ = AudioBus::WrapMemory(params, data_.get());
535 } 541 }
536 ~SyncSocketSource() override {} 542 ~SyncSocketSource() override {}
537 543
538 // AudioSourceCallback::OnMoreData implementation: 544 // AudioSourceCallback::OnMoreData implementation:
539 int OnMoreData(AudioBus* audio_bus, 545 int OnMoreData(base::TimeDelta delay,
540 uint32_t total_bytes_delay, 546 base::TimeTicks /* delay_timestamp */,
541 uint32_t frames_skipped) override { 547 int /* prior_frames_skipped */,
548 AudioBus* dest) override {
549 uint32_t total_bytes_delay =
550 delay.InSecondsF() * params_.GetBytesPerSecond();
542 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay)); 551 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay));
543 uint32_t size = socket_->Receive(data_.get(), data_size_); 552 uint32_t size = socket_->Receive(data_.get(), data_size_);
544 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); 553 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U);
545 audio_bus_->CopyTo(audio_bus); 554 audio_bus_->CopyTo(dest);
546 return audio_bus_->frames(); 555 return audio_bus_->frames();
547 } 556 }
548 557
549 // AudioSourceCallback::OnError implementation: 558 // AudioSourceCallback::OnError implementation:
550 void OnError(AudioOutputStream* stream) override {} 559 void OnError(AudioOutputStream* stream) override {}
551 560
552 private: 561 private:
553 base::SyncSocket* socket_; 562 base::SyncSocket* socket_;
563 const AudioParameters params_;
554 int data_size_; 564 int data_size_;
555 std::unique_ptr<float, base::AlignedFreeDeleter> data_; 565 std::unique_ptr<float, base::AlignedFreeDeleter> data_;
556 std::unique_ptr<AudioBus> audio_bus_; 566 std::unique_ptr<AudioBus> audio_bus_;
557 }; 567 };
558 568
559 struct SyncThreadContext { 569 struct SyncThreadContext {
560 base::SyncSocket* socket; 570 base::SyncSocket* socket;
561 int sample_rate; 571 int sample_rate;
562 int channels; 572 int channels;
563 int frames; 573 int frames;
564 double sine_freq; 574 double sine_freq;
565 uint32_t packet_size_bytes; 575 uint32_t packet_size_bytes;
576 int bytes_per_second;
566 }; 577 };
567 578
568 // This thread provides the data that the SyncSocketSource above needs 579 // This thread provides the data that the SyncSocketSource above needs
569 // using the other end of a SyncSocket. The protocol is as follows: 580 // using the other end of a SyncSocket. The protocol is as follows:
570 // 581 //
571 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread 582 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
572 // <--- audio packet ---------- 583 // <--- audio packet ----------
573 // 584 //
574 DWORD __stdcall SyncSocketThread(void* context) { 585 DWORD __stdcall SyncSocketThread(void* context) {
575 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); 586 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
576 587
577 // Setup AudioBus wrapping data we'll pass over the sync socket. 588 // Setup AudioBus wrapping data we'll pass over the sync socket.
578 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( 589 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
579 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); 590 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
580 std::unique_ptr<AudioBus> audio_bus = 591 std::unique_ptr<AudioBus> audio_bus =
581 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get()); 592 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get());
582 593
583 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); 594 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
584 const int kTwoSecFrames = ctx.sample_rate * 2; 595 const int kTwoSecFrames = ctx.sample_rate * 2;
585 596
586 uint32_t total_bytes_delay = 0; 597 uint32_t total_bytes_delay = 0;
587 int times = 0; 598 int times = 0;
588 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { 599 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
589 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0) 600 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0)
590 break; 601 break;
591 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak(); 602 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak();
592 sine.OnMoreData(audio_bus.get(), total_bytes_delay, 0); 603 base::TimeDelta delay = base::TimeDelta::FromSecondsD(
604 static_cast<double>(total_bytes_delay) / ctx.bytes_per_second);
605 sine.OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
593 ctx.socket->Send(data.get(), ctx.packet_size_bytes); 606 ctx.socket->Send(data.get(), ctx.packet_size_bytes);
594 ++times; 607 ++times;
595 } 608 }
596 609
597 return 0; 610 return 0;
598 } 611 }
599 612
600 // Test the basic operation of AudioOutputStream used with a SyncSocket. 613 // Test the basic operation of AudioOutputStream used with a SyncSocket.
601 // The emphasis is to verify that it is possible to feed data to the audio 614 // The emphasis is to verify that it is possible to feed data to the audio
602 // layer using a source based on SyncSocket. In a real situation we would 615 // layer using a source based on SyncSocket. In a real situation we would
(...skipping 21 matching lines...) Expand all
624 637
625 SyncSocketSource source(&sockets[0], params); 638 SyncSocketSource source(&sockets[0], params);
626 639
627 SyncThreadContext thread_context; 640 SyncThreadContext thread_context;
628 thread_context.sample_rate = params.sample_rate(); 641 thread_context.sample_rate = params.sample_rate();
629 thread_context.sine_freq = 200.0; 642 thread_context.sine_freq = 200.0;
630 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); 643 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
631 thread_context.frames = params.frames_per_buffer(); 644 thread_context.frames = params.frames_per_buffer();
632 thread_context.channels = params.channels(); 645 thread_context.channels = params.channels();
633 thread_context.socket = &sockets[1]; 646 thread_context.socket = &sockets[1];
647 thread_context.bytes_per_second = params.GetBytesPerSecond();
634 648
635 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, 649 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
636 &thread_context, 0, NULL); 650 &thread_context, 0, NULL);
637 651
638 oas->Start(&source); 652 oas->Start(&source);
639 653
640 ::WaitForSingleObject(thread, INFINITE); 654 ::WaitForSingleObject(thread, INFINITE);
641 ::CloseHandle(thread); 655 ::CloseHandle(thread);
642 656
643 oas->Stop(); 657 oas->Stop();
644 oas->Close(); 658 oas->Close();
645 } 659 }
646 660
647 } // namespace media 661 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698