OSDN Git Service

axfer: add support for a mapper for multiple target
[android-x86/external-alsa-utils.git] / axfer / mapper.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mapper.c - an interface of muxer/demuxer between buffer with data frames and
4 //            formatted files.
5 //
6 // Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
7 //
8 // Licensed under the terms of the GNU General Public License, version 2.
9
10 #include "mapper.h"
11 #include "misc.h"
12
13 #include <stdio.h>
14
15 static const char *const mapper_type_labels[] = {
16         [MAPPER_TYPE_MUXER] = "muxer",
17         [MAPPER_TYPE_DEMUXER] = "demuxer",
18 };
19
20 static const char *const mapper_target_labels[] = {
21         [MAPPER_TARGET_SINGLE] = "single",
22         [MAPPER_TARGET_MULTIPLE] = "multiple",
23 };
24
25 int mapper_context_init(struct mapper_context *mapper,
26                         enum mapper_type type, unsigned int cntr_count,
27                         unsigned int verbose)
28 {
29         const struct mapper_data *data = NULL;
30
31         assert(mapper);
32         assert(cntr_count > 0);
33
34         // Detect forgotten to destruct.
35         assert(mapper->private_data == NULL);
36
37         memset(mapper, 0, sizeof(*mapper));
38
39         if (type == MAPPER_TYPE_MUXER) {
40                 if (cntr_count == 1) {
41                         data = &mapper_muxer_single;
42                         mapper->target = MAPPER_TARGET_SINGLE;
43                 } else {
44                         data = &mapper_muxer_multiple;
45                         mapper->target = MAPPER_TARGET_MULTIPLE;
46                 }
47         } else {
48                 if (cntr_count == 1) {
49                         data = &mapper_demuxer_single;
50                         mapper->target = MAPPER_TARGET_SINGLE;
51                 } else {
52                         data = &mapper_demuxer_multiple;
53                         mapper->target = MAPPER_TARGET_MULTIPLE;
54                 }
55         }
56
57         mapper->ops = &data->ops;
58         mapper->type = type;
59
60         mapper->private_data = malloc(data->private_size);
61         if (mapper->private_data == NULL)
62                 return -ENOMEM;
63         memset(mapper->private_data, 0, data->private_size);
64
65         mapper->cntr_count = cntr_count;
66         mapper->verbose = verbose;
67
68         return 0;
69 }
70
71 int mapper_context_pre_process(struct mapper_context *mapper,
72                                snd_pcm_access_t access,
73                                unsigned int bytes_per_sample,
74                                unsigned int samples_per_frame,
75                                unsigned int frames_per_buffer,
76                                struct container_context *cntrs)
77 {
78         int err;
79
80         assert(mapper);
81         assert(access >= SND_PCM_ACCESS_MMAP_INTERLEAVED);
82         assert(access <= SND_PCM_ACCESS_RW_NONINTERLEAVED);
83         assert(bytes_per_sample > 0);
84         assert(samples_per_frame > 0);
85         assert(cntrs);
86
87         // The purpose of multiple target is to mux/demux each channels to/from
88         // containers.
89         if (mapper->target == MAPPER_TARGET_MULTIPLE &&
90             samples_per_frame != mapper->cntr_count)
91                 return -EINVAL;
92
93         mapper->access = access;
94         mapper->bytes_per_sample = bytes_per_sample;
95         mapper->samples_per_frame = samples_per_frame;
96         mapper->frames_per_buffer = frames_per_buffer;
97
98         err = mapper->ops->pre_process(mapper, cntrs, mapper->cntr_count);
99         if (err < 0)
100                 return err;
101
102         if (mapper->verbose > 0) {
103                 fprintf(stderr, "Mapper: %s\n",
104                        mapper_type_labels[mapper->type]);
105                 fprintf(stderr, "  target: %s\n",
106                        mapper_target_labels[mapper->target]);
107                 fprintf(stderr, "  access: %s\n",
108                        snd_pcm_access_name(mapper->access));
109                 fprintf(stderr, "  bytes/sample: %u\n",
110                         mapper->bytes_per_sample);
111                 fprintf(stderr, "  samples/frame: %u\n",
112                         mapper->samples_per_frame);
113                 fprintf(stderr, "  frames/buffer: %lu\n",
114                         mapper->frames_per_buffer);
115         }
116
117         return 0;
118 }
119
120 int mapper_context_process_frames(struct mapper_context *mapper,
121                                   void *frame_buffer,
122                                   unsigned int *frame_count,
123                                   struct container_context *cntrs)
124 {
125         assert(mapper);
126         assert(frame_buffer);
127         assert(frame_count);
128         assert(*frame_count <= mapper->frames_per_buffer);
129         assert(cntrs);
130
131         return mapper->ops->process_frames(mapper, frame_buffer, frame_count,
132                                             cntrs, mapper->cntr_count);
133 }
134
135 void mapper_context_post_process(struct mapper_context *mapper)
136 {
137         assert(mapper);
138
139         if (mapper->ops && mapper->ops->post_process)
140                 mapper->ops->post_process(mapper);
141 }
142
143 void mapper_context_destroy(struct mapper_context *mapper)
144 {
145         assert(mapper);
146
147         if (mapper->private_data)
148                 free(mapper->private_data);
149         mapper->private_data = NULL;
150 }