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