blob: 8d0a05c295179d698f75ba951305c8a0e0de2038
1 | /** |
2 | * \file audiodsp-ctl.c |
3 | * \brief Functions of Auduodsp control |
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 <string.h> |
15 | #include <syslog.h> |
16 | #include <unistd.h> |
17 | #include <errno.h> |
18 | #include <sys/ioctl.h> |
19 | #include <sys/mman.h> |
20 | |
21 | #include <audio-dec.h> |
22 | #include <audiodsp.h> |
23 | #include <log-print.h> |
24 | #include <cutils/properties.h> |
25 | #include <amthreadpool.h> |
26 | #include "Amsysfsutils.h" |
27 | #include "amconfigutils.h" |
28 | |
29 | firmware_s_t firmware_list[] = { |
30 | {0, MCODEC_FMT_MPEG123, "audiodsp_codec_mad.bin"}, |
31 | {1, MCODEC_FMT_AAC, "audiodsp_codec_aac_helix.bin"}, |
32 | {2, MCODEC_FMT_AC3 | MCODEC_FMT_EAC3, "audiodsp_codec_ddp_dcv.bin"}, |
33 | {3, MCODEC_FMT_DTS, "audiodsp_codec_dtshd.bin"}, |
34 | {4, MCODEC_FMT_FLAC, "audiodsp_codec_flac.bin"}, |
35 | {5, MCODEC_FMT_COOK, "audiodsp_codec_cook.bin"}, |
36 | {6, MCODEC_FMT_AMR, "audiodsp_codec_amr.bin"}, |
37 | {7, MCODEC_FMT_RAAC, "audiodsp_codec_raac.bin"}, |
38 | {8, MCODEC_FMT_ADPCM, "audiodsp_codec_adpcm.bin"}, |
39 | {9, MCODEC_FMT_WMA, "audiodsp_codec_wma.bin"}, |
40 | {10, MCODEC_FMT_PCM, "audiodsp_codec_pcm.bin"}, |
41 | {11, MCODEC_FMT_WMAPRO, "audiodsp_codec_wmapro.bin"}, |
42 | {12, MCODEC_FMT_ALAC, "audiodsp_codec_alac.bin"}, |
43 | {13, MCODEC_FMT_VORBIS, "audiodsp_codec_vorbis.bin"}, |
44 | {14, MCODEC_FMT_AAC_LATM, "audiodsp_codec_aac.bin"}, |
45 | {15, MCODEC_FMT_APE, "audiodsp_codec_ape.bin"}, |
46 | |
47 | }; |
48 | |
49 | /** |
50 | * \brief register audio firmware |
51 | * \param fd dsp handle |
52 | * \param fmt audio format |
53 | * \param name audio firmware name |
54 | * \return 0 on success otherwise negative error code |
55 | */ |
56 | static int register_firmware(int fd, int fmt, char *name) |
57 | { |
58 | int ret; |
59 | audiodsp_cmd_t cmd; |
60 | |
61 | cmd.cmd = AUDIODSP_REGISTER_FIRMWARE; |
62 | cmd.fmt = fmt; |
63 | cmd.data = name; |
64 | cmd.data_len = strlen(name); |
65 | |
66 | ret = ioctl(fd, AUDIODSP_REGISTER_FIRMWARE, &cmd); |
67 | |
68 | return ret; |
69 | } |
70 | |
71 | /** |
72 | * \brief switch audio format |
73 | * \param fmt audio format |
74 | * \return new format on success otherwise zero |
75 | */ |
76 | static int switch_audiodsp(adec_audio_format_t fmt) |
77 | { |
78 | switch (fmt) { |
79 | case ADEC_AUDIO_FORMAT_MPEG: |
80 | return MCODEC_FMT_MPEG123; |
81 | |
82 | case ADEC_AUDIO_FORMAT_AAC_LATM: |
83 | return MCODEC_FMT_AAC_LATM; |
84 | |
85 | case ADEC_AUDIO_FORMAT_AAC: |
86 | return MCODEC_FMT_AAC; |
87 | |
88 | case ADEC_AUDIO_FORMAT_AC3: |
89 | return MCODEC_FMT_AC3; |
90 | case ADEC_AUDIO_FORMAT_EAC3: |
91 | return MCODEC_FMT_EAC3; |
92 | |
93 | case ADEC_AUDIO_FORMAT_DTS: |
94 | return MCODEC_FMT_DTS; |
95 | |
96 | case ADEC_AUDIO_FORMAT_FLAC: |
97 | return MCODEC_FMT_FLAC; |
98 | |
99 | case ADEC_AUDIO_FORMAT_COOK: |
100 | return MCODEC_FMT_COOK; |
101 | |
102 | case ADEC_AUDIO_FORMAT_AMR: |
103 | return MCODEC_FMT_AMR; |
104 | |
105 | case ADEC_AUDIO_FORMAT_RAAC: |
106 | return MCODEC_FMT_RAAC; |
107 | |
108 | case ADEC_AUDIO_FORMAT_ADPCM: |
109 | return MCODEC_FMT_ADPCM; |
110 | |
111 | case ADEC_AUDIO_FORMAT_PCM_S16BE: |
112 | case ADEC_AUDIO_FORMAT_PCM_S16LE: |
113 | case ADEC_AUDIO_FORMAT_PCM_U8: |
114 | case ADEC_AUDIO_AFORMAT_PCM_BLURAY: |
115 | case ADEC_AUDIO_FORMAT_PCM_WIFIDISPLAY: |
116 | return MCODEC_FMT_PCM; |
117 | |
118 | case ADEC_AUDIO_FORMAT_WMA: |
119 | return MCODEC_FMT_WMA; |
120 | |
121 | case ADEC_AUDIO_FORMAT_WMAPRO: |
122 | return MCODEC_FMT_WMAPRO; |
123 | case ADEC_AUDIO_AFORMAT_ALAC: |
124 | return MCODEC_FMT_ALAC; |
125 | case ADEC_AUDIO_AFORMAT_VORBIS: |
126 | return MCODEC_FMT_VORBIS; |
127 | case ADEC_AUDIO_FORMAT_APE: |
128 | return MCODEC_FMT_APE; |
129 | default: |
130 | return 0; |
131 | } |
132 | } |
133 | |
134 | /** |
135 | * \brief find audio firmware through audio format |
136 | * \param fmt audio format |
137 | * \return firmware_s struct otherwise null |
138 | */ |
139 | static firmware_s_t * find_firmware_by_fmt(int m_fmt) |
140 | { |
141 | int i; |
142 | int num; |
143 | firmware_s_t *f; |
144 | |
145 | num = ARRAY_SIZE(firmware_list); |
146 | |
147 | for (i = 0; i < num; i++) { |
148 | f = &firmware_list[i]; |
149 | if (f->fmt & m_fmt) { |
150 | return f; |
151 | } |
152 | } |
153 | |
154 | return NULL; |
155 | } |
156 | |
157 | |
158 | /** |
159 | * \brief init audiodsp |
160 | * \param dsp_ops pointer to dsp operation struct |
161 | * \return 0 on success otherwise -1 if an error occurred |
162 | */ |
163 | int audiodsp_init(dsp_operations_t *dsp_ops) |
164 | { |
165 | int i; |
166 | int fd = -1; |
167 | int num; |
168 | int ret; |
169 | firmware_s_t *f; |
170 | |
171 | num = ARRAY_SIZE(firmware_list); |
172 | |
173 | if (dsp_ops->dsp_file_fd < 0) { |
174 | fd = open(DSP_DEV_NOD, O_RDONLY, 0644); |
175 | } |
176 | |
177 | if (fd < 0) { |
178 | adec_print("unable to open audio dsp %s,err: %s", DSP_DEV_NOD, strerror(errno)); |
179 | return -1; |
180 | } |
181 | ioctl(fd, AUDIODSP_UNREGISTER_ALLFIRMWARE, 0); |
182 | for (i = 0; i < num; i++) { |
183 | f = &firmware_list[i]; |
184 | ret = register_firmware(fd, f->fmt, f->name); |
185 | if (ret != 0) { |
186 | adec_print("register firmware error=%d,fmt:%d,name:%s\n", ret, f->fmt, f->name); |
187 | } |
188 | } |
189 | if (i > 0) { |
190 | ret = 0; //ignore the some fmt register error,for compatible some old kernel.can't support muti filename, |
191 | } |
192 | if (ret != 0) { |
193 | close(fd); |
194 | |
195 | } |
196 | |
197 | dsp_ops->dsp_file_fd = fd; |
198 | |
199 | return ret; |
200 | } |
201 | |
202 | /** |
203 | * \brief start audiodsp |
204 | * \param dsp_ops pointer to dsp operation struct |
205 | * \return 0 on success otherwise negative code error |
206 | */ |
207 | static err_count = 0; |
208 | |
209 | #define PARSER_WAIT_MAX 100 |
210 | int audiodsp_start(aml_audio_dec_t *audec) |
211 | { |
212 | int m_fmt; |
213 | int ret = -1; |
214 | unsigned long val; |
215 | dsp_operations_t *dsp_ops = &audec->adsp_ops; |
216 | |
217 | if (dsp_ops->dsp_file_fd < 0) { |
218 | return -1; |
219 | } |
220 | |
221 | if (am_getconfig_bool("media.libplayer.wfd")) { |
222 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_SET_PCM_BUF_SIZE, 8 * 1024); |
223 | } else { |
224 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_SET_PCM_BUF_SIZE, 32 * 1024); |
225 | } |
226 | |
227 | m_fmt = switch_audiodsp(audec->format); |
228 | adec_print("[%s:%d] audio_fmt=%d\n", __FUNCTION__, __LINE__, m_fmt); |
229 | |
230 | if (find_firmware_by_fmt(m_fmt) == NULL) { |
231 | return -2; |
232 | } |
233 | |
234 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_SET_FMT, m_fmt); |
235 | |
236 | ret = ioctl(dsp_ops->dsp_file_fd, AUDIODSP_START, 0); |
237 | if (ret != 0) { |
238 | return -3; |
239 | } |
240 | |
241 | if (audec->need_stop) { //in case stop command comes now |
242 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_STOP, 0); |
243 | return -5; |
244 | } |
245 | |
246 | ret = ioctl(dsp_ops->dsp_file_fd, AUDIODSP_DECODE_START, 0); |
247 | err_count = 0; |
248 | if (ret == 0) { |
249 | do { |
250 | ret = ioctl(dsp_ops->dsp_file_fd, AUDIODSP_WAIT_FORMAT, 0); |
251 | if (ret != 0 && !audec->need_stop) { |
252 | err_count++; |
253 | amthreadpool_thread_usleep(1000 * 20); |
254 | if (err_count > PARSER_WAIT_MAX) { |
255 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_STOP, 0);//audiodsp_start failed,should stop audiodsp |
256 | adec_print("[%s:%d] audio dsp not ready for decode PCM in 2s\n", __FUNCTION__, __LINE__); |
257 | return -4; |
258 | } |
259 | } |
260 | } while (!audec->need_stop && (ret != 0)); |
261 | } |
262 | |
263 | if (ret != 0) { |
264 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_STOP, 0);//audiodsp_start failed,should stop audiodsp |
265 | return -4; |
266 | } |
267 | |
268 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_CHANNELS_NUM, &val); |
269 | if (val != (unsigned long) - 1) { |
270 | audec->channels = val; |
271 | } |
272 | |
273 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_SAMPLERATE, &val); |
274 | if (val != (unsigned long) - 1) { |
275 | audec->samplerate = val; |
276 | } |
277 | |
278 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_BITS_PER_SAMPLE, &val); |
279 | if (val != (unsigned long) - 1) { |
280 | audec->data_width = val; |
281 | } |
282 | adec_print("channels == %d, samplerate == %d\n", audec->channels, audec->samplerate); |
283 | return ret; |
284 | } |
285 | |
286 | /** |
287 | * \brief stop audiodsp |
288 | * \param dsp_ops pointer to dsp operation struct |
289 | * \return 0 on success otherwise -1 if an error occurred |
290 | */ |
291 | int audiodsp_stop(dsp_operations_t *dsp_ops) |
292 | { |
293 | int ret; |
294 | |
295 | if (dsp_ops->dsp_file_fd < 0) { |
296 | return -1; |
297 | } |
298 | |
299 | ret = ioctl(dsp_ops->dsp_file_fd, AUDIODSP_STOP, 0); |
300 | |
301 | return ret; |
302 | } |
303 | |
304 | /** |
305 | * \brief release audiodsp |
306 | * \param dsp_ops pointer to dsp operation struct |
307 | * \return 0 on success otherwise -1 if an error occurred |
308 | */ |
309 | int audiodsp_release(dsp_operations_t *dsp_ops) |
310 | { |
311 | if (dsp_ops->dsp_file_fd < 0) { |
312 | return -1; |
313 | } |
314 | |
315 | close(dsp_ops->dsp_file_fd); |
316 | |
317 | dsp_ops->dsp_file_fd = -1; |
318 | |
319 | return 0; |
320 | } |
321 | |
322 | /** |
323 | * \brief read pcm data from audiodsp |
324 | * \param dsp_ops pointer to dsp operation struct |
325 | * \param buffer point to buffer where storing pcm data |
326 | * \param size read data length |
327 | * \return the number of bytes read |
328 | */ |
329 | int audiodsp_stream_read(dsp_operations_t *dsp_ops, char *buffer, int size) |
330 | { |
331 | if (dsp_ops->dsp_file_fd < 0) { |
332 | adec_print("read error!! audiodsp have not opened\n"); |
333 | return 0; |
334 | } |
335 | |
336 | return read(dsp_ops->dsp_file_fd, buffer, size); |
337 | } |
338 | |
339 | /** |
340 | * \brief get current audio pts |
341 | * \param dsp_ops pointer to dsp operation struct |
342 | * \return current audio pts otherwise -1 if an error occurred |
343 | */ |
344 | unsigned long audiodsp_get_pts(dsp_operations_t *dsp_ops) |
345 | { |
346 | unsigned long val; |
347 | |
348 | if (dsp_ops->dsp_file_fd < 0) { |
349 | adec_print("read error!! audiodsp have not opened\n"); |
350 | return -1; |
351 | } |
352 | |
353 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_PTS, &val); |
354 | |
355 | return val; |
356 | } |
357 | |
358 | /** |
359 | * \brief get current audio pcrscr |
360 | * \param dsp_ops pointer to dsp operation struct |
361 | * \return current audio pcrscr otherwise -1 if an error occurred |
362 | */ |
363 | unsigned long audiodsp_get_pcrscr(dsp_operations_t *dsp_ops) |
364 | { |
365 | unsigned long val; |
366 | |
367 | if (dsp_ops->dsp_file_fd < 0) { |
368 | adec_print("read error!! audiodsp have not opened\n"); |
369 | return -1; |
370 | } |
371 | |
372 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_SYNC_GET_PCRSCR, &val); |
373 | |
374 | return val; |
375 | } |
376 | /** |
377 | * \brief set current audio pts |
378 | * \param dsp_ops pointer to dsp operation struct |
379 | * \return 0 on success otherwise -1 if an error occurred |
380 | */ |
381 | int audiodsp_set_apts(dsp_operations_t *dsp_ops, unsigned long apts) |
382 | { |
383 | |
384 | if (dsp_ops->dsp_file_fd < 0) { |
385 | adec_print("read error!! audiodsp have not opened\n"); |
386 | return -1; |
387 | } |
388 | |
389 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_SYNC_SET_APTS, &apts); |
390 | |
391 | return 0; |
392 | } |
393 | /** |
394 | * \brief get decoded audio frame number |
395 | * \param dsp_ops pointer to dsp operation struct |
396 | * \return audiodsp decoded frame number, -1 if an error occurred |
397 | */ |
398 | int audiodsp_get_decoded_nb_frames(dsp_operations_t *dsp_ops) |
399 | { |
400 | int val = -1; |
401 | if (dsp_ops && dsp_ops->dsp_file_fd) { |
402 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_DECODED_NB_FRAMES, &val); |
403 | } |
404 | //adec_print("get audio decoded frame number==%d\n",val); |
405 | return val; |
406 | } |
407 | |
408 | int audiodsp_get_first_pts_flag(dsp_operations_t *dsp_ops) |
409 | { |
410 | int val; |
411 | |
412 | if (dsp_ops->dsp_file_fd < 0) { |
413 | adec_print("read error!! audiodsp have not opened\n"); |
414 | return -1; |
415 | } |
416 | |
417 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_FIRST_PTS_FLAG, &val); |
418 | |
419 | return val; |
420 | } |
421 | |
422 | int audiodsp_automute_on(dsp_operations_t *dsp_ops) |
423 | { |
424 | int ret; |
425 | |
426 | if (dsp_ops->dsp_file_fd < 0) { |
427 | adec_print("read error!! audiodsp have not opened\n"); |
428 | return -1; |
429 | } |
430 | |
431 | ret = ioctl(dsp_ops->dsp_file_fd, AUDIODSP_AUTOMUTE_ON, 0); |
432 | |
433 | return ret; |
434 | } |
435 | |
436 | int audiodsp_automute_off(dsp_operations_t *dsp_ops) |
437 | { |
438 | int ret; |
439 | |
440 | if (dsp_ops->dsp_file_fd < 0) { |
441 | adec_print("read error!! audiodsp have not opened\n"); |
442 | return -1; |
443 | } |
444 | |
445 | ret = ioctl(dsp_ops->dsp_file_fd, AUDIODSP_AUTOMUTE_OFF, 0); |
446 | |
447 | return ret; |
448 | } |
449 | |
450 | |
451 | int audiodsp_get_pcm_level(dsp_operations_t* dsp_ops) |
452 | { |
453 | int val = 0; |
454 | if (dsp_ops->dsp_file_fd < 0) { |
455 | adec_print("read error !! audiodsp have not opened\n"); |
456 | return -1; |
457 | } |
458 | |
459 | ioctl(dsp_ops->dsp_file_fd, AUDIODSP_GET_PCM_LEVEL, &val); |
460 | return val; |
461 | } |
462 | |
463 | int audiodsp_set_skip_bytes(dsp_operations_t* dsp_ops, unsigned int bytes) |
464 | { |
465 | if (dsp_ops->dsp_file_fd < 0) { |
466 | adec_print("read error !! audiodsp have not opened\n"); |
467 | return -1; |
468 | } |
469 | |
470 | return ioctl(dsp_ops->dsp_file_fd, AUDIODSP_SKIP_BYTES, bytes); |
471 | } |
472 |