Home | History | Annotate | Download | only in tinycompress
      1 /*
      2  * BSD LICENSE
      3  *
      4  * tinycompress library for compress audio offload in alsa
      5  * Copyright (c) 2011-2012, Intel Corporation
      6  * All rights reserved.
      7  *
      8  * Author: Vinod Koul <vinod.koul (at) linux.intel.com>
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions are met:
     12  *
     13  * Redistributions of source code must retain the above copyright notice,
     14  * this list of conditions and the following disclaimer.
     15  * Redistributions in binary form must reproduce the above copyright notice,
     16  * this list of conditions and the following disclaimer in the documentation
     17  * and/or other materials provided with the distribution.
     18  * Neither the name of Intel Corporation nor the names of its contributors
     19  * may be used to endorse or promote products derived from this software
     20  * without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     32  * THE POSSIBILITY OF SUCH DAMAGE.
     33  *
     34  * LGPL LICENSE
     35  *
     36  * tinycompress library for compress audio offload in alsa
     37  * Copyright (c) 2011-2012, Intel Corporation.
     38  *
     39  *
     40  * This program is free software; you can redistribute it and/or modify it
     41  * under the terms and conditions of the GNU Lesser General Public License,
     42  * version 2.1, as published by the Free Software Foundation.
     43  *
     44  * This program is distributed in the hope it will be useful, but WITHOUT
     45  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     46  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     47  * License for more details.
     48  *
     49  * You should have received a copy of the GNU Lesser General Public License
     50  * along with this program; if not, write to
     51  * the Free Software Foundation, Inc.,
     52  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
     53  */
     54 
     55 #include <stdio.h>
     56 #include <stdlib.h>
     57 #include <fcntl.h>
     58 #include <stdarg.h>
     59 #include <string.h>
     60 #include <errno.h>
     61 #include <unistd.h>
     62 #include <poll.h>
     63 #include <stdbool.h>
     64 #include <sys/ioctl.h>
     65 #include <sys/mman.h>
     66 #include <sys/time.h>
     67 #include <limits.h>
     68 
     69 #include <linux/types.h>
     70 #include <linux/ioctl.h>
     71 #define __force
     72 #define __bitwise
     73 #define __user
     74 #include <sound/asound.h>
     75 #include "sound/compress_params.h"
     76 #include "sound/compress_offload.h"
     77 #include "tinycompress/tinycompress.h"
     78 
     79 #define COMPR_ERR_MAX 128
     80 
     81 /* Default maximum time we will wait in a poll() - 20 seconds */
     82 #define DEFAULT_MAX_POLL_WAIT_MS    20000
     83 
     84 struct compress {
     85 	int fd;
     86 	unsigned int flags;
     87 	char error[COMPR_ERR_MAX];
     88 	struct compr_config *config;
     89 	int running;
     90 	int max_poll_wait_ms;
     91 	int nonblocking;
     92 	unsigned int gapless_metadata;
     93 	unsigned int next_track;
     94 };
     95 
     96 static int oops(struct compress *compress, int e, const char *fmt, ...)
     97 {
     98 	va_list ap;
     99 	int sz;
    100 
    101 	va_start(ap, fmt);
    102 	vsnprintf(compress->error, COMPR_ERR_MAX, fmt, ap);
    103 	va_end(ap);
    104 	sz = strlen(compress->error);
    105 
    106 	snprintf(compress->error + sz, COMPR_ERR_MAX - sz,
    107 		": %s", strerror(e));
    108 	errno = e;
    109 
    110 	return -1;
    111 }
    112 
    113 const char *compress_get_error(struct compress *compress)
    114 {
    115 	return compress->error;
    116 }
    117 static struct compress bad_compress = {
    118 	.fd = -1,
    119 };
    120 
    121 int is_compress_running(struct compress *compress)
    122 {
    123 	return ((compress->fd > 0) && compress->running) ? 1 : 0;
    124 }
    125 
    126 int is_compress_ready(struct compress *compress)
    127 {
    128 	return (compress->fd > 0) ? 1 : 0;
    129 }
    130 
    131 static int get_compress_version(struct compress *compress)
    132 {
    133 	int version = 0;
    134 
    135 	if (ioctl(compress->fd, SNDRV_COMPRESS_IOCTL_VERSION, &version)) {
    136 		oops(compress, errno, "cant read version");
    137 		return -1;
    138 	}
    139 	return version;
    140 }
    141 
    142 static bool _is_codec_supported(struct compress *compress, struct compr_config *config,
    143 				const struct snd_compr_caps *caps)
    144 {
    145 	bool codec = false;
    146 	unsigned int i;
    147 
    148 	for (i = 0; i < caps->num_codecs; i++) {
    149 		if (caps->codecs[i] == config->codec->id) {
    150 			/* found the codec */
    151 			codec = true;
    152 			break;
    153 		}
    154 	}
    155 	if (codec == false) {
    156 		oops(compress, ENXIO, "this codec is not supported");
    157 		return false;
    158 	}
    159 
    160 	if (config->fragment_size < caps->min_fragment_size) {
    161 		oops(compress, EINVAL, "requested fragment size %d is below min supported %d",
    162 			config->fragment_size, caps->min_fragment_size);
    163 		return false;
    164 	}
    165 	if (config->fragment_size > caps->max_fragment_size) {
    166 		oops(compress, EINVAL, "requested fragment size %d is above max supported %d",
    167 			config->fragment_size, caps->max_fragment_size);
    168 		return false;
    169 	}
    170 	if (config->fragments < caps->min_fragments) {
    171 		oops(compress, EINVAL, "requested fragments %d are below min supported %d",
    172 			config->fragments, caps->min_fragments);
    173 		return false;
    174 	}
    175 	if (config->fragments > caps->max_fragments) {
    176 		oops(compress, EINVAL, "requested fragments %d are above max supported %d",
    177 			config->fragments, caps->max_fragments);
    178 		return false;
    179 	}
    180 
    181 	/* TODO: match the codec properties */
    182 	return true;
    183 }
    184 
    185 static bool _is_codec_type_supported(int fd, struct snd_codec *codec)
    186 {
    187 	struct snd_compr_caps caps;
    188 	bool found = false;
    189 	unsigned int i;
    190 
    191 	if (ioctl(fd, SNDRV_COMPRESS_GET_CAPS, &caps)) {
    192 		oops(&bad_compress, errno, "cannot get device caps");
    193 		return false;
    194 	}
    195 
    196 	for (i = 0; i < caps.num_codecs; i++) {
    197 		if (caps.codecs[i] == codec->id) {
    198 			/* found the codec */
    199 			found = true;
    200 			break;
    201 		}
    202 	}
    203 	/* TODO: match the codec properties */
    204 	return found;
    205 }
    206 
    207 static inline void
    208 fill_compress_params(struct compr_config *config, struct snd_compr_params *params)
    209 {
    210 	params->buffer.fragment_size = config->fragment_size;
    211 	params->buffer.fragments = config->fragments;
    212 	memcpy(&params->codec, config->codec, sizeof(params->codec));
    213 }
    214 
    215 struct compress *compress_open(unsigned int card, unsigned int device,
    216 		unsigned int flags, struct compr_config *config)
    217 {
    218 	struct compress *compress;
    219 	struct snd_compr_params params;
    220 	struct snd_compr_caps caps;
    221 	char fn[256];
    222 
    223 	if (!config) {
    224 		oops(&bad_compress, EINVAL, "passed bad config");
    225 		return &bad_compress;
    226 	}
    227 
    228 	compress = calloc(1, sizeof(struct compress));
    229 	if (!compress) {
    230 		oops(&bad_compress, errno, "cannot allocate compress object");
    231 		return &bad_compress;
    232 	}
    233 
    234 	compress->next_track = 0;
    235 	compress->gapless_metadata = 0;
    236 	compress->config = calloc(1, sizeof(*config));
    237 	if (!compress->config)
    238 		goto input_fail;
    239 
    240 	snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card, device);
    241 
    242 	compress->max_poll_wait_ms = DEFAULT_MAX_POLL_WAIT_MS;
    243 
    244 	compress->flags = flags;
    245 	if (!((flags & COMPRESS_OUT) || (flags & COMPRESS_IN))) {
    246 		oops(&bad_compress, EINVAL, "can't deduce device direction from given flags");
    247 		goto config_fail;
    248 	}
    249 
    250 	if (flags & COMPRESS_OUT) {
    251 		compress->fd = open(fn, O_RDONLY);
    252 	} else {
    253 		compress->fd = open(fn, O_WRONLY);
    254 	}
    255 	if (compress->fd < 0) {
    256 		oops(&bad_compress, errno, "cannot open device '%s'", fn);
    257 		goto config_fail;
    258 	}
    259 
    260 	if (ioctl(compress->fd, SNDRV_COMPRESS_GET_CAPS, &caps)) {
    261 		oops(compress, errno, "cannot get device caps");
    262 		goto codec_fail;
    263 	}
    264 
    265 	/* If caller passed "don't care" fill in default values */
    266 	if ((config->fragment_size == 0) || (config->fragments == 0)) {
    267 		config->fragment_size = caps.min_fragment_size;
    268 		config->fragments = caps.max_fragments;
    269 	}
    270 
    271 #if 0
    272 	/* FIXME need to turn this On when DSP supports
    273 	 * and treat in no support case
    274 	 */
    275 	if (_is_codec_supported(compress, config, &caps) == false) {
    276 		oops(compress, errno, "codec not supported\n");
    277 		goto codec_fail;
    278 	}
    279 #endif
    280 
    281 	memcpy(compress->config, config, sizeof(*compress->config));
    282 	fill_compress_params(config, &params);
    283 
    284 	if (ioctl(compress->fd, SNDRV_COMPRESS_SET_PARAMS, &params)) {
    285 		oops(&bad_compress, errno, "cannot set device");
    286 		goto codec_fail;
    287 	}
    288 
    289 	return compress;
    290 
    291 codec_fail:
    292 	close(compress->fd);
    293 	compress->fd = -1;
    294 config_fail:
    295 	free(compress->config);
    296 input_fail:
    297 	free(compress);
    298 	return &bad_compress;
    299 }
    300 
    301 void compress_close(struct compress *compress)
    302 {
    303 	if (compress == &bad_compress)
    304 		return;
    305 
    306 	if (compress->fd >= 0)
    307 		close(compress->fd);
    308 	compress->running = 0;
    309 	compress->fd = -1;
    310 	free(compress->config);
    311 	free(compress);
    312 }
    313 
    314 int compress_get_hpointer(struct compress *compress,
    315 		unsigned int *avail, struct timespec *tstamp)
    316 {
    317 	struct snd_compr_avail kavail;
    318 	__u64 time;
    319 
    320 	if (!is_compress_ready(compress))
    321 		return oops(compress, ENODEV, "device not ready");
    322 
    323 	if (ioctl(compress->fd, SNDRV_COMPRESS_AVAIL, &kavail))
    324 		return oops(compress, errno, "cannot get avail");
    325 	if (0 == kavail.tstamp.sampling_rate)
    326 		return oops(compress, ENODATA, "sample rate unknown");
    327 	*avail = (unsigned int)kavail.avail;
    328 	time = kavail.tstamp.pcm_io_frames / kavail.tstamp.sampling_rate;
    329 	tstamp->tv_sec = time;
    330 	time = kavail.tstamp.pcm_io_frames % kavail.tstamp.sampling_rate;
    331 	tstamp->tv_nsec = time * 1000000000 / kavail.tstamp.sampling_rate;
    332 	return 0;
    333 }
    334 
    335 int compress_get_tstamp(struct compress *compress,
    336 			unsigned long *samples, unsigned int *sampling_rate)
    337 {
    338 	struct snd_compr_tstamp ktstamp;
    339 
    340 	if (!is_compress_ready(compress))
    341 		return oops(compress, ENODEV, "device not ready");
    342 
    343 	if (ioctl(compress->fd, SNDRV_COMPRESS_TSTAMP, &ktstamp))
    344 		return oops(compress, errno, "cannot get tstamp");
    345 
    346 	*samples = ktstamp.pcm_io_frames;
    347 	*sampling_rate = ktstamp.sampling_rate;
    348 	return 0;
    349 }
    350 
    351 int compress_write(struct compress *compress, const void *buf, unsigned int size)
    352 {
    353 	struct snd_compr_avail avail;
    354 	struct pollfd fds;
    355 	int to_write = 0;	/* zero indicates we haven't written yet */
    356 	int written, total = 0, ret;
    357 	const char* cbuf = buf;
    358 	const unsigned int frag_size = compress->config->fragment_size;
    359 
    360 	if (!(compress->flags & COMPRESS_IN))
    361 		return oops(compress, EINVAL, "Invalid flag set");
    362 	if (!is_compress_ready(compress))
    363 		return oops(compress, ENODEV, "device not ready");
    364 	fds.fd = compress->fd;
    365 	fds.events = POLLOUT;
    366 
    367 	/*TODO: treat auto start here first */
    368 	while (size) {
    369 		if (ioctl(compress->fd, SNDRV_COMPRESS_AVAIL, &avail))
    370 			return oops(compress, errno, "cannot get avail");
    371 
    372 		/* We can write if we have at least one fragment available
    373 		 * or there is enough space for all remaining data
    374 		 */
    375 		if ((avail.avail < frag_size) && (avail.avail < size)) {
    376 
    377 			if (compress->nonblocking)
    378 				return total;
    379 
    380 			ret = poll(&fds, 1, compress->max_poll_wait_ms);
    381 			if (fds.revents & POLLERR) {
    382 				return oops(compress, EIO, "poll returned error!");
    383 			}
    384 			/* A pause will cause -EBADFD or zero.
    385 			 * This is not an error, just stop writing */
    386 			if ((ret == 0) || (ret == -EBADFD))
    387 				break;
    388 			if (ret < 0)
    389 				return oops(compress, errno, "poll error");
    390 			if (fds.revents & POLLOUT) {
    391 				continue;
    392 			}
    393 		}
    394 		/* write avail bytes */
    395 		if (size > avail.avail)
    396 			to_write =  avail.avail;
    397 		else
    398 			to_write = size;
    399 		written = write(compress->fd, cbuf, to_write);
    400 		/* If play was paused the write returns -EBADFD */
    401 		if (written == -EBADFD)
    402 			break;
    403 		if (written < 0)
    404 			return oops(compress, errno, "write failed!");
    405 
    406 		size -= written;
    407 		cbuf += written;
    408 		total += written;
    409 	}
    410 	return total;
    411 }
    412 
    413 int compress_read(struct compress *compress, void *buf, unsigned int size)
    414 {
    415 	struct snd_compr_avail avail;
    416 	struct pollfd fds;
    417 	int to_read = 0;
    418 	int num_read, total = 0, ret;
    419 	char* cbuf = buf;
    420 	const unsigned int frag_size = compress->config->fragment_size;
    421 
    422 	if (!(compress->flags & COMPRESS_OUT))
    423 		return oops(compress, EINVAL, "Invalid flag set");
    424 	if (!is_compress_ready(compress))
    425 		return oops(compress, ENODEV, "device not ready");
    426 	fds.fd = compress->fd;
    427 	fds.events = POLLIN;
    428 
    429 	while (size) {
    430 		if (ioctl(compress->fd, SNDRV_COMPRESS_AVAIL, &avail))
    431 			return oops(compress, errno, "cannot get avail");
    432 
    433 		if ( (avail.avail < frag_size) && (avail.avail < size) ) {
    434 			/* Less than one fragment available and not at the
    435 			 * end of the read, so poll
    436 			 */
    437 			if (compress->nonblocking)
    438 				return total;
    439 
    440 			ret = poll(&fds, 1, compress->max_poll_wait_ms);
    441 			if (fds.revents & POLLERR) {
    442 				return oops(compress, EIO, "poll returned error!");
    443 			}
    444 			/* A pause will cause -EBADFD or zero.
    445 			 * This is not an error, just stop reading */
    446 			if ((ret == 0) || (ret == -EBADFD))
    447 				break;
    448 			if (ret < 0)
    449 				return oops(compress, errno, "poll error");
    450 			if (fds.revents & POLLIN) {
    451 				continue;
    452 			}
    453 		}
    454 		/* read avail bytes */
    455 		if (size > avail.avail)
    456 			to_read = avail.avail;
    457 		else
    458 			to_read = size;
    459 		num_read = read(compress->fd, cbuf, to_read);
    460 		/* If play was paused the read returns -EBADFD */
    461 		if (num_read == -EBADFD)
    462 			break;
    463 		if (num_read < 0)
    464 			return oops(compress, errno, "read failed!");
    465 
    466 		size -= num_read;
    467 		cbuf += num_read;
    468 		total += num_read;
    469 	}
    470 
    471 	return total;
    472 }
    473 
    474 int compress_start(struct compress *compress)
    475 {
    476 	if (!is_compress_ready(compress))
    477 		return oops(compress, ENODEV, "device not ready");
    478 	if (ioctl(compress->fd, SNDRV_COMPRESS_START))
    479 		return oops(compress, errno, "cannot start the stream");
    480 	compress->running = 1;
    481 	return 0;
    482 
    483 }
    484 
    485 int compress_stop(struct compress *compress)
    486 {
    487 	if (!is_compress_running(compress))
    488 		return oops(compress, ENODEV, "device not ready");
    489 	if (ioctl(compress->fd, SNDRV_COMPRESS_STOP))
    490 		return oops(compress, errno, "cannot stop the stream");
    491 	return 0;
    492 }
    493 
    494 int compress_pause(struct compress *compress)
    495 {
    496 	if (!is_compress_running(compress))
    497 		return oops(compress, ENODEV, "device not ready");
    498 	if (ioctl(compress->fd, SNDRV_COMPRESS_PAUSE))
    499 		return oops(compress, errno, "cannot pause the stream");
    500 	return 0;
    501 }
    502 
    503 int compress_resume(struct compress *compress)
    504 {
    505 	if (ioctl(compress->fd, SNDRV_COMPRESS_RESUME))
    506 		return oops(compress, errno, "cannot resume the stream");
    507 	return 0;
    508 }
    509 
    510 int compress_drain(struct compress *compress)
    511 {
    512 	if (!is_compress_running(compress))
    513 		return oops(compress, ENODEV, "device not ready");
    514 	if (ioctl(compress->fd, SNDRV_COMPRESS_DRAIN))
    515 		return oops(compress, errno, "cannot drain the stream");
    516 	return 0;
    517 }
    518 
    519 int compress_partial_drain(struct compress *compress)
    520 {
    521 	if (!is_compress_running(compress))
    522 		return oops(compress, ENODEV, "device not ready");
    523 
    524 	if (!compress->next_track)
    525 		return oops(compress, EPERM, "next track not signalled");
    526 	if (ioctl(compress->fd, SNDRV_COMPRESS_PARTIAL_DRAIN))
    527 		return oops(compress, errno, "cannot drain the stream\n");
    528 	compress->next_track = 0;
    529 	return 0;
    530 }
    531 
    532 int compress_next_track(struct compress *compress)
    533 {
    534 	if (!is_compress_running(compress))
    535 		return oops(compress, ENODEV, "device not ready");
    536 
    537 	if (!compress->gapless_metadata)
    538 		return oops(compress, EPERM, "metadata not set");
    539 	if (ioctl(compress->fd, SNDRV_COMPRESS_NEXT_TRACK))
    540 		return oops(compress, errno, "cannot set next track\n");
    541 	compress->next_track = 1;
    542 	compress->gapless_metadata = 0;
    543 	return 0;
    544 }
    545 
    546 int compress_set_gapless_metadata(struct compress *compress,
    547 	struct compr_gapless_mdata *mdata)
    548 {
    549 	struct snd_compr_metadata metadata;
    550 	int version;
    551 
    552 	if (!is_compress_ready(compress))
    553 		return oops(compress, ENODEV, "device not ready");
    554 
    555 	version = get_compress_version(compress);
    556 	if (version <= 0)
    557 		return -1;
    558 
    559 	if (version < SNDRV_PROTOCOL_VERSION(0, 1, 1))
    560 		return oops(compress, ENXIO, "gapless apis not supported in kernel");
    561 
    562 	metadata.key = SNDRV_COMPRESS_ENCODER_PADDING;
    563 	metadata.value[0] = mdata->encoder_padding;
    564 	if (ioctl(compress->fd, SNDRV_COMPRESS_SET_METADATA, &metadata))
    565 		return oops(compress, errno, "can't set metadata for stream\n");
    566 
    567 	metadata.key = SNDRV_COMPRESS_ENCODER_DELAY;
    568 	metadata.value[0] = mdata->encoder_delay;
    569 	if (ioctl(compress->fd, SNDRV_COMPRESS_SET_METADATA, &metadata))
    570 		return oops(compress, errno, "can't set metadata for stream\n");
    571 	compress->gapless_metadata = 1;
    572 	return 0;
    573 }
    574 
    575 bool is_codec_supported(unsigned int card, unsigned int device,
    576 		unsigned int flags, struct snd_codec *codec)
    577 {
    578 	unsigned int dev_flag;
    579 	bool ret;
    580 	int fd;
    581 	char fn[256];
    582 
    583 	snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card, device);
    584 
    585 	if (flags & COMPRESS_OUT)
    586 		dev_flag = O_RDONLY;
    587 	else
    588 		dev_flag = O_WRONLY;
    589 
    590 	fd = open(fn, dev_flag);
    591 	if (fd < 0)
    592 		return oops(&bad_compress, errno, "cannot open device '%s'", fn);
    593 
    594 	ret = _is_codec_type_supported(fd, codec);
    595 
    596 	close(fd);
    597 	return ret;
    598 }
    599 
    600 void compress_set_max_poll_wait(struct compress *compress, int milliseconds)
    601 {
    602 	compress->max_poll_wait_ms = milliseconds;
    603 }
    604 
    605 void compress_nonblock(struct compress *compress, int nonblock)
    606 {
    607 	compress->nonblocking = !!nonblock;
    608 }
    609 
    610 int compress_wait(struct compress *compress, int timeout_ms)
    611 {
    612 	struct pollfd fds;
    613 	int ret;
    614 
    615 	fds.fd = compress->fd;
    616 	fds.events = POLLOUT | POLLIN;
    617 
    618 	ret = poll(&fds, 1, timeout_ms);
    619 	if (ret > 0) {
    620 		if (fds.revents & POLLERR)
    621 			return oops(compress, EIO, "poll returned error!");
    622 		if (fds.revents & (POLLOUT | POLLIN))
    623 			return 0;
    624 	}
    625 	if (ret == 0)
    626 		return oops(compress, ETIME, "poll timed out");
    627 	if (ret < 0)
    628 		return oops(compress, errno, "poll error");
    629 
    630 	return oops(compress, EIO, "poll signalled unhandled event");
    631 }
    632 
    633