1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mapper-single.c - a muxer/demuxer for single containers.
4 //
5 // Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6 //
7 // Licensed under the terms of the GNU General Public License, version 2.
8 
9 #include "mapper.h"
10 #include "misc.h"
11 
12 struct single_state {
13 	void (*align_frames)(void *frame_buf, unsigned int frame_count,
14 			     char *buf, unsigned int bytes_per_sample,
15 			     unsigned int samples_per_frame);
16 	char *buf;
17 };
18 
align_to_vector(void * frame_buf,unsigned int frame_count,char * src,unsigned int bytes_per_sample,unsigned samples_per_frame)19 static void align_to_vector(void *frame_buf, unsigned int frame_count,
20 			    char *src, unsigned int bytes_per_sample,
21 			    unsigned samples_per_frame)
22 {
23 	char **dst_bufs = frame_buf;
24 	char *dst;
25 	unsigned int src_pos;
26 	unsigned int dst_pos;
27 	int i, j;
28 
29 	// src: interleaved => dst: a set of interleaved buffers.
30 	for (i = 0; i < samples_per_frame; ++i) {
31 		dst = dst_bufs[i];
32 		for (j = 0; j < frame_count; ++j) {
33 			src_pos = bytes_per_sample * (samples_per_frame * j + i);
34 			dst_pos = bytes_per_sample * j;
35 
36 			memcpy(dst + dst_pos, src + src_pos, bytes_per_sample);
37 		}
38 	}
39 }
40 
align_from_vector(void * frame_buf,unsigned int frame_count,char * dst,unsigned int bytes_per_sample,unsigned int samples_per_frame)41 static void align_from_vector(void *frame_buf, unsigned int frame_count,
42 			      char *dst, unsigned int bytes_per_sample,
43 			      unsigned int samples_per_frame)
44 {
45 	char **src_bufs = frame_buf;
46 	char *src;
47 	unsigned int dst_pos;
48 	unsigned int src_pos;
49 	int i, j;
50 
51 	// src: a set of interleaved buffers => dst:interleaved.
52 	for (i = 0; i < samples_per_frame; ++i) {
53 		src = src_bufs[i];
54 		for (j = 0; j < frame_count; ++j) {
55 			src_pos = bytes_per_sample * j;
56 			dst_pos = bytes_per_sample * (samples_per_frame * j + i);
57 
58 			memcpy(dst + dst_pos, src + src_pos, bytes_per_sample);
59 		}
60 	}
61 }
62 
single_pre_process(struct mapper_context * mapper,struct container_context * cntrs,unsigned int cntr_count)63 static int single_pre_process(struct mapper_context *mapper,
64 			      struct container_context *cntrs,
65 			      unsigned int cntr_count)
66 {
67 	struct single_state *state = mapper->private_data;
68 	unsigned int bytes_per_buffer;
69 
70 	if (cntrs->bytes_per_sample != mapper->bytes_per_sample ||
71 	    cntrs->samples_per_frame != mapper->samples_per_frame)
72 		return -EINVAL;
73 
74 	// Decide method to align frames.
75 	if (mapper->type == MAPPER_TYPE_DEMUXER) {
76 		if (mapper->access == SND_PCM_ACCESS_RW_NONINTERLEAVED ||
77 		    mapper->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED)
78 			state->align_frames = align_from_vector;
79 		else if (mapper->access == SND_PCM_ACCESS_RW_INTERLEAVED ||
80 			 mapper->access == SND_PCM_ACCESS_MMAP_INTERLEAVED)
81 			state->align_frames = NULL;
82 		else
83 			return -EINVAL;
84 	} else {
85 		if (mapper->access == SND_PCM_ACCESS_RW_NONINTERLEAVED ||
86 		    mapper->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED)
87 			state->align_frames = align_to_vector;
88 		else if (mapper->access == SND_PCM_ACCESS_RW_INTERLEAVED ||
89 			 mapper->access == SND_PCM_ACCESS_MMAP_INTERLEAVED)
90 			state->align_frames = NULL;
91 		else
92 			return -EINVAL;
93 	}
94 
95 	if (state->align_frames) {
96 		// Allocate intermediate buffer as the same size as a period.
97 		bytes_per_buffer = mapper->bytes_per_sample *
98 				   mapper->samples_per_frame *
99 				   mapper->frames_per_buffer;
100 		state->buf = malloc(bytes_per_buffer);
101 		if (state->buf == NULL)
102 			return -ENOMEM;
103 		memset(state->buf, 0, bytes_per_buffer);
104 	}
105 
106 	return 0;
107 }
108 
single_muxer_process_frames(struct mapper_context * mapper,void * frame_buf,unsigned int * frame_count,struct container_context * cntrs,unsigned int cntr_count)109 static int single_muxer_process_frames(struct mapper_context *mapper,
110 				       void *frame_buf,
111 				       unsigned int *frame_count,
112 				       struct container_context *cntrs,
113 				       unsigned int cntr_count)
114 {
115 	struct single_state *state = mapper->private_data;
116 	void *src;
117 	int err;
118 
119 	// If need to align PCM frames, process PCM frames to the intermediate
120 	// buffer once.
121 	if (!state->align_frames) {
122 		// The most likely.
123 		src = frame_buf;
124 	} else {
125 		src = state->buf;
126 	}
127 	err = container_context_process_frames(cntrs, src, frame_count);
128 	if (err < 0)
129 		return err;
130 
131 	// Unlikely.
132 	if (src != frame_buf && *frame_count > 0)
133 		state->align_frames(frame_buf, *frame_count, src,
134 				    mapper->bytes_per_sample,
135 				    mapper->samples_per_frame);
136 
137 	return 0;
138 }
139 
single_demuxer_process_frames(struct mapper_context * mapper,void * frame_buf,unsigned int * frame_count,struct container_context * cntrs,unsigned int cntr_count)140 static int single_demuxer_process_frames(struct mapper_context *mapper,
141 					 void *frame_buf,
142 					 unsigned int *frame_count,
143 					 struct container_context *cntrs,
144 					 unsigned int cntr_count)
145 {
146 	struct single_state *state = mapper->private_data;
147 	void *dst;
148 
149 	// If need to align PCM frames, process PCM frames to the intermediate
150 	// buffer once.
151 	if (!state->align_frames) {
152 		// The most likely.
153 		dst = frame_buf;
154 	} else {
155 		state->align_frames(frame_buf, *frame_count, state->buf,
156 				    mapper->bytes_per_sample,
157 				    mapper->samples_per_frame);
158 		dst = state->buf;
159 	}
160 
161 	return container_context_process_frames(cntrs, dst, frame_count);
162 }
163 
single_post_process(struct mapper_context * mapper)164 static void single_post_process(struct mapper_context *mapper)
165 {
166 	struct single_state *state = mapper->private_data;
167 
168 	if (state->buf)
169 		free(state->buf);
170 
171 	state->buf = NULL;
172 	state->align_frames = NULL;
173 }
174 
175 const struct mapper_data mapper_muxer_single = {
176 	.ops = {
177 		.pre_process = single_pre_process,
178 		.process_frames = single_muxer_process_frames,
179 		.post_process = single_post_process,
180 	},
181 	.private_size = sizeof(struct single_state),
182 };
183 
184 const struct mapper_data mapper_demuxer_single = {
185 	.ops = {
186 		.pre_process = single_pre_process,
187 		.process_frames = single_demuxer_process_frames,
188 		.post_process = single_post_process,
189 	},
190 	.private_size = sizeof(struct single_state),
191 };
192