• 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 
7 #include <vector>
8 
9 extern "C" {
10 // For static function test.
11 #include "cras_alsa_helpers.c"
12 }
13 
14 static int snd_pcm_sw_params_set_tstamp_type_called;
15 static int snd_pcm_sw_params_set_tstamp_mode_called;
16 static snd_pcm_uframes_t snd_pcm_htimestamp_avail_ret_val;
17 static timespec snd_pcm_htimestamp_tstamp_ret_val;
18 static std::vector<int> snd_pcm_sw_params_ret_vals;
19 
ResetStubData()20 static void ResetStubData() {
21   snd_pcm_sw_params_set_tstamp_type_called = 0;
22   snd_pcm_sw_params_set_tstamp_mode_called = 0;
23   snd_pcm_htimestamp_avail_ret_val = 0;
24   snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 0;
25   snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 0;
26   snd_pcm_sw_params_ret_vals.clear();
27 }
28 
29 namespace {
30 
create_chmap_cap(snd_pcm_chmap_type type,size_t channels)31 static snd_pcm_chmap_query_t* create_chmap_cap(snd_pcm_chmap_type type,
32                                                size_t channels) {
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] = {-1, -1, 0,  1,  -1, -1,
51                                         -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] = {0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1};
104 
105   fmt = cras_audio_format_create(SND_PCM_FORMAT_S16_LE, 44100, 6);
106   cras_audio_format_set_channel_layout(fmt, channel_layout);
107 
108   /* Create a list of capabilities */
109   c = create_chmap_cap(SND_CHMAP_TYPE_FIXED, 6);
110   c->map.pos[0] = 3;
111   c->map.pos[1] = 4;
112   c->map.pos[2] = 5;
113   c->map.pos[3] = 6;
114   c->map.pos[4] = 7;
115   c->map.pos[5] = 8;
116   caps[0] = c;
117 
118   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
119   c->map.pos[0] = 6;
120   c->map.pos[1] = 4;
121   caps[1] = c;
122 
123   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 6);
124   c->map.pos[0] = 9;
125   c->map.pos[1] = 10;
126   c->map.pos[2] = 5;
127   c->map.pos[3] = 6;
128   c->map.pos[4] = 7;
129   c->map.pos[5] = 8;
130   caps[2] = c;
131   caps[3] = NULL;
132 
133   /* Test if there's a cap matches fmt */
134   c = cras_chmap_caps_match(caps, fmt);
135   ASSERT_NE((void*)NULL, c);
136 
137   caps[0]->map.pos[0] = 7;
138   caps[0]->map.pos[1] = 8;
139   caps[0]->map.pos[4] = 3;
140   caps[0]->map.pos[5] = 4;
141   c = cras_chmap_caps_match(caps, fmt);
142   ASSERT_EQ((void*)NULL, c);
143 
144   caps[0]->type = SND_CHMAP_TYPE_PAIRED;
145   c = cras_chmap_caps_match(caps, fmt);
146   ASSERT_NE((void*)NULL, c);
147 
148   caps[0]->map.pos[0] = 8;
149   caps[0]->map.pos[1] = 7;
150   c = cras_chmap_caps_match(caps, fmt);
151   ASSERT_EQ((void*)NULL, c);
152 
153   caps[0]->type = SND_CHMAP_TYPE_VAR;
154   c = cras_chmap_caps_match(caps, fmt);
155   ASSERT_NE((void*)NULL, c);
156 
157   free(caps[0]);
158   free(caps[1]);
159   free(caps[2]);
160   free(caps[3]);
161   free(caps);
162   cras_audio_format_destroy(fmt);
163 }
164 
TEST(AlsaHelper,Htimestamp)165 TEST(AlsaHelper, Htimestamp) {
166   snd_pcm_t* mock_handle = reinterpret_cast<snd_pcm_t*>(0x1);
167   snd_pcm_uframes_t used;
168   snd_pcm_uframes_t severe_underrun_frames = 480;
169   struct timespec tstamp;
170   const char* dev_name = "dev_name";
171 
172   ResetStubData();
173   tstamp.tv_sec = 0;
174   tstamp.tv_nsec = 0;
175   snd_pcm_htimestamp_avail_ret_val = 20000;
176   snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 10;
177   snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 10000;
178 
179   cras_alsa_get_avail_frames(mock_handle, 48000, severe_underrun_frames,
180                              dev_name, &used, &tstamp);
181   EXPECT_EQ(used, snd_pcm_htimestamp_avail_ret_val);
182   EXPECT_EQ(tstamp.tv_sec, snd_pcm_htimestamp_tstamp_ret_val.tv_sec);
183   EXPECT_EQ(tstamp.tv_nsec, snd_pcm_htimestamp_tstamp_ret_val.tv_nsec);
184 }
185 
TEST(AlsaHelper,GetAvailFramesSevereUnderrun)186 TEST(AlsaHelper, GetAvailFramesSevereUnderrun) {
187   snd_pcm_t* mock_handle = reinterpret_cast<snd_pcm_t*>(0x1);
188   snd_pcm_uframes_t avail;
189   snd_pcm_uframes_t severe_underrun_frames = 480;
190   snd_pcm_uframes_t buffer_size = 48000;
191   struct timespec tstamp;
192   int rc;
193   const char* dev_name = "dev_name";
194 
195   ResetStubData();
196   snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames + 1;
197   rc = cras_alsa_get_avail_frames(mock_handle, buffer_size,
198                                   severe_underrun_frames, dev_name, &avail,
199                                   &tstamp);
200   // Returns -EPIPE when severe underrun happens.
201   EXPECT_EQ(rc, -EPIPE);
202 
203   ResetStubData();
204   snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames;
205   rc = cras_alsa_get_avail_frames(mock_handle, buffer_size,
206                                   severe_underrun_frames, dev_name, &avail,
207                                   &tstamp);
208   // Underrun which is not severe enough will be masked.
209   // avail will be adjusted to buffer_size.
210   EXPECT_EQ(avail, buffer_size);
211   EXPECT_EQ(rc, 0);
212 
213   ResetStubData();
214   snd_pcm_htimestamp_avail_ret_val = buffer_size - 1;
215   rc = cras_alsa_get_avail_frames(mock_handle, buffer_size,
216                                   severe_underrun_frames, dev_name, &avail,
217                                   &tstamp);
218   // When avail < buffer_size, there is no underrun.
219   EXPECT_EQ(avail, buffer_size - 1);
220   EXPECT_EQ(rc, 0);
221 }
222 }  // namespace
223 
224 extern "C" {
225 
snd_pcm_sw_params_current(snd_pcm_t * pcm,snd_pcm_sw_params_t * params)226 int snd_pcm_sw_params_current(snd_pcm_t* pcm, snd_pcm_sw_params_t* params) {
227   return 0;
228 }
229 
snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t * params,snd_pcm_uframes_t * val)230 int snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t* params,
231                                    snd_pcm_uframes_t* val) {
232   return 0;
233 }
234 
snd_pcm_sw_params_set_stop_threshold(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_uframes_t val)235 int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t* pcm,
236                                          snd_pcm_sw_params_t* params,
237                                          snd_pcm_uframes_t val) {
238   return 0;
239 }
240 
snd_pcm_sw_params_set_start_threshold(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_uframes_t val)241 int snd_pcm_sw_params_set_start_threshold(snd_pcm_t* pcm,
242                                           snd_pcm_sw_params_t* params,
243                                           snd_pcm_uframes_t val) {
244   return 0;
245 }
246 
snd_pcm_sw_params_set_period_event(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,int val)247 int snd_pcm_sw_params_set_period_event(snd_pcm_t* pcm,
248                                        snd_pcm_sw_params_t* params,
249                                        int val) {
250   return 0;
251 }
252 
snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_tstamp_t val)253 int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t* pcm,
254                                       snd_pcm_sw_params_t* params,
255                                       snd_pcm_tstamp_t val) {
256   snd_pcm_sw_params_set_tstamp_mode_called++;
257   return 0;
258 }
259 
snd_pcm_sw_params_set_tstamp_type(snd_pcm_t * pcm,snd_pcm_sw_params_t * params,snd_pcm_tstamp_type_t val)260 int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t* pcm,
261                                       snd_pcm_sw_params_t* params,
262                                       snd_pcm_tstamp_type_t val) {
263   snd_pcm_sw_params_set_tstamp_type_called++;
264   return 0;
265 }
266 
snd_pcm_sw_params(snd_pcm_t * pcm,snd_pcm_sw_params_t * params)267 int snd_pcm_sw_params(snd_pcm_t* pcm, snd_pcm_sw_params_t* params) {
268   int rc;
269 
270   if (snd_pcm_sw_params_ret_vals.size() == 0)
271     return 0;
272   rc = snd_pcm_sw_params_ret_vals.back();
273   snd_pcm_sw_params_ret_vals.pop_back();
274   return rc;
275 }
276 
snd_pcm_avail(snd_pcm_t * pcm)277 snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t* pcm) {
278   return snd_pcm_htimestamp_avail_ret_val;
279 }
280 
snd_pcm_htimestamp(snd_pcm_t * pcm,snd_pcm_uframes_t * avail,snd_htimestamp_t * tstamp)281 int snd_pcm_htimestamp(snd_pcm_t* pcm,
282                        snd_pcm_uframes_t* avail,
283                        snd_htimestamp_t* tstamp) {
284   *avail = snd_pcm_htimestamp_avail_ret_val;
285   *tstamp = snd_pcm_htimestamp_tstamp_ret_val;
286   return 0;
287 }
288 }
289 
main(int argc,char ** argv)290 int main(int argc, char** argv) {
291   ::testing::InitGoogleTest(&argc, argv);
292   return RUN_ALL_TESTS();
293 }
294