Skip to content

Commit 87f7e56

Browse files
tinycompress: Add application for accel operation
This 'caccel' applicaton is a demo to show how to call the new introduced accel interface. The kernel patch is: ALSA: compress_offload: introduce accel operation mode As there is conflict when using the API of alsa-lib, add alsa_wrap file to separate the header files: alsa/asoundlib.h sound/asound.h Signed-off-by: Shengjiu Wang <[email protected]>
1 parent e96165e commit 87f7e56

File tree

4 files changed

+337
-1
lines changed

4 files changed

+337
-1
lines changed

src/utils/Makefile.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
bin_PROGRAMS = cplay crecord
1+
bin_PROGRAMS = cplay crecord caccel
22

33
cplay_SOURCES = cplay.c wave.c
44
crecord_SOURCES = crecord.c wave.c
5+
caccel_SOURCES = caccel.c wave.c alsa_wrap.c
56

67
cplay_CFLAGS = -I$(top_srcdir)/include
78
crecord_CFLAGS = -I$(top_srcdir)/include
9+
caccel_CFLAGS = -I$(top_srcdir)/include
810

911

1012
cplay_LDADD = $(top_builddir)/src/lib/libtinycompress.la
1113
crecord_LDADD = $(top_builddir)/src/lib/libtinycompress.la
14+
caccel_LDADD = $(top_builddir)/src/lib/libtinycompress.la -lasound

src/utils/alsa_wrap.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// SPDX-License-Identifier: (LGPL-2.1-only OR BSD-3-Clause)
2+
3+
#include <alsa/asoundlib.h>
4+
5+
snd_pcm_format_t alsa_snd_pcm_format_value(const char *name)
6+
{
7+
return snd_pcm_format_value(name);
8+
}
9+
10+
int alsa_snd_pcm_format_physical_width(snd_pcm_format_t format)
11+
{
12+
return snd_pcm_format_physical_width(format);
13+
}
14+
15+
int alsa_snd_pcm_format_width(snd_pcm_format_t format)
16+
{
17+
return snd_pcm_format_width(format);
18+
}
19+
20+
int alsa_snd_pcm_format_linear(snd_pcm_format_t format)
21+
{
22+
return snd_pcm_format_linear(format);
23+
}
24+
25+
int alsa_snd_pcm_format_signed(snd_pcm_format_t format)
26+
{
27+
return snd_pcm_format_signed(format);
28+
}

src/utils/alsa_wrap.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* SPDX-License-Identifier: (LGPL-2.1-only OR BSD-3-Clause) */
2+
3+
#ifndef __ALSA_WRAP_API_H
4+
#define __ALSA_WRAP_API_H
5+
6+
snd_pcm_format_t alsa_snd_pcm_format_value(const char *name);
7+
int alsa_snd_pcm_format_physical_width(snd_pcm_format_t format);
8+
int alsa_snd_pcm_format_width(snd_pcm_format_t format);
9+
int alsa_snd_pcm_format_linear(snd_pcm_format_t format);
10+
int alsa_snd_pcm_format_signed(snd_pcm_format_t format);
11+
#endif
12+

src/utils/caccel.c

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
// SPDX-License-Identifier: (LGPL-2.1-only OR BSD-3-Clause)
2+
/*
3+
* Copyright 2024 NXP
4+
*/
5+
6+
#include <errno.h>
7+
#include <fcntl.h>
8+
#include <getopt.h>
9+
#include <unistd.h>
10+
#include <stdint.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <string.h>
14+
#include <sys/ioctl.h>
15+
#include <sys/mman.h>
16+
#include <sys/types.h>
17+
#include <unistd.h>
18+
19+
#include "sound/compress_params.h"
20+
#include "sound/compress_offload.h"
21+
#include "tinycompress/tinycompress.h"
22+
#include "tinycompress/tinywave.h"
23+
24+
#include "alsa_wrap.h"
25+
26+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
27+
#define DMA_BUF_SIZE 4096
28+
#define MAP_BUF_SIZE (512 * 1024)
29+
30+
static int verbose;
31+
32+
struct audio_info {
33+
unsigned int card;
34+
unsigned int device;
35+
char *infile;
36+
char *outfile;
37+
unsigned int channels;
38+
unsigned int in_rate;
39+
unsigned short in_samplebits;
40+
unsigned short in_blockalign;
41+
unsigned int out_rate;
42+
unsigned short out_samplebits;
43+
unsigned short out_blockalign;
44+
snd_pcm_format_t in_format;
45+
snd_pcm_format_t out_format;
46+
unsigned int in_dmabuf_size;
47+
};
48+
49+
static void usage(void)
50+
{
51+
fprintf(stderr, "usage: caccel [OPTIONS]\n"
52+
"-c\tcard number\n"
53+
"-d\tdevice node\n"
54+
"-i\tinput wave file\n"
55+
"-o\toutput wave file\n"
56+
"-r\toutput rate\n"
57+
"-f\toutput format\n"
58+
"-b\tbuffer size\n"
59+
"-v\tverbose mode\n"
60+
"-h\tPrints this help list\n\n"
61+
"Example:\n"
62+
"\tcmemtomem -c 1 -d 2 -i input.wav -o output.wav\n"
63+
"Valid codec: SRC\n");
64+
}
65+
66+
static int parse_arguments(int argc, const char *argv[], struct audio_info *info)
67+
{
68+
int c, option_index;
69+
static const char short_options[] = "hvc:d:r:i:o:f:";
70+
static const struct option long_options[] = {
71+
{"help", 0, 0, 'h'},
72+
{"verbose", 0, 0, 'v'},
73+
{"card", 1, 0, 'c'},
74+
{"device", 1, 0, 'd'},
75+
{"inFile", 1, 0, 'i'},
76+
{"outFile", 1, 0, 'o'},
77+
{"outRate", 1, 0, 'r'},
78+
{"outFormat", 1, 0, 'f'},
79+
{0, 0, 0, 0}
80+
};
81+
82+
if (argc < 3)
83+
usage();
84+
85+
while ((c = getopt_long(argc, (char * const*)argv, short_options,
86+
long_options, &option_index)) != -1) {
87+
switch (c) {
88+
case 'c':
89+
info->card = strtol(optarg, NULL, 0);
90+
break;
91+
case 'd':
92+
info->device = strtol(optarg, NULL, 0);
93+
break;
94+
case 'i':
95+
info->infile = optarg;
96+
break;
97+
case 'o':
98+
info->outfile = optarg;
99+
break;
100+
case 'r':
101+
info->out_rate = strtol(optarg, NULL, 0);
102+
break;
103+
case 'f':
104+
info->out_format = alsa_snd_pcm_format_value(optarg);
105+
break;
106+
case 'h':
107+
usage();
108+
exit(EXIT_FAILURE);
109+
case 'v':
110+
verbose = 1;
111+
break;
112+
default:
113+
fprintf(stderr, "Unknown Command -%c\n", c);
114+
exit(EXIT_FAILURE);
115+
}
116+
}
117+
118+
return 0;
119+
}
120+
121+
int main(int argc, const char *argv[])
122+
{
123+
struct wave_header in_header;
124+
struct wave_header out_header;
125+
struct audio_info info;
126+
size_t read, written;
127+
struct compr_task task = {};
128+
struct compr_task_status status = {};
129+
struct compress *compress;
130+
struct compr_config config;
131+
struct snd_codec codec;
132+
FILE *fd_dst = NULL;
133+
FILE *fd_src = NULL;
134+
void *bufin_start;
135+
void *bufout_start;
136+
int length = 0;
137+
int err = 0;
138+
139+
verbose = 0;
140+
memset(&info, 0, sizeof(struct audio_info));
141+
142+
info.out_format = SNDRV_PCM_FORMAT_S16_LE;
143+
144+
if (parse_arguments(argc, argv, &info) != 0)
145+
exit(EXIT_FAILURE);
146+
147+
if (info.out_rate == 0) {
148+
fprintf(stderr, "invalid output rate %d\n", info.out_rate);
149+
exit(EXIT_FAILURE);
150+
}
151+
152+
fd_dst = fopen(info.outfile, "wb+");
153+
if (fd_dst <= 0) {
154+
fprintf(stderr, "output file not found\n");
155+
goto err_dst_not_found;
156+
}
157+
158+
fd_src = fopen(info.infile, "r");
159+
if (fd_src <= 0) {
160+
fprintf(stderr, "input file not found\n");
161+
goto err_src_not_found;
162+
}
163+
164+
read = fread(&in_header, 1, sizeof(in_header), fd_src);
165+
if (read != sizeof(in_header)) {
166+
fprintf(stderr, "Unable to read header\n");
167+
goto err_header_read;
168+
}
169+
170+
if (parse_wave_header(&in_header, &info.channels, &info.in_rate,
171+
(unsigned int *)&info.in_format) == -1) {
172+
fprintf(stderr, "Unable to parse header\n");
173+
goto err_header_read;
174+
}
175+
176+
info.in_blockalign = info.channels * in_header.fmt.samplebits / 8;
177+
info.in_dmabuf_size = (DMA_BUF_SIZE / info.in_blockalign) * info.in_blockalign;
178+
info.out_samplebits = alsa_snd_pcm_format_width(info.out_format);
179+
180+
init_wave_header(&out_header, info.channels, info.out_rate, info.out_samplebits);
181+
182+
written = fwrite(&out_header, 1, sizeof(out_header), fd_dst);
183+
if (written != sizeof(out_header)) {
184+
fprintf(stderr, "Error writing output file header: %s\n",
185+
strerror(errno));
186+
goto err_header_read;
187+
}
188+
189+
codec.id = SND_AUDIOCODEC_PCM;
190+
codec.ch_in = info.channels;
191+
codec.ch_out = info.channels;
192+
codec.format = info.in_format;
193+
codec.sample_rate = info.in_rate;
194+
codec.pcm_format = info.out_format;
195+
codec.options.src_d.out_sample_rate = info.out_rate;
196+
197+
config.codec = &codec;
198+
compress = compress_open(info.card, info.device, COMPRESS_ACCEL, &config);
199+
if (!compress || !is_compress_ready(compress)) {
200+
fprintf(stderr, "Unable to open Compress device %d:%d\n",
201+
info.card, info.device);
202+
fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
203+
goto err_compress_open;
204+
};
205+
206+
err = compress_task_create(compress, &task);
207+
if (err < 0) {
208+
fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
209+
goto err_task_create;
210+
}
211+
212+
bufin_start = mmap(NULL, MAP_BUF_SIZE, PROT_READ | PROT_WRITE,
213+
MAP_SHARED, task.input_fd, 0);
214+
if (bufin_start == MAP_FAILED) {
215+
fprintf(stderr, "Error mapping input buffer\n");
216+
goto err_mmap_in;
217+
}
218+
memset(bufin_start, 0, MAP_BUF_SIZE);
219+
220+
bufout_start = mmap(NULL, MAP_BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
221+
task.output_fd, 0);
222+
if (bufout_start == MAP_FAILED) {
223+
fprintf(stderr, "Error mapping output buffer\n");
224+
goto err_mmap_out;
225+
}
226+
memset(bufout_start, 0, MAP_BUF_SIZE);
227+
228+
if (verbose)
229+
printf("conversion is started\n");
230+
231+
status.seqno = task.seqno;
232+
233+
do {
234+
235+
read = fread(bufin_start, 1, info.in_dmabuf_size, fd_src);
236+
if (read <= 0)
237+
break;
238+
239+
task.input_size = read;
240+
241+
err = compress_task_start(compress, &task);
242+
if (err < 0) {
243+
fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
244+
goto err_process_err;
245+
}
246+
247+
err = compress_task_status(compress, &status);
248+
if (err < 0) {
249+
fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
250+
goto err_process_err;
251+
}
252+
253+
err = compress_task_stop(compress, &task);
254+
if (err < 0) {
255+
fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
256+
goto err_process_err;
257+
}
258+
259+
written = fwrite(bufout_start, 1, status.output_size, fd_dst);
260+
if (written != (size_t)status.output_size) {
261+
fprintf(stderr, "Error writing output file: %s\n",
262+
strerror(errno));
263+
goto err_process_err;
264+
}
265+
266+
} while (read > 0);
267+
268+
fseek(fd_dst, 0L, SEEK_END);
269+
length = ftell(fd_dst);
270+
size_wave_header(&out_header, length - sizeof(out_header));
271+
fseek(fd_dst, 0L, SEEK_SET);
272+
fwrite(&out_header, 1, sizeof(out_header), fd_dst);
273+
274+
if (verbose)
275+
printf("Conversion is finished\n");
276+
277+
err_process_err:
278+
munmap(bufout_start, MAP_BUF_SIZE);
279+
err_mmap_out:
280+
munmap(bufin_start, MAP_BUF_SIZE);
281+
err_mmap_in:
282+
if (compress_task_free(compress, &task) < 0)
283+
fprintf(stderr, "ERR: %s\n", compress_get_error(compress));
284+
err_task_create:
285+
compress_close(compress);
286+
err_compress_open:
287+
err_header_read:
288+
fclose(fd_src);
289+
err_src_not_found:
290+
fclose(fd_dst);
291+
err_dst_not_found:
292+
return err;
293+
}

0 commit comments

Comments
 (0)