00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libavutil/channel_layout.h"
00027 #include "libavutil/opt.h"
00028 #include "libavutil/parseutils.h"
00029 #include "avfilter.h"
00030 #include "formats.h"
00031 #include "audio.h"
00032 #include "video.h"
00033 #include "internal.h"
00034
00035 typedef struct {
00036 const AVClass *class;
00037 int w, h;
00038 char *rate_str;
00039 AVRational rate;
00040 int buf_idx;
00041 AVFilterBufferRef *outpicref;
00042 int req_fullfilled;
00043 int n;
00044 int sample_count_mod;
00045 } ShowWavesContext;
00046
00047 #define OFFSET(x) offsetof(ShowWavesContext, x)
00048 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
00049
00050 static const AVOption showwaves_options[] = {
00051 { "rate", "set video rate", OFFSET(rate_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
00052 { "r", "set video rate", OFFSET(rate_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
00053 { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "600x240"}, 0, 0, FLAGS },
00054 { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "600x240"}, 0, 0, FLAGS },
00055 { "n", "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS },
00056 { NULL },
00057 };
00058
00059 AVFILTER_DEFINE_CLASS(showwaves);
00060
00061 static av_cold int init(AVFilterContext *ctx, const char *args)
00062 {
00063 ShowWavesContext *showwaves = ctx->priv;
00064 int err;
00065
00066 showwaves->class = &showwaves_class;
00067 av_opt_set_defaults(showwaves);
00068 showwaves->buf_idx = 0;
00069
00070 if ((err = av_set_options_string(showwaves, args, "=", ":")) < 0)
00071 return err;
00072
00073 return 0;
00074 }
00075
00076 static av_cold void uninit(AVFilterContext *ctx)
00077 {
00078 ShowWavesContext *showwaves = ctx->priv;
00079
00080 av_freep(&showwaves->rate_str);
00081 avfilter_unref_bufferp(&showwaves->outpicref);
00082 }
00083
00084 static int query_formats(AVFilterContext *ctx)
00085 {
00086 AVFilterFormats *formats = NULL;
00087 AVFilterChannelLayouts *layouts = NULL;
00088 AVFilterLink *inlink = ctx->inputs[0];
00089 AVFilterLink *outlink = ctx->outputs[0];
00090 static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE };
00091 static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
00092
00093
00094 formats = ff_make_format_list(sample_fmts);
00095 if (!formats)
00096 return AVERROR(ENOMEM);
00097 ff_formats_ref(formats, &inlink->out_formats);
00098
00099 layouts = ff_all_channel_layouts();
00100 if (!layouts)
00101 return AVERROR(ENOMEM);
00102 ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
00103
00104 formats = ff_all_samplerates();
00105 if (!formats)
00106 return AVERROR(ENOMEM);
00107 ff_formats_ref(formats, &inlink->out_samplerates);
00108
00109
00110 formats = ff_make_format_list(pix_fmts);
00111 if (!formats)
00112 return AVERROR(ENOMEM);
00113 ff_formats_ref(formats, &outlink->in_formats);
00114
00115 return 0;
00116 }
00117
00118 static int config_output(AVFilterLink *outlink)
00119 {
00120 AVFilterContext *ctx = outlink->src;
00121 AVFilterLink *inlink = ctx->inputs[0];
00122 ShowWavesContext *showwaves = ctx->priv;
00123 int err;
00124
00125 if (showwaves->n && showwaves->rate_str) {
00126 av_log(ctx, AV_LOG_ERROR, "Options 'n' and 'rate' cannot be set at the same time\n");
00127 return AVERROR(EINVAL);
00128 }
00129
00130 if (!showwaves->n) {
00131 if (!showwaves->rate_str)
00132 showwaves->rate = (AVRational){25,1};
00133 else if ((err = av_parse_video_rate(&showwaves->rate, showwaves->rate_str)) < 0) {
00134 av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", showwaves->rate_str);
00135 return err;
00136 }
00137 showwaves->n = FFMAX(1, ((double)inlink->sample_rate / (showwaves->w * av_q2d(showwaves->rate))) + 0.5);
00138 }
00139
00140 outlink->w = showwaves->w;
00141 outlink->h = showwaves->h;
00142 outlink->sample_aspect_ratio = (AVRational){1,1};
00143
00144 outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n},
00145 (AVRational){showwaves->w,1});
00146
00147 av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d\n",
00148 showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n);
00149 return 0;
00150 }
00151
00152 inline static void push_frame(AVFilterLink *outlink)
00153 {
00154 ShowWavesContext *showwaves = outlink->src->priv;
00155
00156 ff_filter_frame(outlink, showwaves->outpicref);
00157 showwaves->req_fullfilled = 1;
00158 showwaves->outpicref = NULL;
00159 showwaves->buf_idx = 0;
00160 }
00161
00162 static int request_frame(AVFilterLink *outlink)
00163 {
00164 ShowWavesContext *showwaves = outlink->src->priv;
00165 AVFilterLink *inlink = outlink->src->inputs[0];
00166 int ret;
00167
00168 showwaves->req_fullfilled = 0;
00169 do {
00170 ret = ff_request_frame(inlink);
00171 } while (!showwaves->req_fullfilled && ret >= 0);
00172
00173 if (ret == AVERROR_EOF && showwaves->outpicref)
00174 push_frame(outlink);
00175 return ret;
00176 }
00177
00178 #define MAX_INT16 ((1<<15) -1)
00179
00180 static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *insamples)
00181 {
00182 AVFilterContext *ctx = inlink->dst;
00183 AVFilterLink *outlink = ctx->outputs[0];
00184 ShowWavesContext *showwaves = ctx->priv;
00185 const int nb_samples = insamples->audio->nb_samples;
00186 AVFilterBufferRef *outpicref = showwaves->outpicref;
00187 int linesize = outpicref ? outpicref->linesize[0] : 0;
00188 int16_t *p = (int16_t *)insamples->data[0];
00189 int nb_channels = av_get_channel_layout_nb_channels(insamples->audio->channel_layout);
00190 int i, j, h;
00191 const int n = showwaves->n;
00192 const int x = 255 / (nb_channels * n);
00193
00194
00195 for (i = 0; i < nb_samples; i++) {
00196 if (!outpicref) {
00197 showwaves->outpicref = outpicref =
00198 ff_get_video_buffer(outlink, AV_PERM_WRITE|AV_PERM_ALIGN,
00199 outlink->w, outlink->h);
00200 if (!outpicref)
00201 return AVERROR(ENOMEM);
00202 outpicref->video->w = outlink->w;
00203 outpicref->video->h = outlink->h;
00204 outpicref->pts = insamples->pts +
00205 av_rescale_q((p - (int16_t *)insamples->data[0]) / nb_channels,
00206 (AVRational){ 1, inlink->sample_rate },
00207 outlink->time_base);
00208 linesize = outpicref->linesize[0];
00209 memset(outpicref->data[0], 0, showwaves->h*linesize);
00210 }
00211 for (j = 0; j < nb_channels; j++) {
00212 h = showwaves->h/2 - av_rescale(*p++, showwaves->h/2, MAX_INT16);
00213 if (h >= 0 && h < outlink->h)
00214 *(outpicref->data[0] + showwaves->buf_idx + h * linesize) += x;
00215 }
00216 showwaves->sample_count_mod++;
00217 if (showwaves->sample_count_mod == n) {
00218 showwaves->sample_count_mod = 0;
00219 showwaves->buf_idx++;
00220 }
00221 if (showwaves->buf_idx == showwaves->w)
00222 push_frame(outlink);
00223 }
00224
00225 avfilter_unref_buffer(insamples);
00226 return 0;
00227 }
00228
00229 static const AVFilterPad showwaves_inputs[] = {
00230 {
00231 .name = "default",
00232 .type = AVMEDIA_TYPE_AUDIO,
00233 .filter_frame = filter_frame,
00234 .min_perms = AV_PERM_READ,
00235 },
00236 { NULL }
00237 };
00238
00239 static const AVFilterPad showwaves_outputs[] = {
00240 {
00241 .name = "default",
00242 .type = AVMEDIA_TYPE_VIDEO,
00243 .config_props = config_output,
00244 .request_frame = request_frame,
00245 },
00246 { NULL }
00247 };
00248
00249 AVFilter avfilter_avf_showwaves = {
00250 .name = "showwaves",
00251 .description = NULL_IF_CONFIG_SMALL("Convert input audio to a video output."),
00252 .init = init,
00253 .uninit = uninit,
00254 .query_formats = query_formats,
00255 .priv_size = sizeof(ShowWavesContext),
00256 .inputs = showwaves_inputs,
00257 .outputs = showwaves_outputs,
00258 .priv_class = &showwaves_class,
00259 };