OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/renderer/media/audio_track_recorder.h" | 5 #include "content/renderer/media/audio_track_recorder.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
34 // Input audio format. | 34 // Input audio format. |
35 const media::AudioParameters::Format kDefaultInputFormat = | 35 const media::AudioParameters::Format kDefaultInputFormat = |
36 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; | 36 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; |
37 const int kDefaultBitsPerSample = 16; | 37 const int kDefaultBitsPerSample = 16; |
38 const int kDefaultSampleRate = 48000; | 38 const int kDefaultSampleRate = 48000; |
39 // The |frames_per_buffer| field of AudioParameters is not used by ATR. | 39 // The |frames_per_buffer| field of AudioParameters is not used by ATR. |
40 const int kIgnoreFramesPerBuffer = 1; | 40 const int kIgnoreFramesPerBuffer = 1; |
41 const int kOpusMaxBufferDurationMS = 120; | 41 const int kMediaStreamAudioTrackBufferDurationMs = 10; |
42 | 42 |
43 const int kFramesPerBuffer = | |
44 kMediaStreamAudioTrackBufferDurationMs * kDefaultSampleRate / 1000; | |
43 } // namespace | 45 } // namespace |
44 | 46 |
45 namespace content { | 47 namespace content { |
46 | 48 |
47 ACTION_P(RunClosure, closure) { | 49 ACTION_P(RunClosure, closure) { |
48 closure.Run(); | 50 closure.Run(); |
49 } | 51 } |
50 | 52 |
51 struct ATRTestParams { | 53 struct ATRTestParams { |
52 const media::AudioParameters::Format input_format; | 54 const media::AudioParameters::Format input_format; |
53 const media::ChannelLayout channel_layout; | 55 const media::ChannelLayout channel_layout; |
54 const int sample_rate; | 56 const int sample_rate; |
55 const int bits_per_sample; | 57 const int bits_per_sample; |
56 }; | 58 }; |
57 | 59 |
58 const ATRTestParams kATRTestParams[] = { | 60 const ATRTestParams kATRTestParams[] = { |
59 // Equivalent to default settings: | 61 // Equivalent to default settings: |
60 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, /* input format */ | 62 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, /* input format */ |
61 media::CHANNEL_LAYOUT_STEREO, /* channel layout */ | 63 media::CHANNEL_LAYOUT_STEREO, /* channel layout */ |
62 kDefaultSampleRate, /* sample rate */ | 64 kDefaultSampleRate, /* sample rate */ |
63 kDefaultBitsPerSample}, /* bits per sample */ | 65 kDefaultBitsPerSample}, /* bits per sample */ |
64 // Change to mono: | 66 // Change to mono: |
65 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO, | 67 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
66 kDefaultSampleRate, kDefaultBitsPerSample}, | 68 media::CHANNEL_LAYOUT_MONO, |
69 kDefaultSampleRate, | |
70 kDefaultBitsPerSample}, | |
67 // Different sampling rate as well: | 71 // Different sampling rate as well: |
68 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO, | |
69 24000, kDefaultBitsPerSample}, | |
70 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 72 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
71 media::CHANNEL_LAYOUT_STEREO, 8000, kDefaultBitsPerSample}, | 73 media::CHANNEL_LAYOUT_MONO, |
74 24000, | |
75 kDefaultBitsPerSample}, | |
76 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
77 media::CHANNEL_LAYOUT_STEREO, | |
78 8000, | |
79 kDefaultBitsPerSample}, | |
80 // Using a non-default Opus sampling rate (48, 24, 16, 12, or 8 kHz). | |
81 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
82 media::CHANNEL_LAYOUT_MONO, | |
83 22050, | |
miu
2016/01/22 00:14:53
Note: Increasing the Opus frame duration (as I men
mcasas
2016/01/22 22:03:53
Acknowledged.
| |
84 kDefaultBitsPerSample}, | |
85 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
86 media::CHANNEL_LAYOUT_STEREO, | |
87 44100, | |
88 kDefaultBitsPerSample}, | |
89 {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
90 media::CHANNEL_LAYOUT_STEREO, | |
91 96000, | |
92 kDefaultBitsPerSample}, | |
72 }; | 93 }; |
73 | 94 |
74 class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> { | 95 class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> { |
75 public: | 96 public: |
76 // Initialize |first_params_| based on test parameters, and |second_params_| | 97 // Initialize |first_params_| based on test parameters, and |second_params_| |
77 // to always be the same thing. | 98 // to always be the same thing. |
78 AudioTrackRecorderTest() | 99 AudioTrackRecorderTest() |
79 : first_params_(GetParam().input_format, | 100 : first_params_(GetParam().input_format, |
80 GetParam().channel_layout, | 101 GetParam().channel_layout, |
81 GetParam().sample_rate, | 102 GetParam().sample_rate, |
(...skipping 14 matching lines...) Expand all Loading... | |
96 ResetDecoder(first_params_); | 117 ResetDecoder(first_params_); |
97 PrepareBlinkTrack(); | 118 PrepareBlinkTrack(); |
98 audio_track_recorder_.reset(new AudioTrackRecorder( | 119 audio_track_recorder_.reset(new AudioTrackRecorder( |
99 blink_track_, base::Bind(&AudioTrackRecorderTest::OnEncodedAudio, | 120 blink_track_, base::Bind(&AudioTrackRecorderTest::OnEncodedAudio, |
100 base::Unretained(this)))); | 121 base::Unretained(this)))); |
101 } | 122 } |
102 | 123 |
103 ~AudioTrackRecorderTest() { | 124 ~AudioTrackRecorderTest() { |
104 opus_decoder_destroy(opus_decoder_); | 125 opus_decoder_destroy(opus_decoder_); |
105 opus_decoder_ = nullptr; | 126 opus_decoder_ = nullptr; |
106 audio_track_recorder_.reset(); | |
107 blink_track_.reset(); | 127 blink_track_.reset(); |
108 blink::WebHeap::collectAllGarbageForTesting(); | 128 blink::WebHeap::collectAllGarbageForTesting(); |
129 audio_track_recorder_.reset(); | |
130 // Let the message loop run to finish destroying the recorder properly. | |
131 base::RunLoop().RunUntilIdle(); | |
109 } | 132 } |
110 | 133 |
111 void ResetDecoder(const media::AudioParameters& params) { | 134 void ResetDecoder(const media::AudioParameters& params) { |
112 if (opus_decoder_) { | 135 if (opus_decoder_) { |
113 opus_decoder_destroy(opus_decoder_); | 136 opus_decoder_destroy(opus_decoder_); |
114 opus_decoder_ = nullptr; | 137 opus_decoder_ = nullptr; |
115 } | 138 } |
116 | 139 |
117 int error; | 140 int error; |
118 opus_decoder_ = | 141 opus_decoder_ = |
119 opus_decoder_create(params.sample_rate(), params.channels(), &error); | 142 opus_decoder_create(kDefaultSampleRate, params.channels(), &error); |
120 EXPECT_TRUE(error == OPUS_OK && opus_decoder_); | 143 EXPECT_TRUE(error == OPUS_OK && opus_decoder_); |
121 | 144 |
122 max_frames_per_buffer_ = | 145 buffer_.reset(new float[kFramesPerBuffer * params.channels()]); |
123 kOpusMaxBufferDurationMS * params.sample_rate() / 1000; | |
124 buffer_.reset(new float[max_frames_per_buffer_ * params.channels()]); | |
125 } | 146 } |
126 | 147 |
127 scoped_ptr<media::AudioBus> GetFirstSourceAudioBus() { | 148 scoped_ptr<media::AudioBus> GetFirstSourceAudioBus() { |
128 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create( | 149 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create( |
129 first_params_.channels(), | 150 first_params_.channels(), first_params_.sample_rate() * |
130 first_params_.sample_rate() * | 151 kMediaStreamAudioTrackBufferDurationMs / |
131 audio_track_recorder_->GetOpusBufferDuration( | 152 1000)); |
132 first_params_.sample_rate()) / | |
133 1000)); | |
134 first_source_.OnMoreData(bus.get(), 0, 0); | 153 first_source_.OnMoreData(bus.get(), 0, 0); |
135 return bus; | 154 return bus; |
136 } | 155 } |
137 scoped_ptr<media::AudioBus> GetSecondSourceAudioBus() { | 156 scoped_ptr<media::AudioBus> GetSecondSourceAudioBus() { |
138 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create( | 157 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create( |
139 second_params_.channels(), | 158 second_params_.channels(), second_params_.sample_rate() * |
140 second_params_.sample_rate() * | 159 kMediaStreamAudioTrackBufferDurationMs / |
141 audio_track_recorder_->GetOpusBufferDuration( | 160 1000)); |
142 second_params_.sample_rate()) / | |
143 1000)); | |
144 second_source_.OnMoreData(bus.get(), 0, 0); | 161 second_source_.OnMoreData(bus.get(), 0, 0); |
145 return bus; | 162 return bus; |
146 } | 163 } |
147 | 164 |
148 MOCK_METHOD3(DoOnEncodedAudio, | 165 MOCK_METHOD3(DoOnEncodedAudio, |
149 void(const media::AudioParameters& params, | 166 void(const media::AudioParameters& params, |
150 std::string encoded_data, | 167 std::string encoded_data, |
151 base::TimeTicks timestamp)); | 168 base::TimeTicks timestamp)); |
152 | 169 |
153 void OnEncodedAudio(const media::AudioParameters& params, | 170 void OnEncodedAudio(const media::AudioParameters& params, |
154 scoped_ptr<std::string> encoded_data, | 171 scoped_ptr<std::string> encoded_data, |
155 base::TimeTicks timestamp) { | 172 base::TimeTicks timestamp) { |
156 EXPECT_TRUE(!encoded_data->empty()); | 173 EXPECT_TRUE(!encoded_data->empty()); |
157 | |
158 // Decode |encoded_data| and check we get the expected number of frames | 174 // Decode |encoded_data| and check we get the expected number of frames |
159 // per buffer. | 175 // per buffer. |
160 EXPECT_EQ( | 176 EXPECT_EQ( |
161 params.sample_rate() * | 177 kDefaultSampleRate * kMediaStreamAudioTrackBufferDurationMs / 1000, |
162 audio_track_recorder_->GetOpusBufferDuration(params.sample_rate()) / | |
163 1000, | |
164 opus_decode_float( | 178 opus_decode_float( |
165 opus_decoder_, | 179 opus_decoder_, |
166 reinterpret_cast<uint8_t*>(string_as_array(encoded_data.get())), | 180 reinterpret_cast<uint8_t*>(string_as_array(encoded_data.get())), |
167 encoded_data->size(), buffer_.get(), max_frames_per_buffer_, 0)); | 181 encoded_data->size(), buffer_.get(), kFramesPerBuffer, 0)); |
168 | 182 |
169 DoOnEncodedAudio(params, *encoded_data, timestamp); | 183 DoOnEncodedAudio(params, *encoded_data, timestamp); |
170 } | 184 } |
171 | 185 |
172 const base::MessageLoop message_loop_; | 186 const base::MessageLoop message_loop_; |
173 | 187 |
174 // ATR and WebMediaStreamTrack for fooling it. | 188 // ATR and WebMediaStreamTrack for fooling it. |
175 scoped_ptr<AudioTrackRecorder> audio_track_recorder_; | 189 scoped_ptr<AudioTrackRecorder> audio_track_recorder_; |
176 blink::WebMediaStreamTrack blink_track_; | 190 blink::WebMediaStreamTrack blink_track_; |
177 | 191 |
178 // Two different sets of AudioParameters for testing re-init of ATR. | 192 // Two different sets of AudioParameters for testing re-init of ATR. |
179 const media::AudioParameters first_params_; | 193 const media::AudioParameters first_params_; |
180 const media::AudioParameters second_params_; | 194 const media::AudioParameters second_params_; |
181 | 195 |
182 // AudioSources for creating AudioBuses. | 196 // AudioSources for creating AudioBuses. |
183 media::SineWaveAudioSource first_source_; | 197 media::SineWaveAudioSource first_source_; |
184 media::SineWaveAudioSource second_source_; | 198 media::SineWaveAudioSource second_source_; |
185 | 199 |
186 // Decoder for verifying data was properly encoded. | 200 // Decoder for verifying data was properly encoded. |
187 OpusDecoder* opus_decoder_; | 201 OpusDecoder* opus_decoder_; |
188 int max_frames_per_buffer_; | |
189 scoped_ptr<float[]> buffer_; | 202 scoped_ptr<float[]> buffer_; |
190 | 203 |
191 private: | 204 private: |
192 // Prepares a blink track of a given MediaStreamType and attaches the native | 205 // Prepares a blink track of a given MediaStreamType and attaches the native |
193 // track, which can be used to capture audio data and pass it to the producer. | 206 // track, which can be used to capture audio data and pass it to the producer. |
194 // Adapted from media::WebRTCLocalAudioSourceProviderTest. | 207 // Adapted from media::WebRTCLocalAudioSourceProviderTest. |
195 void PrepareBlinkTrack() { | 208 void PrepareBlinkTrack() { |
196 MockMediaConstraintFactory constraint_factory; | 209 MockMediaConstraintFactory constraint_factory; |
197 scoped_refptr<WebRtcAudioCapturer> capturer( | 210 scoped_refptr<WebRtcAudioCapturer> capturer( |
198 WebRtcAudioCapturer::CreateCapturer( | 211 WebRtcAudioCapturer::CreateCapturer( |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 .WillOnce(RunClosure(quit_closure)); | 260 .WillOnce(RunClosure(quit_closure)); |
248 audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), time3); | 261 audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), time3); |
249 | 262 |
250 run_loop.Run(); | 263 run_loop.Run(); |
251 Mock::VerifyAndClearExpectations(this); | 264 Mock::VerifyAndClearExpectations(this); |
252 } | 265 } |
253 | 266 |
254 INSTANTIATE_TEST_CASE_P(, AudioTrackRecorderTest, ValuesIn(kATRTestParams)); | 267 INSTANTIATE_TEST_CASE_P(, AudioTrackRecorderTest, ValuesIn(kATRTestParams)); |
255 | 268 |
256 } // namespace content | 269 } // namespace content |
OLD | NEW |