From 2cbdd7c92958cb8226491d8eb23ed2d57d4b841e Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Sat, 20 Oct 2012 01:13:39 +0200 Subject: [PATCH 1/9] fate: ac3: Add dependencies --- tests/fate/ac3.mak | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index 235414d183..59d0780144 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -44,14 +44,17 @@ fate-eac3-4: REF = $(SAMPLES)/eac3/serenity_english_5.1_1536_small.pcm $(FATE_AC3) $(FATE_EAC3): CMP = oneoff -FATE_AC3_ENCODE += fate-ac3-encode +FATE_AC3-$(call DEMDEC, AC3, AC3) += $(FATE_AC3) +FATE_EAC3-$(call DEMDEC, EAC3, EAC3) += $(FATE_EAC3) + +FATE_AC3-$(call ENCDEC, AC3, AC3) += fate-ac3-encode fate-ac3-encode: CMD = enc_dec_pcm ac3 wav s16le $(REF) -c:a ac3 -b:a 128k fate-ac3-encode: CMP_SHIFT = -1024 fate-ac3-encode: CMP_TARGET = 399.62 fate-ac3-encode: SIZE_TOLERANCE = 488 fate-ac3-encode: FUZZ = 3 -FATE_EAC3_ENCODE += fate-eac3-encode +FATE_EAC3-$(call ENCDEC, EAC3, EAC3) += fate-eac3-encode fate-eac3-encode: CMD = enc_dec_pcm eac3 wav s16le $(REF) -c:a eac3 -b:a 128k fate-eac3-encode: CMP_SHIFT = -1024 fate-eac3-encode: CMP_TARGET = 514.02 @@ -61,15 +64,13 @@ fate-eac3-encode: FUZZ = 3 fate-ac3-encode fate-eac3-encode: CMP = stddev fate-ac3-encode fate-eac3-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -FATE_AC3_FIXED_ENCODE += fate-ac3-fixed-encode +FATE_AC3-$(call ENCMUX, AC3_FIXED, AC3) += fate-ac3-fixed-encode fate-ac3-fixed-encode: tests/data/asynth-44100-2.wav fate-ac3-fixed-encode: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav fate-ac3-fixed-encode: CMD = md5 -i $(SRC) -c ac3_fixed -b 128k -f ac3 -flags bitexact fate-ac3-fixed-encode: CMP = oneline fate-ac3-fixed-encode: REF = a1d1fc116463b771abf5aef7ed37d7b1 -FATE_SAMPLES_AVCONV += $(FATE_AC3) $(FATE_AC3_ENCODE) $(FATE_AC3_FIXED_ENCODE) -FATE_SAMPLES_AVCONV += $(FATE_EAC3) $(FATE_EAC3_ENCODE) +FATE_SAMPLES_AVCONV- += $(FATE_AC3-yes) $(FATE_EAC3-yes) -fate-ac3: $(FATE_AC3) $(FATE_AC3_ENCODE) $(FATE_AC3_FIXED_ENCODE) -fate-ac3: $(FATE_EAC3) $(FATE_EAC3_ENCODE) +fate-ac3: $(FATE_AC3-yes) $(FATE_EAC3-yes) From bff5e5f8b3c5892a21a0df7b3352b31511e42a94 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 29 Oct 2012 12:16:05 +0100 Subject: [PATCH 2/9] indeo3: remove duplicate capabilities line. --- libavcodec/indeo3.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index 322d36047f..fc0d2bc11b 100644 --- a/libavcodec/indeo3.c +++ b/libavcodec/indeo3.c @@ -1114,5 +1114,4 @@ AVCodec ff_indeo3_decoder = { .decode = decode_frame, .capabilities = CODEC_CAP_DR1, .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), - .capabilities = CODEC_CAP_DR1, }; From 01b760190d32550683d7c790309acadea3fe0820 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 Oct 2012 22:52:54 +0100 Subject: [PATCH 3/9] lavr: add general API usage doxy Signed-off-by: Anton Khirnov --- libavresample/avresample.h | 71 ++++++++++++++++++++++++++++++++++++++ libavutil/avutil.h | 1 + 2 files changed, 72 insertions(+) diff --git a/libavresample/avresample.h b/libavresample/avresample.h index ea93952e2e..87134b3916 100644 --- a/libavresample/avresample.h +++ b/libavresample/avresample.h @@ -23,9 +23,76 @@ /** * @file + * @ingroup lavr * external API header */ +/** + * @defgroup lavr Libavresample + * @{ + * + * Libavresample (lavr) is a library that handles audio resampling, sample + * format conversion and mixing. + * + * Interaction with lavr is done through AVAudioResampleContext, which is + * allocated with avresample_alloc_context(). It is opaque, so all parameters + * must be set with the @ref avoptions API. + * + * For example the following code will setup conversion from planar float sample + * format to interleaved signed 16-bit integer, downsampling from 48kHz to + * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing + * matrix): + * @code + * AVAudioResampleContext *avr = avresample_alloc_context(); + * av_opt_set_int(avr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0); + * av_opt_set_int(avr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + * av_opt_set_int(avr, "in_sample_rate", 48000, 0); + * av_opt_set_int(avr, "out_sample_rate", 44100, 0); + * av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); + * av_opt_set_int(avr, "out_sample_fmt, AV_SAMPLE_FMT_S16, 0); + * @endcode + * + * Once the context is initialized, it must be opened with avresample_open(). If + * you need to change the conversion parameters, you must close the context with + * avresample_close(), change the parameters as described above, then reopen it + * again. + * + * The conversion itself is done by repeatedly calling avresample_convert(). + * Note that the samples may get buffered in two places in lavr. The first one + * is the output FIFO, where the samples end up if the output buffer is not + * large enough. The data stored in there may be retrieved at any time with + * avresample_read(). The second place is the resampling delay buffer, + * applicable only when resampling is done. The samples in it require more input + * before they can be processed. Their current amount is returned by + * avresample_get_delay(). At the end of conversion the resampling buffer can be + * flushed by calling avresample_convert() with NULL input. + * + * The following code demonstrates the conversion loop assuming the parameters + * from above and caller-defined functions get_input() and handle_output(): + * @code + * uint8_t **input; + * int in_linesize, in_samples; + * + * while (get_input(&input, &in_linesize, &in_samples)) { + * uint8_t *output + * int out_linesize; + * int out_samples = avresample_available(avr) + + * av_rescale_rnd(avresample_get_delay(avr) + + * in_samples, 44100, 48000, AV_ROUND_UP); + * av_samples_alloc(&output, &out_linesize, 2, out_samples, + * AV_SAMPLE_FMT_S16, 0); + * out_samples = avresample_convert(avr, &output, out_linesize, out_samples, + * input, in_linesize, in_samples); + * handle_output(output, out_linesize, out_samples); + * av_freep(&output); + * } + * @endcode + * + * When the conversion is finished and the FIFOs are flushed if required, the + * conversion context and everything associated with it must be freed with + * avresample_free(). + */ + #include "libavutil/audioconvert.h" #include "libavutil/avutil.h" #include "libavutil/dict.h" @@ -289,4 +356,8 @@ int avresample_available(AVAudioResampleContext *avr); */ int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples); +/** + * @} + */ + #endif /* AVRESAMPLE_AVRESAMPLE_H */ diff --git a/libavutil/avutil.h b/libavutil/avutil.h index a1433b4e65..33f9bea723 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -39,6 +39,7 @@ * @li @ref libavf "libavformat" I/O and muxing/demuxing library * @li @ref lavd "libavdevice" special devices muxing/demuxing library * @li @ref lavu "libavutil" common utility library + * @li @ref lavr "libavresample" audio resampling, format conversion and mixing * @li @subpage libswscale color conversion and scaling library */ From dc5793062e7a0f6d195fc403d7ce242729b4ea4a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 28 Oct 2012 22:52:55 +0100 Subject: [PATCH 4/9] lavr: document upper bound on number of output samples. Signed-off-by: Anton Khirnov --- libavresample/avresample.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavresample/avresample.h b/libavresample/avresample.h index 87134b3916..b0a9e247e8 100644 --- a/libavresample/avresample.h +++ b/libavresample/avresample.h @@ -265,6 +265,10 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, /** * Convert input samples and write them to the output FIFO. * + * The upper bound on the number of output samples is given by + * avresample_available() + (avresample_get_delay() + number of input samples) * + * output sample rate / input sample rate. + * * The output data can be NULL or have fewer allocated samples than required. * In this case, any remaining samples not written to the output will be added * to an internal FIFO buffer, to be returned at the next call to this function From 39ef66f5300c2a42acc29937f5417bc2efe09752 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sat, 27 Oct 2012 22:29:56 +0300 Subject: [PATCH 5/9] lpc: Add a function for calculating reflection coefficients from autocorrelation coefficients MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/lpc.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h index cbee46f5db..0e54f0dfab 100644 --- a/libavcodec/lpc.h +++ b/libavcodec/lpc.h @@ -110,6 +110,37 @@ void ff_lpc_end(LPCContext *s); #define LPC_TYPE float #endif +/** + * Schur recursion. + * Produces reflection coefficients from autocorrelation data. + */ +static inline void compute_ref_coefs(const LPC_TYPE *autoc, int max_order, + LPC_TYPE *ref, LPC_TYPE *error) +{ + int i, j; + LPC_TYPE err; + LPC_TYPE gen0[MAX_LPC_ORDER], gen1[MAX_LPC_ORDER]; + + for (i = 0; i < max_order; i++) + gen0[i] = gen1[i] = autoc[i + 1]; + + err = autoc[0]; + ref[0] = -gen1[0] / err; + err += gen1[0] * ref[0]; + if (error) + error[0] = err; + for (i = 1; i < max_order; i++) { + for (j = 0; j < max_order - i; j++) { + gen1[j] = gen1[j + 1] + ref[i - 1] * gen0[j]; + gen0[j] = gen1[j + 1] * ref[i - 1] + gen0[j]; + } + ref[i] = -gen1[0] / err; + err += gen1[0] * ref[i]; + if (error) + error[i] = err; + } +} + /** * Levinson-Durbin recursion. * Produce LPC coefficients from autocorrelation data. From 8b25a20efbf4ca261bcd3327a385330eca775ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 25 Oct 2012 15:33:15 +0300 Subject: [PATCH 6/9] lpc: Add a function for calculating reflection coefficients from samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/lpc.c | 12 ++++++++++++ libavcodec/lpc.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c index 126dbc1266..2093e7e802 100644 --- a/libavcodec/lpc.c +++ b/libavcodec/lpc.c @@ -148,6 +148,18 @@ static int estimate_best_order(double *ref, int min_order, int max_order) return est; } +int ff_lpc_calc_ref_coefs(LPCContext *s, + const int32_t *samples, int order, double *ref) +{ + double autoc[MAX_LPC_ORDER + 1]; + + s->lpc_apply_welch_window(samples, s->blocksize, s->windowed_samples); + s->lpc_compute_autocorr(s->windowed_samples, s->blocksize, order, autoc); + compute_ref_coefs(autoc, order, ref, NULL); + + return order; +} + /** * Calculate LPC coefficients for multiple orders * diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h index 0e54f0dfab..6590608693 100644 --- a/libavcodec/lpc.h +++ b/libavcodec/lpc.h @@ -92,6 +92,9 @@ int ff_lpc_calc_coefs(LPCContext *s, enum FFLPCType lpc_type, int lpc_passes, int omethod, int max_shift, int zero_shift); +int ff_lpc_calc_ref_coefs(LPCContext *s, + const int32_t *samples, int order, double *ref); + /** * Initialize LPCContext. */ From 9b500b8f6c9806f3979f9d1fb874b7f4a802c656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 23 Oct 2012 00:02:41 +0300 Subject: [PATCH 7/9] avcodec: Add a RFC 3389 comfort noise codec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This isn't too useful as a normal codec, but can be used in voip style applications. The decoder updates the noise generator parameters when a packet is given to it for decoding, but if called with an empty packet, it generates more noise according to the last parameters. Signed-off-by: Martin Storsjö --- configure | 1 + libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/cngdec.c | 162 ++++++++++++++++++++++++++++++++++++++++ libavcodec/cngenc.c | 116 ++++++++++++++++++++++++++++ libavcodec/codec_desc.c | 7 ++ libavcodec/version.h | 2 +- 8 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 libavcodec/cngdec.c create mode 100644 libavcodec/cngenc.c diff --git a/configure b/configure index 1a006befe9..2abc465296 100755 --- a/configure +++ b/configure @@ -1440,6 +1440,7 @@ atrac3_decoder_select="mdct" binkaudio_dct_decoder_select="mdct rdft dct sinewin" binkaudio_rdft_decoder_select="mdct rdft sinewin" cavs_decoder_select="golomb mpegvideo" +comfortnoise_encoder_select="lpc" cook_decoder_select="mdct sinewin" cscd_decoder_select="lzo" cscd_decoder_suggest="zlib" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index d8c853ab8d..4d14aea8a4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -129,6 +129,8 @@ OBJS-$(CONFIG_CLJR_DECODER) += cljr.o OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o OBJS-$(CONFIG_CLLC_DECODER) += cllc.o OBJS-$(CONFIG_COOK_DECODER) += cook.o +OBJS-$(CONFIG_COMFORTNOISE_DECODER) += cngdec.o celp_filters.o +OBJS-$(CONFIG_COMFORTNOISE_ENCODER) += cngenc.o OBJS-$(CONFIG_CSCD_DECODER) += cscd.o OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadsp.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b175fbbdc2..e5fb351ec7 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -91,6 +91,7 @@ void avcodec_register_all(void) REGISTER_DECODER (CINEPAK, cinepak); REGISTER_ENCDEC (CLJR, cljr); REGISTER_DECODER (CLLC, cllc); + REGISTER_ENCDEC (COMFORTNOISE, comfortnoise); REGISTER_DECODER (CSCD, cscd); REGISTER_DECODER (CYUV, cyuv); REGISTER_DECODER (DFA, dfa); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c505a922e3..d6a4e4d429 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -406,6 +406,7 @@ enum AVCodecID { AV_CODEC_ID_IAC, AV_CODEC_ID_ILBC, AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c new file mode 100644 index 0000000000..c22fd5577c --- /dev/null +++ b/libavcodec/cngdec.c @@ -0,0 +1,162 @@ +/* + * RFC 3389 comfort noise generator + * Copyright (c) 2012 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "avcodec.h" +#include "celp_filters.h" +#include "libavutil/lfg.h" + +typedef struct CNGContext { + AVFrame avframe; + float *refl_coef, *target_refl_coef; + float *lpc_coef; + int order; + int energy, target_energy; + float *filter_out; + float *excitation; + AVLFG lfg; +} CNGContext; + +static av_cold int cng_decode_close(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + av_free(p->refl_coef); + av_free(p->target_refl_coef); + av_free(p->lpc_coef); + av_free(p->filter_out); + av_free(p->excitation); + return 0; +} + +static av_cold int cng_decode_init(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + avctx->sample_rate = 8000; + + avcodec_get_frame_defaults(&p->avframe); + avctx->coded_frame = &p->avframe; + p->order = 12; + avctx->frame_size = 640; + p->refl_coef = av_mallocz(p->order * sizeof(*p->refl_coef)); + p->target_refl_coef = av_mallocz(p->order * sizeof(*p->target_refl_coef)); + p->lpc_coef = av_mallocz(p->order * sizeof(*p->lpc_coef)); + p->filter_out = av_mallocz((avctx->frame_size + p->order) * + sizeof(*p->filter_out)); + p->excitation = av_mallocz(avctx->frame_size * sizeof(*p->excitation)); + if (!p->refl_coef || !p->target_refl_coef || !p->lpc_coef || + !p->filter_out || !p->excitation) { + cng_decode_close(avctx); + return AVERROR(ENOMEM); + } + + av_lfg_init(&p->lfg, 0); + + return 0; +} + +static void make_lpc_coefs(float *lpc, const float *refl, int order) +{ + float buf[100]; + float *next, *cur; + int m, i; + next = buf; + cur = lpc; + for (m = 0; m < order; m++) { + next[m] = refl[m]; + for (i = 0; i < m; i++) + next[i] = cur[i] + refl[m] * cur[m - i - 1]; + FFSWAP(float*, next, cur); + } + if (cur != lpc) + memcpy(lpc, cur, sizeof(*lpc) * order); +} + +static int cng_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + + CNGContext *p = avctx->priv_data; + int buf_size = avpkt->size; + int ret, i; + int16_t *buf_out; + float e = 1.0; + float scaling; + + if (avpkt->size) { + float dbov = -avpkt->data[0] / 10.0; + p->target_energy = 1081109975 * pow(10, dbov) * 0.75; + memset(p->target_refl_coef, 0, sizeof(p->refl_coef)); + for (i = 0; i < FFMIN(avpkt->size - 1, p->order); i++) { + p->target_refl_coef[i] = (avpkt->data[1 + i] - 127) / 128.0; + } + make_lpc_coefs(p->lpc_coef, p->refl_coef, p->order); + } + + p->energy = p->energy / 2 + p->target_energy / 2; + for (i = 0; i < p->order; i++) + p->refl_coef[i] = 0.6 *p->refl_coef[i] + 0.4 * p->target_refl_coef[i]; + + for (i = 0; i < p->order; i++) + e *= 1.0 - p->refl_coef[i]*p->refl_coef[i]; + + scaling = sqrt(e * p->energy / 1081109975); + for (i = 0; i < avctx->frame_size; i++) { + int r = (av_lfg_get(&p->lfg) & 0xffff) - 0x8000; + p->excitation[i] = scaling * r; + } + ff_celp_lp_synthesis_filterf(p->filter_out + p->order, p->lpc_coef, + p->excitation, avctx->frame_size, p->order); + + p->avframe.nb_samples = avctx->frame_size; + if ((ret = avctx->get_buffer(avctx, &p->avframe)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + buf_out = (int16_t *)p->avframe.data[0]; + for (i = 0; i < avctx->frame_size; i++) + buf_out[i] = p->filter_out[i + p->order]; + memcpy(p->filter_out, p->filter_out + avctx->frame_size, + p->order * sizeof(*p->filter_out)); + + *got_frame_ptr = 1; + *(AVFrame *)data = p->avframe; + + return buf_size; +} + +AVCodec ff_comfortnoise_decoder = { + .name = "comfortnoise", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_COMFORT_NOISE, + .priv_data_size = sizeof(CNGContext), + .init = cng_decode_init, + .decode = cng_decode_frame, + .close = cng_decode_close, + .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, +}; diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c new file mode 100644 index 0000000000..1e3f8f0c8d --- /dev/null +++ b/libavcodec/cngenc.c @@ -0,0 +1,116 @@ +/* + * RFC 3389 comfort noise generator + * Copyright (c) 2012 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "avcodec.h" +#include "internal.h" +#include "lpc.h" + +typedef struct CNGContext { + LPCContext lpc; + int order; + int32_t *samples32; + double *ref_coef; +} CNGContext; + +static av_cold int cng_encode_close(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + ff_lpc_end(&p->lpc); + av_free(p->samples32); + av_free(p->ref_coef); + return 0; +} + +static av_cold int cng_encode_init(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + int ret; + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(EINVAL); + } + + avctx->frame_size = 640; + p->order = 10; + if ((ret = ff_lpc_init(&p->lpc, avctx->frame_size, p->order, FF_LPC_TYPE_LEVINSON)) < 0) + return ret; + p->samples32 = av_malloc(avctx->frame_size * sizeof(*p->samples32)); + p->ref_coef = av_malloc(p->order * sizeof(*p->ref_coef)); + if (!p->samples32 || !p->ref_coef) { + cng_encode_close(avctx); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int cng_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + CNGContext *p = avctx->priv_data; + int ret, i; + double energy = 0; + int qdbov; + int16_t *samples = (int16_t*) frame->data[0]; + + if ((ret = ff_alloc_packet(avpkt, 1 + p->order))) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); + return ret; + } + + for (i = 0; i < frame->nb_samples; i++) { + p->samples32[i] = samples[i]; + energy += samples[i] * samples[i]; + } + energy /= frame->nb_samples; + if (energy > 0) { + double dbov = 10 * log10(energy / 1081109975); + qdbov = av_clip(-floor(dbov), 0, 127); + } else { + qdbov = 127; + } + ret = ff_lpc_calc_ref_coefs(&p->lpc, p->samples32, p->order, p->ref_coef); + avpkt->data[0] = qdbov; + for (i = 0; i < p->order; i++) + avpkt->data[1 + i] = p->ref_coef[i] * 127 + 127; + + *got_packet_ptr = 1; + avpkt->size = 1 + p->order; + + return 0; +} + +AVCodec ff_comfortnoise_encoder = { + .name = "comfortnoise", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_COMFORT_NOISE, + .priv_data_size = sizeof(CNGContext), + .init = cng_encode_init, + .encode2 = cng_encode_frame, + .close = cng_encode_close, + .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 818a35e804..a8ff314394 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2112,6 +2112,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio Codec)"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_COMFORT_NOISE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "comfortnoise", + .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 Comfort Noise"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/version.h b/libavcodec/version.h index b702f4b4b1..5ee7c7c55d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,7 +27,7 @@ */ #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 31 +#define LIBAVCODEC_VERSION_MINOR 32 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From 20dd41af8513de427b00ee598339c9bc5778bdc5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 Oct 2012 21:37:26 +0200 Subject: [PATCH 8/9] lavfi: add ashowinfo filter It can be useful for debugging. Based on a patch by Stefano Sabatini --- Changelog | 1 + doc/filters.texi | 41 +++++++++++ libavfilter/Makefile | 1 + libavfilter/af_ashowinfo.c | 136 +++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 libavfilter/af_ashowinfo.c diff --git a/Changelog b/Changelog index c3d55c1c3c..e2c4273ded 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest. version : - metadata (INFO tag) support in WAV muxer - support for building DLLs using MSVC +- ashowinfo audio filter version 9_beta1: diff --git a/doc/filters.texi b/doc/filters.texi index 8f90e84956..85c8ae0b9b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -175,6 +175,47 @@ stream ends. The default value is 2 seconds. Pass the audio source unchanged to the output. +@section ashowinfo + +Show a line containing various information for each input audio frame. +The input audio is not modified. + +The shown line contains a sequence of key/value pairs of the form +@var{key}:@var{value}. + +A description of each shown parameter follows: + +@table @option +@item n +sequential number of the input frame, starting from 0 + +@item pts +Presentation timestamp of the input frame, in time base units; the time base +depends on the filter input pad, and is usually 1/@var{sample_rate}. + +@item pts_time +presentation timestamp of the input frame in seconds + +@item fmt +sample format + +@item chlayout +channel layout + +@item rate +sample rate for the audio frame + +@item nb_samples +number of samples (per channel) in the frame + +@item checksum +Adler-32 checksum (printed in hexadecimal) of the audio data. For planar audio +the data is treated as if all the planes were concatenated. + +@item plane_checksums +A list of Adler-32 checksums for each data plane. +@end table + @section asplit Split input audio into several identical outputs. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 530aa576ae..9770e1ffc9 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -28,6 +28,7 @@ OBJS-$(CONFIG_AFIFO_FILTER) += fifo.o OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o +OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o OBJS-$(CONFIG_ASPLIT_FILTER) += split.o OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c new file mode 100644 index 0000000000..00e0322f5c --- /dev/null +++ b/libavfilter/af_ashowinfo.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2011 Stefano Sabatini + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * filter for showing textual audio frame information + */ + +#include +#include + +#include "libavutil/adler32.h" +#include "libavutil/audioconvert.h" +#include "libavutil/common.h" +#include "libavutil/mem.h" +#include "libavutil/samplefmt.h" + +#include "audio.h" +#include "avfilter.h" + +typedef struct AShowInfoContext { + /** + * Scratch space for individual plane checksums for planar audio + */ + uint32_t *plane_checksums; + + /** + * Frame counter + */ + uint64_t frame; +} AShowInfoContext; + +static int config_input(AVFilterLink *inlink) +{ + AShowInfoContext *s = inlink->dst->priv; + int channels = av_get_channel_layout_nb_channels(inlink->channel_layout); + s->plane_checksums = av_malloc(channels * sizeof(*s->plane_checksums)); + if (!s->plane_checksums) + return AVERROR(ENOMEM); + + return 0; +} + +static void uninit(AVFilterContext *ctx) +{ + AShowInfoContext *s = ctx->priv; + av_freep(&s->plane_checksums); +} + +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +{ + AVFilterContext *ctx = inlink->dst; + AShowInfoContext *s = ctx->priv; + char chlayout_str[128]; + uint32_t checksum = 0; + int channels = av_get_channel_layout_nb_channels(buf->audio->channel_layout); + int planar = av_sample_fmt_is_planar(buf->format); + int block_align = av_get_bytes_per_sample(buf->format) * (planar ? 1 : channels); + int data_size = buf->audio->nb_samples * block_align; + int planes = planar ? channels : 1; + int i; + + for (i = 0; i < planes; i++) { + uint8_t *data = buf->extended_data[i]; + + s->plane_checksums[i] = av_adler32_update(0, data, data_size); + checksum = i ? av_adler32_update(checksum, data, data_size) : + s->plane_checksums[0]; + } + + av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1, + buf->audio->channel_layout); + + av_log(ctx, AV_LOG_INFO, + "n:%"PRIu64" pts:%"PRId64" pts_time:%f " + "fmt:%s chlayout:%s rate:%d nb_samples:%d " + "checksum:%08X ", + s->frame, buf->pts, buf->pts * av_q2d(inlink->time_base), + av_get_sample_fmt_name(buf->format), chlayout_str, + buf->audio->sample_rate, buf->audio->nb_samples, + checksum); + + av_log(ctx, AV_LOG_INFO, "plane_checksums: [ "); + for (i = 0; i < planes; i++) + av_log(ctx, AV_LOG_INFO, "%08X ", s->plane_checksums[i]); + av_log(ctx, AV_LOG_INFO, "]\n"); + + s->frame++; + return ff_filter_samples(inlink->dst->outputs[0], buf); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .get_audio_buffer = ff_null_get_audio_buffer, + .config_props = config_input, + .filter_samples = filter_samples, + .min_perms = AV_PERM_READ, + }, + { NULL }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL }, +}; + +AVFilter avfilter_af_ashowinfo = { + .name = "ashowinfo", + .description = NULL_IF_CONFIG_SMALL("Show textual information for each audio frame."), + .priv_size = sizeof(AShowInfoContext), + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 94b31154df..e7599315a7 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -39,6 +39,7 @@ void avfilter_register_all(void) REGISTER_FILTER (AFORMAT, aformat, af); REGISTER_FILTER (AMIX, amix, af); REGISTER_FILTER (ANULL, anull, af); + REGISTER_FILTER (ASHOWINFO, ashowinfo, af); REGISTER_FILTER (ASPLIT, asplit, af); REGISTER_FILTER (ASYNCTS, asyncts, af); REGISTER_FILTER (CHANNELMAP, channelmap, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index 0e72a47916..eb5326bda8 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 3 -#define LIBAVFILTER_VERSION_MINOR 1 +#define LIBAVFILTER_VERSION_MINOR 2 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 14f031d7ecfabba0ef02776d4516aa3dcb7c40d8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 24 Oct 2012 09:06:32 +0200 Subject: [PATCH 9/9] dv: use AVStream.index instead of abusing AVStream.id --- libavformat/dv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dv.c b/libavformat/dv.c index 70786b1071..17c545c3ca 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -372,7 +372,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, pkt->data = buf; pkt->size = size; pkt->flags |= AV_PKT_FLAG_KEY; - pkt->stream_index = c->vst->id; + pkt->stream_index = c->vst->index; pkt->pts = c->frames; c->frames++;