Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ppapi / tests / test_media_stream_audio_track.cc
blob020cf0819be9e3c4549c01f53278d133647497c3
1 // Copyright 2014 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 //
5 // Tests PPB_MediaStreamAudioTrack interface.
7 #include "ppapi/tests/test_media_stream_audio_track.h"
9 #include "ppapi/c/private/ppb_testing_private.h"
10 #include "ppapi/cpp/audio_buffer.h"
11 #include "ppapi/cpp/completion_callback.h"
12 #include "ppapi/cpp/instance.h"
13 #include "ppapi/cpp/var.h"
14 #include "ppapi/tests/test_utils.h"
15 #include "ppapi/tests/testing_instance.h"
17 REGISTER_TEST_CASE(MediaStreamAudioTrack);
19 namespace {
21 // Real constants defined in
22 // content/renderer/pepper/pepper_media_stream_audio_track_host.cc.
23 const int32_t kMaxNumberOfBuffers = 1000;
24 const int32_t kMinDuration = 10;
25 const int32_t kMaxDuration = 10000;
26 const int32_t kTimes = 3;
27 const char kJSCode[] =
28 "function gotStream(stream) {"
29 " test_stream = stream;"
30 " var track = stream.getAudioTracks()[0];"
31 " var plugin = document.getElementById('plugin');"
32 " plugin.postMessage(track);"
33 "}"
34 "var constraints = {"
35 " audio: true,"
36 " video: false,"
37 "};"
38 "navigator.getUserMedia = "
39 " navigator.getUserMedia || navigator.webkitGetUserMedia;"
40 "navigator.getUserMedia(constraints,"
41 " gotStream, function() {});";
43 // Helper to check if the |sample_rate| is listed in PP_AudioBuffer_SampleRate
44 // enum.
45 bool IsSampleRateValid(PP_AudioBuffer_SampleRate sample_rate) {
46 switch (sample_rate) {
47 case PP_AUDIOBUFFER_SAMPLERATE_8000:
48 case PP_AUDIOBUFFER_SAMPLERATE_16000:
49 case PP_AUDIOBUFFER_SAMPLERATE_22050:
50 case PP_AUDIOBUFFER_SAMPLERATE_32000:
51 case PP_AUDIOBUFFER_SAMPLERATE_44100:
52 case PP_AUDIOBUFFER_SAMPLERATE_48000:
53 case PP_AUDIOBUFFER_SAMPLERATE_96000:
54 case PP_AUDIOBUFFER_SAMPLERATE_192000:
55 return true;
56 default:
57 return false;
61 } // namespace
63 TestMediaStreamAudioTrack::TestMediaStreamAudioTrack(TestingInstance* instance)
64 : TestCase(instance),
65 event_(instance_->pp_instance()) {
68 bool TestMediaStreamAudioTrack::Init() {
69 return true;
72 TestMediaStreamAudioTrack::~TestMediaStreamAudioTrack() {
75 void TestMediaStreamAudioTrack::RunTests(const std::string& filter) {
76 RUN_TEST(Create, filter);
77 RUN_TEST(GetBuffer, filter);
78 RUN_TEST(Configure, filter);
79 RUN_TEST(ConfigureClose, filter);
82 void TestMediaStreamAudioTrack::HandleMessage(const pp::Var& message) {
83 if (message.is_resource()) {
84 audio_track_ = pp::MediaStreamAudioTrack(message.AsResource());
86 event_.Signal();
89 std::string TestMediaStreamAudioTrack::TestCreate() {
90 // Create a track.
91 instance_->EvalScript(kJSCode);
92 event_.Wait();
93 event_.Reset();
95 ASSERT_FALSE(audio_track_.is_null());
96 ASSERT_FALSE(audio_track_.HasEnded());
97 ASSERT_FALSE(audio_track_.GetId().empty());
99 // Close the track.
100 audio_track_.Close();
101 ASSERT_TRUE(audio_track_.HasEnded());
102 audio_track_ = pp::MediaStreamAudioTrack();
103 PASS();
106 std::string TestMediaStreamAudioTrack::TestGetBuffer() {
107 // Create a track.
108 instance_->EvalScript(kJSCode);
109 event_.Wait();
110 event_.Reset();
112 ASSERT_FALSE(audio_track_.is_null());
113 ASSERT_FALSE(audio_track_.HasEnded());
114 ASSERT_FALSE(audio_track_.GetId().empty());
116 PP_TimeDelta timestamp = 0.0;
118 // Get |kTimes| buffers.
119 for (int i = 0; i < kTimes; ++i) {
120 TestCompletionCallbackWithOutput<pp::AudioBuffer> cc(
121 instance_->pp_instance(), false);
122 cc.WaitForResult(audio_track_.GetBuffer(cc.GetCallback()));
123 ASSERT_EQ(PP_OK, cc.result());
124 pp::AudioBuffer buffer = cc.output();
125 ASSERT_FALSE(buffer.is_null());
126 ASSERT_TRUE(IsSampleRateValid(buffer.GetSampleRate()));
127 ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
129 ASSERT_GE(buffer.GetTimestamp(), timestamp);
130 timestamp = buffer.GetTimestamp();
132 ASSERT_GT(buffer.GetDataBufferSize(), 0U);
133 ASSERT_TRUE(buffer.GetDataBuffer() != NULL);
135 audio_track_.RecycleBuffer(buffer);
137 // A recycled buffer should be invalidated.
138 ASSERT_EQ(buffer.GetSampleRate(), PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN);
139 ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_UNKNOWN);
140 ASSERT_EQ(buffer.GetDataBufferSize(), 0U);
141 ASSERT_TRUE(buffer.GetDataBuffer() == NULL);
144 // Close the track.
145 audio_track_.Close();
146 ASSERT_TRUE(audio_track_.HasEnded());
147 audio_track_ = pp::MediaStreamAudioTrack();
148 PASS();
151 std::string TestMediaStreamAudioTrack::CheckConfigure(
152 int32_t attrib_list[], int32_t expected_result) {
153 TestCompletionCallback cc_configure(instance_->pp_instance(), false);
154 cc_configure.WaitForResult(
155 audio_track_.Configure(attrib_list, cc_configure.GetCallback()));
156 ASSERT_EQ(expected_result, cc_configure.result());
157 PASS();
160 std::string TestMediaStreamAudioTrack::CheckGetBuffer(
161 int times, int expected_duration) {
162 PP_TimeDelta timestamp = 0.0;
163 for (int j = 0; j < times; ++j) {
164 TestCompletionCallbackWithOutput<pp::AudioBuffer> cc_get_buffer(
165 instance_->pp_instance(), false);
166 cc_get_buffer.WaitForResult(
167 audio_track_.GetBuffer(cc_get_buffer.GetCallback()));
168 ASSERT_EQ(PP_OK, cc_get_buffer.result());
169 pp::AudioBuffer buffer = cc_get_buffer.output();
170 ASSERT_FALSE(buffer.is_null());
171 ASSERT_TRUE(IsSampleRateValid(buffer.GetSampleRate()));
172 ASSERT_EQ(buffer.GetSampleSize(), PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
174 ASSERT_GE(buffer.GetTimestamp(), timestamp);
175 timestamp = buffer.GetTimestamp();
177 // TODO(amistry): Figure out how to inject a predictable audio pattern, such
178 // as a sawtooth, and check the buffer data to make sure it's correct.
179 ASSERT_TRUE(buffer.GetDataBuffer() != NULL);
180 if (expected_duration > 0) {
181 uint32_t buffer_size = buffer.GetDataBufferSize();
182 uint32_t channels = buffer.GetNumberOfChannels();
183 uint32_t sample_rate = buffer.GetSampleRate();
184 uint32_t bytes_per_frame = channels * 2;
185 int32_t duration = expected_duration;
186 ASSERT_EQ(buffer_size % bytes_per_frame, 0U);
187 ASSERT_EQ(buffer_size,
188 (duration * sample_rate * bytes_per_frame) / 1000);
189 } else {
190 ASSERT_GT(buffer.GetDataBufferSize(), 0U);
193 audio_track_.RecycleBuffer(buffer);
195 PASS();
198 std::string TestMediaStreamAudioTrack::TestConfigure() {
199 // Create a track.
200 instance_->EvalScript(kJSCode);
201 event_.Wait();
202 event_.Reset();
204 ASSERT_FALSE(audio_track_.is_null());
205 ASSERT_FALSE(audio_track_.HasEnded());
206 ASSERT_FALSE(audio_track_.GetId().empty());
208 // Perform a |Configure()| with no attributes. This ends up making an IPC
209 // call, but the host implementation has a fast-path when there are no changes
210 // to the configuration. This test is intended to hit that fast-path and make
211 // sure it works correctly.
213 int32_t attrib_list[] = {
214 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
216 ASSERT_SUBTEST_SUCCESS(CheckConfigure(attrib_list, PP_OK));
219 // Configure number of buffers.
220 struct {
221 int32_t buffers;
222 int32_t expect_result;
223 } buffers[] = {
224 { 8, PP_OK },
225 { 100, PP_OK },
226 { kMaxNumberOfBuffers, PP_OK },
227 { -1, PP_ERROR_BADARGUMENT },
228 { kMaxNumberOfBuffers + 1, PP_OK }, // Clipped to max value.
229 { 0, PP_OK }, // Use default.
231 for (size_t i = 0; i < sizeof(buffers) / sizeof(buffers[0]); ++i) {
232 int32_t attrib_list[] = {
233 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS, buffers[i].buffers,
234 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
236 ASSERT_SUBTEST_SUCCESS(CheckConfigure(attrib_list,
237 buffers[i].expect_result));
238 // Get some buffers. This should also succeed when configure fails.
239 ASSERT_SUBTEST_SUCCESS(CheckGetBuffer(kTimes, -1));
242 // Configure buffer duration.
243 struct {
244 int32_t duration;
245 int32_t expect_result;
246 } durations[] = {
247 { kMinDuration, PP_OK },
248 { 123, PP_OK },
249 { kMinDuration - 1, PP_ERROR_BADARGUMENT },
250 { kMaxDuration + 1, PP_ERROR_BADARGUMENT },
252 for (size_t i = 0; i < sizeof(durations) / sizeof(durations[0]); ++i) {
253 int32_t attrib_list[] = {
254 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION, durations[i].duration,
255 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
257 ASSERT_SUBTEST_SUCCESS(CheckConfigure(attrib_list,
258 durations[i].expect_result));
260 // Get some buffers. This always works, but the buffer size will vary.
261 int duration =
262 durations[i].expect_result == PP_OK ? durations[i].duration : -1;
263 ASSERT_SUBTEST_SUCCESS(CheckGetBuffer(kTimes, duration));
265 // Test kMaxDuration separately since each GetBuffer will take 10 seconds.
267 int32_t attrib_list[] = {
268 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION, kMaxDuration,
269 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
271 ASSERT_SUBTEST_SUCCESS(CheckConfigure(attrib_list, PP_OK));
274 // Reset the duration to prevent the next part from taking 10 seconds.
276 int32_t attrib_list[] = {
277 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION, kMinDuration,
278 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
280 ASSERT_SUBTEST_SUCCESS(CheckConfigure(attrib_list, PP_OK));
283 // Configure should fail while plugin holds buffers.
285 TestCompletionCallbackWithOutput<pp::AudioBuffer> cc_get_buffer(
286 instance_->pp_instance(), false);
287 cc_get_buffer.WaitForResult(
288 audio_track_.GetBuffer(cc_get_buffer.GetCallback()));
289 ASSERT_EQ(PP_OK, cc_get_buffer.result());
290 pp::AudioBuffer buffer = cc_get_buffer.output();
291 int32_t attrib_list[] = {
292 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS, 0,
293 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
295 TestCompletionCallback cc_configure(instance_->pp_instance(), false);
296 cc_configure.WaitForResult(
297 audio_track_.Configure(attrib_list, cc_configure.GetCallback()));
298 ASSERT_EQ(PP_ERROR_INPROGRESS, cc_configure.result());
299 audio_track_.RecycleBuffer(buffer);
302 // Close the track.
303 audio_track_.Close();
304 ASSERT_TRUE(audio_track_.HasEnded());
305 audio_track_ = pp::MediaStreamAudioTrack();
306 PASS();
309 std::string TestMediaStreamAudioTrack::TestConfigureClose() {
310 // Create a track.
311 instance_->EvalScript(kJSCode);
312 event_.Wait();
313 event_.Reset();
315 ASSERT_FALSE(audio_track_.is_null());
316 ASSERT_FALSE(audio_track_.HasEnded());
317 ASSERT_FALSE(audio_track_.GetId().empty());
319 // Configure the audio track and close it immediately. The Configure() call
320 // should complete.
321 int32_t attrib_list[] = {
322 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS, 10,
323 PP_MEDIASTREAMAUDIOTRACK_ATTRIB_NONE,
325 TestCompletionCallback cc_configure(instance_->pp_instance(), false);
326 int32_t result = audio_track_.Configure(attrib_list,
327 cc_configure.GetCallback());
328 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
329 audio_track_.Close();
330 cc_configure.WaitForResult(result);
331 result = cc_configure.result();
332 // Unfortunately, we can't control whether the configure succeeds or is
333 // aborted.
334 ASSERT_TRUE(result == PP_OK || result == PP_ERROR_ABORTED);
336 PASS();