• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "alsa_soundcard.h"
17 #include "alsa_snd_render.h"
18 #include "osal_time.h"
19 
20 #define HDF_LOG_TAG HDF_AUDIO_HAL_RENDER
21 
22 #define MAX_PERIOD_SIZE                (8 * 1024)
23 #define MIN_PERIOD_SIZE                (4 * 1024)
24 #define AUDIO_RENDER_RECOVER_DELAY     (10 * 1000)
25 #define POLL_EVENT_DEF false
26 #define AUDIO_BUFFER_TIME_DEF 500000
27 #define AUDIO_PERIOD_TIME_DEF 100000
28 #define AUDIO_PERIOD_TIME_RATIO 4
29 #define BIT_COUNT_OF_BYTE       8
30 #define PCM_WAIT_TIMEOUT_MS     100
31 #ifdef SUPPORT_ALSA_CHMAP
32 #define CHMAP_NAME_LENGHT_MAX      256
33 
34 /* channel map list type */
35 #define CHANNEL_MAP_TYPE_FIXED    "FIXED"  /* fixed channel position */
36 #define CHANNEL_MAP_TYPE_VAR      "VAR"    /* freely swappable channel position */
37 #define CHANNEL_MAP_TYPE_PAIRED   "PAIRED" /* pair-wise swappable channel position */
38 #endif
39 
40 static struct AlsaRender *g_alsaRenderList = NULL;
41 static void RegisterRenderImpl(struct AlsaRender *renderIns);
42 
RenderSetPriData(struct AlsaRender * renderIns,RenderPriData data)43 void RenderSetPriData(struct AlsaRender *renderIns, RenderPriData data)
44 {
45     renderIns->priData = data;
46 }
47 
RenderGetPriData(struct AlsaRender * renderIns)48 RenderPriData RenderGetPriData(struct AlsaRender *renderIns)
49 {
50     return renderIns->priData;
51 }
52 
CreateRenderIns(void)53 static int32_t CreateRenderIns(void)
54 {
55     if (g_alsaRenderList == NULL) {
56         g_alsaRenderList = (struct AlsaRender *)OsalMemCalloc(MAX_CARD_NUM * sizeof(struct AlsaRender));
57         if (g_alsaRenderList == NULL) {
58             AUDIO_FUNC_LOGE("Failed to allocate memory!");
59             return HDF_FAILURE;
60         }
61     }
62     return HDF_SUCCESS;
63 }
64 
RenderFreeMemory(void)65 static int32_t RenderFreeMemory(void)
66 {
67     int32_t i;
68 
69     if (g_alsaRenderList != NULL) {
70         for (i = 0; i < MAX_CARD_NUM; i++) {
71             if (g_alsaRenderList[i].soundCard.cardStatus != 0) {
72                 AUDIO_FUNC_LOGE("refCount is not zero, Sound card in use!");
73                 return HDF_ERR_DEVICE_BUSY;
74             }
75 
76             if (g_alsaRenderList[i].priData != NULL) {
77                 OsalMemFree(g_alsaRenderList[i].priData);
78                 g_alsaRenderList[i].priData = NULL;
79             }
80         }
81         AudioMemFree((void **)&g_alsaRenderList);
82         g_alsaRenderList = NULL;
83     }
84 
85     return HDF_SUCCESS;
86 }
87 
SetHWParamsSub(snd_pcm_t * handle,snd_pcm_hw_params_t * params,const struct AudioPcmHwParams * hwParams,snd_pcm_access_t access)88 static int32_t SetHWParamsSub(
89     snd_pcm_t *handle, snd_pcm_hw_params_t *params, const struct AudioPcmHwParams *hwParams, snd_pcm_access_t access)
90 {
91     int32_t ret;
92     snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_S16_LE;
93     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
94     CHECK_NULL_PTR_RETURN_DEFAULT(params);
95 
96     /* set hardware resampling,enable alsa-lib resampling */
97     ret = snd_pcm_hw_params_set_rate_resample(handle, params, 1);
98     if (ret < 0) {
99         AUDIO_FUNC_LOGE("Resampling setup failed for playback: %{public}s", snd_strerror(ret));
100         return HDF_FAILURE;
101     }
102     /* set the interleaved read/write format */
103     ret = snd_pcm_hw_params_set_access(handle, params, access);
104     if (ret < 0) {
105         AUDIO_FUNC_LOGE("Access type not available for playback: %{public}s", snd_strerror(ret));
106         return HDF_FAILURE;
107     }
108     ret = SndConverAlsaPcmFormat(hwParams, &pcmFormat);
109     if (ret < 0) {
110         AUDIO_FUNC_LOGE("SndConverAlsaPcmFormat error.");
111         return HDF_FAILURE;
112     }
113     /* set the sample format */
114     ret = snd_pcm_hw_params_set_format(handle, params, pcmFormat);
115     if (ret < 0) {
116         AUDIO_FUNC_LOGE("Sample format not available for playback: %{public}s, format: %{public}d",
117             snd_strerror(ret), pcmFormat);
118         return HDF_FAILURE;
119     }
120     /* set the count of channels */
121     ret = snd_pcm_hw_params_set_channels(handle, params, hwParams->channels);
122     if (ret < 0) {
123         AUDIO_FUNC_LOGE("Channels count (%{public}u) not available for playbacks: %{public}s", hwParams->channels,
124             snd_strerror(ret));
125         return HDF_FAILURE;
126     }
127 
128     return HDF_SUCCESS;
129 }
130 
SetHWRate(snd_pcm_t * handle,snd_pcm_hw_params_t * params,uint32_t * rate)131 static int32_t SetHWRate(snd_pcm_t *handle, snd_pcm_hw_params_t *params, uint32_t *rate)
132 {
133     int32_t ret;
134     uint32_t rRate;
135     int dir = 0; /* dir Value range (-1,0,1) */
136     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
137     CHECK_NULL_PTR_RETURN_DEFAULT(params);
138     CHECK_NULL_PTR_RETURN_DEFAULT(rate);
139 
140     /* set the stream rate */
141     rRate = *rate;
142     ret = snd_pcm_hw_params_set_rate_near(handle, params, &rRate, &dir);
143     if (ret < 0) {
144         AUDIO_FUNC_LOGE("Rate %{public}uHz not available for playback: %{public}s.", *rate, snd_strerror(ret));
145         return HDF_FAILURE;
146     }
147 
148     if (rRate != *rate) {
149         ret = snd_pcm_hw_params_set_rate_near(handle, params, &rRate, &dir);
150         if (ret < 0) {
151             AUDIO_FUNC_LOGE("Rate %{public}uHz not available for playback: %{public}s.", *rate, snd_strerror(ret));
152             return HDF_FAILURE;
153         }
154     }
155     /* Update to hardware supported rate */
156     *rate = rRate;
157 
158     return HDF_SUCCESS;
159 }
160 
SetHWParams(struct AlsaSoundCard * cardIns,snd_pcm_access_t access)161 static int32_t SetHWParams(struct AlsaSoundCard *cardIns, snd_pcm_access_t access)
162 {
163     int dir = 0; /* dir Value range (-1,0,1) */
164     snd_pcm_uframes_t size;
165     snd_pcm_hw_params_t *hwParams = NULL;
166     struct AlsaRender *renderIns = (struct AlsaRender*)cardIns;
167     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns->pcmHandle);
168 
169     snd_pcm_hw_params_alloca(&hwParams);
170     if (snd_pcm_hw_params_any(cardIns->pcmHandle, hwParams) < 0) {
171         AUDIO_FUNC_LOGE("No configurations available");
172         return HDF_FAILURE;
173     }
174     if (SetHWParamsSub(cardIns->pcmHandle, hwParams, &cardIns->hwParams, access) != HDF_SUCCESS) {
175         AUDIO_FUNC_LOGE("SetHWParamsSub failed!");
176         return HDF_FAILURE;
177     }
178     if (SetHWRate(cardIns->pcmHandle, hwParams, &(cardIns->hwParams.rate)) != HDF_SUCCESS) {
179         AUDIO_FUNC_LOGE("SetHWRate failed!");
180         return HDF_FAILURE;
181     }
182     snd_pcm_hw_params_get_buffer_time_max(hwParams, &renderIns->bufferTime, &dir);
183     if (renderIns->bufferTime > AUDIO_BUFFER_TIME_DEF) {
184         renderIns->bufferTime = AUDIO_BUFFER_TIME_DEF;
185     }
186     renderIns->periodTime = renderIns->bufferTime / AUDIO_PERIOD_TIME_RATIO;
187     if (snd_pcm_hw_params_set_buffer_time_near(cardIns->pcmHandle, hwParams, &renderIns->bufferTime, &dir) < 0) {
188         AUDIO_FUNC_LOGE("Set buffer time %{public}u failed", renderIns->bufferTime);
189         return HDF_FAILURE;
190     }
191     if (snd_pcm_hw_params_get_buffer_size(hwParams, &size) < 0) {
192         AUDIO_FUNC_LOGE("Unable to get buffer size for playback");
193         return HDF_FAILURE;
194     }
195     renderIns->bufferSize = size;
196     if (snd_pcm_hw_params_set_period_time_near(cardIns->pcmHandle, hwParams, &renderIns->periodTime, &dir) < 0) {
197         AUDIO_FUNC_LOGE("Set period time %{public}u failed", renderIns->bufferTime);
198         return HDF_FAILURE;
199     }
200     if (snd_pcm_hw_params_get_period_size(hwParams, &size, &dir) < 0) {
201         AUDIO_FUNC_LOGE("Unable to get period size for playback");
202         return HDF_FAILURE;
203     }
204     renderIns->periodSize = size;
205     if (snd_pcm_hw_params(cardIns->pcmHandle, hwParams) < 0) {
206         AUDIO_FUNC_LOGE("Unable to set hw params for playback");
207         return HDF_FAILURE;
208     }
209 
210     cardIns->canPause = snd_pcm_hw_params_can_pause(hwParams);
211     return HDF_SUCCESS;
212 }
213 
SetSWParams(struct AlsaSoundCard * cardIns)214 static int32_t SetSWParams(struct AlsaSoundCard *cardIns)
215 {
216     int32_t ret;
217     int32_t val = 1; /* val 0 = disable period event, 1 = enable period event */
218     snd_pcm_sw_params_t *swParams = NULL;
219     snd_pcm_t *handle = cardIns->pcmHandle;
220     struct AlsaRender *renderIns = (struct AlsaRender *)cardIns;
221     CHECK_NULL_PTR_RETURN_DEFAULT(handle);
222 
223     snd_pcm_sw_params_alloca(&swParams);
224 
225     /* get the current swparams */
226     ret = snd_pcm_sw_params_current(handle, swParams);
227     if (ret < 0) {
228         AUDIO_FUNC_LOGE("Unable to determine current swparams for playback: %{public}s", snd_strerror(ret));
229         return HDF_FAILURE;
230     }
231     /* start the transfer when the buffer is almost full: */
232     /* (buffer_size / avail_min) * avail_min */
233     if (renderIns->periodSize == 0) {
234         AUDIO_FUNC_LOGE("g_periodSize=0");
235         return HDF_FAILURE;
236     }
237     ret = snd_pcm_sw_params_set_start_threshold(handle, swParams,
238         (renderIns->bufferSize / renderIns->periodSize) * renderIns->periodSize);
239     if (ret < 0) {
240         AUDIO_FUNC_LOGE("Unable to set start threshold mode for playback: %{public}s", snd_strerror(ret));
241         return HDF_FAILURE;
242     }
243     /* allow the transfer when at least period_size samples can be processed */
244     /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
245     ret = snd_pcm_sw_params_set_avail_min(handle, swParams,
246         renderIns->periodEvent ? renderIns->bufferSize : renderIns->periodSize);
247     if (ret < 0) {
248         AUDIO_FUNC_LOGE("Unable to set avail min for playback: %{public}s", snd_strerror(ret));
249         return HDF_FAILURE;
250     }
251 
252     /* enable period events when requested */
253     if (renderIns->periodEvent) {
254         ret = snd_pcm_sw_params_set_period_event(handle, swParams, val);
255         if (ret < 0) {
256             AUDIO_FUNC_LOGE("Unable to set period event: %{public}s", snd_strerror(ret));
257             return HDF_FAILURE;
258         }
259     }
260 
261     /* write the parameters to the playback device */
262     ret = snd_pcm_sw_params(handle, swParams);
263     if (ret < 0) {
264         AUDIO_FUNC_LOGE("Unable to set sw params for playback: %{public}s", snd_strerror(ret));
265         return HDF_FAILURE;
266     }
267 
268     return HDF_SUCCESS;
269 }
270 
ResetRenderParams(struct AlsaSoundCard * cardIns,snd_pcm_access_t access)271 static int32_t ResetRenderParams(struct AlsaSoundCard *cardIns, snd_pcm_access_t access)
272 {
273     int32_t ret;
274     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
275 
276     ret = SetHWParams(cardIns, access);
277     if (ret != HDF_SUCCESS) {
278         AUDIO_FUNC_LOGE("Setting of hwparams failed.");
279         return ret;
280     }
281 
282     ret = SetSWParams(cardIns);
283     if (ret != HDF_SUCCESS) {
284         AUDIO_FUNC_LOGE("Setting of swparams failed.");
285         return ret;
286     }
287 
288     return HDF_SUCCESS;
289 }
290 
GetRenderInsByName(const char * adapterName)291 static struct AlsaRender *GetRenderInsByName(const char *adapterName)
292 {
293     int32_t ret;
294     int32_t i;
295     struct AlsaRender *renderIns = NULL;
296     struct AlsaSoundCard *alsaSnd = NULL;
297 
298     /*
299     fine the instance with the corresponding adapter name, or create one if none.
300     */
301     for (i = 0; i < MAX_CARD_NUM; i++) {
302         alsaSnd = (struct AlsaSoundCard *)&g_alsaRenderList[i];
303         if (alsaSnd->cardStatus) {
304             if (0 == strcmp(alsaSnd->adapterName, adapterName)) {
305                 return &g_alsaRenderList[i];
306             }
307         }
308     }
309 
310     for (i = 0; i < MAX_CARD_NUM; i++) {
311         renderIns = &g_alsaRenderList[i];
312         alsaSnd = (struct AlsaSoundCard *)&g_alsaRenderList[i];
313         if (alsaSnd->cardStatus == 0) {
314             (void)memset_s(renderIns, sizeof(struct AlsaRender), 0, sizeof(struct AlsaRender));
315             ret = strncpy_s(alsaSnd->adapterName, MAX_CARD_NAME_LEN + 1, adapterName, strlen(adapterName));
316             if (ret != 0) {
317                 AUDIO_FUNC_LOGE("strncpy_s failed!");
318                 return NULL;
319             }
320             alsaSnd->cardStatus++;
321             renderIns->periodEvent = POLL_EVENT_DEF;
322             renderIns->periodTime = AUDIO_PERIOD_TIME_DEF;
323             renderIns->bufferTime = AUDIO_BUFFER_TIME_DEF;
324             renderIns->descPins = PIN_NONE;
325             renderIns->resample = 1;
326             return renderIns;
327         }
328     }
329     AUDIO_FUNC_LOGE("Failed to AddCardIns!");
330     return NULL;
331 }
332 
RenderCreateInstance(const char * adapterName)333 struct AlsaRender *RenderCreateInstance(const char* adapterName)
334 {
335     int32_t ret;
336     struct AlsaRender *renderIns = NULL;
337     if (adapterName == NULL || strlen(adapterName) == 0) {
338         AUDIO_FUNC_LOGE("Invalid adapterName!");
339         return NULL;
340     }
341 
342     ret = CreateRenderIns();
343     if (ret != HDF_SUCCESS) {
344         AUDIO_FUNC_LOGE("Failed to create render instance.");
345         return NULL;
346     }
347 
348     renderIns = GetRenderInsByName(adapterName);
349     if (renderIns == NULL) {
350         AUDIO_FUNC_LOGE("get render instance failed.");
351         return NULL;
352     }
353     RegisterRenderImpl(renderIns);
354 
355     ret = SndSaveCardListInfo(SND_PCM_STREAM_PLAYBACK);
356     if (ret != HDF_SUCCESS) {
357         AUDIO_FUNC_LOGE("Failed to save card device info.");
358         return NULL;
359     }
360 
361     ret = SndMatchSelAdapter(&renderIns->soundCard, adapterName);
362     if (ret != HDF_SUCCESS) {
363         SndCloseHandle(&renderIns->soundCard);
364         RenderFreeMemory();
365         return NULL;
366     }
367 
368     RenderOverrideFunc(renderIns);
369     return renderIns;
370 }
371 
RenderGetInstance(const char * adapterName)372 struct AlsaRender *RenderGetInstance(const char *adapterName)
373 {
374     int32_t i;
375 
376     if (adapterName == NULL || strlen(adapterName) == 0) {
377         AUDIO_FUNC_LOGE("Invalid adapterName!");
378         return NULL;
379     }
380 
381     if (g_alsaRenderList == NULL) {
382         AUDIO_FUNC_LOGE("g_alsaRenderList is NULL!");
383         return NULL;
384     }
385 
386     for (i = 0; i < MAX_CARD_NUM; i++) {
387         if (strcmp(g_alsaRenderList[i].soundCard.adapterName, adapterName) == 0) {
388             return &(g_alsaRenderList[i]);
389         }
390     }
391 
392     return NULL;
393 }
394 
395 #ifdef SUPPORT_ALSA_CHMAP
GetChannelsNameFromUser(struct AlsaSoundCard * cardIns,const char * channelsName)396 static int32_t GetChannelsNameFromUser(struct AlsaSoundCard *cardIns, const char *channelsName)
397 {
398     if (channelsName == NULL) {
399         AUDIO_FUNC_LOGE("channelsName is NULL!");
400         return HDF_ERR_INVALID_PARAM;
401     }
402 
403     if (cardIns->hwParams.channelsName == NULL) {
404         cardIns->hwParams.channelsName = (char *)OsalMemCalloc(CHMAP_NAME_LENGHT_MAX);
405         if (cardIns->hwParams.channelsName == NULL) {
406             AUDIO_FUNC_LOGE("Failed to allocate memory!");
407             return HDF_ERR_MALLOC_FAIL;
408         }
409     }
410 
411     (void)memset_s(cardIns->hwParams.channelsName, CHMAP_NAME_LENGHT_MAX, 0, CHMAP_NAME_LENGHT_MAX);
412     int32_t ret = strncpy_s(cardIns->hwParams.channelsName, CHMAP_NAME_LENGHT_MAX - 1,
413         channelsName, strlen(channelsName));
414     if (ret != HDF_SUCCESS) {
415         AUDIO_FUNC_LOGE("strncpy_s failed!");
416         AudioMemFree((void **)&(cardIns->hwParams.channelsName));
417         return HDF_FAILURE;
418     }
419 
420     return HDF_SUCCESS;
421 }
422 #endif
423 
SaveHwParams(struct AlsaSoundCard * cardIns,const struct AudioHwRenderParam * handleData)424  static int32_t SaveHwParams(struct AlsaSoundCard *cardIns, const struct AudioHwRenderParam *handleData)
425 {
426     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
427     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
428 
429     cardIns->hwParams.streamType = AUDIO_RENDER_STREAM;
430     cardIns->hwParams.channels = handleData->frameRenderMode.attrs.channelCount;
431     cardIns->hwParams.rate = handleData->frameRenderMode.attrs.sampleRate;
432     cardIns->hwParams.periodSize = handleData->frameRenderMode.periodSize;
433     cardIns->hwParams.periodCount = handleData->frameRenderMode.periodCount;
434     cardIns->hwParams.format = handleData->frameRenderMode.attrs.format;
435     cardIns->hwParams.period = handleData->frameRenderMode.attrs.period;
436     cardIns->hwParams.frameSize = handleData->frameRenderMode.attrs.frameSize;
437     cardIns->hwParams.isBigEndian = handleData->frameRenderMode.attrs.isBigEndian;
438     cardIns->hwParams.isSignedData = handleData->frameRenderMode.attrs.isSignedData;
439     cardIns->hwParams.startThreshold = handleData->frameRenderMode.attrs.startThreshold;
440     cardIns->hwParams.stopThreshold = handleData->frameRenderMode.attrs.stopThreshold;
441     cardIns->hwParams.silenceThreshold = handleData->frameRenderMode.attrs.silenceThreshold;
442 #ifdef SUPPORT_ALSA_CHMAP
443     /* param 2 by handleData->frameRenderMode.attrs.channelsName, sample channelsName is "FL, FR" */
444     if (GetChannelsNameFromUser(cardIns, "FL, FR") != HDF_SUCCESS) {
445         AUDIO_FUNC_LOGE("GetChannelsNameFromUser failed");
446         return HDF_FAILURE;
447     }
448 #endif
449 
450     return HDF_SUCCESS;
451 }
452 
453 #ifdef SUPPORT_ALSA_CHMAP
PrintChannels(const snd_pcm_chmap_t * map)454 static void PrintChannels(const snd_pcm_chmap_t *map)
455 {
456     char tmp[CHMAP_NAME_LENGHT_MAX] = {0};
457     if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0) {
458         HDF_LOGI("print_channels: %{public}s.", tmp);
459     }
460 }
461 
QueryChmaps(snd_pcm_t * pcm)462 static int32_t QueryChmaps(snd_pcm_t *pcm)
463 {
464     snd_pcm_chmap_query_t **pChmap = NULL;
465     snd_pcm_chmap_query_t *chmap = NULL;
466     const char *champType = NULL;
467     snd_pcm_chmap_query_t **hwChmap = snd_pcm_query_chmaps(pcm);
468     if (hwChmap == NULL) {
469         AUDIO_FUNC_LOGE("This sound card has no chmap component, cannot query maps.");
470         return HDF_FAILURE;
471     }
472 
473     for (pChmap = hwChmap; (chmap = *pChmap) != NULL; pChmap++) {
474         champType = snd_pcm_chmap_type_name(chmap->type);
475         HDF_LOGI("Channel Type = %{public}s, Channels = %{public}d.", champType, chmap->map.channels);
476         if (strncmp(champType, CHANNEL_MAP_TYPE_FIXED, strlen(CHANNEL_MAP_TYPE_FIXED)) == 0) {
477             HDF_LOGW("Fixed channel type does not support modification temporarily!");
478         }
479         PrintChannels(&chmap->map);
480     }
481 
482     snd_pcm_free_chmaps(hwChmap);
483     return HDF_SUCCESS;
484 }
485 
SetChmap(snd_pcm_t * pcm,struct AudioPcmHwParams * hwRenderParams)486 static int32_t SetChmap(snd_pcm_t *pcm, struct AudioPcmHwParams *hwRenderParams)
487 {
488     if (hwRenderParams == NULL || hwRenderParams->channelsName == NULL) {
489         AUDIO_FUNC_LOGE("Parameter is NULL!");
490         return HDF_FAILURE;
491     }
492 
493     snd_pcm_chmap_t *chmap = snd_pcm_chmap_parse_string(hwRenderParams->channelsName);
494     if (chmap == NULL) {
495         AUDIO_FUNC_LOGE("parse chmap error!");
496         return HDF_FAILURE;
497     }
498 
499     if (snd_pcm_set_chmap(pcm, chmap) < 0) {
500         AUDIO_FUNC_LOGE("Cannot set chmap!");
501         free((void *)chmap);
502         return HDF_ERR_NOT_SUPPORT;
503     }
504     free((void *)chmap);
505 
506     chmap = snd_pcm_get_chmap(pcm);
507     if (chmap == NULL) {
508         AUDIO_FUNC_LOGE("Cannot get chmap!");
509         return HDF_ERR_NOT_SUPPORT;
510     }
511 
512     PrintChannels(chmap);
513     free((void *)chmap);
514     return HDF_SUCCESS;
515 }
516 
RenderHwParamsChmaps(struct AlsaSoundCard * cardIns)517 static int32_t RenderHwParamsChmaps(struct AlsaSoundCard *cardIns)
518 {
519     if (QueryChmaps(cardIns->pcmHandle) != HDF_SUCCESS) {
520         AUDIO_FUNC_LOGW("QueryChmaps failed.");
521         return HDF_SUCCESS;
522     }
523     if (SetChmap(cardIns->pcmHandle, &cardIns->hwParams) != HDF_SUCCESS) {
524         AUDIO_FUNC_LOGW("SetChmap failed.");
525     }
526 
527     return HDF_SUCCESS;
528 }
529 #endif
530 
RenderSetParams(struct AlsaRender * renderIns,const struct AudioHwRenderParam * handleData)531 int32_t RenderSetParams(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
532 {
533     int32_t ret;
534     int bitsPerSample;
535     snd_pcm_format_t fmt;
536     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
537     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
538     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
539 
540     SaveHwParams(&renderIns->soundCard, handleData);
541     ret = SetHWParams(cardIns, SND_PCM_ACCESS_RW_INTERLEAVED);
542     if (ret < 0) {
543         AUDIO_FUNC_LOGE("Setting of hwparams failed.");
544         return HDF_FAILURE;
545     }
546 
547     ret = SetSWParams(cardIns);
548     if (ret < 0) {
549         AUDIO_FUNC_LOGE("Setting of swparams failed.");
550         return HDF_FAILURE;
551     }
552 
553 #ifdef SUPPORT_ALSA_CHMAP
554     ret = RenderHwParamsChmaps(&renderIns->soundCard);
555     if (ret < 0) {
556         AUDIO_FUNC_LOGE("Setting of chmaps failed.");
557     }
558 #endif
559 
560     SndConverAlsaPcmFormat(&cardIns->hwParams, &fmt);
561     bitsPerSample = snd_pcm_format_physical_width(fmt);
562     cardIns->hwParams.bitsPerFrame = bitsPerSample * cardIns->hwParams.channels;
563 
564     return HDF_SUCCESS;
565 }
566 
RenderWritei(snd_pcm_t * pcm,const struct AudioHwRenderParam * handleData,const struct AudioPcmHwParams * hwParams)567 static int32_t RenderWritei(snd_pcm_t *pcm, const struct AudioHwRenderParam *handleData,
568     const struct AudioPcmHwParams *hwParams)
569 {
570     int32_t ret, offset;
571     long frames;
572     char *dataBuf;
573     size_t sbufFrameSize;
574     snd_pcm_state_t state;
575     int32_t tryNum = AUDIO_ALSALIB_RETYR;
576 
577     /* Check whether the PCM status is normal */
578     state = snd_pcm_state(pcm);
579     if (state == SND_PCM_STATE_SETUP) {
580         ret = snd_pcm_prepare(pcm);
581         if (ret < 0) {
582             AUDIO_FUNC_LOGE("snd_pcm_prepare fail: %{public}s", snd_strerror(ret));
583             return HDF_FAILURE;
584         }
585     }
586 
587     sbufFrameSize = (size_t)handleData->frameRenderMode.bufferFrameSize;
588     dataBuf = handleData->frameRenderMode.buffer;
589     offset = hwParams->bitsPerFrame / BIT_COUNT_OF_BYTE;
590     while (sbufFrameSize > 0) {
591         frames = snd_pcm_writei(pcm, dataBuf, sbufFrameSize);
592         if (frames > 0) {
593             sbufFrameSize -= frames;
594             dataBuf += frames * offset;
595         } else if (frames == -EAGAIN) {
596             snd_pcm_wait(pcm, PCM_WAIT_TIMEOUT_MS);
597             tryNum--;
598             if (tryNum == 0) {
599                 return HDF_SUCCESS;
600             }
601         } else if (frames == -EBADFD) {
602             /* not #SND_PCM_STATE_PREPARED or #SND_PCM_STATE_RUNNING */
603             AUDIO_FUNC_LOGE("render PCM is not in the right state: %{public}s", snd_strerror(frames));
604             snd_pcm_prepare(pcm);
605             return HDF_FAILURE;
606         } else {
607             /* -ESTRPIPE: a suspend event occurred,
608              * stream is suspended and waiting for an application recovery.
609              * -EPIPE: an underrun occurred.
610              */
611             AUDIO_FUNC_LOGI("err: %{public}s", snd_strerror(ret));
612             ret = snd_pcm_recover(pcm, frames, 0); // 0 for open render recover log.
613             if (ret < 0) {
614                 AUDIO_FUNC_LOGE("snd_pcm_writei failed: %{public}s", snd_strerror(ret));
615                 return HDF_FAILURE;
616             }
617         }
618     }
619 
620     return HDF_SUCCESS;
621 }
622 
WriteiMmap(uint32_t loopTimes,uint32_t lastBuffSize,uint32_t frameSize,struct AlsaSoundCard * cardIns,struct AudioMmapBufferDescriptor * mmapBufDesc)623 static int32_t WriteiMmap(uint32_t loopTimes, uint32_t lastBuffSize, uint32_t frameSize,
624     struct AlsaSoundCard *cardIns, struct AudioMmapBufferDescriptor *mmapBufDesc)
625 {
626     int32_t ret;
627     uint32_t looper = 0;
628     int32_t count = 0;
629     uint32_t copyLen;
630     while (looper < loopTimes) {
631         copyLen = (looper < (loopTimes - 1)) ? MIN_PERIOD_SIZE : lastBuffSize;
632         snd_pcm_uframes_t frames = (snd_pcm_uframes_t)(copyLen / frameSize);
633         ret = snd_pcm_mmap_writei(
634             cardIns->pcmHandle, (char *)mmapBufDesc->memoryAddress + mmapBufDesc->offset, frames);
635         if (ret == -EAGAIN) {
636             count++;
637             if (count > AUDIO_ALSALIB_MMAP_MAX) {
638                 AUDIO_FUNC_LOGE("loop > max !");
639                 return HDF_FAILURE;
640             }
641             continue;
642         }
643         count = 0;
644         if (ret < 0) {
645             AUDIO_FUNC_LOGE("Write error: %{public}s\n", snd_strerror(ret));
646             return HDF_FAILURE;
647         }
648         looper++;
649         mmapBufDesc->offset += copyLen;
650         cardIns->mmapFrames += (uint64_t)frames;
651     }
652     return HDF_SUCCESS;
653 }
654 
RenderWriteiMmap(struct AlsaSoundCard * cardIns,const struct AudioHwRenderParam * handleData)655 static int32_t RenderWriteiMmap(struct AlsaSoundCard *cardIns, const struct AudioHwRenderParam *handleData)
656 {
657     int32_t ret;
658     uint32_t frameSize;
659     uint32_t totalSize;
660     uint32_t lastBuffSize;
661     uint32_t loopTimes;
662     struct AudioMmapBufferDescriptor *mmapBufDesc = NULL;
663     CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
664     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
665 
666     cardIns->mmapFlag = false;
667     ret = ResetRenderParams(cardIns, SND_PCM_ACCESS_MMAP_INTERLEAVED);
668     if (ret < 0) {
669         AUDIO_FUNC_LOGE("AudioSetParamsMmap failed!");
670         return HDF_FAILURE;
671     }
672 
673     frameSize = cardIns->hwParams.channels * cardIns->hwParams.format;
674     if (frameSize == 0) {
675         AUDIO_FUNC_LOGE("frame size = 0!");
676         return HDF_FAILURE;
677     }
678     mmapBufDesc = (struct AudioMmapBufferDescriptor *)&(handleData->frameRenderMode.mmapBufDesc);
679     totalSize = (uint32_t)mmapBufDesc->totalBufferFrames * frameSize;
680     lastBuffSize = ((totalSize % MIN_PERIOD_SIZE) == 0) ? MIN_PERIOD_SIZE : (totalSize % MIN_PERIOD_SIZE);
681     loopTimes = (lastBuffSize == MIN_PERIOD_SIZE) ? (totalSize / MIN_PERIOD_SIZE) : (totalSize / MIN_PERIOD_SIZE + 1);
682 
683     return WriteiMmap(loopTimes, lastBuffSize, frameSize, cardIns, mmapBufDesc);
684 }
685 
RenderOpenImpl(struct AlsaRender * renderIns)686 static int32_t RenderOpenImpl(struct AlsaRender *renderIns)
687 {
688     int32_t ret;
689     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
690     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
691 
692     if (SndisBusy(&renderIns->soundCard)) {
693         AUDIO_FUNC_LOGE("Resource busy!!");
694         return HDF_ERR_DEVICE_BUSY;
695     }
696 
697     ret = snd_pcm_open(&cardIns->pcmHandle, cardIns->devName,
698         SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
699     if (ret < 0) {
700         AUDIO_FUNC_LOGE("snd_pcm_open fail: %{public}s!", snd_strerror(ret));
701         RenderFreeMemory();
702         return HDF_FAILURE;
703     }
704 
705     ret = snd_pcm_nonblock(cardIns->pcmHandle, 1);
706     if (ret < 0) {
707         AUDIO_FUNC_LOGE("snd_pcm_nonblock fail: %{public}s!", snd_strerror(ret));
708         SndCloseHandle(&renderIns->soundCard);
709         RenderFreeMemory();
710         return HDF_FAILURE;
711     }
712 
713     ret = SndOpenMixer(&renderIns->soundCard);
714     if (ret != HDF_SUCCESS) {
715         AUDIO_FUNC_LOGE("SndOpenMixer failed");
716         SndCloseHandle(&renderIns->soundCard);
717         RenderFreeMemory();
718         return HDF_FAILURE;
719     }
720 
721     return HDF_SUCCESS;
722 }
723 
RenderCloseImpl(struct AlsaRender * renderIns)724 static int32_t RenderCloseImpl(struct AlsaRender *renderIns)
725 {
726     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
727 #ifdef SUPPORT_ALSA_CHMAP
728     AudioMemFree((void **)&renderIns->soundCard.hwParams.channelsName);
729 #endif
730     SndCloseHandle(&renderIns->soundCard);
731     RenderFreeMemory();
732     return HDF_SUCCESS;
733 }
734 
RenderWriteImpl(struct AlsaRender * renderIns,const struct AudioHwRenderParam * handleData)735 int32_t RenderWriteImpl(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
736 {
737     int32_t ret;
738     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard*)renderIns;
739     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
740 
741     if (cardIns->pauseState) {
742         AUDIO_FUNC_LOGE("Currently in pause, please check!");
743         return HDF_FAILURE;
744     }
745 
746     if (!cardIns->mmapFlag) {
747         ret = ResetRenderParams(cardIns, SND_PCM_ACCESS_RW_INTERLEAVED);
748         if (ret < 0) {
749             AUDIO_FUNC_LOGE("ResetRenderParams failed!");
750             return HDF_FAILURE;
751         }
752         cardIns->mmapFlag = true;
753     }
754 
755     ret = RenderWritei(cardIns->pcmHandle, handleData, &cardIns->hwParams);
756     if (ret != HDF_SUCCESS) {
757         AUDIO_FUNC_LOGE("RenderWritei failed!");
758         return HDF_FAILURE;
759     }
760 
761     return HDF_SUCCESS;
762 }
763 
RenderGetMmapPositionImpl(struct AlsaRender * renderIns)764 int32_t RenderGetMmapPositionImpl(struct AlsaRender *renderIns)
765 {
766     return renderIns->soundCard.mmapFrames;
767 }
768 
RenderMmapWriteImpl(struct AlsaRender * renderIns,const struct AudioHwRenderParam * handleData)769 int32_t RenderMmapWriteImpl(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
770 {
771     int32_t ret;
772     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
773     CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
774     CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
775 
776     if (cardIns->pauseState) {
777         AUDIO_FUNC_LOGE("Currently in pause, please check!");
778         return HDF_FAILURE;
779     }
780 
781     cardIns->mmapFlag = false;
782     ret = ResetRenderParams(cardIns, SND_PCM_ACCESS_MMAP_INTERLEAVED);
783     if (ret < 0) {
784         AUDIO_FUNC_LOGE("ResetRenderParams failed!");
785         return HDF_FAILURE;
786     }
787 
788     ret = RenderWriteiMmap(cardIns, handleData);
789     if (ret < 0) {
790         AUDIO_FUNC_LOGE("RenderWriteiMmap error!");
791         return HDF_FAILURE;
792     }
793     return HDF_SUCCESS;
794 }
795 
RenderInitImpl(struct AlsaRender * renderIns)796 static int32_t RenderInitImpl(struct AlsaRender* renderIns)
797 {
798     AUDIO_FUNC_LOGE("Not yet realized");
799     return HDF_SUCCESS;
800 }
801 
RenderSelectSceneImpl(struct AlsaRender * renderIns,enum AudioPortPin descPins,const struct PathDeviceInfo * deviceInfo)802 static int32_t RenderSelectSceneImpl(struct AlsaRender *renderIns, enum AudioPortPin descPins,
803     const struct PathDeviceInfo *deviceInfo)
804 {
805     AUDIO_FUNC_LOGE("Not yet realized");
806     return HDF_SUCCESS;
807 }
808 
RenderStartImpl(struct AlsaRender * renderIns)809 static int32_t RenderStartImpl(struct AlsaRender *renderIns)
810 {
811     AUDIO_FUNC_LOGE("Not yet realized");
812     return HDF_SUCCESS;
813 }
814 
RenderStopImpl(struct AlsaRender * renderIns)815 static int32_t RenderStopImpl(struct AlsaRender *renderIns)
816 {
817     AUDIO_FUNC_LOGE("Not yet realized");
818     return HDF_SUCCESS;
819 }
820 
RenderGetVolThresholdImpl(struct AlsaRender * renderIns,long * volMin,long * volMax)821 static int32_t RenderGetVolThresholdImpl(struct AlsaRender *renderIns, long *volMin, long *volMax)
822 {
823     AUDIO_FUNC_LOGE("Not yet realized");
824     return HDF_SUCCESS;
825 }
826 
RenderGetVolumeImpl(struct AlsaRender * renderIns,long * volume)827 static int32_t RenderGetVolumeImpl(struct AlsaRender *renderIns, long *volume)
828 {
829     AUDIO_FUNC_LOGE("Not yet realized");
830     return HDF_SUCCESS;
831 }
832 
RenderSetVolumeImpl(struct AlsaRender * renderIns,long volume)833 static int32_t RenderSetVolumeImpl(struct AlsaRender *renderIns, long volume)
834 {
835     AUDIO_FUNC_LOGE("Not yet realized");
836     return HDF_SUCCESS;
837 }
838 
RenderGetGainThresholdImpl(struct AlsaRender * renderIns,float * gainMin,float * gainMax)839 static int32_t RenderGetGainThresholdImpl(struct AlsaRender *renderIns, float *gainMin, float *gainMax)
840 {
841     AUDIO_FUNC_LOGE("Not yet realized");
842     return HDF_SUCCESS;
843 }
844 
RenderGetGainImpl(struct AlsaRender * renderIns,float * volume)845 static int32_t RenderGetGainImpl(struct AlsaRender *renderIns, float *volume)
846 {
847     AUDIO_FUNC_LOGE("Not yet realized");
848     return HDF_SUCCESS;
849 }
850 
RenderSetGainImpl(struct AlsaRender * renderIns,float volume)851 static int32_t RenderSetGainImpl(struct AlsaRender *renderIns, float volume)
852 {
853     AUDIO_FUNC_LOGE("Not yet realized");
854     return HDF_SUCCESS;
855 }
856 
RenderGetMuteImpl(struct AlsaRender * renderIns)857 static bool RenderGetMuteImpl(struct AlsaRender *renderIns)
858 {
859     AUDIO_FUNC_LOGE("Not yet realized");
860     return false;
861 }
862 
RenderSetMuteImpl(struct AlsaRender * renderIns,bool muteFlag)863 static int32_t RenderSetMuteImpl(struct AlsaRender *renderIns, bool muteFlag)
864 {
865     AUDIO_FUNC_LOGE("Not yet realized");
866     return HDF_SUCCESS;
867 }
868 
RenderSetPauseStateImpl(struct AlsaRender * renderIns,bool pauseFlag)869 static int32_t RenderSetPauseStateImpl(struct AlsaRender *renderIns, bool pauseFlag)
870 {
871     int32_t ret;
872     int enable = pauseFlag ? AUDIO_ALSALIB_IOCTRL_PAUSE : AUDIO_ALSALIB_IOCTRL_RESUME;
873     struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
874 
875     if (cardIns->canPause) {
876         ret = snd_pcm_pause(cardIns->pcmHandle, enable);
877         if (ret < 0) {
878             AUDIO_FUNC_LOGE("snd_pcm_pause failed!");
879             return HDF_FAILURE;
880         }
881     } else {
882         if (enable == AUDIO_ALSALIB_IOCTRL_PAUSE) {
883             snd_pcm_drain(cardIns->pcmHandle);
884         } else {
885             snd_pcm_prepare(cardIns->pcmHandle);
886         }
887     }
888     cardIns->pauseState = pauseFlag;
889 
890     return HDF_SUCCESS;
891 }
892 
RenderGetChannelModeImpl(struct AlsaRender * renderIns,enum AudioChannelMode * mode)893 static int32_t RenderGetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode *mode)
894 {
895     AUDIO_FUNC_LOGE("Not yet realized");
896     return HDF_SUCCESS;
897 }
898 
RenderSetChannelModeImpl(struct AlsaRender * renderIns,enum AudioChannelMode mode)899 static int32_t RenderSetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode mode)
900 {
901     AUDIO_FUNC_LOGE("Not yet realized");
902     return HDF_SUCCESS;
903 }
904 
RegisterRenderImpl(struct AlsaRender * renderIns)905 static void RegisterRenderImpl(struct AlsaRender *renderIns)
906 {
907     if (renderIns == NULL) {
908         AUDIO_FUNC_LOGE("renderIns is NULL!");
909     }
910 
911     renderIns->Init = RenderInitImpl;
912     renderIns->Open = RenderOpenImpl;
913     renderIns->SelectScene = RenderSelectSceneImpl;
914     renderIns->Start = RenderStartImpl;
915     renderIns->Stop = RenderStopImpl;
916     renderIns->Close = RenderCloseImpl;
917     renderIns->Write = RenderWriteImpl;
918     renderIns->MmapWrite = RenderMmapWriteImpl;
919     renderIns->GetMmapPosition = RenderGetMmapPositionImpl;
920     renderIns->GetVolThreshold = RenderGetVolThresholdImpl;
921     renderIns->GetVolume = RenderGetVolumeImpl;
922     renderIns->SetVolume = RenderSetVolumeImpl;
923     renderIns->GetGainThreshold = RenderGetGainThresholdImpl;
924     renderIns->GetGain = RenderGetGainImpl;
925     renderIns->SetGain = RenderSetGainImpl;
926     renderIns->GetMute = RenderGetMuteImpl;
927     renderIns->SetMute = RenderSetMuteImpl;
928     renderIns->SetPauseState = RenderSetPauseStateImpl;
929     renderIns->GetChannelMode = RenderGetChannelModeImpl;
930     renderIns->SetChannelMode = RenderSetChannelModeImpl;
931 }
932 
933