1c72fcc34Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2c72fcc34Sopenharmony_ci// 3c72fcc34Sopenharmony_ci// container-io.c - a unit test for parser/builder of supported containers. 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 "../container.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 container_trial { 30c72fcc34Sopenharmony_ci enum container_format format; 31c72fcc34Sopenharmony_ci 32c72fcc34Sopenharmony_ci struct container_context cntr; 33c72fcc34Sopenharmony_ci bool verbose; 34c72fcc34Sopenharmony_ci}; 35c72fcc34Sopenharmony_ci 36c72fcc34Sopenharmony_cistatic void test_builder(struct container_context *cntr, int fd, 37c72fcc34Sopenharmony_ci enum container_format format, 38c72fcc34Sopenharmony_ci snd_pcm_access_t access, 39c72fcc34Sopenharmony_ci snd_pcm_format_t sample_format, 40c72fcc34Sopenharmony_ci unsigned int samples_per_frame, 41c72fcc34Sopenharmony_ci unsigned int frames_per_second, 42c72fcc34Sopenharmony_ci void *frame_buffer, unsigned int frame_count, 43c72fcc34Sopenharmony_ci bool verbose) 44c72fcc34Sopenharmony_ci{ 45c72fcc34Sopenharmony_ci snd_pcm_format_t sample; 46c72fcc34Sopenharmony_ci unsigned int channels; 47c72fcc34Sopenharmony_ci unsigned int rate; 48c72fcc34Sopenharmony_ci uint64_t max_frame_count; 49c72fcc34Sopenharmony_ci unsigned int handled_frame_count; 50c72fcc34Sopenharmony_ci uint64_t total_frame_count; 51c72fcc34Sopenharmony_ci int err; 52c72fcc34Sopenharmony_ci 53c72fcc34Sopenharmony_ci err = container_builder_init(cntr, fd, format, verbose); 54c72fcc34Sopenharmony_ci assert(err == 0); 55c72fcc34Sopenharmony_ci 56c72fcc34Sopenharmony_ci sample = sample_format; 57c72fcc34Sopenharmony_ci channels = samples_per_frame; 58c72fcc34Sopenharmony_ci rate = frames_per_second; 59c72fcc34Sopenharmony_ci max_frame_count = 0; 60c72fcc34Sopenharmony_ci err = container_context_pre_process(cntr, &sample, &channels, &rate, 61c72fcc34Sopenharmony_ci &max_frame_count); 62c72fcc34Sopenharmony_ci assert(err == 0); 63c72fcc34Sopenharmony_ci assert(sample == sample_format); 64c72fcc34Sopenharmony_ci assert(channels == samples_per_frame); 65c72fcc34Sopenharmony_ci assert(rate == frames_per_second); 66c72fcc34Sopenharmony_ci assert(max_frame_count > 0); 67c72fcc34Sopenharmony_ci 68c72fcc34Sopenharmony_ci handled_frame_count = frame_count; 69c72fcc34Sopenharmony_ci err = container_context_process_frames(cntr, frame_buffer, 70c72fcc34Sopenharmony_ci &handled_frame_count); 71c72fcc34Sopenharmony_ci assert(err == 0); 72c72fcc34Sopenharmony_ci assert(handled_frame_count > 0); 73c72fcc34Sopenharmony_ci assert(handled_frame_count <= frame_count); 74c72fcc34Sopenharmony_ci 75c72fcc34Sopenharmony_ci total_frame_count = 0; 76c72fcc34Sopenharmony_ci err = container_context_post_process(cntr, &total_frame_count); 77c72fcc34Sopenharmony_ci assert(err == 0); 78c72fcc34Sopenharmony_ci assert(total_frame_count == frame_count); 79c72fcc34Sopenharmony_ci 80c72fcc34Sopenharmony_ci container_context_destroy(cntr); 81c72fcc34Sopenharmony_ci} 82c72fcc34Sopenharmony_ci 83c72fcc34Sopenharmony_cistatic void test_parser(struct container_context *cntr, int fd, 84c72fcc34Sopenharmony_ci enum container_format format, 85c72fcc34Sopenharmony_ci snd_pcm_access_t access, snd_pcm_format_t sample_format, 86c72fcc34Sopenharmony_ci unsigned int samples_per_frame, 87c72fcc34Sopenharmony_ci unsigned int frames_per_second, 88c72fcc34Sopenharmony_ci void *frame_buffer, unsigned int frame_count, 89c72fcc34Sopenharmony_ci bool verbose) 90c72fcc34Sopenharmony_ci{ 91c72fcc34Sopenharmony_ci snd_pcm_format_t sample; 92c72fcc34Sopenharmony_ci unsigned int channels; 93c72fcc34Sopenharmony_ci unsigned int rate; 94c72fcc34Sopenharmony_ci uint64_t total_frame_count; 95c72fcc34Sopenharmony_ci unsigned int handled_frame_count; 96c72fcc34Sopenharmony_ci int err; 97c72fcc34Sopenharmony_ci 98c72fcc34Sopenharmony_ci err = container_parser_init(cntr, fd, verbose); 99c72fcc34Sopenharmony_ci assert(err == 0); 100c72fcc34Sopenharmony_ci 101c72fcc34Sopenharmony_ci sample = sample_format; 102c72fcc34Sopenharmony_ci channels = samples_per_frame; 103c72fcc34Sopenharmony_ci rate = frames_per_second; 104c72fcc34Sopenharmony_ci total_frame_count = 0; 105c72fcc34Sopenharmony_ci err = container_context_pre_process(cntr, &sample, &channels, &rate, 106c72fcc34Sopenharmony_ci &total_frame_count); 107c72fcc34Sopenharmony_ci assert(err == 0); 108c72fcc34Sopenharmony_ci assert(sample == sample_format); 109c72fcc34Sopenharmony_ci assert(channels == samples_per_frame); 110c72fcc34Sopenharmony_ci assert(rate == frames_per_second); 111c72fcc34Sopenharmony_ci assert(total_frame_count == frame_count); 112c72fcc34Sopenharmony_ci 113c72fcc34Sopenharmony_ci handled_frame_count = total_frame_count; 114c72fcc34Sopenharmony_ci err = container_context_process_frames(cntr, frame_buffer, 115c72fcc34Sopenharmony_ci &handled_frame_count); 116c72fcc34Sopenharmony_ci assert(err == 0); 117c72fcc34Sopenharmony_ci assert(handled_frame_count == frame_count); 118c72fcc34Sopenharmony_ci 119c72fcc34Sopenharmony_ci total_frame_count = 0; 120c72fcc34Sopenharmony_ci err = container_context_post_process(cntr, &total_frame_count); 121c72fcc34Sopenharmony_ci assert(err == 0); 122c72fcc34Sopenharmony_ci assert(total_frame_count == handled_frame_count); 123c72fcc34Sopenharmony_ci 124c72fcc34Sopenharmony_ci container_context_destroy(cntr); 125c72fcc34Sopenharmony_ci} 126c72fcc34Sopenharmony_ci 127c72fcc34Sopenharmony_cistatic int callback(struct test_generator *gen, snd_pcm_access_t access, 128c72fcc34Sopenharmony_ci snd_pcm_format_t sample_format, 129c72fcc34Sopenharmony_ci unsigned int samples_per_frame, void *frame_buffer, 130c72fcc34Sopenharmony_ci unsigned int frame_count) 131c72fcc34Sopenharmony_ci{ 132c72fcc34Sopenharmony_ci static const unsigned int entries[] = { 133c72fcc34Sopenharmony_ci [0] = 44100, 134c72fcc34Sopenharmony_ci [1] = 48000, 135c72fcc34Sopenharmony_ci [2] = 88200, 136c72fcc34Sopenharmony_ci [3] = 96000, 137c72fcc34Sopenharmony_ci [4] = 176400, 138c72fcc34Sopenharmony_ci [5] = 192000, 139c72fcc34Sopenharmony_ci }; 140c72fcc34Sopenharmony_ci struct container_trial *trial = gen->private_data; 141c72fcc34Sopenharmony_ci unsigned int frames_per_second; 142c72fcc34Sopenharmony_ci const char *const name = "hoge"; 143c72fcc34Sopenharmony_ci unsigned int size; 144c72fcc34Sopenharmony_ci void *buf; 145c72fcc34Sopenharmony_ci int i; 146c72fcc34Sopenharmony_ci int err = 0; 147c72fcc34Sopenharmony_ci 148c72fcc34Sopenharmony_ci size = frame_count * samples_per_frame * 149c72fcc34Sopenharmony_ci snd_pcm_format_physical_width(sample_format) / 8; 150c72fcc34Sopenharmony_ci buf = malloc(size); 151c72fcc34Sopenharmony_ci if (buf == NULL) 152c72fcc34Sopenharmony_ci return -ENOMEM; 153c72fcc34Sopenharmony_ci 154c72fcc34Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(entries); ++i) { 155c72fcc34Sopenharmony_ci int fd; 156c72fcc34Sopenharmony_ci off_t pos; 157c72fcc34Sopenharmony_ci 158c72fcc34Sopenharmony_ci frames_per_second = entries[i]; 159c72fcc34Sopenharmony_ci 160c72fcc34Sopenharmony_ci#ifdef HAVE_MEMFD_CREATE 161c72fcc34Sopenharmony_ci fd = memfd_create(name, 0); 162c72fcc34Sopenharmony_ci#else 163c72fcc34Sopenharmony_ci fd = open(name, O_RDWR | O_CREAT | O_TRUNC, 0644); 164c72fcc34Sopenharmony_ci#endif 165c72fcc34Sopenharmony_ci if (fd < 0) { 166c72fcc34Sopenharmony_ci err = -errno; 167c72fcc34Sopenharmony_ci break; 168c72fcc34Sopenharmony_ci } 169c72fcc34Sopenharmony_ci 170c72fcc34Sopenharmony_ci test_builder(&trial->cntr, fd, trial->format, access, 171c72fcc34Sopenharmony_ci sample_format, samples_per_frame, 172c72fcc34Sopenharmony_ci frames_per_second, frame_buffer, frame_count, 173c72fcc34Sopenharmony_ci trial->verbose); 174c72fcc34Sopenharmony_ci 175c72fcc34Sopenharmony_ci pos = lseek(fd, 0, SEEK_SET); 176c72fcc34Sopenharmony_ci if (pos < 0) { 177c72fcc34Sopenharmony_ci err = -errno; 178c72fcc34Sopenharmony_ci break; 179c72fcc34Sopenharmony_ci } 180c72fcc34Sopenharmony_ci 181c72fcc34Sopenharmony_ci test_parser(&trial->cntr, fd, trial->format, access, 182c72fcc34Sopenharmony_ci sample_format, samples_per_frame, frames_per_second, 183c72fcc34Sopenharmony_ci buf, frame_count, trial->verbose); 184c72fcc34Sopenharmony_ci 185c72fcc34Sopenharmony_ci err = memcmp(buf, frame_buffer, size); 186c72fcc34Sopenharmony_ci assert(err == 0); 187c72fcc34Sopenharmony_ci 188c72fcc34Sopenharmony_ci close(fd); 189c72fcc34Sopenharmony_ci } 190c72fcc34Sopenharmony_ci 191c72fcc34Sopenharmony_ci free(buf); 192c72fcc34Sopenharmony_ci 193c72fcc34Sopenharmony_ci return err; 194c72fcc34Sopenharmony_ci} 195c72fcc34Sopenharmony_ci 196c72fcc34Sopenharmony_ciint main(int argc, const char *argv[]) 197c72fcc34Sopenharmony_ci{ 198c72fcc34Sopenharmony_ci static const uint64_t sample_format_masks[] = { 199c72fcc34Sopenharmony_ci [CONTAINER_FORMAT_RIFF_WAVE] = 200c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U8) | 201c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S16_LE) | 202c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S16_BE) | 203c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_LE) | 204c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_BE) | 205c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S32_LE) | 206c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S32_BE) | 207c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT_LE) | 208c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT_BE) | 209c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT64_LE) | 210c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT64_BE) | 211c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_MU_LAW) | 212c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_A_LAW) | 213c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_3LE) | 214c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_3BE) | 215c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S20_3LE) | 216c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S20_3BE) | 217c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S18_3LE) | 218c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S18_3BE), 219c72fcc34Sopenharmony_ci [CONTAINER_FORMAT_AU] = 220c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S8) | 221c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S16_BE) | 222c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S32_BE) | 223c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT_BE) | 224c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT64_BE) | 225c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_MU_LAW) | 226c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_A_LAW), 227c72fcc34Sopenharmony_ci [CONTAINER_FORMAT_VOC] = 228c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U8) | 229c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S16_LE) | 230c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_MU_LAW) | 231c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_A_LAW), 232c72fcc34Sopenharmony_ci [CONTAINER_FORMAT_RAW] = 233c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S8) | 234c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U8) | 235c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S16_LE) | 236c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S16_BE) | 237c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U16_LE) | 238c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U16_BE) | 239c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_LE) | 240c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_BE) | 241c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U24_LE) | 242c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U24_BE) | 243c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S32_LE) | 244c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S32_BE) | 245c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U32_LE) | 246c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U32_BE) | 247c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT_LE) | 248c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT_BE) | 249c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT64_LE) | 250c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_FLOAT64_BE) | 251c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_IEC958_SUBFRAME_LE) | 252c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_IEC958_SUBFRAME_BE) | 253c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_MU_LAW) | 254c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_A_LAW) | 255c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_3LE) | 256c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S24_3BE) | 257c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U24_3LE) | 258c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U24_3BE) | 259c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S20_3LE) | 260c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S20_3BE) | 261c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U20_3LE) | 262c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U20_3BE) | 263c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S18_3LE) | 264c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_S18_3BE) | 265c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U18_3LE) | 266c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_U18_3BE) | 267c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_DSD_U8) | 268c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_DSD_U16_LE) | 269c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_DSD_U32_LE) | 270c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_DSD_U16_BE) | 271c72fcc34Sopenharmony_ci (1ull << SND_PCM_FORMAT_DSD_U32_BE), 272c72fcc34Sopenharmony_ci }; 273c72fcc34Sopenharmony_ci static const uint64_t access_mask = 274c72fcc34Sopenharmony_ci (1ull << SND_PCM_ACCESS_MMAP_INTERLEAVED) | 275c72fcc34Sopenharmony_ci (1ull << SND_PCM_ACCESS_RW_INTERLEAVED); 276c72fcc34Sopenharmony_ci struct test_generator gen = {0}; 277c72fcc34Sopenharmony_ci struct container_trial *trial; 278c72fcc34Sopenharmony_ci int i; 279c72fcc34Sopenharmony_ci int begin; 280c72fcc34Sopenharmony_ci int end; 281c72fcc34Sopenharmony_ci bool verbose; 282c72fcc34Sopenharmony_ci int err; 283c72fcc34Sopenharmony_ci 284c72fcc34Sopenharmony_ci if (argc > 1) { 285c72fcc34Sopenharmony_ci char *term; 286c72fcc34Sopenharmony_ci begin = strtol(argv[1], &term, 10); 287c72fcc34Sopenharmony_ci if (errno || *term != '\0') 288c72fcc34Sopenharmony_ci return EXIT_FAILURE; 289c72fcc34Sopenharmony_ci if (begin < CONTAINER_FORMAT_RIFF_WAVE && 290c72fcc34Sopenharmony_ci begin > CONTAINER_FORMAT_RAW) 291c72fcc34Sopenharmony_ci return -EXIT_FAILURE; 292c72fcc34Sopenharmony_ci end = begin + 1; 293c72fcc34Sopenharmony_ci verbose = true; 294c72fcc34Sopenharmony_ci } else { 295c72fcc34Sopenharmony_ci begin = CONTAINER_FORMAT_RIFF_WAVE; 296c72fcc34Sopenharmony_ci end = CONTAINER_FORMAT_RAW + 1; 297c72fcc34Sopenharmony_ci verbose = false; 298c72fcc34Sopenharmony_ci } 299c72fcc34Sopenharmony_ci 300c72fcc34Sopenharmony_ci for (i = begin; i < end; ++i) { 301c72fcc34Sopenharmony_ci err = generator_context_init(&gen, access_mask, 302c72fcc34Sopenharmony_ci sample_format_masks[i], 303c72fcc34Sopenharmony_ci 1, 32, 23, 3000, 512, 304c72fcc34Sopenharmony_ci sizeof(struct container_trial)); 305c72fcc34Sopenharmony_ci if (err >= 0) { 306c72fcc34Sopenharmony_ci trial = gen.private_data; 307c72fcc34Sopenharmony_ci trial->format = i; 308c72fcc34Sopenharmony_ci trial->verbose = verbose; 309c72fcc34Sopenharmony_ci err = generator_context_run(&gen, callback); 310c72fcc34Sopenharmony_ci } 311c72fcc34Sopenharmony_ci 312c72fcc34Sopenharmony_ci generator_context_destroy(&gen); 313c72fcc34Sopenharmony_ci 314c72fcc34Sopenharmony_ci if (err < 0) 315c72fcc34Sopenharmony_ci break; 316c72fcc34Sopenharmony_ci } 317c72fcc34Sopenharmony_ci 318c72fcc34Sopenharmony_ci if (err < 0) { 319c72fcc34Sopenharmony_ci printf("%s\n", strerror(-err)); 320c72fcc34Sopenharmony_ci return EXIT_FAILURE; 321c72fcc34Sopenharmony_ci } 322c72fcc34Sopenharmony_ci 323c72fcc34Sopenharmony_ci return EXIT_SUCCESS; 324c72fcc34Sopenharmony_ci} 325