1c72fcc34Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
2c72fcc34Sopenharmony_ci//
3c72fcc34Sopenharmony_ci// mapper-io.c - a unit test for muxer/demuxer for PCM frames on buffer.
4c72fcc34Sopenharmony_ci//
5c72fcc34Sopenharmony_ci// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6c72fcc34Sopenharmony_ci//
7c72fcc34Sopenharmony_ci// Licensed under the terms of the GNU General Public License, version 2.
8c72fcc34Sopenharmony_ci
9c72fcc34Sopenharmony_ci#include <aconfig.h>
10c72fcc34Sopenharmony_ci#ifdef HAVE_MEMFD_CREATE
11c72fcc34Sopenharmony_ci#define _GNU_SOURCE
12c72fcc34Sopenharmony_ci#endif
13c72fcc34Sopenharmony_ci
14c72fcc34Sopenharmony_ci#include "../mapper.h"
15c72fcc34Sopenharmony_ci#include "../misc.h"
16c72fcc34Sopenharmony_ci
17c72fcc34Sopenharmony_ci#include "generator.h"
18c72fcc34Sopenharmony_ci
19c72fcc34Sopenharmony_ci#ifdef HAVE_MEMFD_CREATE
20c72fcc34Sopenharmony_ci#include <sys/mman.h>
21c72fcc34Sopenharmony_ci#endif
22c72fcc34Sopenharmony_ci
23c72fcc34Sopenharmony_ci#include <stdlib.h>
24c72fcc34Sopenharmony_ci#include <unistd.h>
25c72fcc34Sopenharmony_ci#include <stdbool.h>
26c72fcc34Sopenharmony_ci
27c72fcc34Sopenharmony_ci#include <assert.h>
28c72fcc34Sopenharmony_ci
29c72fcc34Sopenharmony_cistruct mapper_trial {
30c72fcc34Sopenharmony_ci	enum container_format cntr_format;
31c72fcc34Sopenharmony_ci	struct container_context *cntrs;
32c72fcc34Sopenharmony_ci
33c72fcc34Sopenharmony_ci	char **paths;
34c72fcc34Sopenharmony_ci
35c72fcc34Sopenharmony_ci	struct mapper_context mapper;
36c72fcc34Sopenharmony_ci	bool verbose;
37c72fcc34Sopenharmony_ci};
38c72fcc34Sopenharmony_ci
39c72fcc34Sopenharmony_cistatic void test_demuxer(struct mapper_context *mapper, snd_pcm_access_t access,
40c72fcc34Sopenharmony_ci			 unsigned int bytes_per_sample,
41c72fcc34Sopenharmony_ci			 unsigned int samples_per_frame,
42c72fcc34Sopenharmony_ci			 unsigned int frames_per_buffer,
43c72fcc34Sopenharmony_ci			 void *frame_buffer, unsigned int frame_count,
44c72fcc34Sopenharmony_ci			 struct container_context *cntrs,
45c72fcc34Sopenharmony_ci			 unsigned int cntr_count, bool verbose)
46c72fcc34Sopenharmony_ci{
47c72fcc34Sopenharmony_ci	unsigned int total_frame_count;
48c72fcc34Sopenharmony_ci	int err;
49c72fcc34Sopenharmony_ci
50c72fcc34Sopenharmony_ci	err = mapper_context_init(mapper, MAPPER_TYPE_DEMUXER, cntr_count,
51c72fcc34Sopenharmony_ci				  verbose);
52c72fcc34Sopenharmony_ci	assert(err == 0);
53c72fcc34Sopenharmony_ci
54c72fcc34Sopenharmony_ci	err = mapper_context_pre_process(mapper, access, bytes_per_sample,
55c72fcc34Sopenharmony_ci					 samples_per_frame, frames_per_buffer,
56c72fcc34Sopenharmony_ci					 cntrs);
57c72fcc34Sopenharmony_ci	assert(err == 0);
58c72fcc34Sopenharmony_ci
59c72fcc34Sopenharmony_ci	total_frame_count = frame_count;
60c72fcc34Sopenharmony_ci	err = mapper_context_process_frames(mapper, frame_buffer,
61c72fcc34Sopenharmony_ci					    &total_frame_count, cntrs);
62c72fcc34Sopenharmony_ci	assert(err == 0);
63c72fcc34Sopenharmony_ci	assert(total_frame_count == frame_count);
64c72fcc34Sopenharmony_ci
65c72fcc34Sopenharmony_ci	mapper_context_post_process(mapper);
66c72fcc34Sopenharmony_ci	mapper_context_destroy(mapper);
67c72fcc34Sopenharmony_ci}
68c72fcc34Sopenharmony_ci
69c72fcc34Sopenharmony_cistatic int test_demux(struct mapper_trial *trial, snd_pcm_access_t access,
70c72fcc34Sopenharmony_ci		      snd_pcm_format_t sample_format,
71c72fcc34Sopenharmony_ci		      unsigned int samples_per_frame,
72c72fcc34Sopenharmony_ci		      unsigned int frames_per_second,
73c72fcc34Sopenharmony_ci		      unsigned int frames_per_buffer,
74c72fcc34Sopenharmony_ci		      void *frame_buffer, unsigned int frame_count,
75c72fcc34Sopenharmony_ci		      int *cntr_fds, unsigned int cntr_count)
76c72fcc34Sopenharmony_ci{
77c72fcc34Sopenharmony_ci	struct container_context *cntrs = trial->cntrs;
78c72fcc34Sopenharmony_ci	enum container_format cntr_format = trial->cntr_format;
79c72fcc34Sopenharmony_ci	unsigned int bytes_per_sample;
80c72fcc34Sopenharmony_ci	uint64_t total_frame_count;
81c72fcc34Sopenharmony_ci	int i;
82c72fcc34Sopenharmony_ci	int err = 0;
83c72fcc34Sopenharmony_ci
84c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
85c72fcc34Sopenharmony_ci		snd_pcm_format_t format;
86c72fcc34Sopenharmony_ci		unsigned int channels;
87c72fcc34Sopenharmony_ci		unsigned int rate;
88c72fcc34Sopenharmony_ci
89c72fcc34Sopenharmony_ci		err = container_builder_init(cntrs + i, cntr_fds[i], cntr_format, 0);
90c72fcc34Sopenharmony_ci		if (err < 0)
91c72fcc34Sopenharmony_ci			goto end;
92c72fcc34Sopenharmony_ci
93c72fcc34Sopenharmony_ci		format = sample_format;
94c72fcc34Sopenharmony_ci		rate = frames_per_second;
95c72fcc34Sopenharmony_ci		total_frame_count = frame_count;
96c72fcc34Sopenharmony_ci		if (cntr_count > 1)
97c72fcc34Sopenharmony_ci			channels = 1;
98c72fcc34Sopenharmony_ci		else
99c72fcc34Sopenharmony_ci			channels = samples_per_frame;
100c72fcc34Sopenharmony_ci		err = container_context_pre_process(cntrs + i, &format,
101c72fcc34Sopenharmony_ci						    &channels, &rate,
102c72fcc34Sopenharmony_ci						    &total_frame_count);
103c72fcc34Sopenharmony_ci		if (err < 0)
104c72fcc34Sopenharmony_ci			goto end;
105c72fcc34Sopenharmony_ci		assert(format == sample_format);
106c72fcc34Sopenharmony_ci		assert(rate == frames_per_second);
107c72fcc34Sopenharmony_ci		assert(total_frame_count >= 0);
108c72fcc34Sopenharmony_ci		if (cntr_count > 1)
109c72fcc34Sopenharmony_ci			assert(channels == 1);
110c72fcc34Sopenharmony_ci		else
111c72fcc34Sopenharmony_ci			assert(channels == samples_per_frame);
112c72fcc34Sopenharmony_ci	}
113c72fcc34Sopenharmony_ci
114c72fcc34Sopenharmony_ci	bytes_per_sample = snd_pcm_format_physical_width(sample_format) / 8;
115c72fcc34Sopenharmony_ci	test_demuxer(&trial->mapper, access, bytes_per_sample,
116c72fcc34Sopenharmony_ci		     samples_per_frame, frames_per_buffer, frame_buffer,
117c72fcc34Sopenharmony_ci		     frame_count, cntrs, cntr_count, trial->verbose);
118c72fcc34Sopenharmony_ci
119c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
120c72fcc34Sopenharmony_ci		container_context_post_process(cntrs + i, &total_frame_count);
121c72fcc34Sopenharmony_ci		assert(total_frame_count == frame_count);
122c72fcc34Sopenharmony_ci	}
123c72fcc34Sopenharmony_ciend:
124c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i)
125c72fcc34Sopenharmony_ci		container_context_destroy(cntrs + i);
126c72fcc34Sopenharmony_ci
127c72fcc34Sopenharmony_ci	return err;
128c72fcc34Sopenharmony_ci}
129c72fcc34Sopenharmony_ci
130c72fcc34Sopenharmony_cistatic void test_muxer(struct mapper_context *mapper, snd_pcm_access_t access,
131c72fcc34Sopenharmony_ci		       unsigned int bytes_per_sample,
132c72fcc34Sopenharmony_ci		       unsigned int samples_per_frame,
133c72fcc34Sopenharmony_ci		       unsigned int frames_per_buffer,
134c72fcc34Sopenharmony_ci		       void *frame_buffer, unsigned int frame_count,
135c72fcc34Sopenharmony_ci		       struct container_context *cntrs,
136c72fcc34Sopenharmony_ci		       unsigned int cntr_count, bool verbose)
137c72fcc34Sopenharmony_ci{
138c72fcc34Sopenharmony_ci	unsigned int total_frame_count;
139c72fcc34Sopenharmony_ci	int err;
140c72fcc34Sopenharmony_ci
141c72fcc34Sopenharmony_ci	err = mapper_context_init(mapper, MAPPER_TYPE_MUXER, cntr_count,
142c72fcc34Sopenharmony_ci				  verbose);
143c72fcc34Sopenharmony_ci	assert(err == 0);
144c72fcc34Sopenharmony_ci
145c72fcc34Sopenharmony_ci	err = mapper_context_pre_process(mapper, access, bytes_per_sample,
146c72fcc34Sopenharmony_ci					 samples_per_frame, frames_per_buffer,
147c72fcc34Sopenharmony_ci					 cntrs);
148c72fcc34Sopenharmony_ci	assert(err == 0);
149c72fcc34Sopenharmony_ci
150c72fcc34Sopenharmony_ci	total_frame_count = frame_count;
151c72fcc34Sopenharmony_ci	err = mapper_context_process_frames(mapper, frame_buffer,
152c72fcc34Sopenharmony_ci					    &total_frame_count, cntrs);
153c72fcc34Sopenharmony_ci	assert(err == 0);
154c72fcc34Sopenharmony_ci	assert(total_frame_count == frame_count);
155c72fcc34Sopenharmony_ci
156c72fcc34Sopenharmony_ci	mapper_context_post_process(mapper);
157c72fcc34Sopenharmony_ci	mapper_context_destroy(mapper);
158c72fcc34Sopenharmony_ci}
159c72fcc34Sopenharmony_ci
160c72fcc34Sopenharmony_cistatic int test_mux(struct mapper_trial *trial, snd_pcm_access_t access,
161c72fcc34Sopenharmony_ci		    snd_pcm_format_t sample_format,
162c72fcc34Sopenharmony_ci		    unsigned int samples_per_frame,
163c72fcc34Sopenharmony_ci		    unsigned int frames_per_second,
164c72fcc34Sopenharmony_ci		    unsigned int frames_per_buffer,
165c72fcc34Sopenharmony_ci		    void *frame_buffer, unsigned int frame_count,
166c72fcc34Sopenharmony_ci		    int *cntr_fds, unsigned int cntr_count)
167c72fcc34Sopenharmony_ci{
168c72fcc34Sopenharmony_ci	struct container_context *cntrs = trial->cntrs;
169c72fcc34Sopenharmony_ci	unsigned int bytes_per_sample;
170c72fcc34Sopenharmony_ci	uint64_t total_frame_count;
171c72fcc34Sopenharmony_ci	int i;
172c72fcc34Sopenharmony_ci	int err = 0;
173c72fcc34Sopenharmony_ci
174c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
175c72fcc34Sopenharmony_ci		snd_pcm_format_t format;
176c72fcc34Sopenharmony_ci		unsigned int channels;
177c72fcc34Sopenharmony_ci		unsigned int rate;
178c72fcc34Sopenharmony_ci
179c72fcc34Sopenharmony_ci		err = container_parser_init(cntrs + i, cntr_fds[i], 0);
180c72fcc34Sopenharmony_ci		if (err < 0)
181c72fcc34Sopenharmony_ci			goto end;
182c72fcc34Sopenharmony_ci
183c72fcc34Sopenharmony_ci		format = sample_format;
184c72fcc34Sopenharmony_ci		rate = frames_per_second;
185c72fcc34Sopenharmony_ci		if (cntr_count > 1)
186c72fcc34Sopenharmony_ci			channels = 1;
187c72fcc34Sopenharmony_ci		else
188c72fcc34Sopenharmony_ci			channels = samples_per_frame;
189c72fcc34Sopenharmony_ci		err = container_context_pre_process(cntrs + i, &format,
190c72fcc34Sopenharmony_ci						    &channels, &rate,
191c72fcc34Sopenharmony_ci						    &total_frame_count);
192c72fcc34Sopenharmony_ci		if (err < 0)
193c72fcc34Sopenharmony_ci			goto end;
194c72fcc34Sopenharmony_ci
195c72fcc34Sopenharmony_ci		assert(format == sample_format);
196c72fcc34Sopenharmony_ci		assert(rate == frames_per_second);
197c72fcc34Sopenharmony_ci		assert(total_frame_count == frame_count);
198c72fcc34Sopenharmony_ci		if (cntr_count > 1)
199c72fcc34Sopenharmony_ci			assert(channels == 1);
200c72fcc34Sopenharmony_ci		else
201c72fcc34Sopenharmony_ci			assert(channels == samples_per_frame);
202c72fcc34Sopenharmony_ci	}
203c72fcc34Sopenharmony_ci
204c72fcc34Sopenharmony_ci	bytes_per_sample = snd_pcm_format_physical_width(sample_format) / 8;
205c72fcc34Sopenharmony_ci	test_muxer(&trial->mapper, access, bytes_per_sample, samples_per_frame,
206c72fcc34Sopenharmony_ci		   frames_per_buffer, frame_buffer, frame_count, cntrs,
207c72fcc34Sopenharmony_ci		   cntr_count, trial->verbose);
208c72fcc34Sopenharmony_ci
209c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
210c72fcc34Sopenharmony_ci		container_context_post_process(cntrs + i, &total_frame_count);
211c72fcc34Sopenharmony_ci		assert(total_frame_count == frame_count);
212c72fcc34Sopenharmony_ci	}
213c72fcc34Sopenharmony_ciend:
214c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i)
215c72fcc34Sopenharmony_ci		container_context_destroy(cntrs + i);
216c72fcc34Sopenharmony_ci
217c72fcc34Sopenharmony_ci	return err;
218c72fcc34Sopenharmony_ci}
219c72fcc34Sopenharmony_ci
220c72fcc34Sopenharmony_cistatic int test_mapper(struct mapper_trial *trial, snd_pcm_access_t access,
221c72fcc34Sopenharmony_ci		    snd_pcm_format_t sample_format,
222c72fcc34Sopenharmony_ci		    unsigned int samples_per_frame,
223c72fcc34Sopenharmony_ci		    unsigned int frames_per_second, void *frame_buffer,
224c72fcc34Sopenharmony_ci		    void *check_buffer, unsigned int frame_count,
225c72fcc34Sopenharmony_ci		    unsigned int cntr_count)
226c72fcc34Sopenharmony_ci{
227c72fcc34Sopenharmony_ci	int *cntr_fds;
228c72fcc34Sopenharmony_ci	unsigned int frames_per_buffer;
229c72fcc34Sopenharmony_ci	int i;
230c72fcc34Sopenharmony_ci	int err;
231c72fcc34Sopenharmony_ci
232c72fcc34Sopenharmony_ci	// Use a buffer aligned by typical size of page frame.
233c72fcc34Sopenharmony_ci	frames_per_buffer = ((frame_count + 4096) / 4096) * 4096;
234c72fcc34Sopenharmony_ci
235c72fcc34Sopenharmony_ci	cntr_fds = calloc(cntr_count, sizeof(*cntr_fds));
236c72fcc34Sopenharmony_ci	if (cntr_fds == NULL)
237c72fcc34Sopenharmony_ci		return -ENOMEM;
238c72fcc34Sopenharmony_ci
239c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
240c72fcc34Sopenharmony_ci		const char *path = trial->paths[i];
241c72fcc34Sopenharmony_ci
242c72fcc34Sopenharmony_ci#ifdef HAVE_MEMFD_CREATE
243c72fcc34Sopenharmony_ci		cntr_fds[i] = memfd_create(path, 0);
244c72fcc34Sopenharmony_ci#else
245c72fcc34Sopenharmony_ci		cntr_fds[i] = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
246c72fcc34Sopenharmony_ci#endif
247c72fcc34Sopenharmony_ci		if (cntr_fds[i] < 0) {
248c72fcc34Sopenharmony_ci			err = -errno;
249c72fcc34Sopenharmony_ci			goto end;
250c72fcc34Sopenharmony_ci		}
251c72fcc34Sopenharmony_ci	}
252c72fcc34Sopenharmony_ci
253c72fcc34Sopenharmony_ci	err = test_demux(trial, access, sample_format, samples_per_frame,
254c72fcc34Sopenharmony_ci			 frames_per_second, frames_per_buffer, frame_buffer,
255c72fcc34Sopenharmony_ci			 frame_count, cntr_fds, cntr_count);
256c72fcc34Sopenharmony_ci	if (err < 0)
257c72fcc34Sopenharmony_ci		goto end;
258c72fcc34Sopenharmony_ci
259c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
260c72fcc34Sopenharmony_ci		off_t pos = lseek(cntr_fds[i], 0, SEEK_SET);
261c72fcc34Sopenharmony_ci		if (pos != 0) {
262c72fcc34Sopenharmony_ci			err = -EIO;
263c72fcc34Sopenharmony_ci			goto end;
264c72fcc34Sopenharmony_ci		}
265c72fcc34Sopenharmony_ci	}
266c72fcc34Sopenharmony_ci
267c72fcc34Sopenharmony_ci	err = test_mux(trial, access, sample_format, samples_per_frame,
268c72fcc34Sopenharmony_ci		       frames_per_second, frames_per_buffer, check_buffer,
269c72fcc34Sopenharmony_ci		       frame_count, cntr_fds, cntr_count);
270c72fcc34Sopenharmony_ciend:
271c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i)
272c72fcc34Sopenharmony_ci		close(cntr_fds[i]);
273c72fcc34Sopenharmony_ci
274c72fcc34Sopenharmony_ci	free(cntr_fds);
275c72fcc34Sopenharmony_ci
276c72fcc34Sopenharmony_ci	return err;
277c72fcc34Sopenharmony_ci}
278c72fcc34Sopenharmony_ci
279c72fcc34Sopenharmony_cistatic int test_i_buf(struct mapper_trial *trial, snd_pcm_access_t access,
280c72fcc34Sopenharmony_ci		      snd_pcm_format_t sample_format,
281c72fcc34Sopenharmony_ci		      unsigned int samples_per_frame,
282c72fcc34Sopenharmony_ci		      unsigned int frames_per_second, void *frame_buffer,
283c72fcc34Sopenharmony_ci		      unsigned int frame_count, unsigned int cntr_count)
284c72fcc34Sopenharmony_ci{
285c72fcc34Sopenharmony_ci	unsigned int size;
286c72fcc34Sopenharmony_ci	char *buf;
287c72fcc34Sopenharmony_ci	int err;
288c72fcc34Sopenharmony_ci
289c72fcc34Sopenharmony_ci	size = frame_count * samples_per_frame *
290c72fcc34Sopenharmony_ci			snd_pcm_format_physical_width(sample_format) / 8;
291c72fcc34Sopenharmony_ci	buf = malloc(size);
292c72fcc34Sopenharmony_ci	if (buf == 0)
293c72fcc34Sopenharmony_ci		return -ENOMEM;
294c72fcc34Sopenharmony_ci	memset(buf, 0, size);
295c72fcc34Sopenharmony_ci
296c72fcc34Sopenharmony_ci	// Test multiple target.
297c72fcc34Sopenharmony_ci	err = test_mapper(trial, access, sample_format, samples_per_frame,
298c72fcc34Sopenharmony_ci			  frames_per_second, frame_buffer, buf,
299c72fcc34Sopenharmony_ci			  frame_count, cntr_count);
300c72fcc34Sopenharmony_ci	if (err < 0)
301c72fcc34Sopenharmony_ci		goto end;
302c72fcc34Sopenharmony_ci	err = memcmp(frame_buffer, buf, size);
303c72fcc34Sopenharmony_ci	assert(err == 0);
304c72fcc34Sopenharmony_ci
305c72fcc34Sopenharmony_ci	// Test single target.
306c72fcc34Sopenharmony_ci	err = test_mapper(trial, access, sample_format, samples_per_frame,
307c72fcc34Sopenharmony_ci			  frames_per_second, frame_buffer, buf,
308c72fcc34Sopenharmony_ci			  frame_count, 1);
309c72fcc34Sopenharmony_ci	if (err < 0)
310c72fcc34Sopenharmony_ci		goto end;
311c72fcc34Sopenharmony_ci	err = memcmp(frame_buffer, buf, size);
312c72fcc34Sopenharmony_ci	assert(err == 0);
313c72fcc34Sopenharmony_ciend:
314c72fcc34Sopenharmony_ci	free(buf);
315c72fcc34Sopenharmony_ci
316c72fcc34Sopenharmony_ci	return err;
317c72fcc34Sopenharmony_ci}
318c72fcc34Sopenharmony_ci
319c72fcc34Sopenharmony_cistatic int test_vector(struct mapper_trial *trial, snd_pcm_access_t access,
320c72fcc34Sopenharmony_ci		       snd_pcm_format_t sample_format,
321c72fcc34Sopenharmony_ci		       unsigned int samples_per_frame,
322c72fcc34Sopenharmony_ci		       unsigned int frames_per_second, void *frame_buffer,
323c72fcc34Sopenharmony_ci		       unsigned int frame_count, unsigned int cntr_count)
324c72fcc34Sopenharmony_ci{
325c72fcc34Sopenharmony_ci	unsigned int size;
326c72fcc34Sopenharmony_ci	char **bufs;
327c72fcc34Sopenharmony_ci	int i;
328c72fcc34Sopenharmony_ci	int err;
329c72fcc34Sopenharmony_ci
330c72fcc34Sopenharmony_ci	bufs = calloc(cntr_count, sizeof(*bufs));
331c72fcc34Sopenharmony_ci	if (bufs == NULL)
332c72fcc34Sopenharmony_ci		return -ENOMEM;
333c72fcc34Sopenharmony_ci
334c72fcc34Sopenharmony_ci	size = frame_count * snd_pcm_format_physical_width(sample_format) / 8;
335c72fcc34Sopenharmony_ci
336c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
337c72fcc34Sopenharmony_ci		bufs[i] = malloc(size);
338c72fcc34Sopenharmony_ci		if (bufs[i] == NULL) {
339c72fcc34Sopenharmony_ci			err = -ENOMEM;
340c72fcc34Sopenharmony_ci			goto end;
341c72fcc34Sopenharmony_ci		}
342c72fcc34Sopenharmony_ci		memset(bufs[i], 0, size);
343c72fcc34Sopenharmony_ci	}
344c72fcc34Sopenharmony_ci
345c72fcc34Sopenharmony_ci	// Test multiple target.
346c72fcc34Sopenharmony_ci	err = test_mapper(trial, access, sample_format, samples_per_frame,
347c72fcc34Sopenharmony_ci			  frames_per_second, frame_buffer, bufs,
348c72fcc34Sopenharmony_ci			  frame_count, cntr_count);
349c72fcc34Sopenharmony_ci	if (err < 0)
350c72fcc34Sopenharmony_ci		goto end;
351c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
352c72fcc34Sopenharmony_ci		char **target = frame_buffer;
353c72fcc34Sopenharmony_ci		err = memcmp(target[i], bufs[i], size);
354c72fcc34Sopenharmony_ci		assert(err == 0);
355c72fcc34Sopenharmony_ci	}
356c72fcc34Sopenharmony_ci
357c72fcc34Sopenharmony_ci	// Test single target.
358c72fcc34Sopenharmony_ci	err = test_mapper(trial, access, sample_format, samples_per_frame,
359c72fcc34Sopenharmony_ci			  frames_per_second, frame_buffer, bufs,
360c72fcc34Sopenharmony_ci			  frame_count, 1);
361c72fcc34Sopenharmony_ci	if (err < 0)
362c72fcc34Sopenharmony_ci		goto end;
363c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
364c72fcc34Sopenharmony_ci		char **target = frame_buffer;
365c72fcc34Sopenharmony_ci		err = memcmp(target[i], bufs[i], size);
366c72fcc34Sopenharmony_ci		assert(err == 0);
367c72fcc34Sopenharmony_ci	}
368c72fcc34Sopenharmony_ciend:
369c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i) {
370c72fcc34Sopenharmony_ci		if (bufs[i])
371c72fcc34Sopenharmony_ci			free(bufs[i]);
372c72fcc34Sopenharmony_ci	}
373c72fcc34Sopenharmony_ci	free(bufs);
374c72fcc34Sopenharmony_ci
375c72fcc34Sopenharmony_ci	return err;
376c72fcc34Sopenharmony_ci}
377c72fcc34Sopenharmony_ci
378c72fcc34Sopenharmony_cistatic int test_n_buf(struct mapper_trial *trial, snd_pcm_access_t access,
379c72fcc34Sopenharmony_ci		      snd_pcm_format_t sample_format,
380c72fcc34Sopenharmony_ci		      unsigned int samples_per_frame,
381c72fcc34Sopenharmony_ci		      unsigned int frames_per_second, void *frame_buffer,
382c72fcc34Sopenharmony_ci		      unsigned int frame_count, unsigned int cntr_count)
383c72fcc34Sopenharmony_ci{
384c72fcc34Sopenharmony_ci	char *test_buf = frame_buffer;
385c72fcc34Sopenharmony_ci	unsigned int size;
386c72fcc34Sopenharmony_ci	char **test_vec;
387c72fcc34Sopenharmony_ci	int i;
388c72fcc34Sopenharmony_ci	int err;
389c72fcc34Sopenharmony_ci
390c72fcc34Sopenharmony_ci	size = frame_count * snd_pcm_format_physical_width(sample_format) / 8;
391c72fcc34Sopenharmony_ci
392c72fcc34Sopenharmony_ci	test_vec = calloc(cntr_count * 2, sizeof(*test_vec));
393c72fcc34Sopenharmony_ci	if (test_vec == NULL)
394c72fcc34Sopenharmony_ci		return -ENOMEM;
395c72fcc34Sopenharmony_ci
396c72fcc34Sopenharmony_ci	for (i = 0; i < cntr_count; ++i)
397c72fcc34Sopenharmony_ci		test_vec[i] = test_buf + size * i;
398c72fcc34Sopenharmony_ci
399c72fcc34Sopenharmony_ci	err = test_vector(trial, access, sample_format, samples_per_frame,
400c72fcc34Sopenharmony_ci			  frames_per_second, test_vec, frame_count, cntr_count);
401c72fcc34Sopenharmony_ci	free(test_vec);
402c72fcc34Sopenharmony_ci
403c72fcc34Sopenharmony_ci	return err;
404c72fcc34Sopenharmony_ci}
405c72fcc34Sopenharmony_ci
406c72fcc34Sopenharmony_cistatic int callback(struct test_generator *gen, snd_pcm_access_t access,
407c72fcc34Sopenharmony_ci		    snd_pcm_format_t sample_format,
408c72fcc34Sopenharmony_ci		    unsigned int samples_per_frame, void *frame_buffer,
409c72fcc34Sopenharmony_ci		    unsigned int frame_count)
410c72fcc34Sopenharmony_ci{
411c72fcc34Sopenharmony_ci
412c72fcc34Sopenharmony_ci	int (*handler)(struct mapper_trial *trial, snd_pcm_access_t access,
413c72fcc34Sopenharmony_ci		       snd_pcm_format_t sample_format,
414c72fcc34Sopenharmony_ci		       unsigned int samples_per_frame,
415c72fcc34Sopenharmony_ci		       unsigned int frames_per_second, void *frame_buffer,
416c72fcc34Sopenharmony_ci		       unsigned int frame_count, unsigned int cntr_count);
417c72fcc34Sopenharmony_ci	struct mapper_trial *trial = gen->private_data;
418c72fcc34Sopenharmony_ci
419c72fcc34Sopenharmony_ci	if (access == SND_PCM_ACCESS_RW_NONINTERLEAVED)
420c72fcc34Sopenharmony_ci		handler = test_vector;
421c72fcc34Sopenharmony_ci	else if (access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED)
422c72fcc34Sopenharmony_ci		handler = test_n_buf;
423c72fcc34Sopenharmony_ci	else
424c72fcc34Sopenharmony_ci		handler = test_i_buf;
425c72fcc34Sopenharmony_ci
426c72fcc34Sopenharmony_ci	return handler(trial, access, sample_format, samples_per_frame, 48000,
427c72fcc34Sopenharmony_ci		       frame_buffer, frame_count, samples_per_frame);
428c72fcc34Sopenharmony_ci};
429c72fcc34Sopenharmony_ci
430c72fcc34Sopenharmony_ciint main(int argc, const char *argv[])
431c72fcc34Sopenharmony_ci{
432c72fcc34Sopenharmony_ci	// Test 8/16/18/20/24/32/64 bytes per sample.
433c72fcc34Sopenharmony_ci	static const uint64_t sample_format_mask =
434c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_U8) |
435c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_S16_LE) |
436c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_S18_3LE) |
437c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_S20_3LE) |
438c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_S24_LE) |
439c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_S32_LE) |
440c72fcc34Sopenharmony_ci			(1ull << SND_PCM_FORMAT_FLOAT64_LE);
441c72fcc34Sopenharmony_ci	uint64_t access_mask;
442c72fcc34Sopenharmony_ci	struct test_generator gen = {0};
443c72fcc34Sopenharmony_ci	struct mapper_trial *trial;
444c72fcc34Sopenharmony_ci	struct container_context *cntrs;
445c72fcc34Sopenharmony_ci	unsigned int samples_per_frame;
446c72fcc34Sopenharmony_ci	char **paths = NULL;
447c72fcc34Sopenharmony_ci	snd_pcm_access_t access;
448c72fcc34Sopenharmony_ci	bool verbose;
449c72fcc34Sopenharmony_ci	int i;
450c72fcc34Sopenharmony_ci	int err;
451c72fcc34Sopenharmony_ci
452c72fcc34Sopenharmony_ci	// Test up to 32 channels.
453c72fcc34Sopenharmony_ci	samples_per_frame = 32;
454c72fcc34Sopenharmony_ci	cntrs = calloc(samples_per_frame, sizeof(*cntrs));
455c72fcc34Sopenharmony_ci	if (cntrs == NULL)
456c72fcc34Sopenharmony_ci		return -ENOMEM;
457c72fcc34Sopenharmony_ci
458c72fcc34Sopenharmony_ci	paths = calloc(samples_per_frame, sizeof(*paths));
459c72fcc34Sopenharmony_ci	if (paths == NULL) {
460c72fcc34Sopenharmony_ci		err = -ENOMEM;
461c72fcc34Sopenharmony_ci		goto end;
462c72fcc34Sopenharmony_ci	}
463c72fcc34Sopenharmony_ci	for (i = 0; i < samples_per_frame; ++i) {
464c72fcc34Sopenharmony_ci		paths[i] = malloc(8);
465c72fcc34Sopenharmony_ci		if (paths[i] == NULL) {
466c72fcc34Sopenharmony_ci			err = -ENOMEM;
467c72fcc34Sopenharmony_ci			goto end;
468c72fcc34Sopenharmony_ci		}
469c72fcc34Sopenharmony_ci		snprintf(paths[i], 8, "hoge%d", i);
470c72fcc34Sopenharmony_ci	}
471c72fcc34Sopenharmony_ci
472c72fcc34Sopenharmony_ci	if (argc > 1) {
473c72fcc34Sopenharmony_ci		char *term;
474c72fcc34Sopenharmony_ci		access = strtol(argv[1], &term, 10);
475c72fcc34Sopenharmony_ci		if (errno != 0 || *term != '\0') {
476c72fcc34Sopenharmony_ci			err = -EINVAL;;
477c72fcc34Sopenharmony_ci			goto end;
478c72fcc34Sopenharmony_ci		}
479c72fcc34Sopenharmony_ci		if (access < SND_PCM_ACCESS_MMAP_INTERLEAVED &&
480c72fcc34Sopenharmony_ci		    access > SND_PCM_ACCESS_RW_NONINTERLEAVED) {
481c72fcc34Sopenharmony_ci			err = -EINVAL;
482c72fcc34Sopenharmony_ci			goto end;
483c72fcc34Sopenharmony_ci		}
484c72fcc34Sopenharmony_ci		if (access == SND_PCM_ACCESS_MMAP_COMPLEX) {
485c72fcc34Sopenharmony_ci			err = -EINVAL;
486c72fcc34Sopenharmony_ci			goto end;
487c72fcc34Sopenharmony_ci		}
488c72fcc34Sopenharmony_ci
489c72fcc34Sopenharmony_ci		access_mask = 1ull << access;
490c72fcc34Sopenharmony_ci		verbose = true;
491c72fcc34Sopenharmony_ci	} else {
492c72fcc34Sopenharmony_ci		access_mask = (1ull << SND_PCM_ACCESS_MMAP_INTERLEAVED) |
493c72fcc34Sopenharmony_ci			      (1ull << SND_PCM_ACCESS_MMAP_NONINTERLEAVED) |
494c72fcc34Sopenharmony_ci			      (1ull << SND_PCM_ACCESS_RW_INTERLEAVED) |
495c72fcc34Sopenharmony_ci			      (1ull << SND_PCM_ACCESS_RW_NONINTERLEAVED);
496c72fcc34Sopenharmony_ci		verbose = false;
497c72fcc34Sopenharmony_ci	}
498c72fcc34Sopenharmony_ci
499c72fcc34Sopenharmony_ci	err = generator_context_init(&gen, access_mask, sample_format_mask,
500c72fcc34Sopenharmony_ci				     1, samples_per_frame,
501c72fcc34Sopenharmony_ci				     23, 4500, 1024,
502c72fcc34Sopenharmony_ci				     sizeof(struct mapper_trial));
503c72fcc34Sopenharmony_ci	if (err < 0)
504c72fcc34Sopenharmony_ci		goto end;
505c72fcc34Sopenharmony_ci
506c72fcc34Sopenharmony_ci	trial = gen.private_data;
507c72fcc34Sopenharmony_ci	trial->cntrs = cntrs;
508c72fcc34Sopenharmony_ci	trial->cntr_format = CONTAINER_FORMAT_RIFF_WAVE;
509c72fcc34Sopenharmony_ci	trial->paths = paths;
510c72fcc34Sopenharmony_ci	trial->verbose = verbose;
511c72fcc34Sopenharmony_ci	err = generator_context_run(&gen, callback);
512c72fcc34Sopenharmony_ci
513c72fcc34Sopenharmony_ci	generator_context_destroy(&gen);
514c72fcc34Sopenharmony_ciend:
515c72fcc34Sopenharmony_ci	if (paths) {
516c72fcc34Sopenharmony_ci		for (i = 0; i < samples_per_frame; ++i)
517c72fcc34Sopenharmony_ci			free(paths[i]);
518c72fcc34Sopenharmony_ci		free(paths);
519c72fcc34Sopenharmony_ci	}
520c72fcc34Sopenharmony_ci	free(cntrs);
521c72fcc34Sopenharmony_ci
522c72fcc34Sopenharmony_ci	if (err < 0) {
523c72fcc34Sopenharmony_ci		printf("%s\n", strerror(-err));
524c72fcc34Sopenharmony_ci		return EXIT_FAILURE;
525c72fcc34Sopenharmony_ci	}
526c72fcc34Sopenharmony_ci
527c72fcc34Sopenharmony_ci	return EXIT_SUCCESS;
528c72fcc34Sopenharmony_ci}
529