From 20dd41af8513de427b00ee598339c9bc5778bdc5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 Oct 2012 21:37:26 +0200 Subject: [PATCH] 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, \ -- 2.11.0