libavfilter/avfilter.c
4dbbcdee
 /*
16790dc3
  * filter layer
3fa77bde
  * Copyright (c) 2007 Bobby Bingham
4dbbcdee
  *
  * 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
  */
 
22364567
 #include "libavutil/atomic.h"
03b07872
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
b3dd30db
 #include "libavutil/buffer.h"
a903f8f0
 #include "libavutil/channel_layout.h"
1d9c2dc8
 #include "libavutil/common.h"
fdd93eab
 #include "libavutil/eval.h"
b3dd30db
 #include "libavutil/hwcontext.h"
565e4993
 #include "libavutil/imgutils.h"
7950e519
 #include "libavutil/internal.h"
befbcc37
 #include "libavutil/opt.h"
b4b66456
 #include "libavutil/pixdesc.h"
867ae7aa
 #include "libavutil/rational.h"
565e4993
 #include "libavutil/samplefmt.h"
472fb3bb
 
02aa0701
 #define FF_INTERNAL_FIELDS 1
 #include "framequeue.h"
 
565e4993
 #include "audio.h"
4dbbcdee
 #include "avfilter.h"
4c24f3ac
 #include "filters.h"
ff1f51a8
 #include "formats.h"
9f0e31d2
 #include "internal.h"
4dbbcdee
 
649c158e
 #include "libavutil/ffversion.h"
 const char av_filter_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
 
a05a44e2
 void ff_tlog_ref(void *ctx, AVFrame *ref, int end)
1488c4dc
 {
     av_unused char buf[16];
134815a0
     ff_tlog(ctx,
a05a44e2
             "ref[%p buf:%p data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64,
             ref, ref->buf, ref->data[0],
1488c4dc
             ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
6af050d7
             ref->pts, ref->pkt_pos);
1488c4dc
 
a05a44e2
     if (ref->width) {
134815a0
         ff_tlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c",
a05a44e2
                 ref->sample_aspect_ratio.num, ref->sample_aspect_ratio.den,
                 ref->width, ref->height,
                 !ref->interlaced_frame     ? 'P' :         /* Progressive  */
                 ref->top_field_first ? 'T' : 'B',    /* Top / Bottom */
                 ref->key_frame,
                 av_get_picture_type_char(ref->pict_type));
1488c4dc
     }
a05a44e2
     if (ref->nb_samples) {
134815a0
         ff_tlog(ctx, " cl:%"PRId64"d n:%d r:%d",
a05a44e2
                 ref->channel_layout,
                 ref->nb_samples,
                 ref->sample_rate);
1488c4dc
     }
 
134815a0
     ff_tlog(ctx, "]%s", end ? "\n" : "");
1488c4dc
 }
 
bf5b5d2b
 unsigned avfilter_version(void)
 {
f810ab45
     av_assert0(LIBAVFILTER_VERSION_MICRO >= 100);
540f1c7b
     return LIBAVFILTER_VERSION_INT;
 }
 
41600690
 const char *avfilter_configuration(void)
c1736936
 {
e528cdac
     return FFMPEG_CONFIGURATION;
c1736936
 }
 
41600690
 const char *avfilter_license(void)
c1736936
 {
 #define LICENSE_PREFIX "libavfilter license: "
0cb88628
     return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
c1736936
 }
 
1cbf7fb4
 void ff_command_queue_pop(AVFilterContext *filter)
3d8176d2
 {
     AVFilterCommand *c= filter->command_queue;
     av_freep(&c->arg);
     av_freep(&c->command);
     filter->command_queue= c->next;
     av_free(c);
 }
 
211a185c
 int ff_insert_pad(unsigned idx, unsigned *count, size_t padidx_off,
fa417fcd
                    AVFilterPad **pads, AVFilterLink ***links,
                    AVFilterPad *newpad)
24618441
 {
211a185c
     AVFilterLink **newlinks;
     AVFilterPad *newpads;
24618441
     unsigned i;
 
     idx = FFMIN(idx, *count);
 
211a185c
     newpads  = av_realloc_array(*pads,  *count + 1, sizeof(AVFilterPad));
     newlinks = av_realloc_array(*links, *count + 1, sizeof(AVFilterLink*));
     if (newpads)
         *pads  = newpads;
     if (newlinks)
         *links = newlinks;
     if (!newpads || !newlinks)
         return AVERROR(ENOMEM);
 
bf5b5d2b
     memmove(*pads  + idx + 1, *pads  + idx, sizeof(AVFilterPad)   * (*count - idx));
     memmove(*links + idx + 1, *links + idx, sizeof(AVFilterLink*) * (*count - idx));
     memcpy(*pads + idx, newpad, sizeof(AVFilterPad));
24618441
     (*links)[idx] = NULL;
 
ca857431
     (*count)++;
bf5b5d2b
     for (i = idx + 1; i < *count; i++)
ab2bfb85
         if ((*links)[i])
             (*(unsigned *)((uint8_t *) (*links)[i] + padidx_off))++;
211a185c
 
     return 0;
24618441
 }
 
4dbbcdee
 int avfilter_link(AVFilterContext *src, unsigned srcpad,
                   AVFilterContext *dst, unsigned dstpad)
 {
     AVFilterLink *link;
 
02aa0701
     av_assert0(src->graph);
     av_assert0(dst->graph);
     av_assert0(src->graph == dst->graph);
 
9baeff95
     if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad ||
         src->outputs[srcpad]      || dst->inputs[dstpad])
88b160a4
         return AVERROR(EINVAL);
4dbbcdee
 
891aeeee
     if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) {
         av_log(src, AV_LOG_ERROR,
bd9939f4
                "Media type mismatch between the '%s' filter output pad %d (%s) and the '%s' filter input pad %d (%s)\n",
                src->name, srcpad, (char *)av_x_if_null(av_get_media_type_string(src->output_pads[srcpad].type), "?"),
                dst->name, dstpad, (char *)av_x_if_null(av_get_media_type_string(dst-> input_pads[dstpad].type), "?"));
891aeeee
         return AVERROR(EINVAL);
     }
 
7e2b15c0
     link = av_mallocz(sizeof(*link));
     if (!link)
         return AVERROR(ENOMEM);
 
     src->outputs[srcpad] = dst->inputs[dstpad] = link;
4dbbcdee
 
1653c11f
     link->src     = src;
     link->dst     = dst;
acc0490f
     link->srcpad  = &src->output_pads[srcpad];
     link->dstpad  = &dst->input_pads[dstpad];
bdab614b
     link->type    = src->output_pads[srcpad].type;
ac627b3d
     av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
bdab614b
     link->format  = -1;
02aa0701
     ff_framequeue_init(&link->fifo, &src->graph->internal->frame_queues);
01942f1d
 
     return 0;
 }
 
e977ca26
 void avfilter_link_free(AVFilterLink **link)
 {
     if (!*link)
         return;
 
a05a44e2
     av_frame_free(&(*link)->partial_buf);
02aa0701
     ff_framequeue_free(&(*link)->fifo);
b1f68f00
     ff_frame_pool_uninit((FFFramePool**)&(*link)->frame_pool);
c2271fa7
 
e977ca26
     av_freep(link);
 }
 
238edd2f
 int avfilter_link_get_channels(AVFilterLink *link)
 {
     return link->channels;
 }
 
918891e1
 void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
02aa0701
 {
     filter->ready = FFMAX(filter->ready, priority);
 }
 
 /**
  * Clear frame_blocked_in on all outputs.
  * This is necessary whenever something changes on input.
  */
 static void filter_unblock(AVFilterContext *filter)
 {
     unsigned i;
 
     for (i = 0; i < filter->nb_outputs; i++)
         filter->outputs[i]->frame_blocked_in = 0;
 }
 
 
108b4de5
 void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
 {
02aa0701
     if (link->status_in == status)
         return;
     av_assert0(!link->status_in);
     link->status_in = status;
     link->status_in_pts = pts;
     link->frame_wanted_out = 0;
     link->frame_blocked_in = 0;
     filter_unblock(link->dst);
     ff_filter_set_ready(link->dst, 200);
108b4de5
 }
 
 void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)
 {
02aa0701
     av_assert0(!link->frame_wanted_out);
     av_assert0(!link->status_out);
     link->status_out = status;
     if (pts != AV_NOPTS_VALUE)
         ff_update_link_current_pts(link, pts);
     filter_unblock(link->dst);
     ff_filter_set_ready(link->src, 200);
108b4de5
 }
 
beeba916
 void avfilter_link_set_closed(AVFilterLink *link, int closed)
 {
108b4de5
     ff_avfilter_link_set_out_status(link, closed ? AVERROR_EOF : 0, AV_NOPTS_VALUE);
beeba916
 }
 
52362e9d
 int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
486adc55
                            unsigned filt_srcpad_idx, unsigned filt_dstpad_idx)
52362e9d
 {
db9dfa3c
     int ret;
acc0490f
     unsigned dstpad_idx = link->dstpad - link->dst->input_pads;
 
1a49a169
     av_log(link->dst, AV_LOG_VERBOSE, "auto-inserting filter '%s' "
08f8b51f
            "between the filter '%s' and the filter '%s'\n",
            filt->name, link->src->name, link->dst->name);
52362e9d
 
acc0490f
     link->dst->inputs[dstpad_idx] = NULL;
486adc55
     if ((ret = avfilter_link(filt, filt_dstpad_idx, link->dst, dstpad_idx)) < 0) {
52362e9d
         /* failed to link output filter to new filter */
acc0490f
         link->dst->inputs[dstpad_idx] = link;
db9dfa3c
         return ret;
52362e9d
     }
 
     /* re-hookup the link to the new destination filter we inserted */
bf5b5d2b
     link->dst                     = filt;
     link->dstpad                  = &filt->input_pads[filt_srcpad_idx];
486adc55
     filt->inputs[filt_srcpad_idx] = link;
52362e9d
 
bdab614b
     /* if any information on supported media formats already exists on the
07d0bba5
      * link, we need to preserve that */
ca857431
     if (link->out_formats)
b74a1da4
         ff_formats_changeref(&link->out_formats,
bf5b5d2b
                              &filt->outputs[filt_dstpad_idx]->out_formats);
ff1f51a8
     if (link->out_samplerates)
b74a1da4
         ff_formats_changeref(&link->out_samplerates,
bf5b5d2b
                              &filt->outputs[filt_dstpad_idx]->out_samplerates);
ff1f51a8
     if (link->out_channel_layouts)
         ff_channel_layouts_changeref(&link->out_channel_layouts,
                                      &filt->outputs[filt_dstpad_idx]->out_channel_layouts);
07d0bba5
 
52362e9d
     return 0;
 }
 
69818105
 int avfilter_config_links(AVFilterContext *filter)
01942f1d
 {
     int (*config_link)(AVFilterLink *);
69818105
     unsigned i;
69f73a89
     int ret;
69818105
 
9baeff95
     for (i = 0; i < filter->nb_inputs; i ++) {
e079d22e
         AVFilterLink *link = filter->inputs[i];
eb553096
         AVFilterLink *inlink;
d21cbbff
 
ca857431
         if (!link) continue;
ac84c1ce
         if (!link->src || !link->dst) {
             av_log(filter, AV_LOG_ERROR,
                    "Not all input and output are properly linked (%d).\n", i);
             return AVERROR(EINVAL);
         }
69818105
 
eb553096
         inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL;
b8b7d5ac
         link->current_pts =
d03eab34
         link->current_pts_us = AV_NOPTS_VALUE;
2ce79727
 
ca857431
         switch (link->init_state) {
69818105
         case AVLINK_INIT:
             continue;
         case AVLINK_STARTINIT:
7a9fd2a0
             av_log(filter, AV_LOG_INFO, "circular filter chain detected\n");
             return 0;
69818105
         case AVLINK_UNINIT:
             link->init_state = AVLINK_STARTINIT;
 
69f73a89
             if ((ret = avfilter_config_links(link->src)) < 0)
                 return ret;
4dbbcdee
 
5f68a91b
             if (!(config_link = link->srcpad->config_props)) {
9baeff95
                 if (link->src->nb_inputs != 1) {
5f68a91b
                     av_log(link->src, AV_LOG_ERROR, "Source filters and filters "
                                                     "with more than one input "
                                                     "must set config_props() "
                                                     "callbacks on all outputs\n");
                     return AVERROR(EINVAL);
                 }
65a80ee1
             } else if ((ret = config_link(link)) < 0) {
                 av_log(link->src, AV_LOG_ERROR,
                        "Failed to configure output pad on %s\n",
                        link->src->name);
69f73a89
                 return ret;
65a80ee1
             }
102fb0e3
 
5f68a91b
             switch (link->type) {
             case AVMEDIA_TYPE_VIDEO:
                 if (!link->time_base.num && !link->time_base.den)
553c5e9f
                     link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q;
5f68a91b
 
                 if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den)
553c5e9f
                     link->sample_aspect_ratio = inlink ?
                         inlink->sample_aspect_ratio : (AVRational){1,1};
5f68a91b
 
553c5e9f
                 if (inlink) {
48ff6683
                     if (!link->frame_rate.num && !link->frame_rate.den)
0b73d0ff
                         link->frame_rate = inlink->frame_rate;
5f68a91b
                     if (!link->w)
553c5e9f
                         link->w = inlink->w;
5f68a91b
                     if (!link->h)
553c5e9f
                         link->h = inlink->h;
5f68a91b
                 } else if (!link->w || !link->h) {
                     av_log(link->src, AV_LOG_ERROR,
                            "Video source filters must set their output link's "
                            "width and height\n");
                     return AVERROR(EINVAL);
                 }
                 break;
 
             case AVMEDIA_TYPE_AUDIO:
553c5e9f
                 if (inlink) {
71c644ce
                     if (!link->time_base.num && !link->time_base.den)
553c5e9f
                         link->time_base = inlink->time_base;
5f68a91b
                 }
71c644ce
 
                 if (!link->time_base.num && !link->time_base.den)
                     link->time_base = (AVRational) {1, link->sample_rate};
5f68a91b
             }
70c275f8
 
b3dd30db
             if (link->src->nb_inputs && link->src->inputs[0]->hw_frames_ctx &&
e3fb74f7
                 !(link->src->filter->flags_internal & FF_FILTER_FLAG_HWFRAME_AWARE)) {
                 av_assert0(!link->hw_frames_ctx &&
                            "should not be set by non-hwframe-aware filter");
                 link->hw_frames_ctx = av_buffer_ref(link->src->inputs[0]->hw_frames_ctx);
                 if (!link->hw_frames_ctx)
                     return AVERROR(ENOMEM);
b3dd30db
             }
 
5b63b156
             if ((config_link = link->dstpad->config_props))
                 if ((ret = config_link(link)) < 0) {
                     av_log(link->dst, AV_LOG_ERROR,
                            "Failed to configure input pad on %s\n",
                            link->dst->name);
                     return ret;
                 }
 
69818105
             link->init_state = AVLINK_INIT;
         }
     }
 
4dbbcdee
     return 0;
 }
 
134815a0
 void ff_tlog_link(void *ctx, AVFilterLink *link, int end)
96da1c51
 {
7986e34d
     if (link->type == AVMEDIA_TYPE_VIDEO) {
134815a0
         ff_tlog(ctx,
5764301d
                 "link[%p s:%dx%d fmt:%s %s->%s]%s",
1d5b1885
                 link, link->w, link->h,
59ee9f78
                 av_get_pix_fmt_name(link->format),
1d5b1885
                 link->src ? link->src->filter->name : "",
                 link->dst ? link->dst->filter->name : "",
                 end ? "\n" : "");
7986e34d
     } else {
         char buf[128];
         av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout);
 
134815a0
         ff_tlog(ctx,
5764301d
                 "link[%p r:%d cl:%s fmt:%s %s->%s]%s",
4381bddc
                 link, (int)link->sample_rate, buf,
7986e34d
                 av_get_sample_fmt_name(link->format),
                 link->src ? link->src->filter->name : "",
                 link->dst ? link->dst->filter->name : "",
                 end ? "\n" : "");
     }
96da1c51
 }
 
803391f7
 int ff_request_frame(AVFilterLink *link)
4dbbcdee
 {
134815a0
     FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1);
96da1c51
 
ae4650f0
     av_assert1(!link->dst->filter->activate);
02aa0701
     if (link->status_out)
         return link->status_out;
     if (link->status_in) {
         if (ff_framequeue_queued_frames(&link->fifo)) {
             av_assert1(!link->frame_wanted_out);
             av_assert1(link->dst->ready >= 300);
             return 0;
         } else {
             /* Acknowledge status change. Filters using ff_request_frame() will
                handle the change automatically. Filters can also check the
                status directly but none do yet. */
             ff_avfilter_link_set_out_status(link, link->status_in, link->status_in_pts);
             return link->status_out;
         }
     }
16557887
     link->frame_wanted_out = 1;
02aa0701
     ff_filter_set_ready(link->src, 100);
16557887
     return 0;
 }
 
123f6dc6
 static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational link_time_base)
f5a9c634
 {
     unsigned i;
     int64_t r = INT64_MAX;
 
     for (i = 0; i < ctx->nb_inputs; i++)
         if (ctx->inputs[i]->status_out == status)
123f6dc6
             r = FFMIN(r, av_rescale_q(ctx->inputs[i]->current_pts, ctx->inputs[i]->time_base, link_time_base));
f5a9c634
     if (r < INT64_MAX)
         return r;
     av_log(ctx, AV_LOG_WARNING, "EOF timestamp not reliable\n");
     for (i = 0; i < ctx->nb_inputs; i++)
123f6dc6
         r = FFMIN(r, av_rescale_q(ctx->inputs[i]->status_in_pts, ctx->inputs[i]->time_base, link_time_base));
f5a9c634
     if (r < INT64_MAX)
         return r;
     return AV_NOPTS_VALUE;
 }
 
c619a4e5
 static int ff_request_frame_to_filter(AVFilterLink *link)
16557887
 {
     int ret = -1;
 
     FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1);
02aa0701
     /* Assume the filter is blocked, let the method clear it if not */
     link->frame_blocked_in = 1;
87d55092
     if (link->srcpad->request_frame)
         ret = link->srcpad->request_frame(link);
     else if (link->src->inputs[0])
         ret = ff_request_frame(link->src->inputs[0]);
     if (ret < 0) {
02aa0701
         if (ret != AVERROR(EAGAIN) && ret != link->status_in)
123f6dc6
             ff_avfilter_link_set_in_status(link, ret, guess_status_pts(link->src, ret, link->time_base));
02aa0701
         if (ret == AVERROR_EOF)
             ret = 0;
87d55092
     }
0689d5e1
     return ret;
4dbbcdee
 }
 
803391f7
 int ff_poll_frame(AVFilterLink *link)
7b02c484
 {
ca857431
     int i, min = INT_MAX;
7b02c484
 
acc0490f
     if (link->srcpad->poll_frame)
         return link->srcpad->poll_frame(link);
c245ddf2
 
9baeff95
     for (i = 0; i < link->src->nb_inputs; i++) {
9dd08b4e
         int val;
ca857431
         if (!link->src->inputs[i])
88b160a4
             return AVERROR(EINVAL);
803391f7
         val = ff_poll_frame(link->src->inputs[i]);
9dd08b4e
         min = FFMIN(min, val);
c245ddf2
     }
7b02c484
 
     return min;
 }
 
abaf4245
 static const char *const var_names[] = {
     "t",
     "n",
     "pos",
     "w",
     "h",
     NULL
 };
 
 enum {
     VAR_T,
     VAR_N,
     VAR_POS,
     VAR_W,
     VAR_H,
     VAR_VARS_NB
 };
38853169
 
 static int set_enable_expr(AVFilterContext *ctx, const char *expr)
 {
     int ret;
     char *expr_dup;
     AVExpr *old = ctx->enable;
 
     if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) {
         av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported "
                "with filter '%s'\n", ctx->filter->name);
         return AVERROR_PATCHWELCOME;
     }
 
     expr_dup = av_strdup(expr);
     if (!expr_dup)
         return AVERROR(ENOMEM);
 
     if (!ctx->var_values) {
         ctx->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctx->var_values));
         if (!ctx->var_values) {
             av_free(expr_dup);
             return AVERROR(ENOMEM);
         }
     }
 
     ret = av_expr_parse((AVExpr**)&ctx->enable, expr_dup, var_names,
                         NULL, NULL, NULL, NULL, 0, ctx->priv);
     if (ret < 0) {
         av_log(ctx->priv, AV_LOG_ERROR,
                "Error when evaluating the expression '%s' for enable\n",
                expr_dup);
         av_free(expr_dup);
         return ret;
     }
 
     av_expr_free(old);
     av_free(ctx->enable_str);
     ctx->enable_str = expr_dup;
     return 0;
 }
 
01590329
 void ff_update_link_current_pts(AVFilterLink *link, int64_t pts)
2ce79727
 {
75d5624c
     if (pts == AV_NOPTS_VALUE)
2ce79727
         return;
b8b7d5ac
     link->current_pts = pts;
d03eab34
     link->current_pts_us = av_rescale_q(pts, link->time_base, AV_TIME_BASE_Q);
d06bfda0
     /* TODO use duration */
2ce79727
     if (link->graph && link->age_index >= 0)
         ff_avfilter_graph_update_heap(link->graph, link);
 }
 
1e5014c7
 int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags)
 {
     if(!strcmp(cmd, "ping")){
bb23bf8f
         char local_res[256] = {0};
 
         if (!res) {
             res = local_res;
             res_len = sizeof(local_res);
         }
1e5014c7
         av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name);
bb23bf8f
         if (res == local_res)
             av_log(filter, AV_LOG_INFO, "%s", res);
1e5014c7
         return 0;
38853169
     }else if(!strcmp(cmd, "enable")) {
         return set_enable_expr(filter, arg);
1e5014c7
     }else if(filter->filter->process_command) {
         return filter->filter->process_command(filter, cmd, arg, res, res_len, flags);
     }
     return AVERROR(ENOSYS);
 }
 
fa2a34cd
 static AVFilter *first_filter;
c0a33c47
 static AVFilter **last_filter = &first_filter;
3555d2e8
 
96a47364
 const AVFilter *avfilter_get_by_name(const char *name)
4dbbcdee
 {
d94c9070
     const AVFilter *f = NULL;
6d8c67a7
 
f160c6a1
     if (!name)
         return NULL;
 
fa2a34cd
     while ((f = avfilter_next(f)))
         if (!strcmp(f->name, name))
d94c9070
             return (AVFilter *)f;
4dbbcdee
 
     return NULL;
 }
 
86a60fa1
 int avfilter_register(AVFilter *filter)
4dbbcdee
 {
c0a33c47
     AVFilter **f = last_filter;
f6dd1455
 
1776177b
     /* the filter must select generic or internal exclusively */
     av_assert0((filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) != AVFILTER_FLAG_SUPPORT_TIMELINE);
 
fa2a34cd
     filter->next = NULL;
835cc0f2
 
133fbfc7
     while(*f || avpriv_atomic_ptr_cas((void * volatile *)f, NULL, filter))
22364567
         f = &(*f)->next;
c0a33c47
     last_filter = &filter->next;
22364567
 
86a60fa1
     return 0;
4dbbcdee
 }
 
fa2a34cd
 const AVFilter *avfilter_next(const AVFilter *prev)
 {
     return prev ? prev->next : first_filter;
 }
 
7e8fe4be
 int avfilter_pad_count(const AVFilterPad *pads)
4dbbcdee
 {
     int count;
 
1fce361d
     if (!pads)
         return 0;
 
bf5b5d2b
     for (count = 0; pads->name; count++)
         pads++;
4dbbcdee
     return count;
 }
 
ee1748ab
 static const char *default_filter_name(void *filter_ctx)
4dbbcdee
 {
4d6a8a2b
     AVFilterContext *ctx = filter_ctx;
     return ctx->name ? ctx->name : ctx->filter->name;
4dbbcdee
 }
 
5c0d8bc4
 static void *filter_child_next(void *obj, void *prev)
 {
     AVFilterContext *ctx = obj;
4d1f31ea
     if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv)
5c0d8bc4
         return ctx->priv;
     return NULL;
 }
 
 static const AVClass *filter_child_class_next(const AVClass *prev)
 {
e4723a82
     const AVFilter *f = NULL;
5c0d8bc4
 
     /* find the filter that corresponds to prev */
fa2a34cd
     while (prev && (f = avfilter_next(f)))
         if (f->priv_class == prev)
5c0d8bc4
             break;
 
     /* could not find filter corresponding to prev */
835cc0f2
     if (prev && !f)
5c0d8bc4
         return NULL;
 
     /* find next filter with specific options */
fa2a34cd
     while ((f = avfilter_next(f)))
         if (f->priv_class)
             return f->priv_class;
4d1f31ea
 
5c0d8bc4
     return NULL;
 }
 
fdd93eab
 #define OFFSET(x) offsetof(AVFilterContext, x)
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM
b5a13865
 static const AVOption avfilter_options[] = {
129bb238
     { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS,
         { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
         { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .unit = "thread_type" },
fdd93eab
     { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
44933908
     { "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT,
         { .i64 = 0 }, 0, INT_MAX, FLAGS },
129bb238
     { NULL },
fdd93eab
 };
 
b049ad50
 static const AVClass avfilter_class = {
908c045f
     .class_name = "AVFilter",
ad347bf4
     .item_name  = default_filter_name,
908c045f
     .version    = LIBAVUTIL_VERSION_INT,
54101214
     .category   = AV_CLASS_CATEGORY_FILTER,
5c0d8bc4
     .child_next = filter_child_next,
     .child_class_next = filter_child_class_next,
b5a13865
     .option           = avfilter_options,
b049ad50
 };
 
0767bfd1
 static int default_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg,
129bb238
                            int *ret, int nb_jobs)
 {
     int i;
 
     for (i = 0; i < nb_jobs; i++) {
         int r = func(ctx, arg, i, nb_jobs);
         if (ret)
             ret[i] = r;
     }
     return 0;
 }
 
bc1a985b
 AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name)
4dbbcdee
 {
8f618f4c
     AVFilterContext *ret;
f8d7b5fe
     int preinited = 0;
8f618f4c
 
     if (!filter)
bc1a985b
         return NULL;
8f618f4c
 
689a5f49
     ret = av_mallocz(sizeof(AVFilterContext));
0699dbb8
     if (!ret)
bc1a985b
         return NULL;
4dbbcdee
 
b049ad50
     ret->av_class = &avfilter_class;
4dbbcdee
     ret->filter   = filter;
2350e69c
     ret->name     = inst_name ? av_strdup(inst_name) : NULL;
0699dbb8
     if (filter->priv_size) {
f8af93ab
         ret->priv     = av_mallocz(filter->priv_size);
0699dbb8
         if (!ret->priv)
             goto err;
     }
f8d7b5fe
     if (filter->preinit) {
         if (filter->preinit(ret) < 0)
             goto err;
         preinited = 1;
     }
4dbbcdee
 
129bb238
     av_opt_set_defaults(ret);
b439c992
     if (filter->priv_class) {
         *(const AVClass**)ret->priv = filter->priv_class;
         av_opt_set_defaults(ret->priv);
     }
 
129bb238
     ret->internal = av_mallocz(sizeof(*ret->internal));
     if (!ret->internal)
         goto err;
     ret->internal->execute = default_execute;
 
7e8fe4be
     ret->nb_inputs = avfilter_pad_count(filter->inputs);
9baeff95
     if (ret->nb_inputs ) {
d9ddbaa9
         ret->input_pads   = av_malloc_array(ret->nb_inputs, sizeof(AVFilterPad));
0699dbb8
         if (!ret->input_pads)
             goto err;
9baeff95
         memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->nb_inputs);
d9ddbaa9
         ret->inputs       = av_mallocz_array(ret->nb_inputs, sizeof(AVFilterLink*));
0699dbb8
         if (!ret->inputs)
             goto err;
689a5f49
     }
c5ef7d7b
 
7e8fe4be
     ret->nb_outputs = avfilter_pad_count(filter->outputs);
9baeff95
     if (ret->nb_outputs) {
d9ddbaa9
         ret->output_pads  = av_malloc_array(ret->nb_outputs, sizeof(AVFilterPad));
0699dbb8
         if (!ret->output_pads)
             goto err;
9baeff95
         memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->nb_outputs);
d9ddbaa9
         ret->outputs      = av_mallocz_array(ret->nb_outputs, sizeof(AVFilterLink*));
0699dbb8
         if (!ret->outputs)
             goto err;
689a5f49
     }
7d0e1392
 
bc1a985b
     return ret;
0699dbb8
 
 err:
f8d7b5fe
     if (preinited)
         filter->uninit(ret);
0699dbb8
     av_freep(&ret->inputs);
     av_freep(&ret->input_pads);
9baeff95
     ret->nb_inputs = 0;
0699dbb8
     av_freep(&ret->outputs);
     av_freep(&ret->output_pads);
9baeff95
     ret->nb_outputs = 0;
0699dbb8
     av_freep(&ret->priv);
129bb238
     av_freep(&ret->internal);
0699dbb8
     av_free(ret);
bc1a985b
     return NULL;
4dbbcdee
 }
 
d79bd604
 static void free_link(AVFilterLink *link)
 {
     if (!link)
         return;
 
     if (link->src)
         link->src->outputs[link->srcpad - link->src->output_pads] = NULL;
     if (link->dst)
         link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
 
b3dd30db
     av_buffer_unref(&link->hw_frames_ctx);
 
d79bd604
     ff_formats_unref(&link->in_formats);
     ff_formats_unref(&link->out_formats);
     ff_formats_unref(&link->in_samplerates);
     ff_formats_unref(&link->out_samplerates);
     ff_channel_layouts_unref(&link->in_channel_layouts);
     ff_channel_layouts_unref(&link->out_channel_layouts);
fb8dde37
     avfilter_link_free(&link);
d79bd604
 }
 
24de0edb
 void avfilter_free(AVFilterContext *filter)
4dbbcdee
 {
     int i;
 
c5f9a66f
     if (!filter)
         return;
 
1565cbc6
     if (filter->graph)
         ff_filter_graph_remove_filter(filter->graph, filter);
 
ca857431
     if (filter->filter->uninit)
4dbbcdee
         filter->filter->uninit(filter);
 
9baeff95
     for (i = 0; i < filter->nb_inputs; i++) {
d79bd604
         free_link(filter->inputs[i]);
4dbbcdee
     }
9baeff95
     for (i = 0; i < filter->nb_outputs; i++) {
d79bd604
         free_link(filter->outputs[i]);
4dbbcdee
     }
 
dcea5850
     if (filter->filter->priv_class)
b439c992
         av_opt_free(filter->priv);
 
07a844f3
     av_buffer_unref(&filter->hw_device_ctx);
 
f4cb4462
     av_freep(&filter->name);
     av_freep(&filter->input_pads);
     av_freep(&filter->output_pads);
     av_freep(&filter->inputs);
     av_freep(&filter->outputs);
     av_freep(&filter->priv);
3d8176d2
     while(filter->command_queue){
1cbf7fb4
         ff_command_queue_pop(filter);
3d8176d2
     }
fdd93eab
     av_opt_free(filter);
     av_expr_free(filter->enable);
     filter->enable = NULL;
     av_freep(&filter->var_values);
129bb238
     av_freep(&filter->internal);
4dbbcdee
     av_free(filter);
 }
 
5b190714
 int ff_filter_get_nb_threads(AVFilterContext *ctx)
 {
      if (ctx->nb_threads > 0)
          return FFMIN(ctx->nb_threads, ctx->graph->nb_threads);
      return ctx->graph->nb_threads;
 }
 
b89ce54e
 static int process_options(AVFilterContext *ctx, AVDictionary **options,
                            const char *args)
b439c992
 {
     const AVOption *o = NULL;
b89ce54e
     int ret, count = 0;
     char *av_uninit(parsed_key), *av_uninit(value);
     const char *key;
90efdf98
     int offset= -1;
b439c992
 
b89ce54e
     if (!args)
         return 0;
 
     while (*args) {
         const char *shorthand = NULL;
 
b439c992
         o = av_opt_next(ctx->priv, o);
b89ce54e
         if (o) {
             if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
                 continue;
             offset = o->offset;
             shorthand = o->name;
b439c992
         }
 
b89ce54e
         ret = av_opt_get_key_value(&args, "=", ":",
                                    shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
                                    &parsed_key, &value);
         if (ret < 0) {
             if (ret == AVERROR(EINVAL))
                 av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", args);
             else
                 av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args,
                        av_err2str(ret));
             return ret;
         }
         if (*args)
             args++;
         if (parsed_key) {
             key = parsed_key;
             while ((o = av_opt_next(ctx->priv, o))); /* discard all remaining shorthand */
         } else {
             key = shorthand;
         }
b439c992
 
b89ce54e
         av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
fdd93eab
 
         if (av_opt_find(ctx, key, NULL, 0, 0)) {
             ret = av_opt_set(ctx, key, value, 0);
3ed56b3b
             if (ret < 0) {
                 av_free(value);
                 av_free(parsed_key);
fdd93eab
                 return ret;
3ed56b3b
             }
fdd93eab
         } else {
b89ce54e
         av_dict_set(options, key, value, 0);
dfa3aaa2
         if ((ret = av_opt_set(ctx->priv, key, value, AV_OPT_SEARCH_CHILDREN)) < 0) {
f6bfeef7
             if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) {
b89ce54e
             if (ret == AVERROR_OPTION_NOT_FOUND)
                 av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
             av_free(value);
             av_free(parsed_key);
             return ret;
f6bfeef7
             }
b89ce54e
         }
fdd93eab
         }
b439c992
 
b89ce54e
         av_free(value);
         av_free(parsed_key);
         count++;
b439c992
     }
fdd93eab
 
     if (ctx->enable_str) {
38853169
         ret = set_enable_expr(ctx, ctx->enable_str);
fdd93eab
         if (ret < 0)
             return ret;
     }
b89ce54e
     return count;
b439c992
 }
 
1ba95a9c
 int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options)
 {
     int ret = 0;
 
129bb238
     ret = av_opt_set_dict(ctx, options);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n");
         return ret;
     }
 
     if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS &&
         ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE &&
         ctx->graph->internal->thread_execute) {
         ctx->thread_type       = AVFILTER_THREAD_SLICE;
         ctx->internal->execute = ctx->graph->internal->thread_execute;
     } else {
         ctx->thread_type = 0;
     }
 
1ba95a9c
     if (ctx->filter->priv_class) {
dfa3aaa2
         ret = av_opt_set_dict2(ctx->priv, options, AV_OPT_SEARCH_CHILDREN);
1ba95a9c
         if (ret < 0) {
             av_log(ctx, AV_LOG_ERROR, "Error applying options to the filter.\n");
             return ret;
         }
     }
 
46de9ba5
     if (ctx->filter->init_opaque)
         ret = ctx->filter->init_opaque(ctx, NULL);
     else if (ctx->filter->init)
1ba95a9c
         ret = ctx->filter->init(ctx);
     else if (ctx->filter->init_dict)
         ret = ctx->filter->init_dict(ctx, options);
 
     return ret;
 }
 
48a5adab
 int avfilter_init_str(AVFilterContext *filter, const char *args)
4dbbcdee
 {
b439c992
     AVDictionary *options = NULL;
     AVDictionaryEntry *e;
bf5b5d2b
     int ret = 0;
4dbbcdee
 
04924bc9
     if (args && *args) {
62549f96
         if (!filter->filter->priv_class) {
             av_log(filter, AV_LOG_ERROR, "This filter does not take any "
                    "options, but options were provided: %s.\n", args);
             return AVERROR(EINVAL);
         }
 
0ed61546
 #if FF_API_OLD_FILTER_OPTS_ERROR
f1e62af0
             if (   !strcmp(filter->filter->name, "format")     ||
5aa1a668
                    !strcmp(filter->filter->name, "noformat")   ||
                    !strcmp(filter->filter->name, "frei0r")     ||
ee0e8d4b
                    !strcmp(filter->filter->name, "frei0r_src") ||
ad9e66a5
                    !strcmp(filter->filter->name, "ocv")        ||
3c821e75
                    !strcmp(filter->filter->name, "pan")        ||
64ce15b9
                    !strcmp(filter->filter->name, "pp")         ||
                    !strcmp(filter->filter->name, "aevalsrc")) {
e67a87ea
             /* a hack for compatibility with the old syntax
              * replace colons with |s */
             char *copy = av_strdup(args);
             char *p    = copy;
5aa1a668
             int nb_leading = 0; // number of leading colons to skip
23a750c9
             int deprecated = 0;
e67a87ea
 
             if (!copy) {
                 ret = AVERROR(ENOMEM);
                 goto fail;
             }
 
ee0e8d4b
             if (!strcmp(filter->filter->name, "frei0r") ||
                 !strcmp(filter->filter->name, "ocv"))
5aa1a668
                 nb_leading = 1;
             else if (!strcmp(filter->filter->name, "frei0r_src"))
                 nb_leading = 3;
 
             while (nb_leading--) {
                 p = strchr(p, ':');
                 if (!p) {
                     p = copy + strlen(copy);
                     break;
                 }
                 p++;
             }
 
23a750c9
             deprecated = strchr(p, ':') != NULL;
e67a87ea
 
64ce15b9
             if (!strcmp(filter->filter->name, "aevalsrc")) {
23a750c9
                 deprecated = 0;
64ce15b9
                 while ((p = strchr(p, ':')) && p[1] != ':') {
                     const char *epos = strchr(p + 1, '=');
                     const char *spos = strchr(p + 1, ':');
                     const int next_token_is_opt = epos && (!spos || epos < spos);
                     if (next_token_is_opt) {
                         p++;
                         break;
                     }
23a750c9
                     /* next token does not contain a '=', assume a channel expression */
                     deprecated = 1;
64ce15b9
                     *p++ = '|';
                 }
23a750c9
                 if (p && *p == ':') { // double sep '::' found
                     deprecated = 1;
64ce15b9
                     memmove(p, p + 1, strlen(p));
23a750c9
                 }
64ce15b9
             } else
e67a87ea
             while ((p = strchr(p, ':')))
                 *p++ = '|';
 
ad7d972e
             if (deprecated) {
                 av_log(filter, AV_LOG_ERROR, "This syntax is deprecated. Use "
                        "'|' to separate the list items ('%s' instead of '%s')\n",
                        copy, args);
                 ret = AVERROR(EINVAL);
             } else {
                 ret = process_options(filter, &options, copy);
             }
e67a87ea
             av_freep(&copy);
 
             if (ret < 0)
                 goto fail;
6495c4c6
         } else
e67a87ea
 #endif
6495c4c6
         {
b89ce54e
             ret = process_options(filter, &options, args);
b439c992
             if (ret < 0)
                 goto fail;
         }
     }
 
1ba95a9c
     ret = avfilter_init_dict(filter, &options);
4fa1f52e
     if (ret < 0)
         goto fail;
b439c992
 
     if ((e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
         av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key);
         ret = AVERROR_OPTION_NOT_FOUND;
         goto fail;
     }
 
 fail:
     av_dict_free(&options);
 
e079d22e
     return ret;
4dbbcdee
 }
88c3b87b
 
4a37d4b3
 const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx)
84b9fbe0
 {
     return pads[pad_idx].name;
 }
 
4a37d4b3
 enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx)
84b9fbe0
 {
     return pads[pad_idx].type;
4dbbcdee
 }
3ed483cd
 
7e350379
 static int default_filter_frame(AVFilterLink *link, AVFrame *frame)
82541d83
 {
     return ff_filter_frame(link->dst->outputs[0], frame);
 }
 
a05a44e2
 static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
82541d83
 {
7e350379
     int (*filter_frame)(AVFilterLink *, AVFrame *);
fdd93eab
     AVFilterContext *dstctx = link->dst;
82541d83
     AVFilterPad *dst = link->dstpad;
a05a44e2
     int ret;
82541d83
 
     if (!(filter_frame = dst->filter_frame))
         filter_frame = default_filter_frame;
 
28c62df6
     if (dst->needs_writable) {
         ret = ff_inlink_make_frame_writable(link, &frame);
abb5e37f
         if (ret < 0)
             goto fail;
28c62df6
     }
82541d83
 
0e3d2496
     ff_inlink_process_commands(link, frame);
e7e4c8df
     dstctx->is_disabled = !ff_inlink_evaluate_timeline_at_frame(link, frame);
82541d83
 
aaae459a
     if (dstctx->is_disabled &&
         (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC))
         filter_frame = default_filter_frame;
846f1421
     ret = filter_frame(link, frame);
183ce55b
     link->frame_count_out++;
82541d83
     return ret;
abb5e37f
 
 fail:
     av_frame_free(&frame);
     return ret;
82541d83
 }
 
a05a44e2
 int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
3ed483cd
 {
02aa0701
     int ret;
3ed483cd
     FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
 
82541d83
     /* Consistency checks */
     if (link->type == AVMEDIA_TYPE_VIDEO) {
5d859e59
         if (strcmp(link->dst->filter->name, "buffersink") &&
             strcmp(link->dst->filter->name, "format") &&
             strcmp(link->dst->filter->name, "idet") &&
             strcmp(link->dst->filter->name, "null") &&
             strcmp(link->dst->filter->name, "scale")) {
82541d83
             av_assert1(frame->format                 == link->format);
a05a44e2
             av_assert1(frame->width               == link->w);
             av_assert1(frame->height               == link->h);
82541d83
         }
     } else {
377883c4
         if (frame->format != link->format) {
             av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n");
             goto error;
         }
6af050d7
         if (frame->channels != link->channels) {
377883c4
             av_log(link->dst, AV_LOG_ERROR, "Channel count change is not supported\n");
             goto error;
         }
         if (frame->channel_layout != link->channel_layout) {
             av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n");
             goto error;
         }
         if (frame->sample_rate != link->sample_rate) {
             av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n");
             goto error;
         }
82541d83
     }
 
02aa0701
     link->frame_blocked_in = link->frame_wanted_out = 0;
183ce55b
     link->frame_count_in++;
02aa0701
     filter_unblock(link->dst);
     ret = ff_framequeue_add(&link->fifo, frame);
     if (ret < 0) {
         av_frame_free(&frame);
         return ret;
3ed483cd
     }
02aa0701
     ff_filter_set_ready(link->dst, 300);
     return 0;
 
377883c4
 error:
     av_frame_free(&frame);
     return AVERROR_PATCHWELCOME;
3ed483cd
 }
8114c101
 
2e5af443
 static int samples_ready(AVFilterLink *link, unsigned min)
02aa0701
 {
     return ff_framequeue_queued_frames(&link->fifo) &&
2e5af443
            (ff_framequeue_queued_samples(&link->fifo) >= min ||
02aa0701
             link->status_in);
 }
 
 static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
                         AVFrame **rframe)
 {
     AVFrame *frame0, *frame, *buf;
     unsigned nb_samples, nb_frames, i, p;
     int ret;
 
     /* Note: this function relies on no format changes and must only be
        called with enough samples. */
2e5af443
     av_assert1(samples_ready(link, link->min_samples));
02aa0701
     frame0 = frame = ff_framequeue_peek(&link->fifo, 0);
fc3a03fc
     if (!link->fifo.samples_skipped && frame->nb_samples >= min && frame->nb_samples <= max) {
02aa0701
         *rframe = ff_framequeue_take(&link->fifo);
         return 0;
     }
     nb_frames = 0;
     nb_samples = 0;
     while (1) {
         if (nb_samples + frame->nb_samples > max) {
             if (nb_samples < min)
                 nb_samples = max;
             break;
         }
         nb_samples += frame->nb_samples;
         nb_frames++;
         if (nb_frames == ff_framequeue_queued_frames(&link->fifo))
             break;
         frame = ff_framequeue_peek(&link->fifo, nb_frames);
     }
 
     buf = ff_get_audio_buffer(link, nb_samples);
     if (!buf)
         return AVERROR(ENOMEM);
     ret = av_frame_copy_props(buf, frame0);
     if (ret < 0) {
         av_frame_free(&buf);
         return ret;
     }
     buf->pts = frame0->pts;
 
     p = 0;
     for (i = 0; i < nb_frames; i++) {
         frame = ff_framequeue_take(&link->fifo);
         av_samples_copy(buf->extended_data, frame->extended_data, p, 0,
                         frame->nb_samples, link->channels, link->format);
         p += frame->nb_samples;
ff8b17c9
         av_frame_free(&frame);
02aa0701
     }
     if (p < nb_samples) {
         unsigned n = nb_samples - p;
         frame = ff_framequeue_peek(&link->fifo, 0);
         av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
                         link->channels, link->format);
383057f8
         ff_framequeue_skip_samples(&link->fifo, n, link->time_base);
02aa0701
     }
 
     *rframe = buf;
     return 0;
 }
 
c619a4e5
 static int ff_filter_frame_to_filter(AVFilterLink *link)
02aa0701
 {
db4a71c0
     AVFrame *frame = NULL;
02aa0701
     AVFilterContext *dst = link->dst;
     int ret;
 
     av_assert1(ff_framequeue_queued_frames(&link->fifo));
db4a71c0
     ret = link->min_samples ?
           ff_inlink_consume_samples(link, link->min_samples, link->max_samples, &frame) :
           ff_inlink_consume_frame(link, &frame);
     av_assert1(ret);
     if (ret < 0) {
         av_assert1(!frame);
         return ret;
02aa0701
     }
     /* The filter will soon have received a new frame, that may allow it to
        produce one or more: unblock its outputs. */
     filter_unblock(dst);
db4a71c0
     /* AVFilterPad.filter_frame() expect frame_count_out to have the value
        before the frame; ff_filter_frame_framed() will re-increment it. */
     link->frame_count_out--;
02aa0701
     ret = ff_filter_frame_framed(link, frame);
     if (ret < 0 && ret != link->status_out) {
         ff_avfilter_link_set_out_status(link, ret, AV_NOPTS_VALUE);
     } else {
         /* Run once again, to see if several frames were available, or if
            the input status has also changed, or any other reason. */
         ff_filter_set_ready(dst, 300);
     }
     return ret;
 }
 
 static int forward_status_change(AVFilterContext *filter, AVFilterLink *in)
 {
     unsigned out = 0, progress = 0;
     int ret;
 
     av_assert0(!in->status_out);
     if (!filter->nb_outputs) {
         /* not necessary with the current API and sinks */
         return 0;
     }
     while (!in->status_out) {
         if (!filter->outputs[out]->status_in) {
             progress++;
             ret = ff_request_frame_to_filter(filter->outputs[out]);
             if (ret < 0)
                 return ret;
         }
         if (++out == filter->nb_outputs) {
             if (!progress) {
                 /* Every output already closed: input no longer interesting
                    (example: overlay in shortest mode, other input closed). */
                 ff_avfilter_link_set_out_status(in, in->status_in, in->status_in_pts);
                 return 0;
             }
             progress = 0;
             out = 0;
         }
     }
     ff_filter_set_ready(filter, 200);
     return 0;
 }
 
 static int ff_filter_activate_default(AVFilterContext *filter)
 {
     unsigned i;
 
     for (i = 0; i < filter->nb_inputs; i++) {
2e5af443
         if (samples_ready(filter->inputs[i], filter->inputs[i]->min_samples)) {
02aa0701
             return ff_filter_frame_to_filter(filter->inputs[i]);
         }
     }
     for (i = 0; i < filter->nb_inputs; i++) {
         if (filter->inputs[i]->status_in && !filter->inputs[i]->status_out) {
             av_assert1(!ff_framequeue_queued_frames(&filter->inputs[i]->fifo));
             return forward_status_change(filter, filter->inputs[i]);
         }
     }
     for (i = 0; i < filter->nb_outputs; i++) {
         if (filter->outputs[i]->frame_wanted_out &&
             !filter->outputs[i]->frame_blocked_in) {
             return ff_request_frame_to_filter(filter->outputs[i]);
         }
     }
     return FFERROR_NOT_READY;
 }
 
 /*
    Filter scheduling and activation
 
    When a filter is activated, it must:
    - if possible, output a frame;
    - else, if relevant, forward the input status change;
    - else, check outputs for wanted frames and forward the requests.
 
    The following AVFilterLink fields are used for activation:
 
    - frame_wanted_out:
 
      This field indicates if a frame is needed on this input of the
      destination filter. A positive value indicates that a frame is needed
      to process queued frames or internal data or to satisfy the
      application; a zero value indicates that a frame is not especially
      needed but could be processed anyway; a negative value indicates that a
      frame would just be queued.
 
      It is set by filters using ff_request_frame() or ff_request_no_frame(),
      when requested by the application through a specific API or when it is
      set on one of the outputs.
 
      It is cleared when a frame is sent from the source using
      ff_filter_frame().
 
      It is also cleared when a status change is sent from the source using
      ff_avfilter_link_set_in_status().
 
    - frame_blocked_in:
 
      This field means that the source filter can not generate a frame as is.
      Its goal is to avoid repeatedly calling the request_frame() method on
      the same link.
 
      It is set by the framework on all outputs of a filter before activating it.
 
      It is automatically cleared by ff_filter_frame().
 
      It is also automatically cleared by ff_avfilter_link_set_in_status().
 
      It is also cleared on all outputs (using filter_unblock()) when
      something happens on an input: processing a frame or changing the
      status.
 
    - fifo:
 
      Contains the frames queued on a filter input. If it contains frames and
      frame_wanted_out is not set, then the filter can be activated. If that
      result in the filter not able to use these frames, the filter must set
      frame_wanted_out to ask for more frames.
 
    - status_in and status_in_pts:
 
      Status (EOF or error code) of the link and timestamp of the status
      change (in link time base, same as frames) as seen from the input of
      the link. The status change is considered happening after the frames
      queued in fifo.
 
      It is set by the source filter using ff_avfilter_link_set_in_status().
 
    - status_out:
 
      Status of the link as seen from the output of the link. The status
      change is considered having already happened.
 
      It is set by the destination filter using
      ff_avfilter_link_set_out_status().
 
    Filters are activated according to the ready field, set using the
    ff_filter_set_ready(). Eventually, a priority queue will be used.
    ff_filter_set_ready() is called whenever anything could cause progress to
    be possible. Marking a filter ready when it is not is not a problem,
    except for the small overhead it causes.
 
    Conditions that cause a filter to be marked ready are:
 
    - frames added on an input link;
 
    - changes in the input or output status of an input link;
 
    - requests for a frame on an output link;
 
    - after any actual processing using the legacy methods (filter_frame(),
      and request_frame() to acknowledge status changes), to run once more
      and check if enough input was present for several frames.
 
    Exemples of scenarios to consider:
 
    - buffersrc: activate if frame_wanted_out to notify the application;
      activate when the application adds a frame to push it immediately.
 
    - testsrc: activate only if frame_wanted_out to produce and push a frame.
 
    - concat (not at stitch points): can process a frame on any output.
      Activate if frame_wanted_out on output to forward on the corresponding
      input. Activate when a frame is present on input to process it
      immediately.
 
    - framesync: needs at least one frame on each input; extra frames on the
      wrong input will accumulate. When a frame is first added on one input,
      set frame_wanted_out<0 on it to avoid getting more (would trigger
      testsrc) and frame_wanted_out>0 on the other to allow processing it.
 
    Activation of old filters:
 
    In order to activate a filter implementing the legacy filter_frame() and
    request_frame() methods, perform the first possible of the following
    actions:
 
    - If an input has frames in fifo and frame_wanted_out == 0, dequeue a
      frame and call filter_frame().
 
      Ratinale: filter frames as soon as possible instead of leaving them
      queued; frame_wanted_out < 0 is not possible since the old API does not
      set it nor provides any similar feedback; frame_wanted_out > 0 happens
      when min_samples > 0 and there are not enough samples queued.
 
    - If an input has status_in set but not status_out, try to call
      request_frame() on one of the outputs in the hope that it will trigger
      request_frame() on the input with status_in and acknowledge it. This is
      awkward and fragile, filters with several inputs or outputs should be
      updated to direct activation as soon as possible.
 
    - If an output has frame_wanted_out > 0 and not frame_blocked_in, call
      request_frame().
 
      Rationale: checking frame_blocked_in is necessary to avoid requesting
      repeatedly on a blocked input if another is not blocked (example:
      [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2).
 
      TODO: respect needs_fifo and remove auto-inserted fifos.
 
  */
 
 int ff_filter_activate(AVFilterContext *filter)
 {
     int ret;
 
3ff01fed
     /* Generic timeline support is not yet implemented but should be easy */
     av_assert1(!(filter->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC &&
                  filter->filter->activate));
02aa0701
     filter->ready = 0;
3ff01fed
     ret = filter->filter->activate ? filter->filter->activate(filter) :
           ff_filter_activate_default(filter);
02aa0701
     if (ret == FFERROR_NOT_READY)
         ret = 0;
     return ret;
 }
 
4c24f3ac
 int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
 {
     *rpts = link->current_pts;
     if (ff_framequeue_queued_frames(&link->fifo))
         return *rstatus = 0;
     if (link->status_out)
         return *rstatus = link->status_out;
     if (!link->status_in)
         return *rstatus = 0;
     *rstatus = link->status_out = link->status_in;
     ff_update_link_current_pts(link, link->status_in_pts);
     *rpts = link->current_pts;
     return 1;
 }
 
d360ddf0
 int ff_inlink_check_available_frame(AVFilterLink *link)
 {
     return ff_framequeue_queued_frames(&link->fifo) > 0;
 }
 
 int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min)
 {
     uint64_t samples = ff_framequeue_queued_samples(&link->fifo);
     av_assert1(min);
     return samples >= min || (link->status_in && samples);
 }
 
 static void consume_update(AVFilterLink *link, const AVFrame *frame)
 {
d3cb1404
     ff_update_link_current_pts(link, frame->pts);
d360ddf0
     ff_inlink_process_commands(link, frame);
     link->dst->is_disabled = !ff_inlink_evaluate_timeline_at_frame(link, frame);
     link->frame_count_out++;
 }
 
 int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
 {
     AVFrame *frame;
 
     *rframe = NULL;
     if (!ff_inlink_check_available_frame(link))
         return 0;
fc3a03fc
 
     if (link->fifo.samples_skipped) {
         frame = ff_framequeue_peek(&link->fifo, 0);
         return ff_inlink_consume_samples(link, frame->nb_samples, frame->nb_samples, rframe);
     }
 
d360ddf0
     frame = ff_framequeue_take(&link->fifo);
     consume_update(link, frame);
     *rframe = frame;
     return 1;
 }
 
 int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max,
                             AVFrame **rframe)
 {
     AVFrame *frame;
     int ret;
 
     av_assert1(min);
     *rframe = NULL;
     if (!ff_inlink_check_available_samples(link, min))
         return 0;
     if (link->status_in)
         min = FFMIN(min, ff_framequeue_queued_samples(&link->fifo));
e6055af0
     ret = take_samples(link, min, max, &frame);
d360ddf0
     if (ret < 0)
         return ret;
     consume_update(link, frame);
     *rframe = frame;
     return 1;
 }
 
28c62df6
 int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe)
 {
     AVFrame *frame = *rframe;
     AVFrame *out;
     int ret;
 
     if (av_frame_is_writable(frame))
         return 0;
     av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n");
 
     switch (link->type) {
     case AVMEDIA_TYPE_VIDEO:
         out = ff_get_video_buffer(link, link->w, link->h);
         break;
     case AVMEDIA_TYPE_AUDIO:
         out = ff_get_audio_buffer(link, frame->nb_samples);
         break;
     default:
         return AVERROR(EINVAL);
     }
     if (!out)
         return AVERROR(ENOMEM);
 
     ret = av_frame_copy_props(out, frame);
     if (ret < 0) {
         av_frame_free(&out);
         return ret;
     }
 
     switch (link->type) {
     case AVMEDIA_TYPE_VIDEO:
         av_image_copy(out->data, out->linesize, (const uint8_t **)frame->data, frame->linesize,
                       frame->format, frame->width, frame->height);
         break;
     case AVMEDIA_TYPE_AUDIO:
         av_samples_copy(out->extended_data, frame->extended_data,
                         0, 0, frame->nb_samples,
6af050d7
                         frame->channels,
28c62df6
                         frame->format);
         break;
     default:
         av_assert0(!"reached");
     }
 
     av_frame_free(&frame);
     *rframe = out;
     return 0;
 }
 
0e3d2496
 int ff_inlink_process_commands(AVFilterLink *link, const AVFrame *frame)
 {
     AVFilterCommand *cmd = link->dst->command_queue;
 
     while(cmd && cmd->time <= frame->pts * av_q2d(link->time_base)){
         av_log(link->dst, AV_LOG_DEBUG,
                "Processing command time:%f command:%s arg:%s\n",
                cmd->time, cmd->command, cmd->arg);
         avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags);
         ff_command_queue_pop(link->dst);
         cmd= link->dst->command_queue;
     }
     return 0;
 }
 
e7e4c8df
 int ff_inlink_evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *frame)
 {
     AVFilterContext *dstctx = link->dst;
     int64_t pts = frame->pts;
6af050d7
     int64_t pos = frame->pkt_pos;
e7e4c8df
 
     if (!dstctx->enable_str)
         return 1;
 
     dstctx->var_values[VAR_N] = link->frame_count_out;
     dstctx->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base);
     dstctx->var_values[VAR_W] = link->w;
     dstctx->var_values[VAR_H] = link->h;
     dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos;
 
     return fabs(av_expr_eval(dstctx->enable, dstctx->var_values, NULL)) >= 0.5;
 }
 
9eb4c79a
 void ff_inlink_request_frame(AVFilterLink *link)
 {
     av_assert1(!link->status_in);
     av_assert1(!link->status_out);
     link->frame_wanted_out = 1;
     ff_filter_set_ready(link->src, 100);
 }
 
76613618
 void ff_inlink_set_status(AVFilterLink *link, int status)
 {
     if (link->status_out)
         return;
     link->frame_wanted_out = 0;
     link->frame_blocked_in = 0;
     ff_avfilter_link_set_out_status(link, status, AV_NOPTS_VALUE);
     while (ff_framequeue_queued_frames(&link->fifo)) {
            AVFrame *frame = ff_framequeue_take(&link->fifo);
            av_frame_free(&frame);
     }
     if (!link->status_in)
         link->status_in = status;
 }
 
 int ff_outlink_get_status(AVFilterLink *link)
 {
     return link->status_in;
 }
 
8114c101
 const AVClass *avfilter_get_class(void)
 {
     return &avfilter_class;
 }