summaryrefslogtreecommitdiff
path: root/amadec/audio_out/alsa-out.c (plain)
blob: 388e5161e28575aefef310be675af9925b9686fe
1/**
2 * \file alsa-out.c
3 * \brief Functions of Auduo output control for Linux Platform
4 * \version 1.0.0
5 * \date 2011-03-08
6 */
7/* Copyright (C) 2007-2011, Amlogic Inc.
8 * All right reserved
9 *
10 */
11#include <stdio.h>
12#include <stdlib.h>
13#include <fcntl.h>
14#include <sys/ioctl.h>
15#include <unistd.h>
16#include <linux/soundcard.h>
17//#include <config.h>
18#include <asoundlib.h>
19
20#include <audio-dec.h>
21#include <adec-pts-mgt.h>
22#include <log-print.h>
23#include <alsa-out.h>
24#include <amthreadpool.h>
25#include <cutils/properties.h>
26
27
28#define USE_INTERPOLATION
29
30static snd_pcm_sframes_t (*readi_func)(snd_pcm_t *handle, void *buffer, snd_pcm_uframes_t size);
31static snd_pcm_sframes_t (*writei_func)(snd_pcm_t *handle, const void *buffer, snd_pcm_uframes_t size);
32static snd_pcm_sframes_t (*readn_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
33static snd_pcm_sframes_t (*writen_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
34
35static float alsa_default_vol = 1.0;
36static int hdmi_out = 0;
37static int fragcount = 16;
38static snd_pcm_uframes_t chunk_size = 1024;
39static char output_buffer[64 * 1024];
40static unsigned char decode_buffer[OUTPUT_BUFFER_SIZE + 64];
41#define PERIOD_SIZE 1024
42#define PERIOD_NUM 4
43
44#ifdef USE_INTERPOLATION
45static int pass1_history[8][8];
46#pragma align_to(64,pass1_history)
47static int pass2_history[8][8];
48#pragma align_to(64,pass2_history)
49static short pass1_interpolation_output[0x4000];
50#pragma align_to(64,pass1_interpolation_output)
51static short interpolation_output[0x8000];
52#pragma align_to(64,interpolation_output)
53static int tv_mode = 0;
54static int getprop_bool(const char * path)
55{
56 char buf[PROPERTY_VALUE_MAX];
57 int ret = -1;
58 ret = property_get(path, buf, NULL);
59 if (ret > 0) {
60 if (strcasecmp(buf,"true") == 0 || strcmp(buf,"1") == 0)
61 return 1;
62 }
63 return 0;
64}
65static inline short CLIPTOSHORT(int x)
66{
67 short res;
68#if 0
69 __asm__ __volatile__(
70 "min r0, %1, 0x7fff\r\n"
71 "max r0, r0, -0x8000\r\n"
72 "mov %0, r0\r\n"
73 :"=r"(res)
74 :"r"(x)
75 :"r0"
76 );
77#else
78 if (x > 0x7fff) {
79 res = 0x7fff;
80 } else if (x < -0x8000) {
81 res = -0x8000;
82 } else {
83 res = x;
84 }
85#endif
86 return res;
87}
88
89static int set_sysfs_type(const char *path, const char *type)
90{
91 int ret = -1;
92 int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
93 if (fd >= 0) {
94 char set_type[10] = {0};
95 int length = snprintf(set_type, sizeof(set_type), "%s", type);
96 if (length > 0)
97 ret = write(fd, set_type, length);
98 adec_print("%s , %s\n", path, set_type);
99 close(fd);
100 }else{
101 adec_print("open hdmi-tx node:%s failed!\n", path);
102 }
103 return ret;
104}
105
106
107static void pcm_interpolation(int interpolation, unsigned num_channel, unsigned num_sample, short *samples)
108{
109 int i, k, l, ch;
110 int *s;
111 short *d;
112 for (ch = 0; ch < num_channel; ch++) {
113 s = pass1_history[ch];
114 if (interpolation < 2) {
115 d = interpolation_output;
116 } else {
117 d = pass1_interpolation_output;
118 }
119 for (i = 0, k = l = ch; i < num_sample; i++, k += num_channel) {
120 s[0] = s[1];
121 s[1] = s[2];
122 s[2] = s[3];
123 s[3] = s[4];
124 s[4] = s[5];
125 s[5] = samples[k];
126 d[l] = s[2];
127 l += num_channel;
128 d[l] = CLIPTOSHORT((150 * (s[2] + s[3]) - 25 * (s[1] + s[4]) + 3 * (s[0] + s[5]) + 128) >> 8);
129 l += num_channel;
130 }
131 if (interpolation >= 2) {
132 s = pass2_history[ch];
133 d = interpolation_output;
134 for (i = 0, k = l = ch; i < num_sample * 2; i++, k += num_channel) {
135 s[0] = s[1];
136 s[1] = s[2];
137 s[2] = s[3];
138 s[3] = s[4];
139 s[4] = s[5];
140 s[5] = pass1_interpolation_output[k];
141 d[l] = s[2];
142 l += num_channel;
143 d[l] = CLIPTOSHORT((150 * (s[2] + s[3]) - 25 * (s[1] + s[4]) + 3 * (s[0] + s[5]) + 128) >> 8);
144 l += num_channel;
145 }
146 }
147 }
148}
149#endif
150
151
152static int set_params(alsa_param_t *alsa_params)
153{
154 snd_pcm_hw_params_t *hwparams;
155 snd_pcm_sw_params_t *swparams;
156 // snd_pcm_uframes_t buffer_size;
157 // snd_pcm_uframes_t boundary;
158 // unsigned int period_time = 0;
159 // unsigned int buffer_time = 0;
160 snd_pcm_uframes_t bufsize;
161 int err;
162 unsigned int rate;
163 snd_pcm_uframes_t start_threshold, stop_threshold;
164 snd_pcm_hw_params_alloca(&hwparams);
165 snd_pcm_sw_params_alloca(&swparams);
166
167 err = snd_pcm_hw_params_any(alsa_params->handle, hwparams);
168 if (err < 0) {
169 adec_print("Broken configuration for this PCM: no configurations available");
170 return err;
171 }
172
173 err = snd_pcm_hw_params_set_access(alsa_params->handle, hwparams,
174 SND_PCM_ACCESS_RW_INTERLEAVED);
175 if (err < 0) {
176 adec_print("Access type not available");
177 return err;
178 }
179 if (tv_mode) {
180 alsa_params->format = SND_PCM_FORMAT_S32_LE;
181 }
182 err = snd_pcm_hw_params_set_format(alsa_params->handle,hwparams,alsa_params->format);
183 if (err < 0) {
184 adec_print("Sample format non available");
185 return err;
186 }
187 alsa_params->format = SND_PCM_FORMAT_S16_LE;
188 if (tv_mode) {
189 alsa_params->channelcount = 8;
190 }
191 err = snd_pcm_hw_params_set_channels(alsa_params->handle, hwparams, alsa_params->channelcount);
192 alsa_params->channelcount = 2;
193 if (err < 0) {
194 adec_print("Channels count non available");
195 return err;
196 }
197
198 rate = alsa_params->rate;
199 err = snd_pcm_hw_params_set_rate_near(alsa_params->handle, hwparams, &alsa_params->rate, 0);
200 assert(err >= 0);
201#if 0
202 err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0);
203 assert(err >= 0);
204 if (buffer_time > 500000) {
205 buffer_time = 500000;
206 }
207
208 period_time = buffer_time / 4;
209
210 err = snd_pcm_hw_params_set_period_time_near(handle, hwparams,
211 &period_time, 0);
212 assert(err >= 0);
213
214 err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams,
215 &buffer_time, 0);
216 assert(err >= 0);
217
218#endif
219 alsa_params->bits_per_sample = snd_pcm_format_physical_width(alsa_params->format);
220 //bits_per_frame = bits_per_sample * hwparams.realchanl;
221 alsa_params->bits_per_frame = alsa_params->bits_per_sample * alsa_params->channelcount;
222 adec_print("bits_per_sample %d,bits_per_frame %d\n",alsa_params->bits_per_sample,alsa_params->bits_per_frame);
223 bufsize = PERIOD_NUM * PERIOD_SIZE;
224
225 if (tv_mode) {
226 set_sysfs_type("/sys/class/amhdmitx/amhdmitx0/aud_output_chs", "2:1");
227 }
228
229 err = snd_pcm_hw_params_set_buffer_size_near(alsa_params->handle, hwparams, &bufsize);
230 if (err < 0) {
231 adec_print("Unable to set buffer size \n");
232 return err;
233 }
234 err = snd_pcm_hw_params_set_period_size_near(alsa_params->handle, hwparams, &chunk_size, NULL);
235 if (err < 0) {
236 adec_print("Unable to set period size \n");
237 return err;
238 }
239
240 //err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &fragcount, NULL);
241 //if (err < 0) {
242 // adec_print("Unable to set periods \n");
243 // return err;
244 //}
245
246 err = snd_pcm_hw_params(alsa_params->handle, hwparams);
247 if (err < 0) {
248 adec_print("Unable to install hw params:");
249 return err;
250 }
251
252 err = snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
253 if (err < 0) {
254 adec_print("Unable to get buffersize \n");
255 return err;
256 }
257 alsa_params->buffer_size = bufsize * alsa_params->bits_per_frame / 8;
258
259#if 1
260 err = snd_pcm_sw_params_current(alsa_params->handle, swparams);
261 if (err < 0) {
262 adec_print("??Unable to get sw-parameters\n");
263 return err;
264 }
265
266 //err = snd_pcm_sw_params_get_boundary(swparams, &boundary);
267 //if (err < 0){
268 // adec_print("Unable to get boundary\n");
269 // return err;
270 //}
271
272 //err = snd_pcm_sw_params_set_start_threshold(handle, swparams, bufsize);
273 //if (err < 0) {
274 // adec_print("Unable to set start threshold \n");
275 // return err;
276 //}
277
278 //err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, buffer_size);
279 //if (err < 0) {
280 // adec_print("Unable to set stop threshold \n");
281 // return err;
282 //}
283
284 // err = snd_pcm_sw_params_set_silence_size(handle, swparams, buffer_size);
285 // if (err < 0) {
286 // adec_print("Unable to set silence size \n");
287 // return err;
288 // }
289
290 err = snd_pcm_sw_params(alsa_params->handle, swparams);
291 if (err < 0) {
292 adec_print("Unable to get sw-parameters\n");
293 return err;
294 }
295
296 //snd_pcm_sw_params_free(swparams);
297#endif
298
299
300 //chunk_bytes = chunk_size * bits_per_frame / 8;
301
302 return 0;
303}
304
305static int alsa_get_hdmi_state()
306{
307 return 0;
308#if 0
309 int fd = -1, err = 0, state = 0;
310 unsigned fileSize = 32;
311 char *read_buf = NULL;
312 static const char *const HDMI_STATE_PATH = "/sys/class/switch/hdmi/state";
313
314 fd = open(HDMI_STATE_PATH, O_RDONLY);
315 if (fd < 0) {
316 adec_print("ERROR: failed to open config file %s error: %d\n", HDMI_STATE_PATH, errno);
317 close(fd);
318 return -EINVAL;
319 }
320
321 read_buf = (char *)malloc(fileSize);
322 if (!read_buf) {
323 adec_print("Failed to malloc read_buf");
324 goto OUT;
325 }
326 memset(read_buf, 0x0, fileSize);
327 err = read(fd, read_buf, fileSize);
328 if (fd < 0) {
329 adec_print("ERROR: failed to read config file %s error: %d\n", HDMI_STATE_PATH, errno);
330 goto OUT;
331 }
332
333 if (*read_buf == '1') {
334 state = 1;
335 }
336
337OUT:
338 free(read_buf);
339 close(fd);
340 return state;
341#endif
342}
343
344static int alsa_get_aml_card()
345{
346 int card = -1, err = 0;
347 int fd = -1;
348 unsigned fileSize = 512;
349 char *read_buf = NULL, *pd = NULL;
350 static const char *const SOUND_CARDS_PATH = "/proc/asound/cards";
351 fd = open(SOUND_CARDS_PATH, O_RDONLY);
352 if (fd < 0) {
353 adec_print("ERROR: failed to open config file %s error: %d\n", SOUND_CARDS_PATH, errno);
354 close(fd);
355 return -EINVAL;
356 }
357
358 read_buf = (char *)malloc(fileSize);
359 if (!read_buf) {
360 adec_print("Failed to malloc read_buf");
361 close(fd);
362 return -ENOMEM;
363 }
364 memset(read_buf, 0x0, fileSize);
365 err = read(fd, read_buf, fileSize);
366 if (fd < 0) {
367 adec_print("ERROR: failed to read config file %s error: %d\n", SOUND_CARDS_PATH, errno);
368 free(read_buf);
369 close(fd);
370 return -EINVAL;
371 }
372 pd = strstr(read_buf, "AML");
373 card = *(pd - 3) - '0';
374
375OUT:
376 free(read_buf);
377 close(fd);
378 return card;
379}
380
381static int alsa_get_spdif_port()
382{
383/* for pcm output,i2s/958 share the same data from i2s,so always use device 0 as i2s output */
384 return 0;
385 int port = -1, err = 0;
386 int fd = -1;
387 unsigned fileSize = 512;
388 char *read_buf = NULL, *pd = NULL;
389 static const char *const SOUND_PCM_PATH = "/proc/asound/pcm";
390 fd = open(SOUND_PCM_PATH, O_RDONLY);
391 if (fd < 0) {
392 adec_print("ERROR: failed to open config file %s error: %d\n", SOUND_PCM_PATH, errno);
393 close(fd);
394 return -EINVAL;
395 }
396
397 read_buf = (char *)malloc(fileSize);
398 if (!read_buf) {
399 adec_print("Failed to malloc read_buf");
400 close(fd);
401 return -ENOMEM;
402 }
403 memset(read_buf, 0x0, fileSize);
404 err = read(fd, read_buf, fileSize);
405 if (fd < 0) {
406 adec_print("ERROR: failed to read config file %s error: %d\n", SOUND_PCM_PATH, errno);
407 free(read_buf);
408 close(fd);
409 return -EINVAL;
410 }
411 pd = strstr(read_buf, "SPDIF");
412 if (!pd) {
413 goto OUT;
414 }
415 adec_print("%s \n", pd);
416
417 port = *(pd - 3) - '0';
418 adec_print("%s \n", (pd - 3));
419
420OUT:
421 free(read_buf);
422 close(fd);
423 return port;
424}
425
426static size_t pcm_write(alsa_param_t * alsa_param, u_char * data, size_t count)
427{
428 snd_pcm_sframes_t r;
429 size_t result = 0;
430 int i;
431 short *sample = (short*)data;
432 /*
433 if (count < chunk_size) {
434 snd_pcm_format_set_silence(hwparams.format, data + count * bits_per_frame / 8, (chunk_size - count) * hwparams.channels);
435 count = chunk_size;
436 }
437 */
438 /* volume control for bootplayer */
439 if (alsa_default_vol != 1.0) {
440 for (i = 0;i < count*2;i++) {
441 sample[i] = (short)(alsa_default_vol*(float)sample[i]);
442 }
443 }
444 // dump pcm data here
445#if 0
446 FILE *fp1=fopen("/data/audio_out.pcm","a+");
447 if (fp1) {
448 int flen=fwrite((char *)data,1,count*2*2,fp1);
449 adec_print("flen = %d---outlen=%d ", flen, count*2*2);
450 fclose(fp1);
451 }else{
452 adec_print("could not open file:audio_out.pcm");
453 }
454#endif
455 int *tmp_buffer = NULL;
456 int bits_per_frame = alsa_param->bits_per_frame;
457 if (tv_mode) {
458 tmp_buffer = (int*)malloc(count*8*4);
459 if (tmp_buffer == NULL) {
460 adec_print("malloc tmp_buffer failed\n");
461 return -1;
462 }
463 int i;
464 int out_frames = count;
465 short *in_buffer = (short*)data;
466 for (i = 0; i < out_frames; i ++) {
467 tmp_buffer[8*i] = ((int)(in_buffer[2*i])) << 16;
468 tmp_buffer[8*i + 1] = ((int)(in_buffer[2*i + 1])) << 16;
469 tmp_buffer[8*i + 2] = ((int)(in_buffer[2*i])) << 16;
470 tmp_buffer[8*i + 3] = ((int)(in_buffer[2*i + 1])) << 16;
471 tmp_buffer[8*i + 4] = 0;
472 tmp_buffer[8*i + 5] = 0;
473 tmp_buffer[8*i + 6] = 0;
474 tmp_buffer[8*i + 7] = 0;
475 }
476 data = (char*)tmp_buffer;
477 bits_per_frame = bits_per_frame*8;//8ch,32bit
478 }
479 while (count > 0) {
480 r = writei_func(alsa_param->handle, data, count);
481
482 if (r == -EINTR) {
483 r = 0;
484 }
485 if (r == -ESTRPIPE) {
486 while ((r = snd_pcm_resume(alsa_param->handle)) == -EAGAIN) {
487 amthreadpool_thread_usleep(1000);
488 }
489 }
490
491 if (r < 0) {
492 printf("xun in\n");
493 if ((r = snd_pcm_prepare(alsa_param->handle)) < 0) {
494 result = 0;
495 goto done;
496 }
497 }
498
499 if (r > 0) {
500 result += r;
501 count -= r;
502 data += r * bits_per_frame / 8;
503 }
504 }
505done:
506 if (tmp_buffer) {
507 free(tmp_buffer);
508 }
509 return result;
510}
511
512static unsigned oversample_play(alsa_param_t * alsa_param, char * src, unsigned count)
513{
514 int frames = 0;
515 int ret, i;
516 unsigned short * to, *from;
517 to = (unsigned short *)output_buffer;
518 from = (unsigned short *)src;
519
520 if (alsa_param->realchanl == 2) {
521 if (alsa_param->oversample == -1) {
522 frames = count * 8 / alsa_param->bits_per_frame;
523 frames = frames & (~(32 - 1));
524 for (i = 0; i < (frames * 2); i += 4) { // i for sample
525 *to++ = *from++;
526 *to ++ = *from++;
527 from += 2;
528 }
529 ret = pcm_write(alsa_param, output_buffer, frames / 2);
530 ret = ret * alsa_param->bits_per_frame / 8;
531 ret = ret * 2;
532 } else if (alsa_param->oversample == 1) {
533 frames = count * 8 / alsa_param->bits_per_frame;
534 frames = frames & (~(16 - 1));
535#ifdef USE_INTERPOLATION
536 pcm_interpolation(1, alsa_param->realchanl, frames, (short*)src);
537 memcpy(output_buffer, interpolation_output, (frames * alsa_param->bits_per_frame / 4));
538#else
539 short l, r;
540 for (i = 0; i < (frames * 2); i += 2) {
541 l = *from++;
542 r = *from++;
543 *to++ = l;
544 *to++ = r;
545 *to++ = l;
546 *to++ = r;
547 }
548#endif
549 ret = pcm_write(alsa_param, output_buffer, frames * 2);
550 ret = ret * alsa_param->bits_per_frame / 8;
551 ret = ret / 2;
552 } else if (alsa_param->oversample == 2) {
553 frames = count * 8 / alsa_param->bits_per_frame;
554 frames = frames & (~(8 - 1));
555#ifdef USE_INTERPOLATION
556 pcm_interpolation(2, alsa_param->realchanl, frames, (short*)src);
557 memcpy(output_buffer, interpolation_output, (frames * alsa_param->bits_per_frame / 2));
558#else
559 short l, r;
560 for (i = 0; i < (frames * 2); i += 2) {
561 l = *from++;
562 r = *from++;
563 *to++ = l;
564 *to++ = r;
565 *to++ = l;
566 *to++ = r;
567 *to++ = l;
568 *to++ = r;
569 *to++ = l;
570 *to++ = r;
571 }
572#endif
573 ret = pcm_write(alsa_param, output_buffer, frames * 4);
574 ret = ret * alsa_param->bits_per_frame / 8;
575 ret = ret / 4;
576 }
577 } else if (alsa_param->realchanl == 1) {
578 if (alsa_param->oversample == -1) {
579 frames = count * 8 / alsa_param->bits_per_frame;
580 frames = frames & (~(32 - 1));
581 for (i = 0; i < (frames * 2); i += 2) {
582 *to++ = *from;
583 *to++ = *from++;
584 from++;
585 }
586 ret = pcm_write(alsa_param, output_buffer, frames);
587 ret = ret * alsa_param->bits_per_frame / 8;
588 } else if (alsa_param->oversample == 0) {
589 frames = count * 8 / (alsa_param->bits_per_frame >> 1);
590 frames = frames & (~(16 - 1));
591 for (i = 0; i < (frames); i++) {
592 *to++ = *from;
593 *to++ = *from++;
594 }
595 ret = pcm_write(alsa_param, output_buffer, frames);
596 ret = ret * (alsa_param->bits_per_frame) / 8;
597 ret = ret / 2;
598 } else if (alsa_param->oversample == 1) {
599 frames = count * 8 / (alsa_param->bits_per_frame >> 1);
600 frames = frames & (~(8 - 1));
601#ifdef USE_INTERPOLATION
602 pcm_interpolation(1, alsa_param->realchanl, frames, (short*)src);
603 from = (unsigned short*)interpolation_output;
604 for (i = 0; i < (frames * 2); i++) {
605 *to++ = *from;
606 *to++ = *from++;
607 }
608#else
609 for (i = 0; i < (frames); i++) {
610 *to++ = *from;
611 *to++ = *from;
612 *to++ = *from;
613 *to++ = *from++;
614 }
615#endif
616 ret = pcm_write(alsa_param, output_buffer, frames * 2);
617 ret = ret * (alsa_param->bits_per_frame) / 8;
618 ret = ret / 4;
619 } else if (alsa_param->oversample == 2) {
620 frames = count * 8 / (alsa_param->bits_per_frame >> 1);
621 frames = frames & (~(8 - 1));
622#ifdef USE_INTERPOLATION
623 pcm_interpolation(2, alsa_param->realchanl, frames, (short*)src);
624 from = (unsigned short*)interpolation_output;
625 for (i = 0; i < (frames * 4); i++) {
626 *to++ = *from;
627 *to++ = *from++;
628 }
629#else
630 for (i = 0; i < (frames); i++) {
631 *to++ = *from;
632 *to++ = *from;
633 *to++ = *from;
634 *to++ = *from;
635 *to++ = *from;
636 *to++ = *from;
637 *to++ = *from;
638 *to++ = *from++;
639 }
640#endif
641 ret = pcm_write(alsa_param, output_buffer, frames * 4);
642 ret = ret * (alsa_param->bits_per_frame) / 8;
643 ret = ret / 8;
644 }
645 }
646
647 return ret;
648}
649
650static int alsa_play(alsa_param_t * alsa_param, char * data, unsigned len)
651{
652 size_t l = 0, r;
653
654 if (!alsa_param->flag) {
655 l = len * 8 / alsa_param->bits_per_frame;
656 l = l & (~(32 - 1)); /*driver only support 32 frames each time */
657 r = pcm_write(alsa_param, data, l);
658 r = r * alsa_param->bits_per_frame / 8;
659 } else {
660 r = oversample_play(alsa_param, data, len);
661 }
662
663 return r ;
664}
665
666static int alsa_swtich_port(alsa_param_t *alsa_params, int card, int port)
667{
668 char dev[10] = {0};
669 adec_print("card = %d, port = %d\n", card, port);
670 sprintf(dev, "hw:%d,%d", (card >= 0) ? card : 0, (port >= 0) ? port : 0);
671 pthread_mutex_lock(&alsa_params->playback_mutex);
672 snd_pcm_drop(alsa_params->handle);
673 snd_pcm_close(alsa_params->handle);
674 alsa_params->handle = NULL;
675 int err = snd_pcm_open(&alsa_params->handle, dev, SND_PCM_STREAM_PLAYBACK, 0);
676
677 if (err < 0) {
678 adec_print("audio open error: %s", snd_strerror(err));
679 pthread_mutex_unlock(&alsa_params->playback_mutex);
680 return -1;
681 }
682
683 set_params(alsa_params);
684 pthread_mutex_unlock(&alsa_params->playback_mutex);
685
686 return 0;
687}
688
689static void *alsa_playback_loop(void *args)
690{
691 int len = 0;
692 int len2 = 0;
693 int offset = 0;
694 aml_audio_dec_t *audec;
695 alsa_param_t *alsa_params;
696 unsigned char *buffer = (unsigned char *)(((unsigned long)decode_buffer + 32) & (~0x1f));
697
698 char value[PROPERTY_VALUE_MAX]={0};
699 audec = (aml_audio_dec_t *)args;
700 alsa_params = (alsa_param_t *)audec->aout_ops.private_data;
701
702 // bootplayer default volume configuration
703 if (property_get("media.amplayer.boot_vol",value,NULL) > 0) {
704 alsa_default_vol = atof(value);
705 if (alsa_default_vol < 0.0 || alsa_default_vol > 1.0 ) {
706 adec_print("wrong alsa default volume %f, set to 1.0 \n",alsa_default_vol);
707 alsa_default_vol = 1.0;
708 }
709 }
710 adec_print("alsa default volume %f \n",alsa_default_vol);
711 /* pthread_mutex_init(&alsa_params->playback_mutex, NULL);
712 pthread_cond_init(&alsa_params->playback_cond, NULL);*/
713
714 while (!alsa_params->wait_flag && alsa_params->stop_flag == 0) {
715 amthreadpool_thread_usleep(10000);
716 }
717
718 adec_print("alsa playback loop start to run !\n");
719
720 while (!alsa_params->stop_flag) {
721#if 0
722 if (hdmi_out == 0) {
723 adec_print("===dynmiac get hdmi plugin state===\n");
724 if (alsa_get_hdmi_state() == 1) {
725 if (alsa_swtich_port(alsa_params, alsa_get_aml_card(), alsa_get_spdif_port()) == -1) {
726 adec_print("switch to hdmi port failed.\n");
727 goto exit;
728 }
729
730 hdmi_out = 1;
731 adec_print("[%s,%d]get hdmi device, use hdmi device \n", __FUNCTION__, __LINE__);
732 }
733 } else if (alsa_get_hdmi_state() == 0) {
734 if (alsa_swtich_port(alsa_params, alsa_get_aml_card(), 0) == -1) {
735 adec_print("switch to default port failed.\n");
736 goto exit;
737 }
738
739 hdmi_out = 0;
740 adec_print("[%s,%d]get default device, use default device \n", __FUNCTION__, __LINE__);
741 }
742#endif
743 while ((len < (128 * 2)) && (!alsa_params->stop_flag)) {
744 if (offset > 0) {
745 memcpy(buffer, buffer + offset, len);
746 }
747 len2 = audec->adsp_ops.dsp_read(&audec->adsp_ops, (buffer + len), (OUTPUT_BUFFER_SIZE - len));
748 len = len + len2;
749 offset = 0;
750 }
751 audec->pcm_bytes_readed += len;
752 while (alsa_params->pause_flag) {
753 amthreadpool_thread_usleep(10000);
754 }
755 if (alsa_params->stop_flag) {
756 goto exit;
757 }
758 adec_refresh_pts(audec);
759
760 len2 = alsa_play(alsa_params, (buffer + offset), len);
761 if (len2 >= 0) {
762 len -= len2;
763 offset += len2;
764 } else {
765 len = 0;
766 offset = 0;
767 }
768 }
769exit:
770 adec_print("Exit alsa playback loop !\n");
771 pthread_exit(NULL);
772 return NULL;
773}
774
775/**
776 * \brief output initialization
777 * \param audec pointer to audec
778 * \return 0 on success otherwise negative error code
779 */
780int alsa_init(struct aml_audio_dec* audec)
781{
782 adec_print("alsa out init");
783 char sound_card_dev[10] = {0};
784 int sound_card_id = 0;
785 int sound_dev_id = 0;
786 int err;
787 pthread_t tid;
788 alsa_param_t *alsa_param;
789 audio_out_operations_t *out_ops = &audec->aout_ops;
790 tv_mode = getprop_bool("ro.platform.has.tvuimode");
791 alsa_param = (alsa_param_t *)malloc(sizeof(alsa_param_t));
792 if (!alsa_param) {
793 adec_print("alloc alsa_param failed, not enough memory!");
794 return -1;
795 }
796 memset(alsa_param, 0, sizeof(alsa_param_t));
797
798 if (audec->samplerate >= (88200 + 96000) / 2) {
799 alsa_param->flag = 1;
800 alsa_param->oversample = -1;
801 alsa_param->rate = 48000;
802 } else if (audec->samplerate >= (64000 + 88200) / 2) {
803 alsa_param->flag = 1;
804 alsa_param->oversample = -1;
805 alsa_param->rate = 44100;
806 } else if (audec->samplerate >= (48000 + 64000) / 2) {
807 alsa_param->flag = 1;
808 alsa_param->oversample = -1;
809 alsa_param->rate = 32000;
810 } else if (audec->samplerate >= (44100 + 48000) / 2) {
811 alsa_param->oversample = 0;
812 alsa_param->rate = 48000;
813 if (audec->channels == 1) {
814 alsa_param->flag = 1;
815 } else if (audec->channels == 2) {
816 alsa_param->flag = 0;
817 }
818 } else if (audec->samplerate >= (32000 + 44100) / 2) {
819 alsa_param->oversample = 0;
820 alsa_param->rate = 44100;
821 if (audec->channels == 1) {
822 alsa_param->flag = 1;
823 } else if (audec->channels == 2) {
824 alsa_param->flag = 0;
825 }
826 } else if (audec->samplerate >= (24000 + 32000) / 2) {
827 alsa_param->oversample = 0;
828 alsa_param->rate = 32000;
829 if (audec->channels == 1) {
830 alsa_param->flag = 1;
831 } else if (audec->channels == 2) {
832 alsa_param->flag = 0;
833 }
834 } else if (audec->samplerate >= (22050 + 24000) / 2) {
835 alsa_param->flag = 1;
836 alsa_param->oversample = 1;
837 alsa_param->rate = 48000;
838 } else if (audec->samplerate >= (16000 + 22050) / 2) {
839 alsa_param->flag = 1;
840 alsa_param->oversample = 1;
841 alsa_param->rate = 44100;
842 } else if (audec->samplerate >= (12000 + 16000) / 2) {
843 alsa_param->flag = 1;
844 alsa_param->oversample = 1;
845 alsa_param->rate = 32000;
846 } else if (audec->samplerate >= (11025 + 12000) / 2) {
847 alsa_param->flag = 1;
848 alsa_param->oversample = 2;
849 alsa_param->rate = 48000;
850 } else if (audec->samplerate >= (8000 + 11025) / 2) {
851 alsa_param->flag = 1;
852 alsa_param->oversample = 2;
853 alsa_param->rate = 44100;
854 } else {
855 alsa_param->flag = 1;
856 alsa_param->oversample = 2;
857 alsa_param->rate = 32000;
858 }
859
860 alsa_param->channelcount = 2;
861 alsa_param->realchanl = audec->channels;
862 //alsa_param->rate = audec->samplerate;
863 alsa_param->format = SND_PCM_FORMAT_S16_LE;
864 alsa_param->wait_flag = 0;
865
866#ifdef USE_INTERPOLATION
867 memset(pass1_history, 0, 64 * sizeof(int));
868 memset(pass2_history, 0, 64 * sizeof(int));
869#endif
870
871 sound_card_id = alsa_get_aml_card();
872 if (sound_card_id < 0) {
873 sound_card_id = 0;
874 adec_print("get aml card fail, use default \n");
875 }
876#if 0
877 if (alsa_get_hdmi_state() == 1) {
878 sound_dev_id = alsa_get_spdif_port();
879 if (sound_dev_id < 0) {
880 sound_dev_id = 0;
881 adec_print("get aml card device fail, use default \n");
882 } else {
883 hdmi_out = 1;
884 }
885 adec_print("get hdmi device, use hdmi device \n");
886 }
887#endif
888 sprintf(sound_card_dev, "hw:%d,%d", sound_card_id, sound_dev_id);
889 err = snd_pcm_open(&alsa_param->handle, sound_card_dev, SND_PCM_STREAM_PLAYBACK, 0);
890 if (err < 0) {
891 adec_print("audio open error: %s", snd_strerror(err));
892 return -1;
893 }
894 readi_func = snd_pcm_readi;
895 writei_func = snd_pcm_writei;
896 readn_func = snd_pcm_readn;
897 writen_func = snd_pcm_writen;
898
899 set_params(alsa_param);
900
901 out_ops->private_data = (void *)alsa_param;
902
903 /*TODO: create play thread */
904 pthread_mutex_init(&alsa_param->playback_mutex, NULL);
905 pthread_cond_init(&alsa_param->playback_cond, NULL);
906 err = amthreadpool_pthread_create(&tid, NULL, (void *)alsa_playback_loop, (void *)audec);
907 if (err != 0) {
908 adec_print("alsa_playback_loop thread create failed!");
909 snd_pcm_close(alsa_param->handle);
910 return -1;
911 }
912 pthread_setname_np(tid, "ALSAOUTLOOP");
913
914 adec_print("Create alsa playback loop thread success ! tid = %d\n", tid);
915
916 alsa_param->playback_tid = tid;
917
918 return 0;
919}
920
921/**
922 * \brief start output
923 * \param audec pointer to audec
924 * \return 0 on success otherwise negative error code
925 *
926 * Call alsa_start(), then the callback will start being called.
927 */
928int alsa_start(struct aml_audio_dec* audec)
929{
930 adec_print("alsa out start!\n");
931
932 audio_out_operations_t *out_ops = &audec->aout_ops;
933 alsa_param_t *alsa_param = (alsa_param_t *)out_ops->private_data;
934
935 pthread_mutex_lock(&alsa_param->playback_mutex);
936 adec_print("yvonne pthread_cond_signalalsa_param->wait_flag=1\n");
937 alsa_param->wait_flag = 1; //yvonneadded
938 pthread_cond_signal(&alsa_param->playback_cond);
939 pthread_mutex_unlock(&alsa_param->playback_mutex);
940 adec_print("exit alsa out start!\n");
941
942 return 0;
943}
944
945/**
946 * \brief pause output
947 * \param audec pointer to audec
948 * \return 0 on success otherwise negative error code
949 */
950int alsa_pause(struct aml_audio_dec* audec)
951{
952 adec_print("alsa out pause\n");
953
954 int res;
955 alsa_param_t *alsa_params;
956
957 alsa_params = (alsa_param_t *)audec->aout_ops.private_data;
958 pthread_mutex_lock(&alsa_params->playback_mutex);
959
960 alsa_params->pause_flag = 1;
961 while ((res = snd_pcm_pause(alsa_params->handle, 1)) == -EAGAIN) {
962 sleep(1);
963 }
964 pthread_mutex_unlock(&alsa_params->playback_mutex);
965 adec_print("exit alsa out pause\n");
966
967 return res;
968}
969
970/**
971 * \brief resume output
972 * \param audec pointer to audec
973 * \return 0 on success otherwise negative error code
974 */
975int alsa_resume(struct aml_audio_dec* audec)
976{
977 adec_print("alsa out rsume\n");
978
979 int res;
980 alsa_param_t *alsa_params;
981
982 alsa_params = (alsa_param_t *)audec->aout_ops.private_data;
983 pthread_mutex_lock(&alsa_params->playback_mutex);
984
985 alsa_params->pause_flag = 0;
986 while ((res = snd_pcm_pause(alsa_params->handle, 0)) == -EAGAIN) {
987 sleep(1);
988 }
989 pthread_mutex_unlock(&alsa_params->playback_mutex);
990
991 return res;
992}
993
994/**
995 * \brief stop output
996 * \param audec pointer to audec
997 * \return 0 on success otherwise negative error code
998 */
999int alsa_stop(struct aml_audio_dec* audec)
1000{
1001 adec_print("enter alsa out stop\n");
1002
1003 alsa_param_t *alsa_params;
1004
1005 alsa_params = (alsa_param_t *)audec->aout_ops.private_data;
1006 pthread_mutex_lock(&alsa_params->playback_mutex);
1007 alsa_params->pause_flag = 0;
1008 alsa_params->stop_flag = 1;
1009 //alsa_params->wait_flag = 0;
1010 pthread_cond_signal(&alsa_params->playback_cond);
1011 amthreadpool_pthread_join(alsa_params->playback_tid, NULL);
1012 pthread_cond_destroy(&alsa_params->playback_cond);
1013
1014
1015 snd_pcm_drop(alsa_params->handle);
1016 snd_pcm_close(alsa_params->handle);
1017 pthread_mutex_unlock(&alsa_params->playback_mutex);
1018 pthread_mutex_destroy(&alsa_params->playback_mutex);
1019
1020 free(alsa_params);
1021 audec->aout_ops.private_data = NULL;
1022 adec_print("exit alsa out stop\n");
1023
1024 return 0;
1025}
1026
1027static int alsa_get_space(alsa_param_t * alsa_param)
1028{
1029 snd_pcm_status_t *status;
1030 int ret;
1031 int bits_per_sample = alsa_param->bits_per_sample;
1032 snd_pcm_status_alloca(&status);
1033 if ((ret = snd_pcm_status(alsa_param->handle, status)) < 0) {
1034 adec_print("Cannot get pcm status \n");
1035 return 0;
1036 }
1037 ret = snd_pcm_status_get_avail(status) * alsa_param->bits_per_sample / 8;
1038 if (ret > alsa_param->buffer_size) {
1039 ret = alsa_param->buffer_size;
1040 }
1041 return ret;
1042}
1043
1044/**
1045 * \brief get output latency in ms
1046 * \param audec pointer to audec
1047 * \return output latency
1048 */
1049unsigned long alsa_latency(struct aml_audio_dec* audec)
1050{
1051 int buffered_data;
1052 int sample_num;
1053 alsa_param_t *alsa_param = (alsa_param_t *)audec->aout_ops.private_data;
1054 int bits_per_sample = alsa_param->bits_per_sample;
1055 if (tv_mode) {
1056 bits_per_sample = bits_per_sample*4;
1057 }
1058 buffered_data = alsa_param->buffer_size - alsa_get_space(alsa_param);
1059 sample_num = buffered_data / (alsa_param->channelcount * (bits_per_sample / 8)); /*16/2*/
1060 return ((sample_num * 1000) / alsa_param->rate);
1061}
1062
1063static int alsa_mute(struct aml_audio_dec* audec, adec_bool_t en)
1064{
1065 return 0;
1066}
1067/**
1068 * \brief get output handle
1069 * \param audec pointer to audec
1070 */
1071void get_output_func(struct aml_audio_dec* audec)
1072{
1073 audio_out_operations_t *out_ops = &audec->aout_ops;
1074
1075 out_ops->init = alsa_init;
1076 out_ops->start = alsa_start;
1077 out_ops->pause = alsa_pause;
1078 out_ops->resume = alsa_resume;
1079 out_ops->mute = alsa_mute;
1080 out_ops->stop = alsa_stop;
1081 out_ops->latency = alsa_latency;
1082}
1083