diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-10-30 14:40:22 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-10-30 14:40:22 +0100 |
commit | e79c3858b35fcc77c68c33b627958e736686957e (patch) | |
tree | 5f933517c2909def4e2930a409b0a460eb4f41fd | |
parent | cd37963684d8ee9819af15ccebe09d84839101dd (diff) | |
parent | 14f031d7ecfabba0ef02776d4516aa3dcb7c40d8 (diff) | |
download | ffmpeg-e79c3858b35fcc77c68c33b627958e736686957e.tar.gz |
Merge commit '14f031d7ecfabba0ef02776d4516aa3dcb7c40d8'
* commit '14f031d7ecfabba0ef02776d4516aa3dcb7c40d8':
dv: use AVStream.index instead of abusing AVStream.id
lavfi: add ashowinfo filter
avcodec: Add a RFC 3389 comfort noise codec
lpc: Add a function for calculating reflection coefficients from samples
lpc: Add a function for calculating reflection coefficients from autocorrelation coefficients
lavr: document upper bound on number of output samples.
lavr: add general API usage doxy
indeo3: remove duplicate capabilities line.
fate: ac3: Add dependencies
Conflicts:
Changelog
doc/filters.texi
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/codec_desc.c
libavcodec/version.h
libavfilter/Makefile
libavfilter/af_ashowinfo.c
libavfilter/allfilters.c
libavfilter/version.h
libavutil/avutil.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | doc/filters.texi | 27 | ||||
-rw-r--r-- | libavcodec/Makefile | 2 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 1 | ||||
-rw-r--r-- | libavcodec/cngdec.c | 162 | ||||
-rw-r--r-- | libavcodec/cngenc.c | 116 | ||||
-rw-r--r-- | libavcodec/codec_desc.c | 7 | ||||
-rw-r--r-- | libavcodec/lpc.c | 12 | ||||
-rw-r--r-- | libavcodec/lpc.h | 34 | ||||
-rw-r--r-- | libavcodec/version.h | 2 | ||||
-rw-r--r-- | libavfilter/af_ashowinfo.c | 141 | ||||
-rw-r--r-- | libavfilter/version.h | 2 | ||||
-rw-r--r-- | libavformat/dv.c | 2 | ||||
-rw-r--r-- | libavresample/avresample.h | 75 | ||||
-rw-r--r-- | libavutil/avutil.h | 1 | ||||
-rw-r--r-- | tests/fate/ac3.mak | 15 |
17 files changed, 522 insertions, 79 deletions
@@ -1607,6 +1607,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/doc/filters.texi b/doc/filters.texi index 0e77914a6e..a264606d54 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -414,37 +414,34 @@ A description of each shown parameter follows: sequential number of the input frame, starting from 0 @item pts -presentation TimeStamp of the input frame, expressed as a number of -time base units. The time base unit depends on the filter input pad, and -is usually 1/@var{sample_rate}. +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, expressed as a number of -seconds +presentation timestamp of the input frame in seconds @item pos position of the frame in the input stream, -1 if this information in unavailable and/or meaningless (for example in case of synthetic audio) @item fmt -sample format name +sample format @item chlayout -channel layout description - -@item nb_samples -number of samples (per each channel) contained in the filtered frame +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 all the planes of the input frame +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_checksum -Adler-32 checksum (printed in hexadecimal) for each input frame plane, -expressed in the form "[@var{c0} @var{c1} @var{c2} @var{c3} @var{c4} @var{c5} -@var{c6} @var{c7}]" +@item plane_checksums +A list of Adler-32 checksums for each data plane. @end table @section asplit diff --git a/libavcodec/Makefile b/libavcodec/Makefile index bb97e5df08..5f8776da0a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -145,6 +145,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_CPIA_DECODER) += cpia.o OBJS-$(CONFIG_CSCD_DECODER) += cscd.o OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 8d11909ffb..6bad573617 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -97,6 +97,7 @@ void avcodec_register_all(void) REGISTER_DECODER (CINEPAK, cinepak); REGISTER_ENCDEC (CLJR, cljr); REGISTER_DECODER (CLLC, cllc); + REGISTER_ENCDEC (COMFORTNOISE, comfortnoise); REGISTER_DECODER (CPIA, cpia); REGISTER_DECODER (CSCD, cscd); REGISTER_DECODER (CYUV, cyuv); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1495c9e2bd..a08cd031aa 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -426,6 +426,7 @@ enum AVCodecID { AV_CODEC_ID_IAC, AV_CODEC_ID_ILBC, AV_CODEC_ID_OPUS_DEPRECATED, + AV_CODEC_ID_COMFORT_NOISE, AV_CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), AV_CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), AV_CODEC_ID_SONIC = MKBETAG('S','O','N','C'), diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c new file mode 100644 index 0000000000..0daeb9b969 --- /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 FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> + +#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..a1dcfa6115 --- /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 FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <math.h> + +#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 09b3015f37..48dbe06b1f 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2265,6 +2265,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .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, + }, + { .id = AV_CODEC_ID_TAK, .type = AVMEDIA_TYPE_AUDIO, .name = "tak", diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c index 5ccd5a8e08..019689a247 100644 --- a/libavcodec/lpc.c +++ b/libavcodec/lpc.c @@ -149,6 +149,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 b9c35bd303..24f776a244 100644 --- a/libavcodec/lpc.h +++ b/libavcodec/lpc.h @@ -93,6 +93,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. */ @@ -112,6 +115,37 @@ void ff_lpc_end(LPCContext *s); #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. */ diff --git a/libavcodec/version.h b/libavcodec/version.h index f878efe811..67ff16919d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 69 +#define LIBAVCODEC_VERSION_MINOR 70 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index 25a5e2ca67..1a70deee28 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -23,84 +23,117 @@ * filter for showing textual audio frame information */ +#include <inttypes.h> +#include <stddef.h> + #include "libavutil/adler32.h" #include "libavutil/audioconvert.h" +#include "libavutil/common.h" +#include "libavutil/mem.h" #include "libavutil/timestamp.h" +#include "libavutil/samplefmt.h" + #include "audio.h" #include "avfilter.h" -typedef struct { - unsigned int frame; -} ShowInfoContext; +typedef struct AShowInfoContext { + /** + * Scratch space for individual plane checksums for planar audio + */ + uint32_t *plane_checksums; + + /** + * Frame counter + */ + uint64_t frame; +} AShowInfoContext; -static av_cold int init(AVFilterContext *ctx, const char *args) +static int config_input(AVFilterLink *inlink) { - ShowInfoContext *showinfo = ctx->priv; - showinfo->frame = 0; + 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 int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) +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; - ShowInfoContext *showinfo = ctx->priv; - uint32_t plane_checksum[8] = {0}, checksum = 0; + AShowInfoContext *s = ctx->priv; char chlayout_str[128]; - int plane; - int linesize = - samplesref->audio->nb_samples * - av_get_bytes_per_sample(samplesref->format); - if (!av_sample_fmt_is_planar(samplesref->format)) - linesize *= av_get_channel_layout_nb_channels(samplesref->audio->channel_layout); - - for (plane = 0; plane < 8 && samplesref->data[plane]; plane++) { - uint8_t *data = samplesref->data[plane]; - - plane_checksum[plane] = av_adler32_update(plane_checksum[plane], - data, linesize); - checksum = av_adler32_update(checksum, data, linesize); + 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, - samplesref->audio->channel_layout); + buf->audio->channel_layout); av_log(ctx, AV_LOG_INFO, - "n:%d pts:%s pts_time:%s pos:%"PRId64" " - "fmt:%s chlayout:%s nb_samples:%d rate:%d " - "checksum:%08X plane_checksum[%08X", - showinfo->frame, - av_ts2str(samplesref->pts), av_ts2timestr(samplesref->pts, &inlink->time_base), - samplesref->pos, - av_get_sample_fmt_name(samplesref->format), - chlayout_str, - samplesref->audio->nb_samples, - samplesref->audio->sample_rate, - checksum, - plane_checksum[0]); - - for (plane = 1; plane < 8 && samplesref->data[plane]; plane++) - av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]); + "n:%"PRIu64" pts:%s pts_time:%s pos:%"PRId64" " + "fmt:%s chlayout:%s rate:%d nb_samples:%d " + "checksum:%08X ", + s->frame, + av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base), + buf->pos, + 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"); - showinfo->frame++; - return ff_filter_samples(inlink->dst->outputs[0], samplesref); + 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(ShowInfoContext), - .init = init, - - .inputs = (const AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_AUDIO, - .get_audio_buffer = ff_null_get_audio_buffer, - .filter_samples = filter_samples, - .min_perms = AV_PERM_READ, }, - { .name = NULL}}, - - .outputs = (const AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_AUDIO }, - { .name = NULL}}, + .priv_size = sizeof(AShowInfoContext), + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, }; diff --git a/libavfilter/version.h b/libavfilter/version.h index ff381079c5..f09b6cb0e4 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #define LIBAVFILTER_VERSION_MAJOR 3 #define LIBAVFILTER_VERSION_MINOR 20 -#define LIBAVFILTER_VERSION_MICRO 109 +#define LIBAVFILTER_VERSION_MICRO 110 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavformat/dv.c b/libavformat/dv.c index 1d5ec2cf89..75d2136628 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -391,7 +391,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, pkt->pos = pos; 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++; diff --git a/libavresample/avresample.h b/libavresample/avresample.h index ea93952e2e..b0a9e247e8 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" @@ -198,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 @@ -289,4 +360,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 ae6eef1245..db016a58dd 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 libswresample "libswresample" audio resampling, format conversion and mixing * @li @subpage libpostproc post processing library * @li @subpage libswscale color conversion and scaling library */ diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index d15c7cd5be..cde214175c 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 = 4 -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 -ab 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) |