[FFmpeg-devel] [PATCH] ffplay changes for lavfi audio

Stefano Sabatini stefano.sabatini-lala
Sat Aug 21 17:00:35 CEST 2010


On date Saturday 2010-08-21 03:39:27 -0700, S.N. Hemanth Meenakshisundaram encoded:
> ffplay changes based off latest SVN. Passes 'make test'. This is needed
> for testing af_resample.c patch from earlier and other filters.
> 
> ---
>  ffplay.c |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 204 insertions(+), 0 deletions(-)
> 
> 
> 

> diff --git a/ffplay.c b/ffplay.c
> index efc079b..8babe2e 100644
> --- a/ffplay.c
> +++ b/ffplay.c
> @@ -106,6 +106,7 @@ typedef struct VideoPicture {
>  
>  #if CONFIG_AVFILTER
>      AVFilterBufferRef *picref;
> +    AVFilterBufferRef *samplesref;
>  #endif
>  } VideoPicture;
>  
> @@ -211,6 +212,8 @@ typedef struct VideoState {
>  
>  #if CONFIG_AVFILTER
>      AVFilterContext *out_video_filter;          ///<the last filter in the video chain
> +    AVFilterContext *out_audio_filter;          ///<the last filter in the audio chain
> +    AVFilterGraph *agraph;
>  #endif
>  
>      float skip_frames;
> @@ -220,6 +223,7 @@ typedef struct VideoState {
>  
>  static void show_help(void);
>  static int audio_write_get_buf_size(VideoState *is);
> +static int audio_decode_frame(VideoState *is, double *pts_ptr);
>  
>  /* options specified by the user */
>  static AVInputFormat *file_iformat;
> @@ -269,6 +273,7 @@ static int framedrop=1;
>  static int rdftspeed=20;
>  #if CONFIG_AVFILTER
>  static char *vfilters = NULL;
> +static char *afilters = NULL;
>  #endif
>  
>  /* current context */
> @@ -1835,6 +1840,144 @@ static AVFilter output_filter =
>                                    { .name = NULL }},
>      .outputs   = (AVFilterPad[]) {{ .name = NULL }},
>  };
> +
> +typedef struct {
> +    VideoState *is;
> +} AudioFilterPriv;
> +
> +static int input_audio_init(AVFilterContext *ctx, const char *args, void *opaque)
> +{
> +    AudioFilterPriv *priv = ctx->priv;
> +
> +    if (!opaque) return AVERROR(EINVAL);
> +
> +    priv->is = opaque;
> +
> +    return 0;
> +}
> +
> +static void input_audio_uninit(AVFilterContext *ctx)
> +{
> +}
> +
> +static int input_request_audio_frame(AVFilterLink *link)
> +{
> +    AudioFilterPriv *priv = link->src->priv;
> +    AVFilterBufferRef *samplesref;
> +    AVCodecContext *avctx;
> +    double pts = 0;
> +    int buf_size = 0;
> +
> +    buf_size = audio_decode_frame(priv->is, &pts);
> +    avctx = priv->is->audio_st->codec;
> +    if (buf_size <= 0)
> +        return AVERROR(EINVAL);
> +
> +    /* FIXME Currently audio streams seem to have no info on planar/packed.
> +     * Assuming packed here and passing 0 as last attribute to get_audio_buffer.
> +     */
> +    if (!avctx->channel_layout) {
> +        avctx->channel_layout = avcodec_guess_channel_layout(avctx->channels, 0, NULL);
> +    }
> +
> +    samplesref = avfilter_get_audio_buffer(link, AV_PERM_WRITE, avctx->sample_fmt, 
> +                                           buf_size, avctx->channel_layout, 0);
> +    memcpy(samplesref->data[0], priv->is->audio_buf, buf_size);
> +
> +    samplesref->pts         = (int64_t) pts;
> +    samplesref->audio->sample_rate = (int64_t) avctx->sample_rate;
> +    avfilter_filter_samples(link, samplesref);
> +
> +    return 0;
> +}
> +
> +static int input_query_audio_formats(AVFilterContext *ctx)
> +{
> +    AudioFilterPriv *priv = ctx->priv;
> +    enum SampleFormat sample_fmts[] = {
> +        priv->is->audio_st->codec->sample_fmt, SAMPLE_FMT_NONE
> +    };
> +
> +    avfilter_set_common_formats(ctx, avfilter_make_format_list(sample_fmts));
> +    return 0;
> +}
> +
> +static int input_config_audio_props(AVFilterLink *link)
> +{
> +    FilterPriv *priv  = link->src->priv;
> +    AVCodecContext *avctx = priv->is->audio_st->codec;
> +
> +    if (!avctx->channel_layout)
> +        avctx->channel_layout = avcodec_guess_channel_layout(avctx->channels, 0, NULL);
> +    link->channel_layout = avctx->channel_layout;
> +    link->sample_rate = avctx->sample_rate;
> +    return 0;
> +}
> +
> +static AVFilter input_audio_filter =
> +{
> +    .name      = "ffplay_audio_input",
> +
> +    .priv_size = sizeof(AudioFilterPriv),
> +
> +    .init      = input_audio_init,
> +    .uninit    = input_audio_uninit,
> +
> +    .query_formats = input_query_audio_formats,
> +
> +    .inputs    = (AVFilterPad[]) {{ .name = NULL }},
> +    .outputs   = (AVFilterPad[]) {{ .name = "default",
> +                                    .type = AVMEDIA_TYPE_AUDIO,
> +                                    .request_frame = input_request_audio_frame,
> +                                    .config_props  = input_config_audio_props, },
> +                                  { .name = NULL }},
> +};
> +
> +static void output_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
> +{
> +}
> +
> +static int output_query_audio_formats(AVFilterContext *ctx)
> +{
> +    enum SampleFormat sample_fmts[] = { SAMPLE_FMT_S16, SAMPLE_FMT_NONE };
> +
> +    avfilter_set_common_formats(ctx, avfilter_make_format_list(sample_fmts));
> +    return 0;
> +}
> +
> +static int get_filtered_audio_samples(AVFilterContext *ctx, VideoState *is, double *pts)
> +{
> +    AVFilterBufferRef *samplesref;
> +    int ret, size;
> +
> +    if ((ret = avfilter_request_frame(ctx->inputs[0])))
> +        return ret;
> +    if (!(samplesref = ctx->inputs[0]->cur_buf))
> +        return AVERROR(EINVAL);
> +    ctx->inputs[0]->cur_buf = NULL;
> +    size = samplesref->audio->size;
> +
> +    *pts          = samplesref->pts;
> +
> +    memcpy(is->audio_buf, samplesref->data[0], size);
> +    avfilter_unref_buffer(samplesref);
> +
> +    return size;
> +}
> +
> +static AVFilter output_audio_filter =
> +{
> +    .name      = "ffplay_audio_output",
> +
> +    .query_formats = output_query_audio_formats,
> +
> +    .inputs    = (AVFilterPad[]) {{ .name           = "default",
> +                                    .type           = AVMEDIA_TYPE_AUDIO,
> +                                    .filter_samples = output_filter_samples,
> +                                    .min_perms      = AV_PERM_READ, },
> +                                  { .name = NULL }},
> +    .outputs   = (AVFilterPad[]) {{ .name = NULL }},
> +};
>  #endif  /* CONFIG_AVFILTER */
>  
>  static int video_thread(void *arg)
> @@ -2226,7 +2369,11 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
>  
>      while (len > 0) {
>          if (is->audio_buf_index >= is->audio_buf_size) {
> +#if CONFIG_AVFILTER
> +           audio_size = get_filtered_audio_samples(is->out_audio_filter, is, &pts);
> +#else
>             audio_size = audio_decode_frame(is, &pts);
> +#endif
>             if (audio_size < 0) {
>                  /* if error, just output silence */
>                 is->audio_buf = is->audio_buf1;
> @@ -2258,6 +2405,10 @@ static int stream_component_open(VideoState *is, int stream_index)
>      AVCodecContext *avctx;
>      AVCodec *codec;
>      SDL_AudioSpec wanted_spec, spec;
> +#if CONFIG_AVFILTER
> +    AVFilterContext *afilt_src = NULL, *afilt_out = NULL;
> +    int ret = AVERROR(EINVAL);
> +#endif
>  
>      if (stream_index < 0 || stream_index >= ic->nb_streams)
>          return -1;
> @@ -2326,6 +2477,48 @@ static int stream_component_open(VideoState *is, int stream_index)
>          is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
>  
>          memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
> +
> +#if CONFIG_AVFILTER
> +    is->agraph = av_mallocz(sizeof(AVFilterGraph));
> +    if (avfilter_open(&afilt_src, &input_audio_filter,  "asrc") < 0)   goto the_end;
> +    if (avfilter_open(&afilt_out, &output_audio_filter, "aout") < 0)   goto the_end;
> +
> +    if ((ret = avfilter_init_filter(afilt_src, NULL, is)) < 0)         goto the_end;
> +    if ((ret = avfilter_init_filter(afilt_out, NULL, NULL)) < 0)       goto the_end;
> +
> +
> +    if (afilters) {
> +        AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
> +        AVFilterInOut *inputs  = av_malloc(sizeof(AVFilterInOut));
> +
> +        outputs->name    = av_strdup("in");
> +        outputs->filter  = afilt_src;
> +        outputs->pad_idx = 0;
> +        outputs->next    = NULL;
> +
> +        inputs->name    = av_strdup("out");
> +        inputs->filter  = afilt_out;
> +        inputs->pad_idx = 0;
> +        inputs->next    = NULL;
> +
> +        if ((ret = avfilter_graph_parse(is->agraph, afilters, inputs, outputs, NULL)) < 0)
> +            goto the_end;
> +
> +        av_freep(&afilters);
> +
> +    } else
> +        if (avfilter_link(afilt_src, 0, afilt_out, 0) < 0)             goto the_end;
> +
> +    if ((ret = avfilter_graph_add_filter(is->agraph, afilt_src)) < 0)  goto the_end;
> +    if ((ret = avfilter_graph_add_filter(is->agraph, afilt_out)) < 0)  goto the_end;
> +
> +    if ((ret = avfilter_graph_check_validity(is->agraph, NULL)) < 0)   goto the_end;
> +    if ((ret = avfilter_graph_config_formats(is->agraph, NULL)) < 0)   goto the_end;
> +    if ((ret = avfilter_graph_config_links(is->agraph, NULL)) < 0)     goto the_end;
> +
> +    is->out_audio_filter = afilt_out;
> +#endif
> +
>          packet_queue_init(&is->audioq);
>          SDL_PauseAudio(0);
>          break;
> @@ -2349,6 +2542,12 @@ static int stream_component_open(VideoState *is, int stream_index)
>          break;
>      }
>      return 0;
> +#if CONFIG_AVFILTER
> +the_end:
> +    avfilter_graph_destroy(is->agraph);
> +    av_freep(&(is->agraph));
> +    return ret;
> +#endif
>  }
>  
>  static void stream_component_close(VideoState *is, int stream_index)
> @@ -2370,6 +2569,10 @@ static void stream_component_close(VideoState *is, int stream_index)
>          if (is->reformat_ctx)
>              av_audio_convert_free(is->reformat_ctx);
>          is->reformat_ctx = NULL;
> +#if CONFIG_AVFILTER
> +        avfilter_graph_destroy(is->agraph);
> +        av_freep(&(is->agraph));
> +#endif
>          break;
>      case AVMEDIA_TYPE_VIDEO:
>          packet_queue_abort(&is->videoq);
> @@ -3085,6 +3288,7 @@ static const OptionDef options[] = {
>      { "window_title", OPT_STRING | HAS_ARG, {(void*)&window_title}, "set window title", "window title" },
>  #if CONFIG_AVFILTER
>      { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
> +    { "af", OPT_STRING | HAS_ARG, {(void*)&afilters}, "audio filters", "filter list" },
>  #endif
>      { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, {(void*)&rdftspeed}, "rdft speed", "msecs" },
>      { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },

Missing documentation for -af and Changelog entry, looks OK otherwise.

Regards.
-- 
FFmpeg = Formidable Faithless Multipurpose Patchable Embarassing Guru



More information about the ffmpeg-devel mailing list