blob: 7e8e9e91a89e21c17fbb8a08d704eff53118f0c2 [file] [log] [blame]
Tao Guo2913b912017-01-11 17:56:14 +08001#include <stdio.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <sys/poll.h>
5#include <stdlib.h>
6#include <string.h>
7#include <errno.h>
8#include <unistd.h>
9
10#include <pthread.h>
11#include <sys/ioctl.h>
12#include <fcntl.h>
13
14#include "amAudio.h"
15
16#define LOG_TAG "amAudio_Test"
17
18#undef LOGI
19#define LOGI(fmt, ...) printf("I/%s: ", LOG_TAG);printf(fmt, ##__VA_ARGS__);
20#undef LOGE
21#define LOGE(fmt, ...) printf("E/%s: ", LOG_TAG);printf(fmt, ##__VA_ARGS__);
22#undef LOGD
23#define LOGD(fmt, ...) printf("D/%s: ", LOG_TAG);printf(fmt, ##__VA_ARGS__);
24
25//#define WRITE_AUDIO_OUT_TO_FILE
26#define SELF_TEST
27
28#define AUDIO_IN "/dev/amaudio_in"
29#define AUDIO_OUT "/dev/amaudio_out"
30
31#define AMAUDIO_IOC_MAGIC 'A'
32#define AMAUDIO_IOC_GET_I2S_OUT_SIZE _IOW(AMAUDIO_IOC_MAGIC, 0x00, int)
33#define AMAUDIO_IOC_GET_I2S_OUT_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x01, int)
34#define AMAUDIO_IOC_SET_I2S_OUT_RD_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x02, int)
35#define AMAUDIO_IOC_GET_I2S_IN_SIZE _IOW(AMAUDIO_IOC_MAGIC, 0x03, int)
36#define AMAUDIO_IOC_GET_I2S_IN_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x04, int)
37#define AMAUDIO_IOC_SET_I2S_IN_RD_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x05, int)
38#define AMAUDIO_IOC_SET_I2S_IN_MODE _IOW(AMAUDIO_IOC_MAGIC, 0x06, int)
39#define AMAUDIO_IOC_SET_I2S_OUT_MODE _IOW(AMAUDIO_IOC_MAGIC, 0x07, int)
40#define AMAUDIO_IOC_GET_I2S_IN_RD_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x08, int)
41#define AMAUDIO_IOC_GET_I2S_OUT_RD_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x09, int)
42#define AMAUDIO_IOC_SET_I2S_IN_WR_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x0a, int)
43#define AMAUDIO_IOC_SET_I2S_OUT_WR_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x0b, int)
44#define AMAUDIO_IOC_GET_I2S_IN_WR_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x0c, int)
45#define AMAUDIO_IOC_GET_I2S_OUT_WR_PTR _IOW(AMAUDIO_IOC_MAGIC, 0x0d, int)
46#define AMAUDIO_IOC_SET_LEFT_MONO _IOW(AMAUDIO_IOC_MAGIC, 0x0e, int)
47#define AMAUDIO_IOC_SET_RIGHT_MONO _IOW(AMAUDIO_IOC_MAGIC, 0x0f, int)
48#define AMAUDIO_IOC_SET_STEREO _IOW(AMAUDIO_IOC_MAGIC, 0x10, int)
49#define AMAUDIO_IOC_SET_CHANNEL_SWAP _IOW(AMAUDIO_IOC_MAGIC, 0x11, int)
50#define AMAUDIO_IOC_DIRECT_AUDIO _IOW(AMAUDIO_IOC_MAGIC, 0x12, int)
51#define AMAUDIO_IOC_DIRECT_LEFT_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x13, int)
52#define AMAUDIO_IOC_DIRECT_RIGHT_GAIN _IOW(AMAUDIO_IOC_MAGIC, 0x14, int)
53
54#define M_AUDIO_THREAD_DELAY_TIME 4000
55#define AUDIO_BUFFER_SIZE 19200
56
57static int amAudio_InHandle = -1;
58static int amAudio_OutHandle = -1;
59static int amAudio_InSize = -1;
60static int amAudio_OutSize = -1;
61static unsigned char *amAudio_In_BufAddr = NULL;
62static unsigned char *amAudio_Out_BufAddr = NULL;
63unsigned char *inbuffer_current_position = NULL;
64unsigned char *outbuffer_current_position = NULL;
65
66unsigned char *amAudio_In_BufAddr_half = NULL;
67unsigned char *amAudio_Out_BufAddr_half = NULL;
68
69static pthread_t amAudio_ThreadID = 0;
70static int amAudio_ThreadExitFlag = 0;
71
72#define NODATA 0
73#define BUFFER1_READY 1
74#define BUFFER2_READY 2
75
76typedef struct Buffer_status {
77 int status;
78 unsigned char *user_read;
79} Buffer_status;
80
81Buffer_status Output_buffer_status;
82
83#ifdef WRITE_AUDIO_OUT_TO_FILE
84static FILE *FileIn = NULL;
85static FILE *FileOut = NULL;
86
87#endif
88
89static int amAudio_InInit(void)
90{
91 unsigned int hwptr;
92
93 hwptr = ioctl (amAudio_InHandle, AMAUDIO_IOC_GET_I2S_IN_PTR);
94 if (hwptr == 0xFFFFFFFF)
95 {
96 LOGI("amAudio_InInit Error!\n");
97 return -1;
98 }
99 ioctl (amAudio_InHandle, AMAUDIO_IOC_SET_I2S_IN_RD_PTR, hwptr);
100 inbuffer_current_position = amAudio_In_BufAddr;
101 return 0;
102}
103
104static int amAudio_OutInit(void)
105{
106 unsigned int hwptr;
107
108 hwptr= ioctl (amAudio_OutHandle, AMAUDIO_IOC_GET_I2S_OUT_PTR);
109 if (hwptr == 0xFFFFFFFF)
110 {
111 LOGI("amAudio_OutInit Error!\n");
112 return -1;
113 }
114 ioctl (amAudio_OutHandle, AMAUDIO_IOC_SET_I2S_OUT_RD_PTR, hwptr);
115 outbuffer_current_position = amAudio_Out_BufAddr;
116 return 0;
117}
118
119static int amAudio_InProc(void)
120{
121 int Ret;
122 int hwptr;
123 int rdptr;
124 int Bytes;
125 int PosBytes;
126 int left_size = AUDIO_BUFFER_SIZE - (inbuffer_current_position - amAudio_In_BufAddr);
127
128 if(amAudio_InHandle == -1){
129 LOGE("amAudio_InHandle error: %d\n", -1);
130 }
131
132 hwptr = ioctl (amAudio_InHandle, AMAUDIO_IOC_GET_I2S_IN_PTR);
133 if (hwptr == 0xFFFFFFFF)
134 return -1;
135
136 rdptr = ioctl (amAudio_InHandle, AMAUDIO_IOC_GET_I2S_IN_RD_PTR);
137 if (rdptr == 0xFFFFFFFF)
138 return -1;
139
140 Bytes = (hwptr - rdptr + amAudio_InSize) % amAudio_InSize;
141 Bytes = Bytes >> 2 << 2;
142
143 //LOGD("amAudio in hwptr: %x, rdptr: %x, Bytes: %x, left_size = %x\n", hwptr, rdptr, Bytes,left_size);
144
145 if (Bytes == 0)
146 return 0;
147
148 if(hwptr > rdptr){
149 PosBytes = Bytes;
150 if(left_size >= PosBytes){
151 Ret = read (amAudio_InHandle, inbuffer_current_position, PosBytes);
152 if(Ret != PosBytes){
153 LOGE("amAudio_in fail to read! Ret = %d, PosBytes = %d \n",Ret, PosBytes);
154 return -1;
155 }
156#ifdef WRITE_AUDIO_OUT_TO_FILE
157 fwrite(inbuffer_current_position, 1, PosBytes, FileIn);
158#endif
159 inbuffer_current_position += PosBytes;
160 if(left_size == PosBytes){
161 inbuffer_current_position = amAudio_In_BufAddr;
162 }
163 }else{
164 Ret = read (amAudio_InHandle, inbuffer_current_position, left_size);
165 if(Ret != left_size){
166 LOGE("amAudio_in fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
167 return -1;
168 }
169#ifdef WRITE_AUDIO_OUT_TO_FILE
170 fwrite(inbuffer_current_position, 1, left_size, FileIn);
171#endif
172 inbuffer_current_position = amAudio_In_BufAddr;
173 left_size = PosBytes - left_size;
174 Ret = read (amAudio_InHandle, inbuffer_current_position, left_size);
175 if(Ret != left_size){
176 LOGE("amAudio_in fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
177 return -1;
178 }
179#ifdef WRITE_AUDIO_OUT_TO_FILE
180 fwrite(inbuffer_current_position, 1, left_size, FileIn);
181#endif
182 inbuffer_current_position = amAudio_In_BufAddr + left_size;
183 }
184 }else{
185
186 PosBytes = amAudio_InSize - rdptr;
187
188 if(left_size >= PosBytes){
189 Ret = read (amAudio_InHandle, inbuffer_current_position, PosBytes);
190 if(Ret != PosBytes){
191 LOGE("amAudio_in fail to read! Ret = %d, PosBytes = %d \n",Ret, PosBytes);
192 return -1;
193 }
194#ifdef WRITE_AUDIO_OUT_TO_FILE
195 fwrite(inbuffer_current_position, 1, PosBytes, FileIn);
196#endif
197 inbuffer_current_position += PosBytes;
198 if(left_size == PosBytes)
199 inbuffer_current_position = amAudio_In_BufAddr;
200 }else{
201 Ret = read (amAudio_InHandle, inbuffer_current_position, left_size);
202 if(Ret != left_size){
203 LOGE("amAudio_in fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
204 return -1;
205 }
206#ifdef WRITE_AUDIO_OUT_TO_FILE
207 fwrite(inbuffer_current_position, 1, left_size, FileIn);
208#endif
209 inbuffer_current_position = amAudio_In_BufAddr;
210 left_size = PosBytes - left_size;
211 Ret = read (amAudio_InHandle, inbuffer_current_position, left_size);
212 if(Ret != left_size){
213 LOGE("amAudio_in fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
214 return -1;
215 }
216#ifdef WRITE_AUDIO_OUT_TO_FILE
217 fwrite(inbuffer_current_position, 1, left_size, FileIn);
218#endif
219 inbuffer_current_position = amAudio_In_BufAddr + left_size;
220 }
221
222 PosBytes = Bytes - PosBytes;
223
224 left_size = AUDIO_BUFFER_SIZE - (inbuffer_current_position - amAudio_In_BufAddr);
225
226 if(left_size >= PosBytes){
227 Ret = read (amAudio_InHandle, inbuffer_current_position, PosBytes);
228 if(Ret != PosBytes){
229 LOGE("amAudio_in fail to read! Ret = %d, PosBytes = %d \n",Ret, PosBytes);
230 return -1;
231 }
232#ifdef WRITE_AUDIO_OUT_TO_FILE
233 fwrite(inbuffer_current_position, 1, PosBytes, FileIn);
234#endif
235 inbuffer_current_position += PosBytes;
236 if(left_size == PosBytes)
237 inbuffer_current_position = amAudio_In_BufAddr;
238 }else{
239 Ret = read (amAudio_InHandle, inbuffer_current_position, left_size);
240 if(Ret != left_size){
241 LOGE("amAudio_in fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
242 return -1;
243 }
244#ifdef WRITE_AUDIO_OUT_TO_FILE
245 fwrite(inbuffer_current_position, 1, left_size, FileIn);
246#endif
247 inbuffer_current_position = amAudio_In_BufAddr;
248 left_size = PosBytes - left_size;
249 Ret = read (amAudio_InHandle, inbuffer_current_position, left_size);
250 if(Ret != left_size){
251 LOGE("amAudio_in fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
252 return -1;
253 }
254#ifdef WRITE_AUDIO_OUT_TO_FILE
255 fwrite(inbuffer_current_position, 1, left_size, FileIn);
256#endif
257 inbuffer_current_position = amAudio_In_BufAddr + left_size;
258 }
259
260 }
261 return 0;
262}
263
264static int amAudio_OutProc(void)
265{
266 int hwptr;
267 int rdptr;
268 int Bytes;
269 int Ret;
270 int PosBytes;
271 int left_size = AUDIO_BUFFER_SIZE - (outbuffer_current_position - amAudio_Out_BufAddr);
272
273 hwptr = ioctl (amAudio_OutHandle, AMAUDIO_IOC_GET_I2S_OUT_PTR);
274 if (hwptr == 0xFFFFFFFF)
275 return -1;
276
277 rdptr = ioctl (amAudio_OutHandle, AMAUDIO_IOC_GET_I2S_OUT_RD_PTR);
278 if (rdptr == 0xFFFFFFFF)
279 return -1;
280
281 Bytes = (hwptr - rdptr + amAudio_OutSize) % amAudio_OutSize;
282 Bytes = Bytes >> 2 << 2;
283
284 //LOGD("amAudio out hwptr: %x, rdptr: %x, Bytes: %x, left_size = %x, status = %d\n", hwptr, rdptr, Bytes,left_size,(int)Output_buffer_status.status);
285
286 if (Bytes == 0)
287 return 0;
288
289 if(hwptr > rdptr)
290 PosBytes = Bytes;
291 else
292 PosBytes = amAudio_OutSize - rdptr;
293 {
294 if(left_size >= PosBytes){
295 Ret = read (amAudio_OutHandle, outbuffer_current_position, PosBytes);
296 if(Ret != PosBytes){
297 LOGE("amAudio_out fail to read! Ret = %d, PosBytes = %d \n",Ret, PosBytes);
298 return -1;
299 }
300#ifdef WRITE_AUDIO_OUT_TO_FILE
301 fwrite(outbuffer_current_position, 1, PosBytes, FileOut);
302#endif
303 outbuffer_current_position += PosBytes;
304
305 if (outbuffer_current_position - PosBytes < amAudio_Out_BufAddr_half){
306 if (outbuffer_current_position >= amAudio_Out_BufAddr_half)
307 Output_buffer_status.status = BUFFER1_READY;
308 Output_buffer_status.user_read = amAudio_Out_BufAddr;
309 }
310 else{
311 Output_buffer_status.user_read = amAudio_Out_BufAddr_half;
312 }
313 if(left_size == PosBytes){
314 outbuffer_current_position = amAudio_Out_BufAddr;
315 Output_buffer_status.status |= BUFFER2_READY;
316 }
317 }else{
318 Ret = read (amAudio_OutHandle, outbuffer_current_position, left_size);
319 if(Ret != left_size){
320 LOGE("amAudio_out fail to read! Ret = %d, left_size = %d \n",Ret, left_size);
321 return -1;
322 }
323#ifdef WRITE_AUDIO_OUT_TO_FILE
324 fwrite(outbuffer_current_position, 1, left_size, FileOut);
325#endif
326 if (outbuffer_current_position < amAudio_Out_BufAddr_half){
327 Output_buffer_status.status = BUFFER1_READY|BUFFER2_READY;
328 Output_buffer_status.user_read = amAudio_Out_BufAddr;
329 }
330 else{
331 Output_buffer_status.status = BUFFER2_READY;
332 Output_buffer_status.user_read = amAudio_Out_BufAddr_half;
333 }
334 outbuffer_current_position = amAudio_Out_BufAddr;
335 }
336 }
337 return 0;
338}
339
340static void *amAudio_Thread(void *data)
341{
342 int Ret = 0;
343 int Status = 0;
344 newDataCallback callback = (newDataCallback)data;
345 while (1)
346 {
347 if (amAudio_ThreadExitFlag == 1)
348 {
349 amAudio_ThreadExitFlag = 0;
350 break;
351 }
352
353 switch (Status)
354 {
355 case 0:
356 //Ret = amAudio_InInit();
357 if (Ret == 0)
358 {
359 Status = 1;
360 }
361 break;
362 case 1:
363 Ret = amAudio_OutInit();
364 if (Ret == 0)
365 {
366 Status = 2;
367 }
368 break;
369 case 2:
370 //Ret = amAudio_InProc();
371 if (Ret == 0)
372 {
373 Status = 3;
374 }else{
375 Status = 0;
376 }
377 break;
378 case 3:
379 Ret = amAudio_OutProc();
380 if (Ret == 0)
381 {
382 Status = 2;
383 }else{
384 Status = 1;
385 }
386 if ((Output_buffer_status.status & BUFFER1_READY)
387 ||(Output_buffer_status.status & BUFFER2_READY)){
388 if ((Output_buffer_status.status & BUFFER1_READY)
389 &&(Output_buffer_status.status & BUFFER2_READY))
390 (*callback)(Output_buffer_status.user_read, AUDIO_BUFFER_SIZE);
391 else
392 (*callback)(Output_buffer_status.user_read, AUDIO_BUFFER_SIZE/2);
393 Output_buffer_status.status = NODATA;
394 }
395 break;
396 if(Status == 0 && Status == 1)
397 LOGE("error: new reset!\n");
398 }
399
400 usleep (M_AUDIO_THREAD_DELAY_TIME);
401 }
402
403 pthread_exit (0);
404
405 return ((void*)0);
406}
407
408static int amAudio_AmlogicInit (newDataCallback callback)
409{
410 pthread_attr_t attr;
411 struct sched_param param;
412 int Ret;
413
414 /*amAudio_InHandle = open (AUDIO_IN, O_RDWR);
415 if (amAudio_InHandle < 0)
416 {
417 LOGE("The device amaudio_in cant't be opened!\n");
418 return -1;
419 }*/
420
421 amAudio_OutHandle = -1;
422 while (amAudio_OutHandle < 0){
423 amAudio_OutHandle = open (AUDIO_OUT, O_RDWR);
424 if (amAudio_OutHandle < 0){
425 LOGE("The device amaudio_out cant't be opened!\n");
426 sleep(5);
427 }
428 else{
429 break;
430 }
431 if (amAudio_ThreadExitFlag == 1){
432 amAudio_ThreadExitFlag = 0;
433 return -1;
434 }
435 }
436
437 //ioctl (amAudio_InHandle, AMAUDIO_IOC_SET_I2S_IN_MODE, 1);
438 ioctl (amAudio_OutHandle, AMAUDIO_IOC_SET_I2S_OUT_MODE, 1);
439
440 //ioctl (amAudio_InHandle, AMAUDIO_IOC_DIRECT_LEFT_GAIN, 0);
441 //ioctl (amAudio_InHandle, AMAUDIO_IOC_DIRECT_RIGHT_GAIN, 0);
442
443 /*amAudio_InSize = ioctl (amAudio_InHandle, AMAUDIO_IOC_GET_I2S_IN_SIZE, 0);
444 LOGI("amAudio_InSize = 0x%x !\n",amAudio_InSize);
445 if (amAudio_InSize == -1)
446 {
447 close (amAudio_OutHandle);
448 amAudio_OutHandle = -1;
449 close (amAudio_InHandle);
450 amAudio_InHandle = -1;
451 return -1;
452 }*/
453
454 amAudio_OutSize = ioctl (amAudio_OutHandle, AMAUDIO_IOC_GET_I2S_OUT_SIZE, 0);
455 LOGI("amAudio_OutSize = 0x%x !\n",amAudio_OutSize);
456 if (amAudio_OutSize == -1)
457 {
458 close (amAudio_OutHandle);
459 amAudio_OutHandle = -1;
460 //close (amAudio_InHandle);
461 //amAudio_InHandle = -1;
462 return -1;
463 }
464
465 amAudio_In_BufAddr = (unsigned char *)malloc (AUDIO_BUFFER_SIZE);
466 amAudio_Out_BufAddr = (unsigned char *)malloc (AUDIO_BUFFER_SIZE);
467
468 /*if (amAudio_In_BufAddr == NULL || amAudio_Out_BufAddr == NULL)
469 {
470 LOGE("Fail to malloc amaudio buffer!\n");
471 close (amAudio_OutHandle);
472 amAudio_OutHandle = -1;
473 close (amAudio_InHandle);
474 amAudio_InHandle = -1;
475 return -1;
476 }*/
477
478 amAudio_In_BufAddr_half = amAudio_In_BufAddr + AUDIO_BUFFER_SIZE/2;
479 amAudio_Out_BufAddr_half = amAudio_Out_BufAddr + AUDIO_BUFFER_SIZE/2;
480 Output_buffer_status.status = NODATA;
481 Output_buffer_status.user_read = NULL;
482
483 pthread_attr_init (&attr);
484 pthread_attr_setschedpolicy (&attr, SCHED_RR);
485 param.sched_priority = sched_get_priority_max (SCHED_RR);
486 pthread_attr_setschedparam (&attr, &param);
487 amAudio_ThreadExitFlag = 0;
488 Ret = pthread_create (&amAudio_ThreadID, &attr, &amAudio_Thread, (void*)callback);
489 pthread_attr_destroy (&attr);
490
491 if (Ret != 0)
492 {
493 LOGE("Fail to create thread!\n");
494 free(amAudio_In_BufAddr);
495 amAudio_In_BufAddr = NULL;
496 free(amAudio_Out_BufAddr);
497 amAudio_Out_BufAddr = NULL;
498
499 close (amAudio_OutHandle);
500 amAudio_OutHandle = -1;
501 //close (amAudio_InHandle);
502 //amAudio_InHandle = -1;
503 return -1;
504 }
505
506 return 0;
507}
508
509static int amAudio_AmlogicFinish (void)
510{
511 amAudio_ThreadExitFlag = 1;
512 pthread_join(amAudio_ThreadID, NULL);
513
514 free(amAudio_In_BufAddr);
515 amAudio_In_BufAddr = NULL;
516
517 free(amAudio_Out_BufAddr);
518 amAudio_Out_BufAddr = NULL;
519
520 close (amAudio_OutHandle);
521 amAudio_OutHandle = -1;
522
523 //close (amAudio_InHandle);
524 //amAudio_InHandle = -1;
525
526 return 0;
527}
528
529int amAudio_Init(newDataCallback callback)
530{
531 int Ret;
532
533 LOGI("Audio capture start!\n");
534
535#ifdef WRITE_AUDIO_OUT_TO_FILE
536 FileIn = fopen ("/mnt/test_in.pcm", "wb");
537 FileOut = fopen ("/mnt/test_out.pcm", "wb");
538 if(FileOut == NULL || FileIn == NULL)
539 LOGE("The file can't be opened!\n");
540#endif
541
542 Ret = amAudio_AmlogicInit(callback);
543 if (Ret == 0){
544 return 0;
545 }else{
546 amAudio_AmlogicFinish();
547 return -1;
548 }
549}
550
551int amAudio_Finish (void)
552{
553 amAudio_AmlogicFinish ();
554
555#ifdef WRITE_AUDIO_OUT_TO_FILE
556 if (FileOut != NULL)
557 {
558 fclose (FileOut);
559 FileOut = NULL;
560 }
561#endif
562 LOGI("Audio capture finish!\n");
563 return 0;
564}
565
566#ifdef SELF_TEST
567static FILE *pcm_dumpfile = NULL;
568void amAudio_Callback(unsigned char *buf, unsigned len)
569{
570 if (pcm_dumpfile){
571 LOGD("write %x %x to file\n", buf, len);
572 fwrite(buf, len, 1, pcm_dumpfile);
573 }
574}
575
576int main (void)
577{
578 pcm_dumpfile = fopen("output.pcm","wb");
579 amAudio_Init(&amAudio_Callback);
580 //while (1);
581 sleep(10);
582 amAudio_Finish();
583 if (pcm_dumpfile)
584 fclose(pcm_dumpfile);
585 return 0;
586}
587#endif
588