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

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 CQ errors. Created 4 years, 3 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"
(...skipping 19 matching lines...) Expand all
46 47
47 // This class allows to find out if the callbacks are occurring as 48 // This class allows to find out if the callbacks are occurring as
48 // expected and if any error has been reported. 49 // expected and if any error has been reported.
49 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { 50 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
50 public: 51 public:
51 TestSourceBasic() 52 TestSourceBasic()
52 : callback_count_(0), 53 : callback_count_(0),
53 had_error_(0) { 54 had_error_(0) {
54 } 55 }
55 // AudioSourceCallback::OnMoreData implementation: 56 // AudioSourceCallback::OnMoreData implementation:
56 int OnMoreData(AudioBus* audio_bus, 57 int OnMoreData(base::TimeDelta /* delay */,
57 uint32_t total_bytes_delay, 58 base::TimeTicks /* delay_timestamp */,
58 uint32_t frames_skipped) override { 59 int /* prior_frames_skipped */,
60 AudioBus* dest) override {
59 ++callback_count_; 61 ++callback_count_;
60 // Touch the channel memory value to make sure memory is good. 62 // Touch the channel memory value to make sure memory is good.
61 audio_bus->Zero(); 63 dest->Zero();
62 return audio_bus->frames(); 64 return dest->frames();
63 } 65 }
64 // AudioSourceCallback::OnError implementation: 66 // AudioSourceCallback::OnError implementation:
65 void OnError(AudioOutputStream* stream) override { ++had_error_; } 67 void OnError(AudioOutputStream* stream) override { ++had_error_; }
66 // Returns how many times OnMoreData() has been called. 68 // Returns how many times OnMoreData() has been called.
67 int callback_count() const { 69 int callback_count() const {
68 return callback_count_; 70 return callback_count_;
69 } 71 }
70 // Returns how many times the OnError callback was called. 72 // Returns how many times the OnError callback was called.
71 int had_error() const { 73 int had_error() const {
72 return had_error_; 74 return had_error_;
73 } 75 }
74 76
75 void set_error(bool error) { 77 void set_error(bool error) {
76 had_error_ += error ? 1 : 0; 78 had_error_ += error ? 1 : 0;
77 } 79 }
78 80
79 private: 81 private:
80 int callback_count_; 82 int callback_count_;
81 int had_error_; 83 int had_error_;
82 }; 84 };
83 85
84 const int kMaxNumBuffers = 3; 86 const int kMaxNumBuffers = 3;
85 // Specializes TestSourceBasic to simulate a source that blocks for some time 87 // Specializes TestSourceBasic to simulate a source that blocks for some time
86 // in the OnMoreData callback. 88 // in the OnMoreData callback.
87 class TestSourceLaggy : public TestSourceBasic { 89 class TestSourceLaggy : public TestSourceBasic {
88 public: 90 public:
89 explicit TestSourceLaggy(int lag_in_ms) 91 explicit TestSourceLaggy(int lag_in_ms)
90 : lag_in_ms_(lag_in_ms) { 92 : lag_in_ms_(lag_in_ms) {
91 } 93 }
92 int OnMoreData(AudioBus* audio_bus, 94 int OnMoreData(base::TimeDelta delay,
93 uint32_t total_bytes_delay, 95 base::TimeTicks delay_timestamp,
94 uint32_t frames_skipped) override { 96 int prior_frames_skipped,
97 AudioBus* dest) override {
95 // Call the base, which increments the callback_count_. 98 // Call the base, which increments the callback_count_.
96 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay, frames_skipped); 99 TestSourceBasic::OnMoreData(delay, delay_timestamp, prior_frames_skipped,
100 dest);
97 if (callback_count() > kMaxNumBuffers) { 101 if (callback_count() > kMaxNumBuffers) {
98 ::Sleep(lag_in_ms_); 102 ::Sleep(lag_in_ms_);
99 } 103 }
100 return audio_bus->frames(); 104 return dest->frames();
101 } 105 }
102 private: 106 private:
103 int lag_in_ms_; 107 int lag_in_ms_;
104 }; 108 };
105 109
106 // Helper class to memory map an entire file. The mapping is read-only. Don't 110 // 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 111 // use for gigabyte-sized files. Attempts to write to this memory generate
108 // memory access violations. 112 // memory access violations.
109 class ReadOnlyMappedFile { 113 class ReadOnlyMappedFile {
110 public: 114 public:
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 484 uint32_t samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
481 AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream( 485 AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream(
482 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 486 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
483 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), 487 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
484 std::string(), AudioManager::LogCallback()); 488 std::string(), AudioManager::LogCallback());
485 ASSERT_TRUE(NULL != oas); 489 ASSERT_TRUE(NULL != oas);
486 490
487 NiceMock<MockAudioSourceCallback> source; 491 NiceMock<MockAudioSourceCallback> source;
488 EXPECT_TRUE(oas->Open()); 492 EXPECT_TRUE(oas->Open());
489 493
490 uint32_t bytes_100_ms = samples_100_ms * 2; 494 const base::TimeDelta 100_ms = base::TimeDelta::FromMilliseconds(100);
495 const base::TimeDelta 200_ms = base::TimeDelta::FromMilliseconds(200);
491 496
492 // Audio output stream has either a double or triple buffer scheme. 497 // 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 498 // 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 499 // 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 500 // 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. 501 // pending bytes will go down and eventually read zero.
498 InSequence s; 502 InSequence s;
499 503
500 EXPECT_CALL(source, OnMoreData(NotNull(), 0, 0)).WillOnce(Invoke(ClearData)); 504 EXPECT_CALL(source, OnMoreData(base::TimeDelta(), _, 0, NotNull()))
505 .WillOnce(Invoke(ClearData));
501 506
502 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this 507 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
503 // test is run on Vista, these expectations will fail. 508 // test is run on Vista, these expectations will fail.
504 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 0)) 509 EXPECT_CALL(source, OnMoreData(100_ms, _, 0, NotNull()))
505 .WillOnce(Invoke(ClearData)); 510 .WillOnce(Invoke(ClearData));
506 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms, 0)) 511 EXPECT_CALL(source, OnMoreData(200_ms, _, 0, NotNull()))
507 .WillOnce(Invoke(ClearData)); 512 .WillOnce(Invoke(ClearData));
508 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms, 0)) 513 EXPECT_CALL(source, OnMoreData(200_ms, _, 0, NotNull()))
509 .Times(AnyNumber()) 514 .Times(AnyNumber())
510 .WillRepeatedly(Return(0)); 515 .WillRepeatedly(Return(0));
511 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 0)) 516 EXPECT_CALL(source, OnMoreData(100_ms, _, 0, NotNull()))
512 .Times(AnyNumber()) 517 .Times(AnyNumber())
513 .WillRepeatedly(Return(0)); 518 .WillRepeatedly(Return(0));
514 EXPECT_CALL(source, OnMoreData(NotNull(), 0, 0)) 519 EXPECT_CALL(source, OnMoreData(base::TimeDelta(), _, 0, NotNull()))
515 .Times(AnyNumber()) 520 .Times(AnyNumber())
516 .WillRepeatedly(Return(0)); 521 .WillRepeatedly(Return(0));
517 522
518 oas->Start(&source); 523 oas->Start(&source);
519 ::Sleep(500); 524 ::Sleep(500);
520 oas->Stop(); 525 oas->Stop();
521 oas->Close(); 526 oas->Close();
522 } 527 }
523 528
524 // Simple source that uses a SyncSocket to retrieve the audio data 529 // Simple source that uses a SyncSocket to retrieve the audio data
525 // from a potentially remote thread. 530 // from a potentially remote thread.
526 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { 531 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
527 public: 532 public:
528 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) 533 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
529 : socket_(socket) { 534 : socket_(socket), params_(params) {
530 // Setup AudioBus wrapping data we'll receive over the sync socket. 535 // Setup AudioBus wrapping data we'll receive over the sync socket.
531 data_size_ = AudioBus::CalculateMemorySize(params); 536 data_size_ = AudioBus::CalculateMemorySize(params);
532 data_.reset(static_cast<float*>( 537 data_.reset(static_cast<float*>(
533 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); 538 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
534 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); 539 audio_bus_ = AudioBus::WrapMemory(params, data_.get());
535 } 540 }
536 ~SyncSocketSource() override {} 541 ~SyncSocketSource() override {}
537 542
538 // AudioSourceCallback::OnMoreData implementation: 543 // AudioSourceCallback::OnMoreData implementation:
539 int OnMoreData(AudioBus* audio_bus, 544 int OnMoreData(base::TimeDelta delay,
540 uint32_t total_bytes_delay, 545 base::TimeTicks /* delay_timestamp */,
541 uint32_t frames_skipped) override { 546 int /* prior_frames_skipped */,
547 AudioBus* dest) override {
548 uint32_t total_bytes_delay =
549 delay.InSecondsF() * params_.GetBytesPerSecond();
542 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay)); 550 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay));
543 uint32_t size = socket_->Receive(data_.get(), data_size_); 551 uint32_t size = socket_->Receive(data_.get(), data_size_);
544 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); 552 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*dest_->channel(0)), 0U);
545 audio_bus_->CopyTo(audio_bus); 553 dest_->CopyTo(dest);
546 return audio_bus_->frames(); 554 return dest_->frames();
547 } 555 }
548 556
549 // AudioSourceCallback::OnError implementation: 557 // AudioSourceCallback::OnError implementation:
550 void OnError(AudioOutputStream* stream) override {} 558 void OnError(AudioOutputStream* stream) override {}
551 559
552 private: 560 private:
553 base::SyncSocket* socket_; 561 base::SyncSocket* socket_;
562 const AudioParameters params_;
554 int data_size_; 563 int data_size_;
555 std::unique_ptr<float, base::AlignedFreeDeleter> data_; 564 std::unique_ptr<float, base::AlignedFreeDeleter> data_;
556 std::unique_ptr<AudioBus> audio_bus_; 565 std::unique_ptr<AudioBus> audio_bus_;
557 }; 566 };
558 567
559 struct SyncThreadContext { 568 struct SyncThreadContext {
560 base::SyncSocket* socket; 569 base::SyncSocket* socket;
561 int sample_rate; 570 int sample_rate;
562 int channels; 571 int channels;
563 int frames; 572 int frames;
564 double sine_freq; 573 double sine_freq;
565 uint32_t packet_size_bytes; 574 uint32_t packet_size_bytes;
575 int bytes_per_second;
566 }; 576 };
567 577
568 // This thread provides the data that the SyncSocketSource above needs 578 // This thread provides the data that the SyncSocketSource above needs
569 // using the other end of a SyncSocket. The protocol is as follows: 579 // using the other end of a SyncSocket. The protocol is as follows:
570 // 580 //
571 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread 581 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
572 // <--- audio packet ---------- 582 // <--- audio packet ----------
573 // 583 //
574 DWORD __stdcall SyncSocketThread(void* context) { 584 DWORD __stdcall SyncSocketThread(void* context) {
575 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); 585 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
576 586
577 // Setup AudioBus wrapping data we'll pass over the sync socket. 587 // Setup AudioBus wrapping data we'll pass over the sync socket.
578 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( 588 std::unique_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
579 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); 589 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
580 std::unique_ptr<AudioBus> audio_bus = 590 std::unique_ptr<AudioBus> audio_bus =
581 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get()); 591 AudioBus::WrapMemory(ctx.channels, ctx.frames, data.get());
582 592
583 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); 593 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
584 const int kTwoSecFrames = ctx.sample_rate * 2; 594 const int kTwoSecFrames = ctx.sample_rate * 2;
585 595
586 uint32_t total_bytes_delay = 0; 596 uint32_t total_bytes_delay = 0;
587 int times = 0; 597 int times = 0;
588 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { 598 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
589 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0) 599 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0)
590 break; 600 break;
591 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak(); 601 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak();
592 sine.OnMoreData(audio_bus.get(), total_bytes_delay, 0); 602 base::TimeDelta delay = base::TimeDelta::FromSecondsD(
603 static_cast<double>(total_bytes_delay) / ctx.bytes_per_second);
604 sine.OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
593 ctx.socket->Send(data.get(), ctx.packet_size_bytes); 605 ctx.socket->Send(data.get(), ctx.packet_size_bytes);
594 ++times; 606 ++times;
595 } 607 }
596 608
597 return 0; 609 return 0;
598 } 610 }
599 611
600 // Test the basic operation of AudioOutputStream used with a SyncSocket. 612 // 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 613 // 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 614 // layer using a source based on SyncSocket. In a real situation we would
(...skipping 21 matching lines...) Expand all
624 636
625 SyncSocketSource source(&sockets[0], params); 637 SyncSocketSource source(&sockets[0], params);
626 638
627 SyncThreadContext thread_context; 639 SyncThreadContext thread_context;
628 thread_context.sample_rate = params.sample_rate(); 640 thread_context.sample_rate = params.sample_rate();
629 thread_context.sine_freq = 200.0; 641 thread_context.sine_freq = 200.0;
630 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); 642 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
631 thread_context.frames = params.frames_per_buffer(); 643 thread_context.frames = params.frames_per_buffer();
632 thread_context.channels = params.channels(); 644 thread_context.channels = params.channels();
633 thread_context.socket = &sockets[1]; 645 thread_context.socket = &sockets[1];
646 thread_context.bytes_per_second = params.GetBytesPerSecond();
634 647
635 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, 648 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
636 &thread_context, 0, NULL); 649 &thread_context, 0, NULL);
637 650
638 oas->Start(&source); 651 oas->Start(&source);
639 652
640 ::WaitForSingleObject(thread, INFINITE); 653 ::WaitForSingleObject(thread, INFINITE);
641 ::CloseHandle(thread); 654 ::CloseHandle(thread);
642 655
643 oas->Stop(); 656 oas->Stop();
644 oas->Close(); 657 oas->Close();
645 } 658 }
646 659
647 } // namespace media 660 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698