blob: f51a91272f75405f8afc097be479f067440c1a1a
1 | /** |
2 | * \file adec-internal-mgt.c |
3 | * \brief Audio Dec Message Loop Thread |
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 <string.h> |
14 | #include <fcntl.h> |
15 | #include <pthread.h> |
16 | #include <sys/ioctl.h> |
17 | |
18 | #include <audio-dec.h> |
19 | #include <adec-pts-mgt.h> |
20 | #include <cutils/properties.h> |
21 | #include <dts_enc.h> |
22 | #include <Amsysfsutils.h> |
23 | #include <amthreadpool.h> |
24 | #include <amconfigutils.h> |
25 | #include <unistd.h> |
26 | #include "audiodsp_update_format.h" |
27 | |
28 | #define MULTICH_SUPPORT_PROPERTY "media.multich.support.info" |
29 | #define PCM_88_96_SUPPORT "media.libplayer.88_96K" |
30 | |
31 | extern int RegisterDecode(aml_audio_dec_t *audec, int type); |
32 | extern void get_output_func(struct aml_audio_dec* audec); |
33 | |
34 | static int64_t gettime_ms(void) |
35 | { |
36 | struct timeval tv; |
37 | gettimeofday(&tv, NULL); |
38 | return (int64_t)tv.tv_sec * 1000 + tv.tv_usec/1000; |
39 | } |
40 | |
41 | |
42 | |
43 | static int set_tsync_enable(int enable) |
44 | { |
45 | |
46 | char *path = "/sys/class/tsync/enable"; |
47 | return amsysfs_set_sysfs_int(path, enable); |
48 | } |
49 | |
50 | typedef struct { |
51 | // int no; |
52 | int audio_id; |
53 | char type[16]; |
54 | } audio_type_t; |
55 | |
56 | audio_type_t audio_type[] = { |
57 | {ACODEC_FMT_AAC, "aac"}, |
58 | {ACODEC_FMT_AC3, "ac3"}, |
59 | {ACODEC_FMT_DTS, "dts"}, |
60 | {ACODEC_FMT_FLAC, "flac"}, |
61 | {ACODEC_FMT_COOK, "cook"}, |
62 | {ACODEC_FMT_AMR, "amr"}, |
63 | {ACODEC_FMT_RAAC, "raac"}, |
64 | {ACODEC_FMT_WMA, "wma"}, |
65 | {ACODEC_FMT_WMAPRO, "wmapro"}, |
66 | {ACODEC_FMT_ALAC, "alac"}, |
67 | {ACODEC_FMT_VORBIS, "vorbis"}, |
68 | {ACODEC_FMT_AAC_LATM, "aac_latm"}, |
69 | {ACODEC_FMT_APE, "ape"}, |
70 | {ACODEC_FMT_MPEG, "mp3"},//mp3 |
71 | {ACODEC_FMT_MPEG2, "mp3"},//mp2 |
72 | {ACODEC_FMT_MPEG1, "mp3"},//mp1 |
73 | {ACODEC_FMT_EAC3, "eac3"}, |
74 | {ACODEC_FMT_TRUEHD, "thd"}, |
75 | {ACODEC_FMT_PCM_S16BE, "pcm"}, |
76 | {ACODEC_FMT_PCM_S16LE, "pcm"}, |
77 | {ACODEC_FMT_PCM_U8, "pcm"}, |
78 | {ACODEC_FMT_PCM_BLURAY, "pcm"}, |
79 | {ACODEC_FMT_WIFIDISPLAY, "pcm"}, |
80 | {ACODEC_FMT_ALAW, "pcm"}, |
81 | {ACODEC_FMT_MULAW, "pcm"}, |
82 | |
83 | {ACODEC_FMT_ADPCM, "adpcm"}, |
84 | {ACODEC_FMT_WMAVOI, "wmavoi"}, |
85 | {ACODEC_FMT_DRA, "dra"}, |
86 | {ACODEC_FMT_NULL, "null"}, |
87 | |
88 | }; |
89 | |
90 | extern int match_types(const char *filetypestr, const char *typesetting); |
91 | |
92 | static int audio_decoder = AUDIO_ARC_DECODER; |
93 | static int audio_hardware_ctrl(hw_command_t cmd) |
94 | { |
95 | int fd; |
96 | |
97 | fd = open(AUDIO_CTRL_DEVICE, O_RDONLY); |
98 | if (fd < 0) { |
99 | adec_print("Open Device %s Failed!", AUDIO_CTRL_DEVICE); |
100 | return -1; |
101 | } |
102 | |
103 | switch (cmd) { |
104 | case HW_CHANNELS_SWAP: |
105 | ioctl(fd, AMAUDIO_IOC_SET_CHANNEL_SWAP, 0); |
106 | break; |
107 | |
108 | case HW_LEFT_CHANNEL_MONO: |
109 | ioctl(fd, AMAUDIO_IOC_SET_LEFT_MONO, 0); |
110 | break; |
111 | |
112 | case HW_RIGHT_CHANNEL_MONO: |
113 | ioctl(fd, AMAUDIO_IOC_SET_RIGHT_MONO, 0); |
114 | break; |
115 | |
116 | case HW_STEREO_MODE: |
117 | ioctl(fd, AMAUDIO_IOC_SET_STEREO, 0); |
118 | break; |
119 | |
120 | default: |
121 | adec_print("Unknow Command %d!", cmd); |
122 | break; |
123 | |
124 | }; |
125 | |
126 | close(fd); |
127 | |
128 | return 0; |
129 | |
130 | } |
131 | |
132 | /** |
133 | * \brief start audio dec when receive START command. |
134 | * \param audec pointer to audec |
135 | */ |
136 | static void start_adec(aml_audio_dec_t *audec) |
137 | { |
138 | int ret; |
139 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
140 | dsp_operations_t *dsp_ops = &audec->adsp_ops; |
141 | unsigned long vpts, apts; |
142 | int times = 0; |
143 | char buf[32]; |
144 | apts = vpts = 0; |
145 | |
146 | char value[PROPERTY_VALUE_MAX] = {0}; |
147 | int wait_count = 100; |
148 | if (property_get("media.amadec.wait_count", value, NULL) > 0) { |
149 | wait_count = atoi(value); |
150 | } |
151 | adec_print("wait first apts count :%d \n", wait_count); |
152 | |
153 | audec->no_first_apts = 0; |
154 | if (audec->state == INITTED) { |
155 | |
156 | while ((!audiodsp_get_first_pts_flag(dsp_ops)) && (!audec->need_stop) && (!audec->no_first_apts)) { |
157 | adec_print("wait first pts checkin complete times=%d,!\n", times); |
158 | times++; |
159 | |
160 | if (times >= wait_count) { |
161 | // read vpts |
162 | amsysfs_get_sysfs_str(TSYNC_VPTS, buf, sizeof(buf)); |
163 | if (sscanf(buf, "0x%lx", &vpts) < 1) { |
164 | adec_print("unable to get vpts from: %s", buf); |
165 | return; |
166 | } |
167 | |
168 | // save vpts to apts |
169 | adec_print("## can't get first apts, save vpts to apts,vpts=%lx, \n", vpts); |
170 | |
171 | sprintf(buf, "0x%lx", vpts); |
172 | |
173 | amsysfs_set_sysfs_str(TSYNC_APTS, buf); |
174 | |
175 | audec->no_first_apts = 1; |
176 | } |
177 | amthreadpool_thread_usleep(100000); |
178 | } |
179 | /*Since audio_track->start consumed too much time |
180 | *for the first time after platform restart, |
181 | *so execute start cmd before adec_pts_start |
182 | */ |
183 | aout_ops->start(audec); |
184 | aout_ops->pause(audec); |
185 | /*start the the pts scr,...*/ |
186 | ret = adec_pts_start(audec); |
187 | |
188 | //adec_pts_droppcm(audec); |
189 | |
190 | if (audec->auto_mute) { |
191 | avsync_en(0); |
192 | audiodsp_automute_on(dsp_ops); |
193 | adec_pts_pause(); |
194 | |
195 | while ((!audec->need_stop) && track_switch_pts(audec)) { |
196 | amthreadpool_thread_usleep(1000); |
197 | } |
198 | |
199 | audiodsp_automute_off(dsp_ops); |
200 | avsync_en(1); |
201 | adec_pts_resume(); |
202 | |
203 | audec->auto_mute = 0; |
204 | } |
205 | |
206 | aout_ops->resume(audec); |
207 | audec->state = ACTIVE; |
208 | |
209 | } |
210 | } |
211 | |
212 | /** |
213 | * \brief pause audio dec when receive PAUSE command. |
214 | * \param audec pointer to audec |
215 | */ |
216 | static void pause_adec(aml_audio_dec_t *audec) |
217 | { |
218 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
219 | |
220 | if (audec->state == ACTIVE) { |
221 | audec->state = PAUSED; |
222 | adec_pts_pause(); |
223 | aout_ops->pause(audec); |
224 | } |
225 | } |
226 | |
227 | /** |
228 | * \brief resume audio dec when receive RESUME command. |
229 | * \param audec pointer to audec |
230 | */ |
231 | static void resume_adec(aml_audio_dec_t *audec) |
232 | { |
233 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
234 | |
235 | if (audec->state == PAUSED) { |
236 | audec->state = ACTIVE; |
237 | audec->refresh_pts_readytime_ms = gettime_ms() + |
238 | am_getconfig_int_def("media.amadec.wait_fresh_ms", 200); |
239 | aout_ops->resume(audec); |
240 | adec_pts_resume(); |
241 | } |
242 | } |
243 | |
244 | /** |
245 | * \brief stop audio dec when receive STOP command. |
246 | * \param audec pointer to audec |
247 | */ |
248 | static void stop_adec(aml_audio_dec_t *audec) |
249 | { |
250 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
251 | |
252 | if (audec->state > INITING) { |
253 | audec->state = STOPPED; |
254 | aout_ops->mute(audec, 1); //mute output, some repeat sound in audioflinger after stop |
255 | aout_ops->stop(audec); |
256 | feeder_release(audec); |
257 | } |
258 | } |
259 | |
260 | /** |
261 | * \brief release audio dec when receive RELEASE command. |
262 | * \param audec pointer to audec |
263 | */ |
264 | static void release_adec(aml_audio_dec_t *audec) |
265 | { |
266 | audec->state = TERMINATED; |
267 | } |
268 | |
269 | /** |
270 | * \brief mute audio dec when receive MUTE command. |
271 | * \param audec pointer to audec |
272 | * \param en 1 = mute, 0 = unmute |
273 | */ |
274 | static void mute_adec(aml_audio_dec_t *audec, int en) |
275 | { |
276 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
277 | |
278 | if (aout_ops->mute) { |
279 | adec_print("%s the output !\n", (en ? "mute" : "unmute")); |
280 | aout_ops->mute(audec, en); |
281 | audec->muted = en; |
282 | } |
283 | } |
284 | |
285 | /** |
286 | * \brief set volume to audio dec when receive SET_VOL command. |
287 | * \param audec pointer to audec |
288 | * \param vol volume value |
289 | */ |
290 | static void adec_set_volume(aml_audio_dec_t *audec, float vol) |
291 | { |
292 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
293 | |
294 | if (aout_ops->set_volume) { |
295 | adec_print("set audio volume! vol = %f\n", vol); |
296 | aout_ops->set_volume(audec, vol); |
297 | } |
298 | } |
299 | |
300 | /** |
301 | * \brief set volume to audio dec when receive SET_LRVOL command. |
302 | * \param audec pointer to audec |
303 | * \param lvol left channel volume value |
304 | * \param rvol right channel volume value |
305 | */ |
306 | static void adec_set_lrvolume(aml_audio_dec_t *audec, float lvol, float rvol) |
307 | { |
308 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
309 | |
310 | if (aout_ops->set_lrvolume) { |
311 | adec_print("set audio volume! left vol = %f,right vol:%f\n", lvol, rvol); |
312 | aout_ops->set_lrvolume(audec, lvol, rvol); |
313 | } |
314 | } |
315 | static void adec_flag_check(aml_audio_dec_t *audec) |
316 | { |
317 | audio_out_operations_t *aout_ops = &audec->aout_ops; |
318 | |
319 | if (audec->auto_mute && (audec->state > INITTED) && (audec->state != PAUSED)) { |
320 | aout_ops->pause(audec); |
321 | adec_print("automute, pause audio out!\n"); |
322 | amthreadpool_thread_usleep(10000); |
323 | while ((!audec->need_stop) && track_switch_pts(audec)) { |
324 | amthreadpool_thread_usleep(1000); |
325 | } |
326 | aout_ops->resume(audec); |
327 | adec_print("resume audio out, automute invalid\n"); |
328 | audec->auto_mute = 0; |
329 | } |
330 | } |
331 | |
332 | static int write_buffer(char *outbuf, int outlen) |
333 | { |
334 | return 0; |
335 | } |
336 | |
337 | |
338 | static void *adec_message_loop(void *args) |
339 | { |
340 | int ret; |
341 | aml_audio_dec_t *audec; |
342 | audio_out_operations_t *aout_ops; |
343 | adec_cmd_t *msg = NULL; |
344 | |
345 | audec = (aml_audio_dec_t *)args; |
346 | aout_ops = &audec->aout_ops; |
347 | |
348 | while (!audec->need_stop) { |
349 | audec->state = INITING; |
350 | ret = feeder_init(audec); |
351 | if (ret == 0) { |
352 | ret = aout_ops->init(audec); |
353 | if (ret) { |
354 | adec_print("Audio out device init failed!"); |
355 | feeder_release(audec); |
356 | continue; |
357 | } |
358 | audec->state = INITTED; |
359 | adec_print("Audio out device init ok!"); |
360 | start_adec(audec); |
361 | if (dtsenc_init() != -1) { |
362 | dtsenc_start(); |
363 | } |
364 | |
365 | break; |
366 | } |
367 | |
368 | if (!audec->need_stop) { |
369 | amthreadpool_thread_usleep(100000); |
370 | } |
371 | } |
372 | |
373 | do { |
374 | //if(message_pool_empty(audec)) |
375 | //{ |
376 | //adec_print("there is no message !\n"); |
377 | // amthreadpool_thread_usleep(100000); |
378 | // continue; |
379 | //} |
380 | adec_reset_track(audec); |
381 | adec_flag_check(audec); |
382 | |
383 | msg = adec_get_message(audec); |
384 | if (!msg) { |
385 | amthreadpool_thread_usleep(100000); |
386 | continue; |
387 | } |
388 | |
389 | switch (msg->ctrl_cmd) { |
390 | case CMD_START: |
391 | |
392 | adec_print("Receive START Command!\n"); |
393 | start_adec(audec); |
394 | dtsenc_start(); |
395 | break; |
396 | |
397 | case CMD_PAUSE: |
398 | |
399 | adec_print("Receive PAUSE Command!"); |
400 | pause_adec(audec); |
401 | dtsenc_pause(); |
402 | break; |
403 | |
404 | case CMD_RESUME: |
405 | |
406 | adec_print("Receive RESUME Command!"); |
407 | resume_adec(audec); |
408 | dtsenc_resume(); |
409 | break; |
410 | |
411 | case CMD_STOP: |
412 | |
413 | adec_print("Receive STOP Command!"); |
414 | adec_print("audec->state=%d (INITING/3) when Rec_STOP_CMD\n", audec->state); |
415 | stop_adec(audec); |
416 | dtsenc_stop(); |
417 | break; |
418 | |
419 | case CMD_MUTE: |
420 | |
421 | adec_print("Receive Mute Command!"); |
422 | if (msg->has_arg) { |
423 | mute_adec(audec, msg->value.en); |
424 | } |
425 | break; |
426 | |
427 | case CMD_SET_VOL: |
428 | |
429 | adec_print("Receive Set Vol Command!"); |
430 | if (msg->has_arg) { |
431 | adec_set_volume(audec, msg->value.volume); |
432 | } |
433 | break; |
434 | case CMD_SET_LRVOL: |
435 | |
436 | adec_print("Receive Set LRVol Command!"); |
437 | if (msg->has_arg) { |
438 | adec_set_lrvolume(audec, msg->value.volume, msg->value_ext.volume); |
439 | } |
440 | break; |
441 | |
442 | case CMD_CHANL_SWAP: |
443 | |
444 | adec_print("Receive Channels Swap Command!"); |
445 | audio_hardware_ctrl(HW_CHANNELS_SWAP); |
446 | break; |
447 | |
448 | case CMD_LEFT_MONO: |
449 | |
450 | adec_print("Receive Left Mono Command!"); |
451 | audio_hardware_ctrl(HW_LEFT_CHANNEL_MONO); |
452 | break; |
453 | |
454 | case CMD_RIGHT_MONO: |
455 | |
456 | adec_print("Receive Right Mono Command!"); |
457 | audio_hardware_ctrl(HW_RIGHT_CHANNEL_MONO); |
458 | break; |
459 | |
460 | case CMD_STEREO: |
461 | |
462 | adec_print("Receive Stereo Command!"); |
463 | audio_hardware_ctrl(HW_STEREO_MODE); |
464 | break; |
465 | |
466 | case CMD_RELEASE: |
467 | |
468 | adec_print("Receive RELEASE Command!"); |
469 | release_adec(audec); |
470 | dtsenc_release(); |
471 | break; |
472 | |
473 | default: |
474 | adec_print("Unknow Command!"); |
475 | break; |
476 | |
477 | } |
478 | |
479 | if (msg) { |
480 | adec_message_free(msg); |
481 | msg = NULL; |
482 | } |
483 | } while (audec->state != TERMINATED); |
484 | |
485 | adec_print("Exit Message Loop Thread!"); |
486 | pthread_exit(NULL); |
487 | return NULL; |
488 | } |
489 | |
490 | /** |
491 | * \brief start audio dec |
492 | * \param audec pointer to audec |
493 | * \return 0 on success otherwise -1 if an error occurred |
494 | */ |
495 | int match_types(const char *filetypestr, const char *typesetting) |
496 | { |
497 | const char * psets = typesetting; |
498 | const char *psetend; |
499 | int psetlen = 0; |
500 | char typestr[64] = ""; |
501 | if (filetypestr == NULL || typesetting == NULL) { |
502 | return 0; |
503 | } |
504 | |
505 | while (psets && psets[0] != '\0') { |
506 | psetlen = 0; |
507 | psetend = strchr(psets, ','); |
508 | if (psetend != NULL && psetend > psets && psetend - psets < 64) { |
509 | psetlen = psetend - psets; |
510 | memcpy(typestr, psets, psetlen); |
511 | typestr[psetlen] = '\0'; |
512 | psets = &psetend[1]; //skip ";" |
513 | } else { |
514 | strcpy(typestr, psets); |
515 | psets = NULL; |
516 | } |
517 | if (strlen(typestr) > 0 && (strlen(typestr) == strlen(filetypestr))) { |
518 | if (strstr(filetypestr, typestr) != NULL) { |
519 | return 1; |
520 | } |
521 | } |
522 | } |
523 | return 0; |
524 | } |
525 | |
526 | /* |
527 | digital_raw: |
528 | 0 2ch PCM |
529 | 1 spdif passthrough ,for DTS,DD |
530 | 2 HDMI passthrough for DD,DTSHD,TrueHD |
531 | 3 Multi-channel PCM HDMI passthrough |
532 | */ |
533 | static void set_multichs_prop() |
534 | { |
535 | char * infobuf; |
536 | int channel = 0; |
537 | int dgraw = 0; |
538 | dgraw = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); |
539 | infobuf = (char *)malloc(1024 * sizeof(char)); |
540 | property_set(PCM_88_96_SUPPORT, "0"); |
541 | if (infobuf == NULL) { |
542 | adec_print("%s: malloc infobuf failed.\n", __FUNCTION__); |
543 | } else { |
544 | int fd = open("/sys/class/amhdmitx/amhdmitx0/aud_cap", O_RDONLY); |
545 | if (fd != -1) { |
546 | int nread = read(fd, infobuf, 1024); |
547 | int i; |
548 | nread = nread - 5; |
549 | for (i = 0; i < nread; i++) { |
550 | if ((infobuf[i] == 'P') && (infobuf[i + 1] == 'C') && (infobuf[i + 2] == 'M')) { |
551 | if (dgraw == 3) { // if configured mutli-channel output,check if the HDMI sink support multi-channel PCM output |
552 | if (infobuf[i + 5] == '8') { |
553 | property_set(MULTICH_SUPPORT_PROPERTY, "hdmi8"); |
554 | channel = channel < 8 ? 8 : channel; |
555 | } |
556 | if (infobuf[i + 5] == '6') { |
557 | property_set(MULTICH_SUPPORT_PROPERTY, "hdmi6"); |
558 | channel = channel < 6 ? 6 : channel; |
559 | } |
560 | if (infobuf[i + 5] == '2') { |
561 | property_set(MULTICH_SUPPORT_PROPERTY, "hdmi2"); |
562 | channel = channel < 2 ? 2 : channel; |
563 | } |
564 | } else { |
565 | property_set(MULTICH_SUPPORT_PROPERTY, "hdmi2"); |
566 | channel = channel < 2 ? 2 : channel; |
567 | } |
568 | } else if ( |
569 | ((infobuf[i] == '8') && (infobuf[i + 1] == '8') && (infobuf[i + 2] == '.') && (infobuf[i + 3] == '2')) |
570 | || ((infobuf[i] == '9') && (infobuf[i + 1] == '6'))) { |
571 | property_set(PCM_88_96_SUPPORT, "1"); |
572 | } |
573 | } |
574 | if (channel == 0) { |
575 | property_set(MULTICH_SUPPORT_PROPERTY, "speaker"); |
576 | } |
577 | adec_print("%s: aud_cap support channel number: %d ch\n", __FUNCTION__, channel); |
578 | close(fd); |
579 | free(infobuf); |
580 | infobuf = NULL; |
581 | } else { |
582 | adec_print("%s: open hdmi driver aud_cap node failed \n", __FUNCTION__); |
583 | free(infobuf); |
584 | infobuf = NULL; |
585 | } |
586 | } |
587 | } |
588 | |
589 | static int set_audio_decoder(aml_audio_dec_t *audec) |
590 | { |
591 | int audio_id; |
592 | int i; |
593 | int num; |
594 | int ret; |
595 | audio_type_t *t; |
596 | char value[PROPERTY_VALUE_MAX]; |
597 | |
598 | |
599 | audio_id = audec->format; |
600 | |
601 | num = ARRAY_SIZE(audio_type); |
602 | for (i = 0; i < num; i++) { |
603 | t = &audio_type[i]; |
604 | if (t->audio_id == audio_id) { |
605 | break; |
606 | } |
607 | } |
608 | |
609 | if (match_types(t->type, "thd") || match_types(t->type, "wmavoi") || match_types(t->type, "dra") ) { |
610 | adec_print("audio format is %s, so chose AUDIO_ARM_DECODER", t->type); |
611 | audio_decoder = AUDIO_ARM_DECODER; |
612 | goto exit; |
613 | } |
614 | |
615 | |
616 | ret = property_get("media.arm.audio.decoder", value, NULL); |
617 | adec_print("media.amplayer.audiocodec = %s, t->type = %s\n", value, t->type); |
618 | if (ret > 0 && match_types(t->type, value)) { |
619 | char type_value[] = "ac3,eac3"; |
620 | set_multichs_prop(); |
621 | if (match_types(t->type, type_value)) { |
622 | #ifdef DOLBY_USE_ARMDEC |
623 | adec_print("DOLBY_USE_ARMDEC=%d", DOLBY_USE_ARMDEC); |
624 | #ifndef USE_ARM_AUDIO_DEC |
625 | if (access("/system/etc/firmware/audiodsp_codec_ddp_dcv.bin",0 /*F_OK*/)) { |
626 | #endif |
627 | audio_decoder = AUDIO_ARM_DECODER; |
628 | #ifndef USE_ARM_AUDIO_DEC |
629 | }else{ |
630 | audio_decoder = AUDIO_ARC_DECODER; |
631 | } |
632 | #endif |
633 | #else |
634 | audio_decoder = AUDIO_ARC_DECODER; |
635 | adec_print("<DOLBY_USE_ARMDEC> is not DEFINED,use ARC_Decoder\n!"); |
636 | #endif |
637 | } |
638 | #ifndef USE_ARM_AUDIO_DEC |
639 | else if (match_types(t->type, "dts")) { |
640 | if (access("/system/etc/firmware/audiodsp_codec_dtshd.bin", 0/*F_OK*/)) { |
641 | adec_print("using no license dts component"); |
642 | audio_decoder = AUDIO_ARM_DECODER; |
643 | } else { |
644 | adec_print("using audiodsp dts decoder"); |
645 | audio_decoder = AUDIO_ARC_DECODER; |
646 | } |
647 | } |
648 | #endif |
649 | else { |
650 | audio_decoder = AUDIO_ARM_DECODER; |
651 | } |
652 | goto exit; |
653 | } |
654 | |
655 | ret = property_get("media.arc.audio.decoder", value, NULL); |
656 | adec_print("media.amplayer.audiocodec = %s, t->type = %s\n", value, t->type); |
657 | if (ret > 0 && match_types(t->type, value)) { |
658 | if (audec->dspdec_not_supported == 0) { |
659 | audio_decoder = AUDIO_ARC_DECODER; |
660 | } else { |
661 | audio_decoder = AUDIO_ARM_DECODER; |
662 | adec_print("[%s:%d]arc decoder not support this audio yet,switch to ARM decoder \n", __FUNCTION__, __LINE__); |
663 | } |
664 | goto exit; |
665 | } |
666 | |
667 | ret = property_get("media.ffmpeg.audio.decoder", value, NULL); |
668 | adec_print("media.amplayer.audiocodec = %s, t->type = %s\n", value, t->type); |
669 | if (ret > 0 && match_types(t->type, value)) { |
670 | audio_decoder = AUDIO_FFMPEG_DECODER; |
671 | goto exit; |
672 | } |
673 | |
674 | audio_decoder = AUDIO_ARC_DECODER; //set arc decoder as default |
675 | if (audec->dspdec_not_supported == 1) { |
676 | audio_decoder = AUDIO_ARM_DECODER; |
677 | adec_print("[%s:%d]arc decoder not support this audio yet,switch to ARM decoder \n", __FUNCTION__, __LINE__); |
678 | } |
679 | exit: |
680 | if (am_getconfig_bool("media.libplayer.wfd") && (audio_id == ACODEC_FMT_WIFIDISPLAY || audio_id == ACODEC_FMT_AAC)) { |
681 | adec_print("wfd use arm decoder \n"); |
682 | audio_decoder = AUDIO_ARMWFD_DECODER; |
683 | } |
684 | return 0; |
685 | } |
686 | |
687 | int get_audio_decoder(void) |
688 | { |
689 | //adec_print("audio_decoder = %d\n", audio_decoder); |
690 | return audio_decoder; |
691 | } |
692 | |
693 | int vdec_pts_pause(void) |
694 | { |
695 | return amsysfs_set_sysfs_str(TSYNC_EVENT, "VIDEO_PAUSE:0x1"); |
696 | } |
697 | |
698 | int adec_thread_wait(aml_audio_dec_t *audec, int microseconds) |
699 | { |
700 | struct timespec pthread_ts; |
701 | struct timeval now; |
702 | adec_thread_mgt_t *mgt = &audec->thread_mgt; |
703 | int ret; |
704 | |
705 | gettimeofday(&now, NULL); |
706 | pthread_ts.tv_sec = now.tv_sec + (microseconds + now.tv_usec) / 1000000; |
707 | pthread_ts.tv_nsec = ((microseconds + now.tv_usec) * 1000) % 1000000000; |
708 | pthread_mutex_lock(&mgt->pthread_mutex); |
709 | ret = pthread_cond_timedwait(&mgt->pthread_cond, &mgt->pthread_mutex, &pthread_ts); |
710 | pthread_mutex_unlock(&mgt->pthread_mutex); |
711 | return ret; |
712 | } |
713 | int adec_thread_wakeup(aml_audio_dec_t *audec) |
714 | { |
715 | adec_thread_mgt_t *mgt = &audec->thread_mgt; |
716 | int ret; |
717 | |
718 | pthread_mutex_lock(&mgt->pthread_mutex); |
719 | ret = pthread_cond_signal(&mgt->pthread_cond); |
720 | pthread_mutex_unlock(&mgt->pthread_mutex); |
721 | |
722 | return ret; |
723 | } |
724 | |
725 | int audiodec_init(aml_audio_dec_t *audec) |
726 | { |
727 | int ret = 0; |
728 | pthread_t tid; |
729 | char value[PROPERTY_VALUE_MAX] = {0}; |
730 | unsigned wfd = 0; |
731 | adec_print("audiodec_init!"); |
732 | adec_message_pool_init(audec); |
733 | get_output_func(audec); |
734 | int nCodecType = audec->format; |
735 | set_audio_decoder(audec); |
736 | audec->format_changed_flag = 0; |
737 | audec->audio_decoder_enabled = -1;//default set a invalid value |
738 | audec->mix_lr_channel_enable = -1; |
739 | audec->pre_gain_enable = -1; |
740 | audec->pre_gain = 1.0; |
741 | audec->pre_mute = 0; |
742 | audec->VersionNum = -1; |
743 | audec->refresh_pts_readytime_ms = 0; |
744 | if (am_getconfig_bool("media.libplayer.wfd")) { |
745 | wfd = 1; |
746 | } |
747 | if (get_audio_decoder() == AUDIO_ARC_DECODER) { |
748 | audec->adsp_ops.dsp_file_fd = -1; |
749 | ret = amthreadpool_pthread_create(&tid, NULL, (void *)adec_message_loop, (void *)audec); |
750 | pthread_setname_np(tid, "AmadecMsgloop"); |
751 | } else if (wfd && (nCodecType == ACODEC_FMT_AAC || nCodecType == ACODEC_FMT_WIFIDISPLAY)) { |
752 | adec_print("using wfd audio decoder \n"); |
753 | ret = amthreadpool_pthread_create(&tid, NULL, (void *)adec_wfddec_msg_loop, (void *)audec); |
754 | audec->audio_decoder_enabled = 0x1; |
755 | pthread_setname_np(tid, "AmadecWFDMsgloop"); |
756 | } else { |
757 | int codec_type = get_audio_decoder(); |
758 | RegisterDecode(audec, codec_type); |
759 | ret = amthreadpool_pthread_create(&tid, NULL, (void *)adec_armdec_loop, (void *)audec); |
760 | pthread_mutex_init(&audec->thread_mgt.pthread_mutex, NULL); |
761 | pthread_cond_init(&audec->thread_mgt.pthread_cond, NULL); |
762 | audec->thread_mgt.pthread_id = tid; |
763 | pthread_setname_np(tid, "AmadecArmdecLP"); |
764 | } |
765 | if (ret != 0) { |
766 | adec_print("Create adec main thread failed!\n"); |
767 | return ret; |
768 | } |
769 | adec_print("Create adec main thread success! tid = %d\n", tid); |
770 | audec->thread_pid = tid; |
771 | return ret; |
772 | } |
773 |