[FFmpeg-soc] [soc]: r1866 - in libavfilter: avfilter.c avfilter.h avfiltergraph.c diffs/04_ffmpeg_filters.diff vf_fps.c

vitor subversion at mplayerhq.hu
Wed Feb 6 20:55:37 CET 2008


Author: vitor
Date: Wed Feb  6 20:55:36 2008
New Revision: 1866

Log:
Implement poll_frame() method. Fix ffmpeg.c bug with 
vf_fps filter.


Modified:
   libavfilter/avfilter.c
   libavfilter/avfilter.h
   libavfilter/avfiltergraph.c
   libavfilter/diffs/04_ffmpeg_filters.diff
   libavfilter/vf_fps.c

Modified: libavfilter/avfilter.c
==============================================================================
--- libavfilter/avfilter.c	(original)
+++ libavfilter/avfilter.c	Wed Feb  6 20:55:36 2008
@@ -185,6 +185,22 @@ int avfilter_request_frame(AVFilterLink 
     else return -1;
 }
 
+int avfilter_poll_frame(AVFilterLink *link)
+{
+    int i, min=INT_MAX;
+
+    if(link_spad(link).poll_frame)
+        return link_spad(link).poll_frame(link);
+    else
+        for (i=0; i<link->src->input_count; i++) {
+            if(!link->src->inputs[i])
+                return -1;
+            min = FFMIN(min, avfilter_poll_frame(link->src->inputs[i]));
+        }
+
+    return min;
+}
+
 /* XXX: should we do the duplicating of the picture ref here, instead of
  * forcing the source filter to do it? */
 void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref)

Modified: libavfilter/avfilter.h
==============================================================================
--- libavfilter/avfilter.h	(original)
+++ libavfilter/avfilter.h	Wed Feb  6 20:55:36 2008
@@ -186,6 +186,8 @@ void avfilter_formats_ref(AVFilterFormat
  */
 void avfilter_formats_unref(AVFilterFormats **ref);
 
+int avfilter_poll_frame(AVFilterLink *link);
+
 /**
  * A filter pad used for either input or output
  */
@@ -259,6 +261,17 @@ struct AVFilterPad
     void (*draw_slice)(AVFilterLink *link, int y, int height);
 
     /**
+     * Frame poll callback.  This returns the number of immediately available
+     * frames. It should return a positive value if the next request_frame()
+     * is guaranteed to return one frame (with no delay).
+     *
+     * Defaults to just calling the source poll_frame() method.
+     *
+     * Output video pads only.
+     */
+    int (*poll_frame)(AVFilterLink *link);
+
+    /**
      * Frame request callback.  A call to this should result in at least one
      * frame being output over the given link.  This should return zero on
      * success, and another value on error.

Modified: libavfilter/avfiltergraph.c
==============================================================================
--- libavfilter/avfiltergraph.c	(original)
+++ libavfilter/avfiltergraph.c	Wed Feb  6 20:55:36 2008
@@ -69,6 +69,15 @@ static int link_in_request_frame(AVFilte
     return avfilter_request_frame(link2);
 }
 
+
+static int link_in_poll_frame(AVFilterLink *link)
+{
+    AVFilterLink *link2 = get_extern_input_link(link);
+    if(!link2)
+        return -1;
+    return avfilter_poll_frame(link2);
+}
+
 static int link_in_config_props(AVFilterLink *link)
 {
     AVFilterLink *link2 = get_extern_input_link(link);
@@ -236,6 +245,16 @@ static int graph_out_request_frame(AVFil
     return -1;
 }
 
+static int graph_out_poll_frame(AVFilterLink *link)
+{
+    AVFilterLink *link2 = get_intern_output_link(link);
+
+    if(!link2)
+        return -1;
+
+    return avfilter_poll_frame(link2);
+}
+
 static int graph_out_config_props(AVFilterLink *link)
 {
     GraphContext *graph = link->src->priv;
@@ -276,6 +295,7 @@ static int add_graph_input(AVFilterConte
         .name          = NULL,          /* FIXME? */
         .type          = AV_PAD_VIDEO,
         .request_frame = link_in_request_frame,
+        .poll_frame    = link_in_poll_frame,
         .config_props  = link_in_config_props,
     };
 
@@ -296,6 +316,7 @@ static int add_graph_output(AVFilterCont
         .name             = name,
         .type             = AV_PAD_VIDEO,
         .request_frame    = graph_out_request_frame,
+        .poll_frame       = graph_out_poll_frame,
         .config_props     = graph_out_config_props,
     };
     AVFilterPad dummy_inpad =

Modified: libavfilter/diffs/04_ffmpeg_filters.diff
==============================================================================
--- libavfilter/diffs/04_ffmpeg_filters.diff	(original)
+++ libavfilter/diffs/04_ffmpeg_filters.diff	Wed Feb  6 20:55:36 2008
@@ -24,7 +24,7 @@ Index: ffmpeg.c
  
  static int intra_only = 0;
  static int audio_sample_rate = 44100;
-@@ -275,6 +283,12 @@
+@@ -275,6 +283,13 @@
                                  is not defined */
      int64_t       pts;       /* current pts */
      int is_start;            /* is 1 at the start and after a discontinuity */
@@ -32,12 +32,13 @@ Index: ffmpeg.c
 +    AVFilterContext *out_video_filter;
 +    AVFilterContext *input_video_filter;
 +    AVFrame *filter_frame;
++    int has_filter_frame;
 +    AVFilterPicRef *picref;
 +#endif
  } AVInputStream;
  
  typedef struct AVInputFile {
-@@ -290,6 +304,259 @@
+@@ -290,6 +305,268 @@
  static struct termios oldtty;
  #endif
  
@@ -64,6 +65,12 @@ Index: ffmpeg.c
 +    av_free(priv->ist->filter_frame);
 +}
 +
++static int poll_frame(AVFilterLink *link)
++{
++    FilterInPriv *priv = link->src->priv;
++    return !!(priv->ist->has_filter_frame);
++}
++
 +static int input_request_frame(AVFilterLink *link)
 +{
 +    FilterInPriv *priv = link->src->priv;
@@ -84,6 +91,8 @@ Index: ffmpeg.c
 +    avfilter_end_frame(link);
 +    avfilter_unref_pic(picref);
 +
++    priv->ist->has_filter_frame = 0;
++
 +    return 0;
 +}
 +
@@ -122,6 +131,7 @@ Index: ffmpeg.c
 +    .outputs   = (AVFilterPad[]) {{ .name = "default",
 +                                    .type = AV_PAD_VIDEO,
 +                                    .request_frame = input_request_frame,
++                                    .poll_frame = poll_frame,
 +                                    .config_props  = input_config_props, },
 +                                  { .name = NULL }},
 +};
@@ -155,7 +165,7 @@ Index: ffmpeg.c
 +}
 +
 +static int get_filtered_video_pic(AVFilterContext *ctx,
-+                                  AVFilterPicRef **picref, AVPicture *pic2,
++                                  AVFilterPicRef **picref, AVFrame *pic2,
 +                                  uint64_t *pts)
 +{
 +    AVFilterPicRef *pic;
@@ -297,21 +307,7 @@ Index: ffmpeg.c
  static void term_exit(void)
  {
  #ifdef HAVE_TERMIOS_H
-@@ -635,6 +902,13 @@
-         frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height,
-                            1000000 * ist->pts / AV_TIME_BASE);
- 
-+#if ENABLE_AVFILTER
-+    memcpy(ist->filter_frame->data,  picture2->data, sizeof(picture2->data));
-+    memcpy(ist->filter_frame->linesize, picture2->linesize, sizeof(picture2->linesize));
-+
-+    if (get_filtered_video_pic(ist->out_video_filter, &ist->picref, picture2, &ist->pts) < 0)
-+        fprintf(stderr, "Error: get_filtered_video_pic failed!\n");
-+#endif
-     if (picture != picture2)
-         *picture = *picture2;
-     *bufp = buf;
-@@ -745,6 +1019,9 @@
+@@ -745,6 +1022,9 @@
      if (nb_frames <= 0)
          return;
  
@@ -321,7 +317,7 @@ Index: ffmpeg.c
      if (ost->video_crop) {
          if (av_picture_crop((AVPicture *)&picture_crop_temp, (AVPicture *)in_picture, dec->pix_fmt, ost->topBand, ost->leftBand) < 0) {
              av_log(NULL, AV_LOG_ERROR, "error cropping picture\n");
-@@ -754,6 +1031,7 @@
+@@ -754,6 +1034,7 @@
      } else {
          formatted_picture = in_picture;
      }
@@ -329,7 +325,7 @@ Index: ffmpeg.c
  
      final_picture = formatted_picture;
      padding_src = formatted_picture;
-@@ -769,12 +1047,14 @@
+@@ -769,12 +1050,14 @@
          }
      }
  
@@ -344,18 +340,48 @@ Index: ffmpeg.c
  
      if (ost->video_pad) {
          av_picture_pad((AVPicture*)final_picture, (AVPicture *)padding_src,
-@@ -1275,6 +1555,10 @@
-                     }
-                 }
-             }
+@@ -1154,6 +1437,17 @@
+                                     &buffer_to_free);
+         }
+ 
 +#if ENABLE_AVFILTER
-+        if(ist->picref)
-+            avfilter_unref_pic(ist->picref);
++        if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO) {
++            // add it to be filtered
++            memcpy(ist->filter_frame->data,  picture.data,
++                   sizeof(picture.data));
++            memcpy(ist->filter_frame->linesize, picture.linesize,
++                   sizeof(picture.linesize));
++            ist->has_filter_frame = 1;
++        }
 +#endif
-         av_free(buffer_to_free);
-         /* XXX: allocate the subtitles in the codec ? */
-         if (subtitle_to_free) {
-@@ -1680,10 +1964,21 @@
++
+         // preprocess audio (volume)
+         if (ist->st->codec->codec_type == CODEC_TYPE_AUDIO) {
+             if (audio_volume != 256) {
+@@ -1216,10 +1510,22 @@
+                             do_audio_out(os, ost, ist, data_buf, data_size);
+                             break;
+                         case CODEC_TYPE_VIDEO:
++#if ENABLE_AVFILTER
++                            while(avfilter_poll_frame(ist->out_video_filter->inputs[0])) {
++                                get_filtered_video_pic(ist->out_video_filter, &ist->picref, &picture, &ist->pts);
++                                do_video_out(os, ost, ist, &picture, &frame_size);
++                                video_size += frame_size;
++                                if (vstats_filename && frame_size)
++                                    do_video_stats(os, ost, frame_size);
++                                if(ist->picref)
++                                    avfilter_unref_pic(ist->picref);
++                            }
++#else
+                             do_video_out(os, ost, ist, &picture, &frame_size);
+                             video_size += frame_size;
+                             if (vstats_filename && frame_size)
+                                 do_video_stats(os, ost, frame_size);
++#endif
+                             break;
+                         case CODEC_TYPE_SUBTITLE:
+                             do_subtitle_out(os, ost, ist, &subtitle,
+@@ -1680,10 +1986,21 @@
                          fprintf(stderr, "Cannot get resampling context\n");
                          exit(1);
                      }
@@ -377,7 +403,7 @@ Index: ffmpeg.c
                  break;
              case CODEC_TYPE_SUBTITLE:
                  ost->encoding_needed = 1;
-@@ -3782,6 +4077,9 @@
+@@ -3782,6 +4099,9 @@
  #ifdef CONFIG_VHOOK
      { "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" },
  #endif

Modified: libavfilter/vf_fps.c
==============================================================================
--- libavfilter/vf_fps.c	(original)
+++ libavfilter/vf_fps.c	Wed Feb  6 20:55:36 2008
@@ -32,6 +32,8 @@ typedef struct {
     uint64_t timebase;
     uint64_t pts;
     AVFilterPicRef *pic;
+    int videoend;
+    int has_frame;
 } FPSContext;
 
 static int init(AVFilterContext *ctx, const char *args, void *opaque)
@@ -63,6 +65,23 @@ static void start_frame(AVFilterLink *li
     fps->pic = picref;
 }
 
+static int poll_frame(AVFilterLink *link)
+{
+    FPSContext *fps = link->src->priv;
+
+    if (fps->has_frame)
+        return 1;
+
+    if(avfilter_poll_frame(link->src->inputs[0]) &&
+       avfilter_request_frame(link->src->inputs[0])) {
+        fps->videoend = 1;
+        return 1;
+    }
+
+    fps->has_frame = !!(fps->pic && fps->pic->pts >= fps->pts);
+    return fps->has_frame;
+}
+
 static void end_frame(AVFilterLink *link)
 {
 }
@@ -71,14 +90,22 @@ static int request_frame(AVFilterLink *l
 {
     FPSContext *fps = link->src->priv;
 
-    while(!fps->pic || fps->pic->pts < fps->pts)
-        if(avfilter_request_frame(link->src->inputs[0]))
-            return -1;
+    if (fps->videoend)
+        return -1;
 
+    if (!fps->has_frame) // Support for filtering without poll_frame usage
+        while(!fps->pic || fps->pic->pts < fps->pts)
+            if(avfilter_request_frame(link->src->inputs[0]))
+                return -1;
+
+    fps->has_frame=0;
     avfilter_start_frame(link, avfilter_ref_pic(fps->pic, ~AV_PERM_WRITE));
     avfilter_draw_slice (link, 0, fps->pic->h);
     avfilter_end_frame  (link);
 
+    avfilter_unref_pic(fps->pic);
+    fps->pic = NULL;
+
     fps->pts += fps->timebase;
 
     return 0;
@@ -101,6 +128,7 @@ AVFilter avfilter_vf_fps =
                                   { .name = NULL}},
     .outputs   = (AVFilterPad[]) {{ .name            = "default",
                                     .type            = AV_PAD_VIDEO,
+                                    .poll_frame      = poll_frame,
                                     .request_frame   = request_frame, },
                                   { .name = NULL}},
 };



More information about the FFmpeg-soc mailing list