Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package alsa-plugins for openSUSE:Factory checked in at 2021-12-08 22:08:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/alsa-plugins (Old) and /work/SRC/openSUSE:Factory/.alsa-plugins.new.31177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "alsa-plugins" Wed Dec 8 22:08:39 2021 rev:112 rq:936044 version:1.2.6 Changes: -------- --- /work/SRC/openSUSE:Factory/alsa-plugins/alsa-plugins.changes 2021-06-05 23:30:50.396365752 +0200 +++ /work/SRC/openSUSE:Factory/.alsa-plugins.new.31177/alsa-plugins.changes 2021-12-08 22:09:03.594865511 +0100 @@ -1,0 +2,8 @@ +Mon Dec 6 15:02:33 CET 2021 - [email protected] + +- Update to version 1.2.6: + Fixes for a52 plugin, jack, rate-lav. For details, see URL: + https://alsa-project.org/wiki/Changes_v1.2.5.1_v1.2.6#alsa-plugins +- Add *.sig file for the source tarball + +------------------------------------------------------------------- Old: ---- alsa-plugins-1.2.5.tar.bz2 New: ---- alsa-plugins-1.2.6.tar.bz2 alsa-plugins-1.2.6.tar.bz2.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ alsa-plugins.spec ++++++ --- /var/tmp/diff_new_pack.4a1sYk/_old 2021-12-08 22:09:04.202865796 +0100 +++ /var/tmp/diff_new_pack.4a1sYk/_new 2021-12-08 22:09:04.206865798 +0100 @@ -23,14 +23,15 @@ %endif Name: alsa-plugins -Version: 1.2.5 +Version: 1.2.6 Release: 0 Summary: Extra Plug-Ins for ALSA Library License: LGPL-2.1-or-later Group: System/Libraries -Url: https://www.alsa-project.org +URL: https://www.alsa-project.org Source: https://www.alsa-project.org/files/pub/plugins/alsa-plugins-%{version}.tar.bz2 -Source1: baselibs.conf +Source1: https://www.alsa-project.org/files/pub/plugins/alsa-plugins-%{version}.tar.bz2.sig +Source2: baselibs.conf BuildRequires: libtool BuildRequires: pkgconfig(alsa) >= 1.2.5 %if %{build_aaf} ++++++ alsa-plugins-1.2.5.tar.bz2 -> alsa-plugins-1.2.6.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/a52/60-a52-encoder.conf new/alsa-plugins-1.2.6/a52/60-a52-encoder.conf --- old/alsa-plugins-1.2.5/a52/60-a52-encoder.conf 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/a52/60-a52-encoder.conf 2021-12-06 11:17:29.000000000 +0100 @@ -36,3 +36,10 @@ description "Plugin to convert multichannel stream to A52 (AC3) bitstream" } } + +# +# A quick test command: +# CARD=1 # replace with your IEC958 card +# DEVICE=1 # replace with your IEC958 PCM device number +# speaker-test -d -b 2000000 -c 6 -D"plug:{SLAVE=\"a52:${CARD},'hw:${CARD},${DEVICE}'\"}" +# diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/a52/pcm_a52.c new/alsa-plugins-1.2.6/a52/pcm_a52.c --- old/alsa-plugins-1.2.5/a52/pcm_a52.c 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/a52/pcm_a52.c 2021-12-06 11:17:29.000000000 +0100 @@ -41,7 +41,12 @@ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 34, 0) #include <libavutil/channel_layout.h> #include <libavutil/mem.h> -#define USE_AVCODEC_FRAME +#define USE_AVCODEC_FRAME 1 +#endif + +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 91, 0) +#include <libavcodec/packet.h> +#define USE_AVCODEC_PACKET_ALLOC #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 0, 0) @@ -62,6 +67,12 @@ #define AV_CODEC_ID_AC3 CODEC_ID_AC3 #endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 0) +#ifndef AV_INPUT_BUFFER_PADDING_SIZE +#define AV_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE +#endif +#endif + #if LIBAVCODEC_VERSION_INT < 0x371c01 #define av_frame_alloc avcodec_alloc_frame #define av_frame_free avcodec_free_frame @@ -72,20 +83,29 @@ snd_pcm_t *slave; AVCodec *codec; AVCodecContext *avctx; + snd_pcm_format_t src_format; + unsigned int src_sample_bits; + unsigned int src_sample_bytes; snd_pcm_format_t format; int av_format; unsigned int channels; unsigned int rate; unsigned int bitrate; - short *inbuf; + void *inbuf; unsigned char *outbuf; + unsigned char *outbuf1; + unsigned char *outbuf2; int outbuf_size; - snd_pcm_uframes_t transfer; int remain; int filled; unsigned int slave_period_size; unsigned int slave_buffer_size; + snd_pcm_uframes_t pointer; + snd_pcm_uframes_t boundary; snd_pcm_hw_params_t *hw_params; +#ifdef USE_AVCODEC_PACKET_ALLOC + AVPacket *pkt; +#endif #ifdef USE_AVCODEC_FRAME AVFrame *frame; int is_planar; @@ -98,70 +118,103 @@ #define use_planar(rec) 0 #endif -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 34, 0) +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 91, 0) +static int do_encode(struct a52_ctx *rec) +{ + AVPacket *pkt = rec->pkt; + int ret; + + ret = avcodec_send_frame(rec->avctx, rec->frame); + if (ret < 0) + return -EINVAL; + ret = avcodec_receive_packet(rec->avctx, pkt); + if (ret < 0) + return -EINVAL; + + if (pkt->size > rec->outbuf_size - 8) + return -EINVAL; + memcpy(rec->outbuf1 + 8, pkt->data, pkt->size); + + return pkt->size; +} +#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 34, 0) static int do_encode(struct a52_ctx *rec) { AVPacket pkt = { - .data = rec->outbuf + 8, + .data = rec->outbuf1 + 8, .size = rec->outbuf_size - 8 }; - int got_frame; + int ret, got_frame; + + ret = avcodec_encode_audio2(rec->avctx, &pkt, rec->frame, &got_frame); + if (ret < 0) + return -EINVAL; - avcodec_encode_audio2(rec->avctx, &pkt, rec->frame, &got_frame); return pkt.size; } #else static int do_encode(struct a52_ctx *rec) { - return avcodec_encode_audio(rec->avctx, rec->outbuf + 8, - rec->outbuf_size - 8, - rec->inbuf); + int ret = avcodec_encode_audio(rec->avctx, rec->outbuf1 + 8, + rec->outbuf_size - 8, + rec->inbuf); + if (ret < 0) + return -EINVAL; + + return ret; } #endif /* convert the PCM data to A52 stream in IEC958 */ -static void convert_data(struct a52_ctx *rec) +static int convert_data(struct a52_ctx *rec) { + unsigned char *buf; int out_bytes = do_encode(rec); - rec->outbuf[0] = 0xf8; /* sync words */ - rec->outbuf[1] = 0x72; - rec->outbuf[2] = 0x4e; - rec->outbuf[3] = 0x1f; - rec->outbuf[4] = rec->outbuf[13] & 7; /* bsmod */ - rec->outbuf[5] = 0x01; /* data type */ - rec->outbuf[6] = ((out_bytes * 8) >> 8) & 0xff; - rec->outbuf[7] = (out_bytes * 8) & 0xff; + if (out_bytes < 0) + return out_bytes; + + buf = rec->outbuf1; + buf[0] = 0xf8; /* sync words */ + buf[1] = 0x72; + buf[2] = 0x4e; + buf[3] = 0x1f; + buf[4] = buf[13] & 7; /* bsmod */ + buf[5] = 0x01; /* data type */ + buf[6] = ((out_bytes * 8) >> 8) & 0xff; + buf[7] = (out_bytes * 8) & 0xff; /* swap bytes for little-endian 16bit */ - if (rec->format == SND_PCM_FORMAT_S16_LE) - swab(rec->outbuf, rec->outbuf, out_bytes + 8); - memset(rec->outbuf + 8 + out_bytes, 0, + if (rec->format == SND_PCM_FORMAT_S16_LE) { + swab(rec->outbuf1, rec->outbuf2, out_bytes + 8); + buf = rec->outbuf2; + } + rec->outbuf = buf; + memset(buf + 8 + out_bytes, 0, rec->outbuf_size - 8 - out_bytes); rec->remain = rec->outbuf_size / 4; rec->filled = 0; + + return 0; } /* write pending encoded data to the slave pcm */ static int write_out_pending(snd_pcm_ioplug_t *io, struct a52_ctx *rec) { - int err, ofs = (rec->avctx->frame_size - rec->remain) * 4; - - if (! rec->remain) - return 0; + snd_pcm_sframes_t ret; + unsigned int ofs; while (rec->remain) { - err = snd_pcm_writei(rec->slave, rec->outbuf + ofs, rec->remain); - if (err < 0) { - if (err == -EPIPE) + ofs = (rec->avctx->frame_size - rec->remain) * 4; + ret = snd_pcm_writei(rec->slave, rec->outbuf + ofs, rec->remain); + if (ret < 0) { + if (ret == -EPIPE) io->state = SND_PCM_STATE_XRUN; - if (err == -EAGAIN) + if (ret == -EAGAIN) break; - return err; - } else if (! err) + return ret; + } else if (! ret) break; - if (err < rec->remain) - ofs += (rec->remain - err) * 4; - rec->remain -= err; + rec->remain -= ret; } return 0; } @@ -176,8 +229,8 @@ unsigned int i; for (i = 0; i < io->channels; i++) - memset(rec->frame->data[i] + rec->filled * 2, 0, - (rec->avctx->frame_size - rec->filled) * 2); + memset(rec->frame->data[i] + rec->filled * rec->src_sample_bytes, 0, + (rec->avctx->frame_size - rec->filled) * rec->src_sample_bytes); } #else #define clear_remaining_planar_data(io) /*NOP*/ @@ -195,10 +248,12 @@ if (use_planar(rec)) clear_remaining_planar_data(io); else { - memset(rec->inbuf + rec->filled * io->channels, 0, - (rec->avctx->frame_size - rec->filled) * io->channels * 2); + memset(rec->inbuf + rec->filled * io->channels * rec->src_sample_bytes, 0, + (rec->avctx->frame_size - rec->filled) * io->channels * rec->src_sample_bytes); } - convert_data(rec); + err = convert_data(rec); + if (err < 0) + return err; } err = write_out_pending(io, rec); if (err < 0) @@ -208,7 +263,8 @@ } /* check whether the areas consist of a continuous interleaved stream */ -static int check_interleaved(const snd_pcm_channel_area_t *areas, +static int check_interleaved(struct a52_ctx *rec, + const snd_pcm_channel_area_t *areas, unsigned int channels) { unsigned int ch; @@ -218,8 +274,8 @@ for (ch = 0; ch < channels; ch++) { if (areas[ch].addr != areas[0].addr || - areas[ch].first != ch * 16 || - areas[ch].step != channels * 16) + areas[ch].first != ch * rec->src_sample_bits || + areas[ch].step != channels * rec->src_sample_bits) return 0; } return 1; @@ -237,8 +293,7 @@ { struct a52_ctx *rec = io->private_data; unsigned int len = rec->avctx->frame_size - rec->filled; - short *src, *dst; - unsigned int src_step; + void *_dst; int err; static unsigned int ch_index[3][6] = { { 0, 1 }, @@ -257,20 +312,23 @@ /* If there are still frames left in outbuf, we can't * accept a full a52 frame, because this would overwrite - * the frames in outbuf. */ - if (rec->remain && len) + * the frames in outbuf. This should not happen! The a52_pointer() + * callback should limit the transferred frames correctly. */ + if (rec->remain && len) { + SNDERR("fill data issue (remain is %i)", rec->remain); len--; + } if (size > len) size = len; - dst = rec->inbuf + rec->filled * io->channels; + _dst = rec->inbuf + rec->filled * io->channels * rec->src_sample_bytes; if (!use_planar(rec) && interleaved) { - memcpy(dst, areas->addr + offset * io->channels * 2, - size * io->channels * 2); - } else { - unsigned int i, ch, dst_step; - short *dst1; + memcpy(_dst, areas->addr + offset * io->channels * rec->src_sample_bytes, + size * io->channels * rec->src_sample_bytes); + } else if (rec->src_sample_bits == 16) { + unsigned int i, ch, src_step, dst_step; + short *src, *dst = _dst, *dst1; /* flatten copy to n-channel interleaved */ dst_step = io->channels; @@ -281,8 +339,8 @@ (ap->first + offset * ap->step) / 8); #ifdef USE_AVCODEC_FRAME - if (use_planar(rec)) { - memcpy(rec->frame->data[ch], src, size * 2); + if (use_planar(rec) && !interleaved) { + memcpy(rec->frame->data[ch] + rec->filled * 2, src, size * 2); continue; } #endif @@ -294,10 +352,40 @@ dst1 += dst_step; } } + } else if (rec->src_sample_bits == 32) { + unsigned int i, ch, src_step, dst_step; + int *src, *dst = _dst, *dst1; + + /* flatten copy to n-channel interleaved */ + dst_step = io->channels; + for (ch = 0; ch < io->channels; ch++, dst++) { + const snd_pcm_channel_area_t *ap; + ap = &areas[ch_index[io->channels / 2 - 1][ch]]; + src = (int *)(ap->addr + + (ap->first + offset * ap->step) / 8); + +#ifdef USE_AVCODEC_FRAME + if (use_planar(rec) && !interleaved) { + memcpy(rec->frame->data[ch] + rec->filled * 4, src, size * 4); + continue; + } +#endif + dst1 = dst; + src_step = ap->step / 32; /* in word */ + for (i = 0; i < size; i++) { + *dst1 = *src; + src += src_step; + dst1 += dst_step; + } + } + } else { + return -EIO; } rec->filled += size; if (rec->filled == rec->avctx->frame_size) { - convert_data(rec); + err = convert_data(rec); + if (err < 0) + return err; write_out_pending(io, rec); } return (int)size; @@ -314,7 +402,7 @@ struct a52_ctx *rec = io->private_data; snd_pcm_sframes_t result = 0; int err = 0; - int interleaved = check_interleaved(areas, io->channels); + int interleaved = check_interleaved(rec, areas, io->channels); do { err = fill_data(io, areas, offset, size, interleaved); @@ -323,7 +411,8 @@ offset += (unsigned int)err; size -= (unsigned int)err; result += err; - rec->transfer += err; + rec->pointer += err; + rec->pointer %= rec->boundary; } while (size); return result > 0 ? result : err; } @@ -336,7 +425,7 @@ static snd_pcm_sframes_t a52_pointer(snd_pcm_ioplug_t *io) { struct a52_ctx *rec = io->private_data; - snd_pcm_sframes_t avail; + snd_pcm_sframes_t avail, delay; snd_pcm_state_t state; state = snd_pcm_state(rec->slave); @@ -345,31 +434,31 @@ case SND_PCM_STATE_DRAINING: break; case SND_PCM_STATE_XRUN: - case SND_PCM_STATE_SUSPENDED: return -EPIPE; + case SND_PCM_STATE_SUSPENDED: + return -ESTRPIPE; default: return 0; } - avail = 0; - /* Write what we have from outbuf. */ write_out_pending(io, rec); - /* If there is anything remaining in outbuf, we can't - * accept any full packets. */ - if (rec->remain == 0) - { - /* Round the slave frames to multiples of the packet size. */ - avail += (snd_pcm_avail_update(rec->slave) / rec->avctx->frame_size) * rec->avctx->frame_size; - } - + avail = snd_pcm_avail(rec->slave); if (avail < 0) - avail = 0; - else if (avail >= io->buffer_size) - avail = io->buffer_size - 1; + return avail; - return (io->appl_ptr + avail) % io->buffer_size; + /* get buffer delay without additional FIFO information */ + delay = rec->slave_buffer_size - avail; + while (delay < 0) + delay += rec->slave_buffer_size; + + avail = rec->pointer - delay - rec->remain - rec->filled; +#ifdef SND_PCM_IOPLUG_FLAG_BOUNDARY_WA + return avail % rec->boundary; +#else + return avail % io->buffer_size; +#endif } /* set up the fixed parameters of slave PCM hw_parmas */ @@ -463,6 +552,25 @@ } /* + * dump callback + */ +static void a52_dump(snd_pcm_ioplug_t *io, snd_output_t *out) +{ + struct a52_ctx *rec = io->private_data; + snd_pcm_t *pcm = io->pcm; + + snd_output_printf(out, "%s\n", io->name); + snd_output_printf(out, "Its setup is:\n"); + snd_pcm_dump_setup(pcm, out); + snd_output_printf(out, " %-13s: %s\n", "av_format", av_get_sample_fmt_name(rec->av_format)); + snd_output_printf(out, " %-13s: %i\n", "av_frame_size", rec->avctx ? rec->avctx->frame_size : -1); + snd_output_printf(out, " %-13s: %i\n", "remain", rec->remain); + snd_output_printf(out, " %-13s: %i\n", "filled", rec->filled); + snd_output_printf(out, "Slave: "); + snd_pcm_dump(rec->slave, out); +} + +/* * sw_params callback * * Set up slave PCM sw_params @@ -476,6 +584,7 @@ snd_pcm_sw_params_get_avail_min(params, &avail_min); snd_pcm_sw_params_get_start_threshold(params, &start_threshold); + snd_pcm_sw_params_get_boundary(params, &rec->boundary); len = avail_min; len += (int)rec->slave_buffer_size - (int)io->buffer_size; @@ -525,21 +634,27 @@ } #ifdef USE_AVCODEC_FRAME - if (rec->frame) { +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 91, 0) + if (rec->frame) av_freep(&rec->frame->data[0]); - rec->inbuf = NULL; - } +#endif #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0) av_frame_free(&rec->frame); #else av_freep(&rec->frame); #endif -#endif - +#else /* USE_AVCODEC_FRAME */ free(rec->inbuf); rec->inbuf = NULL; - free(rec->outbuf); - rec->outbuf = NULL; +#endif /* USE_AVCODEC_FRAME */ + +#ifdef USE_AVCODEC_PACKET_ALLOC + av_packet_free(&rec->pkt); +#endif + free(rec->outbuf2); + rec->outbuf2 = NULL; + free(rec->outbuf1); + rec->outbuf1 = NULL; } /* @@ -577,14 +692,22 @@ rec->frame = av_frame_alloc(); if (!rec->frame) return -ENOMEM; + rec->frame->nb_samples = rec->avctx->frame_size; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 91, 0) + rec->frame->format = rec->avctx->sample_fmt; + rec->frame->channels = rec->avctx->channels; + rec->frame->channel_layout = rec->avctx->channel_layout; + if (av_frame_get_buffer(rec->frame, 0)) + return -ENOMEM; +#else if (av_samples_alloc(rec->frame->data, rec->frame->linesize, io->channels, rec->avctx->frame_size, rec->avctx->sample_fmt, 0) < 0) return -ENOMEM; - rec->frame->nb_samples = rec->avctx->frame_size; - rec->inbuf = (short *)rec->frame->data[0]; +#endif + rec->inbuf = rec->frame->data[0]; #else - rec->inbuf = malloc(rec->avctx->frame_size * 2 * io->channels); + rec->inbuf = malloc(rec->avctx->frame_size * io->channels * rec->src_sample_bytes); #endif if (!rec->inbuf) return -ENOMEM; @@ -622,15 +745,28 @@ if (err < 0) return -EINVAL; +#ifdef USE_AVCODEC_PACKET_ALLOC + rec->pkt = av_packet_alloc(); + if (!rec->pkt) + return -ENOMEM; +#endif + rec->outbuf_size = rec->avctx->frame_size * 4; - rec->outbuf = malloc(rec->outbuf_size); - if (! rec->outbuf) + rec->outbuf1 = malloc(rec->outbuf_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (! rec->outbuf1) return -ENOMEM; + memset(rec->outbuf1 + rec->outbuf_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + if (rec->format == SND_PCM_FORMAT_S16_LE) { + rec->outbuf2 = malloc(rec->outbuf_size); + if ( !rec->outbuf2) + return -ENOMEM; + } if (alloc_input_buffer(io)) return -ENOMEM; - rec->transfer = 0; + rec->pointer = 0; rec->remain = 0; rec->filled = 0; @@ -669,10 +805,9 @@ snd_pcm_t *slave = rec->slave; a52_free(rec); - if (slave) { - rec->slave = NULL; + free(rec); + if (slave) return snd_pcm_close(slave); - } return 0; } @@ -737,6 +872,7 @@ .close = a52_close, .hw_params = a52_hw_params, .hw_free = a52_hw_free, + .dump = a52_dump, .sw_params = a52_sw_params, .prepare = a52_prepare, .drain = a52_drain, @@ -773,8 +909,20 @@ SND_PCM_ACCESS_MMAP_NONINTERLEAVED, SND_PCM_ACCESS_RW_NONINTERLEAVED }; - unsigned int formats[] = { SND_PCM_FORMAT_S16 }; - int err; + static struct format { + int av; + snd_pcm_format_t alib; + } formats[] = { + { .av = AV_SAMPLE_FMT_S16, .alib = SND_PCM_FORMAT_S16 }, +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 95, 0) && USE_AVCODEC_FRAME + { .av = AV_SAMPLE_FMT_S16P, .alib = SND_PCM_FORMAT_S16 }, + { .av = AV_SAMPLE_FMT_S32, .alib = SND_PCM_FORMAT_S32 }, + { .av = AV_SAMPLE_FMT_S32P, .alib = SND_PCM_FORMAT_S32 }, + { .av = AV_SAMPLE_FMT_FLTP, .alib = SND_PCM_FORMAT_FLOAT } +#endif + }; + int err, dir; + unsigned int i, fmt; snd_pcm_uframes_t buffer_max; unsigned int period_bytes, max_periods; @@ -791,8 +939,22 @@ if (err < 0) return err; + rec->src_format = SND_PCM_FORMAT_UNKNOWN; + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (formats[i].av == rec->av_format) { + rec->src_format = formats[i].alib; + break; + } + if (rec->src_format == SND_PCM_FORMAT_UNKNOWN) { + SNDERR("A/V format '%s' is not supported", av_get_sample_fmt_name(rec->av_format)); + return -EINVAL; + } + fmt = rec->src_format; + rec->src_sample_bits = snd_pcm_format_physical_width(rec->src_format); + rec->src_sample_bytes = rec->src_sample_bits / 8; + if ((err = snd_pcm_ioplug_set_param_list(&rec->io, SND_PCM_IOPLUG_HW_FORMAT, - ARRAY_SIZE(formats), formats)) < 0 || + 1, &fmt)) < 0 || (err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_CHANNELS, rec->channels, rec->channels)) < 0 || (err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_RATE, @@ -803,8 +965,11 @@ return err; snd_pcm_hw_params_get_buffer_size_max(rec->hw_params, &buffer_max); + dir = -1; + snd_pcm_hw_params_get_periods_max(rec->hw_params, &max_periods, &dir); period_bytes = A52_FRAME_SIZE * 2 * rec->channels; - max_periods = buffer_max / A52_FRAME_SIZE; + if (buffer_max / A52_FRAME_SIZE < max_periods) + max_periods = buffer_max / A52_FRAME_SIZE; if ((err = snd_pcm_ioplug_set_param_minmax(&rec->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, period_bytes, period_bytes)) < 0 || @@ -824,11 +989,12 @@ int err; const char *card = NULL; const char *pcm_string = NULL; + const char *avcodec = NULL; unsigned int rate = 48000; unsigned int bitrate = 448; unsigned int channels = 6; snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; - char devstr[128], tmpcard[8]; + char devstr[128], tmpcard[16]; struct a52_ctx *rec; if (stream != SND_PCM_STREAM_PLAYBACK) { @@ -921,6 +1087,16 @@ } continue; } + if (strcmp(id, "avcodec") == 0) { + const char *str; + err = snd_config_get_string(n, &str); + if (err < 0) { + SNDERR("invalid type for %s", id); + return -EINVAL; + } + avcodec = str; + continue; + } SNDERR("Unknown field %s", id); return -EINVAL; } @@ -931,6 +1107,7 @@ return -ENOMEM; } + rec->src_format = SND_PCM_FORMAT_UNKNOWN; rec->rate = rate; rec->bitrate = bitrate; rec->channels = channels; @@ -939,11 +1116,17 @@ #ifndef USE_AVCODEC_FRAME avcodec_init(); #endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 91, 0) avcodec_register_all(); +#endif - rec->codec = avcodec_find_encoder_by_name("ac3_fixed"); - if (rec->codec == NULL) - rec->codec = avcodec_find_encoder_by_name("ac3"); + if (avcodec) { + rec->codec = avcodec_find_encoder_by_name(avcodec); + } else { + rec->codec = avcodec_find_encoder_by_name("ac3_fixed"); + if (rec->codec == NULL) + rec->codec = avcodec_find_encoder_by_name("ac3"); + } if (rec->codec == NULL) rec->codec = avcodec_find_encoder(AV_CODEC_ID_AC3); if (rec->codec == NULL) { @@ -954,7 +1137,7 @@ if (! pcm_string || pcm_string[0] == '\0') { snprintf(devstr, sizeof(devstr), - "iec958:{AES0 0x%x AES1 0x%x AES2 0x%x AES3 0x%x %s%s}", + "iec958:{AES0 0x%x AES1 0x%x AES2 0x%x AES3 0x%x%s%s}", IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO | IEC958_AES0_CON_NOT_COPYRIGHT, IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, @@ -980,6 +1163,9 @@ rec->io.mmap_rw = 0; rec->io.callback = &a52_ops; rec->io.private_data = rec; +#ifdef SND_PCM_IOPLUG_FLAG_BOUNDARY_WA + rec->io.flags = SND_PCM_IOPLUG_FLAG_BOUNDARY_WA; +#endif #ifdef USE_AVCODEC_FRAME rec->av_format = rec->codec->sample_fmts[0]; rec->is_planar = av_sample_fmt_is_planar(rec->av_format); @@ -993,7 +1179,7 @@ if ((err = a52_set_hw_constraint(rec)) < 0) { snd_pcm_ioplug_delete(&rec->io); - goto error; + return err; } *pcmp = rec->io.pcm; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/configure new/alsa-plugins-1.2.6/configure --- old/alsa-plugins-1.2.5/configure 2021-05-27 22:06:36.000000000 +0200 +++ new/alsa-plugins-1.2.6/configure 2021-12-06 12:44:24.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for alsa-plugins 1.2.5. +# Generated by GNU Autoconf 2.69 for alsa-plugins 1.2.6. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='alsa-plugins' PACKAGE_TARNAME='alsa-plugins' -PACKAGE_VERSION='1.2.5' -PACKAGE_STRING='alsa-plugins 1.2.5' +PACKAGE_VERSION='1.2.6' +PACKAGE_STRING='alsa-plugins 1.2.6' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1421,7 +1421,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures alsa-plugins 1.2.5 to adapt to many kinds of systems. +\`configure' configures alsa-plugins 1.2.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1492,7 +1492,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of alsa-plugins 1.2.5:";; + short | recursive ) echo "Configuration of alsa-plugins 1.2.6:";; esac cat <<\_ACEOF @@ -1660,7 +1660,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -alsa-plugins configure 1.2.5 +alsa-plugins configure 1.2.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2025,7 +2025,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by alsa-plugins $as_me 1.2.5, which was +It was created by alsa-plugins $as_me 1.2.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2888,7 +2888,7 @@ # Define the identity of the package. PACKAGE='alsa-plugins' - VERSION='1.2.5' + VERSION='1.2.6' cat >>confdefs.h <<_ACEOF @@ -13031,12 +13031,12 @@ pkg_cv_LIBAV_CFLAGS="$LIBAV_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec libavutil libavresample\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libavcodec libavutil libavresample") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec libavutil libswresample\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libavcodec libavutil libswresample") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_LIBAV_CFLAGS=`$PKG_CONFIG --cflags "libavcodec libavutil libavresample" 2>/dev/null` + pkg_cv_LIBAV_CFLAGS=`$PKG_CONFIG --cflags "libavcodec libavutil libswresample" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -13048,12 +13048,12 @@ pkg_cv_LIBAV_LIBS="$LIBAV_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec libavutil libavresample\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libavcodec libavutil libavresample") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec libavutil libswresample\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libavcodec libavutil libswresample") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_LIBAV_LIBS=`$PKG_CONFIG --libs "libavcodec libavutil libavresample" 2>/dev/null` + pkg_cv_LIBAV_LIBS=`$PKG_CONFIG --libs "libavcodec libavutil libswresample" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -13074,9 +13074,9 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - LIBAV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec libavutil libavresample" 2>&1` + LIBAV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec libavutil libswresample" 2>&1` else - LIBAV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec libavutil libavresample" 2>&1` + LIBAV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec libavutil libswresample" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBAV_PKG_ERRORS" >&5 @@ -14217,7 +14217,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by alsa-plugins $as_me 1.2.5, which was +This file was extended by alsa-plugins $as_me 1.2.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14283,7 +14283,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -alsa-plugins config.status 1.2.5 +alsa-plugins config.status 1.2.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/configure.ac new/alsa-plugins-1.2.6/configure.ac --- old/alsa-plugins-1.2.5/configure.ac 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/configure.ac 2021-12-06 11:17:29.000000000 +0100 @@ -1,5 +1,5 @@ AC_PREREQ(2.59) -AC_INIT(alsa-plugins, 1.2.5) +AC_INIT(alsa-plugins, 1.2.6) AM_INIT_AUTOMAKE AC_PREFIX_DEFAULT(/usr) @@ -93,7 +93,7 @@ AS_HELP_STRING([--disable-libav], [Do not build plugins depending on libav/ffmpeg (a52,lavrate...)])) if test "x$enable_libav" != "xno"; then - PKG_CHECK_MODULES(LIBAV, [libavcodec libavutil libavresample], [HAVE_LIBAV=yes], [HAVE_LIBAV=no]) + PKG_CHECK_MODULES(LIBAV, [libavcodec libavutil libswresample], [HAVE_LIBAV=yes], [HAVE_LIBAV=no]) fi if test "x$HAVE_LIBAV" = "xno"; then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/doc/a52.txt new/alsa-plugins-1.2.6/doc/a52.txt --- old/alsa-plugins-1.2.5/doc/a52.txt 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/doc/a52.txt 2021-12-06 11:17:29.000000000 +0100 @@ -1,11 +1,17 @@ A52 OUTPUT PLUGIN ================= -This plugin converts S16 linear format to A52 compressed stream and -send to an SPDIF output. It requires libavcodec for encoding the -audio stream. +This plugin converts S16(P), S32P, or FLTP formats to an A52 compressed +stream and sends it to an S/PDIF output. It requires libavcodec for +encoding the audio stream. -A PCM using this plugin can be defined like below: +The input format is determined by the version of libavcodec it is +compiled against and which ac3 codec libavcodec is configured to use. + +A global configuration, /usr/share/alsa/alsa.conf.d/60-a52-encoder.conf +defines a52 PCMs for devices with the IEC958 non-audio status bit set. + +A PCM using this plugin can be manually defined like below: pcm.myout { type a52 @@ -61,5 +67,6 @@ } -The plugin reads always S16 format (i.e. native-endian) as input, so -you'd need plug layer appropriately to covert it. +The plugin only reads the format determined by libavcodec (native- +endian S16(P), S32P or FLTP) as input, so you'll need a plug layer to +appropriately convert it. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/doc/lavrate.txt new/alsa-plugins-1.2.6/doc/lavrate.txt --- old/alsa-plugins-1.2.5/doc/lavrate.txt 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/doc/lavrate.txt 2021-12-06 11:17:29.000000000 +0100 @@ -2,7 +2,7 @@ =========================================0 The plugin in rate-lavr subdirectory is an external rate converter using -libavresample library. You can use this rate converter plugin by defining a +libswresample library. You can use this rate converter plugin by defining a rate PCM with "converter" parameter, such as: pcm.my_rate { @@ -16,7 +16,7 @@ Or, more easily, define a global variable "defaults.pcm.rate_converter", which is used as the default converter type by plug and rate plugins: - defaults.pcm.rate_converter "lavcrate" + defaults.pcm.rate_converter "lavrate" Write the above in your ~/.asoundrc or /etc/asound.conf. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/jack/Makefile.am new/alsa-plugins-1.2.6/jack/Makefile.am --- old/alsa-plugins-1.2.5/jack/Makefile.am 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/jack/Makefile.am 2021-12-06 11:17:29.000000000 +0100 @@ -12,7 +12,7 @@ AM_LDFLAGS = -module -avoid-version -export-dynamic -no-undefined $(LDFLAGS_NOUNDEFINED) libasound_module_pcm_jack_la_SOURCES = pcm_jack.c -libasound_module_pcm_jack_la_LIBADD = @ALSA_LIBS@ @JACK_LIBS@ +libasound_module_pcm_jack_la_LIBADD = @ALSA_LIBS@ @JACK_LIBS@ -lpthread include ../install-hooks.am diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/jack/Makefile.in new/alsa-plugins-1.2.6/jack/Makefile.in --- old/alsa-plugins-1.2.5/jack/Makefile.in 2021-05-27 22:06:35.000000000 +0200 +++ new/alsa-plugins-1.2.6/jack/Makefile.in 2021-12-06 12:44:23.000000000 +0100 @@ -358,7 +358,7 @@ AM_CFLAGS = -Wall -g @ALSA_CFLAGS@ @JACK_CFLAGS@ AM_LDFLAGS = -module -avoid-version -export-dynamic -no-undefined $(LDFLAGS_NOUNDEFINED) libasound_module_pcm_jack_la_SOURCES = pcm_jack.c -libasound_module_pcm_jack_la_LIBADD = @ALSA_LIBS@ @JACK_LIBS@ +libasound_module_pcm_jack_la_LIBADD = @ALSA_LIBS@ @JACK_LIBS@ -lpthread all: all-am .SUFFIXES: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/jack/pcm_jack.c new/alsa-plugins-1.2.6/jack/pcm_jack.c --- old/alsa-plugins-1.2.5/jack/pcm_jack.c 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/jack/pcm_jack.c 2021-12-06 11:17:29.000000000 +0100 @@ -28,6 +28,7 @@ #include <jack/jack.h> #include <alsa/asoundlib.h> #include <alsa/pcm_external.h> +#include <pthread.h> #define MAX_PERIODS_MULTIPLE 64 @@ -44,6 +45,8 @@ int fd; int activated; /* jack is activated? */ + pthread_mutex_t running_mutex; + int running; /* jack is running? */ snd_pcm_jack_port_list_t **port_names; unsigned int num_ports; @@ -159,6 +162,7 @@ free(jack->port_names); jack->port_names = NULL; } + pthread_mutex_destroy (&jack->running_mutex); if (jack->fd >= 0) close(jack->fd); if (jack->io.poll_fd >= 0) @@ -207,6 +211,18 @@ snd_pcm_jack_t *jack = io->private_data; snd_pcm_uframes_t xfer = 0; unsigned int channel; + + if (pthread_mutex_trylock (&jack->running_mutex) == EBUSY) { + /* Note that locking should only ever fail if + * snd_pcm_jack_start or snd_pcm_jack_stop is called at the + * same time, in which case dropping the current buffer is not + * an issue. */ + return 0; + } + if (!jack->running) { + pthread_mutex_unlock (&jack->running_mutex); + return 0; + } for (channel = 0; channel < io->channels; channel++) { jack->areas[channel].addr = @@ -268,6 +284,8 @@ pcm_poll_unblock_check(io); /* unblock socket for polling if needed */ + pthread_mutex_unlock (&jack->running_mutex); + return 0; } @@ -365,7 +383,10 @@ static int snd_pcm_jack_start(snd_pcm_ioplug_t *io) { - (void)io; + snd_pcm_jack_t *jack = io->private_data; + pthread_mutex_lock (&jack->running_mutex); + jack->running = 1; + pthread_mutex_unlock (&jack->running_mutex); /* * Since the processing of jack_activate() and jack_connect() take a * while longer, snd_pcm_jack_start() was blocked. @@ -382,7 +403,10 @@ static int snd_pcm_jack_stop(snd_pcm_ioplug_t *io) { - (void)io; + snd_pcm_jack_t *jack = io->private_data; + pthread_mutex_lock (&jack->running_mutex); + jack->running = 0; + pthread_mutex_unlock (&jack->running_mutex); return 0; } @@ -548,6 +572,8 @@ if (!jack) return -ENOMEM; + pthread_mutex_init (&jack->running_mutex, NULL); + jack->fd = -1; jack->io.poll_fd = -1; jack->use_period_alignment = use_period_alignment; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/rate/rate_samplerate.c new/alsa-plugins-1.2.6/rate/rate_samplerate.c --- old/alsa-plugins-1.2.5/rate/rate_samplerate.c 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/rate/rate_samplerate.c 2021-12-06 11:17:29.000000000 +0100 @@ -40,9 +40,12 @@ #include <alsa/pcm_rate.h> struct rate_src { + unsigned int version; double ratio; int converter; unsigned int channels; + int in_int; + int out_int; float *src_buf; float *dst_buf; SRC_STATE *state; @@ -109,6 +112,13 @@ rate->data.src_ratio = rate->ratio; rate->data.end_of_input = 0; +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + if (rate->version >= 0x010003) { + rate->in_int = info->in.format == SND_PCM_FORMAT_S32; + rate->out_int = info->out.format == SND_PCM_FORMAT_S32; + } +#endif + return 0; } @@ -128,24 +138,56 @@ src_reset(rate->state); } -static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int dst_frames, - const int16_t *src, unsigned int src_frames) +static void do_convert(struct rate_src *rate, + void *dst, unsigned int dst_frames, + const void *src, unsigned int src_frames) { - struct rate_src *rate = obj; unsigned int ofs; rate->data.input_frames = src_frames; rate->data.output_frames = dst_frames; rate->data.end_of_input = 0; - src_short_to_float_array(src, rate->src_buf, src_frames * rate->channels); + if (rate->in_int) + src_int_to_float_array(src, rate->src_buf, src_frames * rate->channels); + else + src_short_to_float_array(src, rate->src_buf, src_frames * rate->channels); src_process(rate->state, &rate->data); if (rate->data.output_frames_gen < dst_frames) ofs = dst_frames - rate->data.output_frames_gen; else ofs = 0; - src_float_to_short_array(rate->dst_buf, dst + ofs * rate->channels, - rate->data.output_frames_gen * rate->channels); + if (rate->out_int) + src_float_to_int_array(rate->dst_buf, dst + ofs * rate->channels * 4, + rate->data.output_frames_gen * rate->channels); + else + src_float_to_short_array(rate->dst_buf, dst + ofs * rate->channels * 2, + rate->data.output_frames_gen * rate->channels); +} + +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 +static void pcm_src_convert(void *obj, + const snd_pcm_channel_area_t *dst_areas, + snd_pcm_uframes_t dst_offset, + unsigned int dst_frames, + const snd_pcm_channel_area_t *src_areas, + snd_pcm_uframes_t src_offset, + unsigned int src_frames) +{ + struct rate_src *rate = obj; + const void *src = snd_pcm_channel_area_addr(src_areas, src_offset); + void *dst = snd_pcm_channel_area_addr(dst_areas, dst_offset); + + do_convert(rate, dst, dst_frames, src, src_frames); +} +#endif + +static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int dst_frames, + const int16_t *src, unsigned int src_frames) +{ + struct rate_src *rate = obj; + + do_convert(rate, dst, dst_frames, src, src_frames); } static void pcm_src_close(void *obj) @@ -167,12 +209,28 @@ } #endif +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 +static int get_supported_formats(void *obj, uint64_t *in_formats, + uint64_t *out_formats, + unsigned int *flags) +{ + *in_formats = *out_formats = + (1ULL << SND_PCM_FORMAT_S16) | + (1ULL << SND_PCM_FORMAT_S32); + *flags = SND_PCM_RATE_FLAG_INTERLEAVED; + return 0; +} +#endif + static snd_pcm_rate_ops_t pcm_src_ops = { .close = pcm_src_close, .init = pcm_src_init, .free = pcm_src_free, .reset = pcm_src_reset, .adjust_pitch = pcm_src_adjust_pitch, +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + .convert = pcm_src_convert, +#endif .convert_s16 = pcm_src_convert_s16, .input_frames = input_frames, .output_frames = output_frames, @@ -181,6 +239,9 @@ .get_supported_rates = get_supported_rates, .dump = dump, #endif +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + .get_supported_formats = get_supported_formats, +#endif }; static int pcm_src_open(unsigned int version, void **objp, @@ -188,24 +249,27 @@ { struct rate_src *rate; -#if SND_PCM_RATE_PLUGIN_VERSION < 0x010002 - if (version != SND_PCM_RATE_PLUGIN_VERSION) { - fprintf(stderr, "Invalid rate plugin version %x\n", version); - return -EINVAL; - } -#endif rate = calloc(1, sizeof(*rate)); if (! rate) return -ENOMEM; + + rate->version = version; rate->converter = type; *objp = rate; #if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002 - if (version == 0x010001) + if (version == 0x010001) { memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_old_ops_t)); - else + return 0; + } +#endif +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + if (version == 0x010002) { + memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_v2_ops_t)); + return 0; + } #endif - *ops = pcm_src_ops; + *ops = pcm_src_ops; return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/rate-lav/rate_lavrate.c new/alsa-plugins-1.2.6/rate-lav/rate_lavrate.c --- old/alsa-plugins-1.2.5/rate-lav/rate_lavrate.c 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/rate-lav/rate_lavrate.c 2021-12-06 11:17:29.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Rate converter plugin using libavresample + * Rate converter plugin using libswresample * Copyright (c) 2014 by Anton Khirnov * * This library is free software; you can redistribute it and/or @@ -17,7 +17,7 @@ #include <alsa/asoundlib.h> #include <alsa/pcm_rate.h> -#include <libavresample/avresample.h> +#include <libswresample/swresample.h> #include <libavutil/channel_layout.h> #include <libavutil/opt.h> #include <libavutil/mathematics.h> @@ -25,15 +25,15 @@ static unsigned int filter_size = 16; -static unsigned int phase_shift = 10; /* auto-adjusts */ -static double cutoff = 0; /* auto-adjusts */ struct rate_src { - AVAudioResampleContext *avr; + SwrContext *avr; unsigned int in_rate; unsigned int out_rate; unsigned int channels; + + unsigned int version; }; static snd_pcm_uframes_t input_frames(void *obj ATTRIBUTE_UNUSED, @@ -51,51 +51,67 @@ static void pcm_src_free(void *obj) { struct rate_src *rate = obj; - avresample_free(&rate->avr); + swr_free(&rate->avr); +} + +static int to_av_format(snd_pcm_format_t f) +{ + switch (f) { + case SND_PCM_FORMAT_FLOAT: + return AV_SAMPLE_FMT_FLT; + case SND_PCM_FORMAT_U8: + return AV_SAMPLE_FMT_U8; + case SND_PCM_FORMAT_S16: + return AV_SAMPLE_FMT_S16; + case SND_PCM_FORMAT_S32: + default: + return AV_SAMPLE_FMT_S32; + } +} + +static int support_multi_format(struct rate_src *rate) +{ +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + return rate->version >= 0x010003; +#else + return 0; +#endif } static int pcm_src_init(void *obj, snd_pcm_rate_info_t *info) { struct rate_src *rate = obj; - int i, ir, or; + int fmt; if (!rate->avr || rate->channels != info->channels) { int ret; pcm_src_free(rate); rate->channels = info->channels; - ir = rate->in_rate = info->in.rate; - or = rate->out_rate = info->out.rate; - i = av_gcd(or, ir); - if (or > ir) { - phase_shift = or/i; - } else { - phase_shift = ir/i; - } - if (cutoff <= 0.0) { - cutoff = 1.0 - 1.0/filter_size; - if (cutoff < 0.80) - cutoff = 0.80; - } + rate->in_rate = info->in.rate; + rate->out_rate = info->out.rate; - rate->avr = avresample_alloc_context(); + rate->avr = swr_alloc(); if (!rate->avr) return -ENOMEM; - av_opt_set_int(rate->avr, "in_sample_rate", info->in.rate, 0); - av_opt_set_int(rate->avr, "out_sample_rate", info->out.rate, 0); - av_opt_set_int(rate->avr, "in_sample_format", AV_SAMPLE_FMT_S16, 0); - av_opt_set_int(rate->avr, "out_sample_format", AV_SAMPLE_FMT_S16, 0); - av_opt_set_int(rate->avr, "in_channel_layout", av_get_default_channel_layout(rate->channels), 0); - av_opt_set_int(rate->avr, "out_channel_layout", av_get_default_channel_layout(rate->channels), 0); - - av_opt_set_int(rate->avr, "filter_size", filter_size, 0); - av_opt_set_int(rate->avr, "phase_shift", phase_shift, 0); - av_opt_set_double(rate->avr, "cutoff", cutoff, 0); + av_opt_set_channel_layout(rate->avr, "in_channel_layout", + av_get_default_channel_layout(rate->channels), 0); + av_opt_set_channel_layout(rate->avr, "out_channel_layout", + av_get_default_channel_layout(rate->channels), 0); + av_opt_set_int(rate->avr, "in_sample_rate", rate->in_rate, 0); + av_opt_set_int(rate->avr, "out_sample_rate", rate->out_rate, 0); + fmt = support_multi_format(rate) ? info->in.format : SND_PCM_FORMAT_S16; + av_opt_set_sample_fmt(rate->avr, "in_sample_fmt", + to_av_format(fmt), 0); + fmt = support_multi_format(rate) ? info->out.format : SND_PCM_FORMAT_S16; + av_opt_set_sample_fmt(rate->avr, "out_sample_fmt", + to_av_format(fmt), 0); - ret = avresample_open(rate->avr); + ret = swr_init(rate->avr); if (ret < 0) { - avresample_free(&rate->avr); + SNDERR("sw_init() error %d\n", ret); + swr_free(&rate->avr); return -EINVAL; } } @@ -118,26 +134,51 @@ if (rate->avr) { #if 0 - avresample_close(rate->avr); - avresample_open(rate->avr); + swr_free(rate->avr); + swr_init(rate->avr); #endif } } +static void do_convert(struct rate_src *rate, + void *dst, unsigned int dst_frames, + const void *src, unsigned int src_frames) +{ + unsigned int total_in = swr_get_delay(rate->avr, rate->in_rate) + src_frames; + + swr_convert(rate->avr, (uint8_t **)&dst, dst_frames, + (const uint8_t **)&src, src_frames); + + swr_set_compensation(rate->avr, + total_in - src_frames > filter_size ? 0 : 1, + src_frames); +} + +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 +static void pcm_src_convert(void *obj, + const snd_pcm_channel_area_t *dst_areas, + snd_pcm_uframes_t dst_offset, + unsigned int dst_frames, + const snd_pcm_channel_area_t *src_areas, + snd_pcm_uframes_t src_offset, + unsigned int src_frames) +{ + struct rate_src *rate = obj; + const void *src = snd_pcm_channel_area_addr(src_areas, src_offset); + void *dst = snd_pcm_channel_area_addr(dst_areas, dst_offset); + + do_convert(rate, dst, dst_frames, src, src_frames); +} +#endif + static void pcm_src_convert_s16(void *obj, int16_t *dst, unsigned int dst_frames, const int16_t *src, unsigned int src_frames) { struct rate_src *rate = obj; - int chans = rate->channels; - unsigned int total_in = avresample_get_delay(rate->avr) + src_frames; - avresample_convert(rate->avr, (uint8_t **)&dst, dst_frames * chans * 2, dst_frames, - (uint8_t **)&src, src_frames * chans * 2, src_frames); - - avresample_set_compensation(rate->avr, - total_in - src_frames > filter_size ? 0 : 1, src_frames); + do_convert(rate, dst, dst_frames, src, src_frames); } static void pcm_src_close(void *obj) @@ -156,7 +197,21 @@ static void dump(void *obj ATTRIBUTE_UNUSED, snd_output_t *out) { - snd_output_printf(out, "Converter: libavr\n"); + snd_output_printf(out, "Converter: libswresample\n"); +} +#endif + +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 +static int get_supported_formats(void *obj, uint64_t *in_formats, + uint64_t *out_formats, + unsigned int *flags) +{ + *in_formats = *out_formats = + (1ULL << SND_PCM_FORMAT_U8) | + (1ULL << SND_PCM_FORMAT_S16) | + (1ULL << SND_PCM_FORMAT_S32); + *flags = SND_PCM_RATE_FLAG_INTERLEAVED; + return 0; } #endif @@ -166,6 +221,9 @@ .free = pcm_src_free, .reset = pcm_src_reset, .adjust_pitch = pcm_src_adjust_pitch, +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + .convert = pcm_src_convert, +#endif .convert_s16 = pcm_src_convert_s16, .input_frames = input_frames, .output_frames = output_frames, @@ -174,31 +232,35 @@ .get_supported_rates = get_supported_rates, .dump = dump, #endif +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + .get_supported_formats = get_supported_formats, +#endif }; int pcm_src_open(unsigned int version, void **objp, snd_pcm_rate_ops_t *ops) - { struct rate_src *rate; -#if SND_PCM_RATE_PLUGIN_VERSION < 0x010002 - if (version != SND_PCM_RATE_PLUGIN_VERSION) { - fprintf(stderr, "Invalid rate plugin version %x\n", version); - return -EINVAL; - } -#endif rate = calloc(1, sizeof(*rate)); if (!rate) return -ENOMEM; *objp = rate; rate->avr = NULL; + rate->version = version; #if SND_PCM_RATE_PLUGIN_VERSION >= 0x010002 - if (version == 0x010001) + if (version == 0x010001) { memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_old_ops_t)); - else + return 0; + } +#endif +#if SND_PCM_RATE_PLUGIN_VERSION >= 0x010003 + if (version == 0x010002) { + memcpy(ops, &pcm_src_ops, sizeof(snd_pcm_rate_v2_ops_t)); + return 0; + } #endif - *ops = pcm_src_ops; + *ops = pcm_src_ops; return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/usb_stream/pcm_usb_stream.c new/alsa-plugins-1.2.6/usb_stream/pcm_usb_stream.c --- old/alsa-plugins-1.2.5/usb_stream/pcm_usb_stream.c 2021-05-27 19:18:39.000000000 +0200 +++ new/alsa-plugins-1.2.6/usb_stream/pcm_usb_stream.c 2021-12-06 11:17:29.000000000 +0100 @@ -474,7 +474,7 @@ if (snd_config_get_id(n, &id) < 0) continue; - if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0) + if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || strcmp(id, "hint") == 0) continue; if (strcmp(id, "card") == 0) { card = snd_config_get_card(n); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/alsa-plugins-1.2.5/version new/alsa-plugins-1.2.6/version --- old/alsa-plugins-1.2.5/version 2021-05-27 22:06:40.000000000 +0200 +++ new/alsa-plugins-1.2.6/version 2021-12-06 12:44:28.000000000 +0100 @@ -1 +1 @@ -1.2.5 +1.2.6
