• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium OS 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 #include <gtest/gtest.h>
6 #include <vector>
7 
8 extern "C" {
9 // For static function test.
10 #include "cras_alsa_helpers.c"
11 }
12 
13 static int snd_pcm_sw_params_set_tstamp_type_called;
14 static int snd_pcm_sw_params_set_tstamp_mode_called;
15 static snd_pcm_uframes_t snd_pcm_htimestamp_avail_ret_val;
16 static timespec snd_pcm_htimestamp_tstamp_ret_val;
17 static std::vector<int> snd_pcm_sw_params_ret_vals;
18 
ResetStubData()19 static void ResetStubData() {
20   snd_pcm_sw_params_set_tstamp_type_called = 0;
21   snd_pcm_sw_params_set_tstamp_mode_called = 0;
22   snd_pcm_htimestamp_avail_ret_val = 0;
23   snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 0;
24   snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 0;
25   snd_pcm_sw_params_ret_vals.clear();
26 }
27 
28 namespace {
29 
create_chmap_cap(snd_pcm_chmap_type type,size_t channels)30 static snd_pcm_chmap_query_t *create_chmap_cap(snd_pcm_chmap_type type,
31 					       size_t channels)
32 {
33   snd_pcm_chmap_query_t *c;
34   c = (snd_pcm_chmap_query_t *)calloc(channels + 2, sizeof(int));
35   c->type = type;
36   c->map.channels = channels;
37   return c;
38 }
39 
TEST(AlsaHelper,MatchChannelMapCapabilityStereo)40 TEST(AlsaHelper, MatchChannelMapCapabilityStereo) {
41   snd_pcm_chmap_query_t **caps;
42   snd_pcm_chmap_query_t *c;
43   struct cras_audio_format *fmt;
44 
45   caps = (snd_pcm_chmap_query_t **)calloc(4, sizeof(*caps));
46 
47   /* Layout (CRAS_CH_RL, CRAS_CH_RR) corresponds to
48    * ALSA channel map (5, 6)
49    */
50   int8_t channel_layout[CRAS_CH_MAX] =
51       {-1, -1, 0, 1, -1, -1, -1, -1, -1, -1, -1};
52 
53   fmt = cras_audio_format_create(SND_PCM_FORMAT_S16_LE, 44100, 2);
54   cras_audio_format_set_channel_layout(fmt, channel_layout);
55 
56   /* Create a list of capabilities */
57   c = create_chmap_cap(SND_CHMAP_TYPE_FIXED, 3);
58   c->map.pos[0] = 3;
59   c->map.pos[1] = 4;
60   c->map.pos[2] = 5;
61   caps[0] = c;
62 
63   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
64   c->map.pos[0] = 5;
65   c->map.pos[1] = 6;
66   caps[1] = c;
67 
68   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
69   c->map.pos[0] = 9;
70   c->map.pos[1] = 10;
71   caps[2] = c;
72 
73   caps[3] = NULL;
74 
75   /* Test if there's a cap matches fmt */
76   c = cras_chmap_caps_match(caps, fmt);
77   ASSERT_NE((void *)NULL, c);
78 
79   caps[1]->map.pos[0] = 5;
80   caps[1]->map.pos[1] = 7;
81 
82   c = cras_chmap_caps_match(caps, fmt);
83   ASSERT_EQ((void *)NULL, c);
84 
85   free(caps[0]);
86   free(caps[1]);
87   free(caps[2]);
88   free(caps[3]);
89   free(caps);
90   cras_audio_format_destroy(fmt);
91 }
92 
TEST(AlsaHelper,MatchChannelMapCapability51)93 TEST(AlsaHelper, MatchChannelMapCapability51) {
94   snd_pcm_chmap_query_t **caps = NULL;
95   snd_pcm_chmap_query_t *c = NULL;
96   struct cras_audio_format *fmt;
97 
98   caps = (snd_pcm_chmap_query_t **)calloc(4, sizeof(*caps));
99 
100   /* Layout (CRAS_CH_FL, CRAS_CH_FR, CRAS_CH_RL, CRAS_CH_RR, CRAS_CH_FC)
101    * corresponds to ALSA channel map (3, 4, 5, 6, 7)
102    */
103   int8_t channel_layout[CRAS_CH_MAX] =
104       {0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1};
105 
106   fmt = cras_audio_format_create(SND_PCM_FORMAT_S16_LE, 44100, 6);
107   cras_audio_format_set_channel_layout(fmt, channel_layout);
108 
109   /* Create a list of capabilities */
110   c = create_chmap_cap(SND_CHMAP_TYPE_FIXED, 6);
111   c->map.pos[0] = 3;
112   c->map.pos[1] = 4;
113   c->map.pos[2] = 5;
114   c->map.pos[3] = 6;
115   c->map.pos[4] = 7;
116   c->map.pos[5] = 8;
117   caps[0] = c;
118 
119   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
120   c->map.pos[0] = 6;
121   c->map.pos[1] = 4;
122   caps[1] = c;
123 
124   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 6);
125   c->map.pos[0] = 9;
126   c->map.pos[1] = 10;
127   c->map.pos[2] = 5;
128   c->map.pos[3] = 6;
129   c->map.pos[4] = 7;
130   c->map.pos[5] = 8;
131   caps[2] = c;
132   caps[3] = NULL;
133 
134   /* Test if there's a cap matches fmt */
135   c = cras_chmap_caps_match(caps, fmt);
136   ASSERT_NE((void *)NULL, c);
137 
138   caps[0]->map.pos[0] = 7;
139   caps[0]->map.pos[1] = 8;
140   caps[0]->map.pos[4] = 3;
141   caps[0]->map.pos[5] = 4;
142   c = cras_chmap_caps_match(caps, fmt);
143   ASSERT_EQ((void *)NULL, c);
144 
145   caps[0]->type = SND_CHMAP_TYPE_PAIRED;
146   c = cras_chmap_caps_match(caps, fmt);
147   ASSERT_NE((void *)NULL, c);
148 
149   caps[0]->map.pos[0] = 8;
150   caps[0]->map.pos[1] = 7;
151   c = cras_chmap_caps_match(caps, fmt);
152   ASSERT_EQ((void *)NULL, c);
153 
154   caps[0]->type = SND_CHMAP_TYPE_VAR;
155   c = cras_chmap_caps_match(caps, fmt);
156   ASSERT_NE((void *)NULL, c);
157 
158   free(caps[0]);
159   free(caps[1]);
160   free(caps[2]);
161   free(caps[3]);
162   free(caps);
163   cras_audio_format_destroy(fmt);
164 }
165 
TEST(AlsaHelper,Htimestamp)166 TEST(AlsaHelper, Htimestamp) {
167   snd_pcm_t *dummy_handle = reinterpret_cast<snd_pcm_t*>(0x1);
168   snd_pcm_uframes_t used;
169   snd_pcm_uframes_t severe_underrun_frames = 480;
170   struct timespec tstamp;
171   int htimestamp_enabled = 1;
172   const char *dev_name = "dev_name";
173 
174   // Enable htimestamp use.
175   ResetStubData();
176   EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled));
177   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 1);
178   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 1);
179   EXPECT_EQ(1, htimestamp_enabled);
180 
181   // Try to enable htimestamp use: not supported.
182   ResetStubData();
183   snd_pcm_sw_params_ret_vals.push_back(-EINVAL);
184   EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled));
185   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 2);
186   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 2);
187   EXPECT_EQ(0, htimestamp_enabled);
188 
189   // Disable htimestamp use.
190   ResetStubData();
191   EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled));
192   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 0);
193   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 0);
194 
195   ResetStubData();
196   tstamp.tv_sec = 0;
197   tstamp.tv_nsec = 0;
198   snd_pcm_htimestamp_avail_ret_val = 20000;
199   snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 10;
200   snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 10000;
201 
202   cras_alsa_get_avail_frames(dummy_handle, 48000, severe_underrun_frames,
203                              dev_name, &used, &tstamp);
204   EXPECT_EQ(used, snd_pcm_htimestamp_avail_ret_val);
205   EXPECT_EQ(tstamp.tv_sec, snd_pcm_htimestamp_tstamp_ret_val.tv_sec);
206   EXPECT_EQ(tstamp.tv_nsec, snd_pcm_htimestamp_tstamp_ret_val.tv_nsec);
207 }
208 
TEST(AlsaHelper,GetAvailFramesSevereUnderrun)209 TEST(AlsaHelper, GetAvailFramesSevereUnderrun) {
210   snd_pcm_t *dummy_handle = reinterpret_cast<snd_pcm_t*>(0x1);
211   snd_pcm_uframes_t avail;
212   snd_pcm_uframes_t severe_underrun_frames = 480;
213   snd_pcm_uframes_t buffer_size = 48000;
214   struct timespec tstamp;
215   int rc;
216   const char *dev_name = "dev_name";
217 
218   ResetStubData();
219   snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames + 1;
220   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
221                                   severe_underrun_frames, dev_name,
222                                   &avail, &tstamp);
223   // Returns -EPIPE when severe underrun happens.
224   EXPECT_EQ(rc, -EPIPE);
225 
226   ResetStubData();
227   snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames;
228   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
229                                   severe_underrun_frames, dev_name,
230                                   &avail, &tstamp);
231   // Underrun which is not severe enough will be masked.
232   // avail will be adjusted to buffer_size.
233   EXPECT_EQ(avail, buffer_size);
234   EXPECT_EQ(rc, 0);
235 
236   ResetStubData();
237   snd_pcm_htimestamp_avail_ret_val = buffer_size - 1;
238   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
239                                   severe_underrun_frames, dev_name,
240                                   &avail, &tstamp);
241   // When avail < buffer_size, there is no underrun.
242   EXPECT_EQ(avail, buffer_size - 1);
243   EXPECT_EQ(rc, 0);
244 }
245 } // namespace
246 
247 extern "C" {
248 
snd_pcm_sw_params_current(snd_pcm_t * pcm,snd_pcm_sw_params_t * params)249 int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) {
250   return 0;
251 }
252 
snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t * params,snd_pcm_uframes_t * val)253 int snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t *params,
254                                    snd_pcm_uframes_t *val) {
255   return 0;
256 }
257 
snd_pcm_sw_params_set_stop_threshold(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_uframes_t val)258 int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm,
259                                          snd_pcm_sw_params_t *params,
260                                          snd_pcm_uframes_t val) {
261   return 0;
262 }
263 
snd_pcm_sw_params_set_start_threshold(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_uframes_t val)264 int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm,
265                                           snd_pcm_sw_params_t *params,
266                                           snd_pcm_uframes_t val) {
267   return 0;
268 }
269 
snd_pcm_sw_params_set_period_event(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,int val)270 int snd_pcm_sw_params_set_period_event(snd_pcm_t *pcm,
271                                        snd_pcm_sw_params_t *params, int val) {
272   return 0;
273 }
274 
snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_tstamp_t val)275 int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm,
276                                       snd_pcm_sw_params_t *params,
277                                       snd_pcm_tstamp_t val) {
278   snd_pcm_sw_params_set_tstamp_mode_called++;
279   return 0;
280 }
281 
snd_pcm_sw_params_set_tstamp_type(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_tstamp_type_t val)282 int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm,
283                                       snd_pcm_sw_params_t *params,
284                                       snd_pcm_tstamp_type_t val) {
285   snd_pcm_sw_params_set_tstamp_type_called++;
286   return 0;
287 }
288 
snd_pcm_sw_params(snd_pcm_t * pcm,snd_pcm_sw_params_t * params)289 int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) {
290   int rc;
291 
292   if (snd_pcm_sw_params_ret_vals.size() == 0)
293     return 0;
294   rc = snd_pcm_sw_params_ret_vals.back();
295   snd_pcm_sw_params_ret_vals.pop_back();
296   return rc;
297 }
298 
snd_pcm_avail(snd_pcm_t * pcm)299 snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm) {
300   return snd_pcm_htimestamp_avail_ret_val;
301 }
302 
snd_pcm_htimestamp(snd_pcm_t * pcm,snd_pcm_uframes_t * avail,snd_htimestamp_t * tstamp)303 int snd_pcm_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
304                        snd_htimestamp_t *tstamp) {
305   *avail = snd_pcm_htimestamp_avail_ret_val;
306   *tstamp = snd_pcm_htimestamp_tstamp_ret_val;
307   return 0;
308 }
309 
310 }
311 
main(int argc,char ** argv)312 int main(int argc, char **argv) {
313   ::testing::InitGoogleTest(&argc, argv);
314   return RUN_ALL_TESTS();
315 }
316