blob: e7fa8554fb05112696e8662456796e83fa4f8745 [file] [log] [blame]
Tim Yao5351d702020-01-20 16:56:42 -08001/*
2 * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <sys/mman.h>
19#include <fcntl.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <unistd.h>
23#include "audio_if.h"
24
25#define min(a, b) ((a) < (b) ? (a) : (b))
26#define WRITE_UNIT 4096
27
28#define FORMAT_PCM16 0
29#define FORMAT_PCM32 1
30#define FORMAT_DD 2
31#define FORMAT_MAT 3
32#define FORMAT_IEC61937 4
33#define FORMAT_AC4 5
34#define FORMAT_MAX 6
35
36static int format_tab[] = {AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_32_BIT, AUDIO_FORMAT_AC3, AUDIO_FORMAT_MAT, AUDIO_FORMAT_IEC61937, AUDIO_FORMAT_AC4};
37static const char *format_str[] = {
38 "PCM_16", "PCM_32", "DOLBY DD/DD+", "DOLBY MAT", "IEC_61937", "AC4"
39};
40
41static int format_is_pcm(int format)
42{
43 return (format == FORMAT_PCM16) || (format == FORMAT_PCM32);
44}
45
46static unsigned char *fmap(const char *fn, int *size, int *fd)
47{
48 int fd_r, r;
49 struct stat st;
50 unsigned char *p;
51
52 fd_r = open(fn, O_RDWR);
53
54 if (fd_r < 0)
55 return NULL;
56
57 *fd = fd_r;
58 r = fstat(fd_r, &st);
59 *size = st.st_size;
60 return mmap(0, st.st_size, PROT_READ|PROT_EXEC, MAP_SHARED, fd_r, 0);
61}
62
63static void funmap(unsigned char *p, int size, int fd)
64{
65 if (p && size > 0)
66 munmap(p, size);
67 if (fd >= 0)
68 close(fd);
69}
70
71static int test_stream(struct audio_stream_out *stream, unsigned char *buf, int size)
72{
73 int ret;
74 int len = size;
75 unsigned char *data = buf;
76
77 ret = stream->common.standby(&stream->common);
78 if (ret) {
79 fprintf(stderr, "%s %d, ret:%x\n",
80 __func__, __LINE__, ret);
81 return -1;
82 }
83
84 ret = stream->set_volume(stream, 1.0f, 1.0f);
85 if (ret) {
86 fprintf(stderr, "%s %d, ret:%x\n", __func__, __LINE__, ret);
87 return -1;
88 }
89
90 while (len > 0) {
91 ssize_t s = stream->write(stream, data, min(len, WRITE_UNIT));
92 if (s < 0) {
93 fprintf(stderr, "stream writing error %d\n", s);
94 break;
95 }
96
97 len -= s;
98 data += s;
99 }
100
101 return 0;
102}
103
104static void test_output_stream(audio_hw_device_t *device, unsigned char *buf, int size, struct audio_config *config)
105{
106 struct audio_stream_out *stream;
107 int ret;
108
109 printf("open output speaker...\n");
110 ret = device->open_output_stream(device,
111 0, AUDIO_DEVICE_OUT_SPEAKER,
112 AUDIO_OUTPUT_FLAG_PRIMARY, config,
113 &stream, NULL);
114 if (ret) {
115 printf("fail\n");
116 return;
117 } else {
118 printf("success\n");
119 }
120
121 test_stream(stream, buf, size);
122
123 printf("close output speaker...\n");
124 device->close_output_stream(device, stream);
125}
126
127int main(int argc, char **argv)
128{
129 audio_hw_device_t *device;
130 int ret, c = -1, format = FORMAT_MAX, ch = 0, sr = 0;
131 struct audio_config config;
132 const char *fn = NULL;
133 int size = 0;
134 unsigned char *buf;
135 int fd = -1;
136
137 if (argc == 1) {
138 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
139 return 0;
140 }
141
142 while ((c = getopt(argc, argv, "f:c:r:")) != -1) {
143 switch (c) {
144 case 'f':
145 format = atoi(optarg);
146 break;
147 case 'c':
148 ch = atoi(optarg);
149 break;
150 case 'r':
151 sr = atoi(optarg);
152 break;
153 case '?':
154 fprintf(stderr, "Error in an argument.\n");
155 return -1;
156 default:
157 return -1;
158 }
159 }
160
161 if (optind < argc) {
162 fn = argv[optind];
163 }
164
165 if (!fn) {
166 fprintf(stderr, "No file name specified\n");
167 return -1;
168 }
169
170 if ((format < 0) || (format >= FORMAT_MAX)) {
171 int i;
172 fprintf(stderr, "Wrong format, valid format:\n");
173 for (i = 0; i < FORMAT_MAX; i++)
174 fprintf(stderr, "\t%d: %s\n", i, format_str[i]);
175 return -1;
176 }
177
178 if (format_is_pcm(format)) {
179 if ((ch < 1) || (ch > 8)) {
180 fprintf(stderr, "Wrong channel number, valid range [1-8]\n");
181 return -1;
182 }
183 if ((sr != 32000) && (sr != 44100) && (sr != 48000)) {
184 fprintf(stderr, "Invalid sample rate, valid options [32000, 44100, 48000]\n");
185 return -1;
186 }
187 if ((ch != 1) && (ch != 2) && (ch != 6) && (ch != 8)) {
188 fprintf(stderr, "Invalid channel number, valid options [1, 2, 6, 8]\n");
189 return -1;
190 }
191 }
192
193 ret = audio_hw_load_interface(&device);
194 if (ret) {
195 fprintf(stderr, "%s %d error:%d\n", __func__, __LINE__, ret);
196 return ret;
197 }
198 printf("hw version: %x\n", device->common.version);
199 printf("hal api version: %x\n", device->common.module->hal_api_version);
200 printf("module id: %s\n", device->common.module->id);
201 printf("module name: %s\n", device->common.module->name);
202
203 if (device->get_supported_devices) {
204 uint32_t support_dev = 0;
205 support_dev = device->get_supported_devices(device);
206 printf("supported device: %x\n", support_dev);
207 }
208
209 int inited = device->init_check(device);
210 if (inited) {
211 printf("device not inited, quit\n");
212 goto exit;
213 }
214
215 buf = fmap(fn, &size, &fd);
216 if (!buf) {
217 fprintf(stderr, "Error, cannot open input file\n");
218 goto exit;
219 }
220
221 /* set audio config */
222 memset(&config, 0, sizeof(config));
223
224 if (format_is_pcm(format)) {
225 config.sample_rate = sr;
226 switch (ch) {
227 case 1:
228 config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
229 break;
230 case 2:
231 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
232 break;
233 case 6:
234 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
235 break;
236 case 8:
237 config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
238 break;
239 default:
240 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
241 break;
242 }
243 } else {
244 config.sample_rate = 48000;
245 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
246 }
247 config.format = format_tab[format];
248
249 test_output_stream(device, buf, size, &config);
250
251 funmap(buf, size, fd);
252
253exit:
254 audio_hw_unload_interface(device);
255 return 0;
256}