blob: 1ee68c2cd56870675470416b5a78b8164a317ac4
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <fcntl.h> |
5 | #include <pthread.h> |
6 | #include <sys/ioctl.h> |
7 | #include <dlfcn.h> |
8 | |
9 | #include <audio-dec.h> |
10 | #include <adec-pts-mgt.h> |
11 | #include <adec_write.h> |
12 | #include "adec_omx_brige.h" |
13 | #include <amthreadpool.h> |
14 | #include "Amsysfsutils.h" |
15 | #include "amconfigutils.h" |
16 | |
17 | #define LOG_TAG "Adec_omx_bridge" |
18 | #define adec_print(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) |
19 | #define SIZE_FOR_MX_BYPASS (48*1024) //about 0.25s for 48K_16bit |
20 | |
21 | int find_omx_lib(aml_audio_dec_t *audec) |
22 | { |
23 | audio_decoder_operations_t *adec_ops = audec->adec_ops; |
24 | audec->StageFrightCodecEnableType = 0; |
25 | audec->parm_omx_codec_init = NULL; |
26 | audec->parm_omx_codec_read = NULL; |
27 | audec->parm_omx_codec_close = NULL; |
28 | audec->parm_omx_codec_start = NULL; |
29 | audec->parm_omx_codec_pause = NULL; |
30 | audec->parm_omx_codec_get_declen = NULL; |
31 | audec->parm_omx_codec_get_FS = NULL; |
32 | audec->parm_omx_codec_get_Nch = NULL; |
33 | |
34 | if (audec->format == ACODEC_FMT_AC3) { |
35 | #ifndef USE_ARM_AUDIO_DEC |
36 | audec->adec_ops->nOutBufSize = SIZE_FOR_MX_BYPASS; |
37 | #endif |
38 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_AC3; |
39 | } else if (audec->format == ACODEC_FMT_EAC3) { |
40 | #ifndef USE_ARM_AUDIO_DEC |
41 | audec->adec_ops->nOutBufSize = SIZE_FOR_MX_BYPASS; |
42 | #endif |
43 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_EAC3; |
44 | } else if (audec->format == ACODEC_FMT_ALAC) { |
45 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_ALAC; |
46 | } else if (audec->format == ACODEC_FMT_MPEG || audec->format == ACODEC_FMT_MPEG1 || audec->format == ACODEC_FMT_MPEG2) { |
47 | if (0/*!am_getconfig_bool("media.libplayer.usemad")*/) { |
48 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_MPEG_LAYER_II; //mpeg1-3, new omx libmpg123 |
49 | } |
50 | } else if (audec->format == ACODEC_FMT_WMA) { |
51 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_WMA; |
52 | } else if (audec->format == ACODEC_FMT_WMAPRO) { |
53 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_WMAPRO; |
54 | } else if (audec->format == ACODEC_FMT_DTS) { |
55 | #ifndef USE_ARM_AUDIO_DEC |
56 | audec->adec_ops->nOutBufSize = SIZE_FOR_MX_BYPASS; |
57 | #endif |
58 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_DTSHD; |
59 | } else if (audec->format == ACODEC_FMT_VORBIS) { |
60 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_VORBIS; |
61 | } else if (audec->format == ACODEC_FMT_TRUEHD) { |
62 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_TRUEHD; |
63 | } else if (audec->format == ACODEC_FMT_WMAVOI) { |
64 | audec->StageFrightCodecEnableType = OMX_ENABLE_CODEC_WMAVOI; |
65 | } |
66 | |
67 | adec_print("%s %d audec->format=%d \n", __FUNCTION__, __LINE__, audec->format); |
68 | |
69 | if (audec->StageFrightCodecEnableType) { |
70 | int *fd = NULL; |
71 | fd = dlopen("libamadec_omx_api.so", RTLD_NOW); |
72 | if (fd != NULL) { |
73 | audec->parm_omx_codec_init = dlsym(fd, "arm_omx_codec_init"); |
74 | audec->parm_omx_codec_read = dlsym(fd, "arm_omx_codec_read"); |
75 | audec->parm_omx_codec_close = dlsym(fd, "arm_omx_codec_close"); |
76 | audec->parm_omx_codec_start = dlsym(fd, "arm_omx_codec_start"); |
77 | audec->parm_omx_codec_pause = dlsym(fd, "arm_omx_codec_pause"); |
78 | audec->parm_omx_codec_get_declen = dlsym(fd, "arm_omx_codec_get_declen"); |
79 | audec->parm_omx_codec_get_FS = dlsym(fd, "arm_omx_codec_get_FS"); |
80 | audec->parm_omx_codec_get_Nch = dlsym(fd, "arm_omx_codec_get_Nch"); |
81 | } else { |
82 | adec_print("[NOTE]cant find libamadec_omx_api.so ,StageFrightCodecEnableType=0\n"); |
83 | audec->StageFrightCodecEnableType = 0; |
84 | return 0; |
85 | } |
86 | } |
87 | |
88 | if (audec->parm_omx_codec_init == NULL || audec->parm_omx_codec_read == NULL || audec->parm_omx_codec_close == NULL || |
89 | audec->parm_omx_codec_start == NULL || audec->parm_omx_codec_pause == NULL || audec->parm_omx_codec_get_declen == NULL || |
90 | audec->parm_omx_codec_get_FS == NULL || audec->parm_omx_codec_get_Nch == NULL |
91 | ) { |
92 | adec_print("[NOTE]load func_api in libamadec_omx_api.so faided, StageFrightCodecEnableType=0\n"); |
93 | audec->StageFrightCodecEnableType = 0; |
94 | return 0; |
95 | } |
96 | adec_print("%s %d StageFrightCodecEnableType=%d \n", __FUNCTION__, __LINE__, audec->StageFrightCodecEnableType); |
97 | return audec->StageFrightCodecEnableType; |
98 | } |
99 | |
100 | static char pcm_buf_tmp[AVCODEC_MAX_AUDIO_FRAME_SIZE];//max frame size out buf |
101 | void omx_codec_Release(); |
102 | extern int read_buffer(unsigned char *buffer, int size); |
103 | |
104 | void *audio_decode_loop_omx(void *args) |
105 | { |
106 | int ret; |
107 | aml_audio_dec_t *audec; |
108 | audio_out_operations_t *aout_ops; |
109 | audio_decoder_operations_t *adec_ops; |
110 | |
111 | int nNextFrameSize = 0; //next read frame size |
112 | int nAudioFormat; |
113 | char *inbuf = NULL;//real buffer |
114 | int dlen = 0;//decode size one time |
115 | int outlen = 0; |
116 | char *outbuf = pcm_buf_tmp, *outbuf_raw; |
117 | int outlen_raw = 0; |
118 | int rawoutput_enable; |
119 | buffer_stream_t *g_bst, *g_bst_raw; |
120 | AudioInfo g_AudioInfo = {0}; |
121 | adec_print("\n\naudio_decode_loop_omx start!\n"); |
122 | |
123 | audec = (aml_audio_dec_t *)args; |
124 | aout_ops = &audec->aout_ops; |
125 | adec_ops = audec->adec_ops; |
126 | memset(outbuf, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE); |
127 | nAudioFormat = audec->format; |
128 | nNextFrameSize = adec_ops->nInBufSize; |
129 | g_bst = audec->g_bst; |
130 | g_bst_raw = audec->g_bst_raw; |
131 | |
132 | rawoutput_enable = amsysfs_get_sysfs_int("/sys/class/audiodsp/digital_raw"); |
133 | adec_print("rawoutput_enable/%d", rawoutput_enable); |
134 | if (rawoutput_enable == 1 && audec->StageFrightCodecEnableType == OMX_ENABLE_CODEC_TRUEHD) { |
135 | adec_print("truehd passthrough enable only when hdmi passthr\n"); |
136 | rawoutput_enable = 0; |
137 | } |
138 | if (audec->parm_omx_codec_init && audec->parm_omx_codec_start) { |
139 | (*audec->parm_omx_codec_init)(audec, audec->StageFrightCodecEnableType, (void*)read_buffer, &audec->exit_decode_thread); |
140 | (*audec->parm_omx_codec_start)(audec); |
141 | } else { |
142 | audec->exit_decode_thread = 1; |
143 | adec_print("audio_decode_loop_omx start failed!"); |
144 | } |
145 | audec->OmxFirstFrameDecoded = 0; |
146 | while (1) { |
147 | exit_decode_loop: |
148 | if (audec->exit_decode_thread) { //detect quit condition |
149 | break; |
150 | } |
151 | outbuf = pcm_buf_tmp; |
152 | outlen = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
153 | (*audec->parm_omx_codec_read)(audec, outbuf, &outlen, &audec->exit_decode_thread); |
154 | |
155 | outlen_raw = 0; |
156 | if (audec->StageFrightCodecEnableType == OMX_ENABLE_CODEC_DTSHD || |
157 | audec->StageFrightCodecEnableType == OMX_ENABLE_CODEC_TRUEHD) { |
158 | int outlen0 = outlen; |
159 | if (outlen > 8) { |
160 | memcpy(&outlen, outbuf, 4); |
161 | outbuf += 4; |
162 | if (outlen + 8 < outlen0) { |
163 | memcpy(&outlen_raw, outbuf + outlen, 4); |
164 | outbuf_raw = outbuf + outlen + 4; |
165 | } |
166 | } else { |
167 | outlen = 0; |
168 | } |
169 | } else if ((audec->StageFrightCodecEnableType == OMX_ENABLE_CODEC_AC3) || |
170 | (audec->StageFrightCodecEnableType == OMX_ENABLE_CODEC_EAC3)) { |
171 | if (outlen > 8) { |
172 | memcpy(&outlen, outbuf, 4); |
173 | outbuf += 4; |
174 | memcpy(&outlen_raw, outbuf + outlen, 4); |
175 | outbuf_raw = outbuf + outlen + 4; |
176 | memset(outbuf + outlen, 0, 4); |
177 | } else { |
178 | outlen = 0; |
179 | } |
180 | } |
181 | if (outlen > 0) { |
182 | memset(&g_AudioInfo, 0, sizeof(AudioInfo)); |
183 | g_AudioInfo.channels = (*audec->parm_omx_codec_get_Nch)(audec); |
184 | g_AudioInfo.samplerate = (*audec->parm_omx_codec_get_FS)(audec); |
185 | if (g_AudioInfo.channels != 0 && g_AudioInfo.samplerate != 0) { |
186 | if (!audec->OmxFirstFrameDecoded) { |
187 | g_bst->channels = audec->channels = g_AudioInfo.channels; |
188 | g_bst->samplerate = audec->samplerate = g_AudioInfo.samplerate; |
189 | audec->OmxFirstFrameDecoded = 1; |
190 | } else if (audec->OmxFirstFrameDecoded == 1) { |
191 | if ((g_AudioInfo.channels != g_bst->channels) || (g_AudioInfo.samplerate != g_bst->samplerate)) { |
192 | while (audec->format_changed_flag && !audec->exit_decode_thread) { |
193 | amthreadpool_thread_usleep(20000); |
194 | } |
195 | if (!audec->exit_decode_thread) { |
196 | adec_print("Info Changed: src:sample:%d channel:%d dest sample:%d channel:%d \n", |
197 | g_bst->samplerate, g_bst->channels, g_AudioInfo.samplerate, g_AudioInfo.channels); |
198 | g_bst->channels = g_AudioInfo.channels; |
199 | g_bst->samplerate = g_AudioInfo.samplerate; |
200 | aout_ops->pause(audec); |
201 | audec->format_changed_flag = 1; |
202 | } |
203 | } |
204 | } |
205 | } |
206 | } |
207 | if (outlen > 0) { |
208 | dlen = (*audec->parm_omx_codec_get_declen)(audec); |
209 | } else { |
210 | dlen = 0; |
211 | } |
212 | //write to the pcm buffer |
213 | audec->decode_offset += dlen; |
214 | audec->pcm_cache_size = outlen; |
215 | |
216 | if (g_bst) { |
217 | int wlen = 0; |
218 | while (outlen && !audec->exit_decode_thread) { |
219 | if ((g_bst->buf_length - g_bst->buf_level) < outlen) { |
220 | amthreadpool_thread_usleep(20000); |
221 | continue; |
222 | } |
223 | wlen = write_pcm_buffer(outbuf, g_bst, outlen); |
224 | outlen -= wlen; |
225 | audec->pcm_cache_size -= wlen; |
226 | } |
227 | |
228 | while (rawoutput_enable && !audec->exit_decode_thread && outlen_raw && aout_ops->audio_out_raw_enable) { |
229 | if (g_bst_raw->buf_length - g_bst_raw->buf_level < outlen_raw) { |
230 | amthreadpool_thread_usleep(20000); |
231 | continue; |
232 | } |
233 | wlen = write_pcm_buffer(outbuf_raw, g_bst_raw, outlen_raw); |
234 | outlen_raw -= wlen; |
235 | } |
236 | } |
237 | } |
238 | |
239 | adec_print("[%s %d] has stepped out decodeloop \n", __FUNCTION__, __LINE__); |
240 | if (audec->StageFrightCodecEnableType && audec->parm_omx_codec_close) { |
241 | (*audec->parm_omx_codec_close)(audec); |
242 | } |
243 | adec_print("Exit audio_decode_loop_omx Thread finished!"); |
244 | pthread_exit(NULL); |
245 | return NULL; |
246 | } |
247 | |
248 | |
249 | void start_decode_thread_omx(aml_audio_dec_t *audec) |
250 | { |
251 | int ret; |
252 | pthread_t tid; |
253 | int wait_aout_ops_start_time = 0; |
254 | |
255 | ret = amthreadpool_pthread_create(&tid, NULL, (void *)audio_decode_loop_omx, (void *)audec); |
256 | if (ret != 0) { |
257 | adec_print("Create <audio_decode_loop_omx> thread failed!\n"); |
258 | return; |
259 | } |
260 | audec->sn_threadid = tid; |
261 | pthread_setname_np(tid, "AmadecDecodeLP"); |
262 | adec_print("Create <audio_decode_loop_omx> thread success! tid = %d\n", tid); |
263 | |
264 | while ((!audec->need_stop) && (!audec->OmxFirstFrameDecoded)) { |
265 | amthreadpool_thread_usleep(50); |
266 | wait_aout_ops_start_time++; |
267 | } |
268 | adec_print("[%s] start thread finished: <audec->OmxFirstFrameDecoded=%d> used time: %d*50(us)\n", __FUNCTION__, audec->OmxFirstFrameDecoded, wait_aout_ops_start_time); |
269 | |
270 | } |
271 | |
272 | |
273 | void stop_decode_thread_omx(aml_audio_dec_t *audec) |
274 | { |
275 | audec->exit_decode_thread = 1; |
276 | int ret = amthreadpool_pthread_join(audec->sn_threadid, NULL); |
277 | //audec->exit_decode_thread = 0; |
278 | audec->sn_threadid = -1; |
279 | audec->sn_getpackage_threadid = -1; |
280 | } |
281 | |
282 | |
283 | |
284 | |
285 |