func: static int end_frame(AVFilterLink *inlink)
  
  {
  
      AVFilterContext    *ctx = inlink->dst;
  
      FPSContext           *s = ctx->priv;
  
      AVFilterLink   *outlink = ctx->outputs[0];
  
      AVFilterBufferRef  *buf = inlink->cur_buf;
  
      int64_t delta;
  
      int i, ret;
  
  
  
      inlink->cur_buf = NULL;
  
      s->frames_in++;
  
      /* discard frames until we get the first timestamp */
  
      if (s->pts == AV_NOPTS_VALUE) {
  
          if (buf->pts != AV_NOPTS_VALUE) {
  
              write_to_fifo(s->fifo, buf);
  
              s->first_pts = s->pts = buf->pts;
  
          } else {
  
              av_log(ctx, AV_LOG_WARNING, "Discarding initial frame(s) with no "
  
                     "timestamp.\n");
  
              avfilter_unref_buffer(buf);
  
              s->drop++;
  
          }
  
          return 0;
  
      }
  
  
  
      /* now wait for the next timestamp */
  
      if (buf->pts == AV_NOPTS_VALUE) {
  
          return write_to_fifo(s->fifo, buf);
  
      }
  
  
  
      /* number of output frames */
  
      delta = av_rescale_q(buf->pts - s->pts, inlink->time_base,
  
                           outlink->time_base);
  
  
  
      if (delta < 1) {
  
          /* drop the frame and everything buffered except the first */
  
          AVFilterBufferRef *tmp;
  
          int drop = av_fifo_size(s->fifo)/sizeof(AVFilterBufferRef*);
  
  
  
          av_log(ctx, AV_LOG_DEBUG, "Dropping %d frame(s).\n", drop);
  
          s->drop += drop;
  
  
  
          av_fifo_generic_read(s->fifo, &tmp, sizeof(tmp), NULL);
  
          flush_fifo(s->fifo);
  
          ret = write_to_fifo(s->fifo, tmp);
  
  
  
          avfilter_unref_buffer(buf);
  
          return ret;
  
      }
  
  
  
      /* can output >= 1 frames */
  
      for (i = 0; i < delta; i++) {
  
          AVFilterBufferRef *buf_out;
  
          av_fifo_generic_read(s->fifo, &buf_out, sizeof(buf_out), NULL);
  
  
  
          /* duplicate the frame if needed */
  
          if (!av_fifo_size(s->fifo) && i < delta - 1) {
  
              av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n");
  
              write_to_fifo(s->fifo, avfilter_ref_buffer(buf_out, AV_PERM_READ));
  
              s->dup++;
  
          }
  
  
  
          buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
  
                                      outlink->time_base) + s->frames_out;
  
  
  
          if ((ret = ff_start_frame(outlink, buf_out)) < 0 ||
  
              (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
  
              (ret = ff_end_frame(outlink)) < 0) {
  
              avfilter_unref_bufferp(&buf);
  
              return ret;
  
          }
  
  
  
          s->frames_out++;
  
      }
  
      flush_fifo(s->fifo);
  
  
  
      ret = write_to_fifo(s->fifo, buf);
  
      s->pts = s->first_pts + av_rescale_q(s->frames_out, outlink->time_base, inlink->time_base);
  
  
  
      return ret;
  
  }
  